I need to find out the alignment and size information for the standard integral types and pointer types at GCC build time.
The information is needed to work out the sizes of data structures so that warnings about size mismatches can be produced. The information is needed at build time because the parser and validator do not have access to the gcc back end code when the compiler runs. So this information needs to be worked out earlier and generated as Lisp code ie in the build phase. I have found tm.h, and also bconfig.h, config.h and tconfig.h. The sizes are more or less OK as there are macros for sizes, apart from pointer sizes in some cases. The alignment is the main problem; the alignments for i386 are not constants but function calls and vary in certain scenarios. My current attempt at doing this is below. I fully acknowledge that it is not correct. That is the reason for this posting. Does anyone have any suggestions about how to get this information at build time? Apart from some simple solution which I hope someone will come up with I have two other possible avenues to solve the problem 1. Have some sort of install process which compiles and that extracts the information out of the target compiler. Eg I could write a small program which prints out the __alignof__ values and sizeof values for various data items. This information then gets stored somewhere that it can be used by the Lisp code. 2. Turn GCC into a libgccbackend and call it from my lisp code at run time using a foreign function interface. This would make it unnecessary to get the information at build time because the Lisp code could get it from the compiler back end when compiling the program. This would be a last resort at this stage due to possibilities for misuse of a libgccbackend and also the foreign function interface overheads. Tim Josling /* -*- C -*- */ /* Copyright ... FILE Generate target-info file, - data item attributes for target time. Output goes to standard output. */ #include <stdlib.h> #include <stdio.h> #include <stdint.h> #define IN_GCC #include "tconfig.h" #include "system.h" #include "coretypes.h" #include "tm.h" /* We don't want fancy_abort */ #undef abort #ifndef BIGGEST_FIELD_ALIGNMENT #define BIGGEST_FIELD_ALIGNMENT 32 #endif #ifndef BITS_PER_UNIT #define BITS_PER_UNIT 8 #endif #ifndef POINTER_SIZE #ifdef TARGET_64BIT #define POINTER_SIZE 64 #else #define POINTER_SIZE 32 #endif #endif /* Fake because some macro needs it. */ int ix86_isa_flags = 0; static int maxint (int a, int b) { return (a>b?a:b); } static void print_one_item (char *name, char *actual_usage, char *basic_type, int size_bits) { printf ("(defconstant %s-attributes\n" " (gcb:make-usage-attributes\n" " :usage cbt:%s\n" " :basic-type cbt:%s\n" " :size %d\n" " :default-alignment %d\n" " :sync-alignment %d))\n", name, actual_usage, basic_type, size_bits/BITS_PER_UNIT, 1, maxint (size_bits/BITS_PER_UNIT, /* This alignment is all wrong but there doesn't seem to be any way to get the true figure out of GCC short of doing a cross-build and then running a program on the target machine. */ BIGGEST_FIELD_ALIGNMENT/BITS_PER_UNIT)); } int main (int argc, char **argv) { fprintf (stderr, "TARGET_64BIT %d\n", TARGET_64BIT); fprintf (stderr, "POINTER_SIZE %d\n", POINTER_SIZE); if (argc != 1) { fprintf (stderr, "Unexpected number of parameters - should be none \n"); abort (); } printf ("...file header stuff"); print_one_item ("char", "binary-char", "binary", BITS_PER_UNIT); print_one_item ("short", "binary-short", "binary", SHORT_TYPE_SIZE); print_one_item ("int", "binary-int", "binary", INT_TYPE_SIZE); print_one_item ("long", "binary-long", "binary", LONG_TYPE_SIZE); print_one_item ("long-long", "binary-long-long", "binary", LONG_LONG_TYPE_SIZE); print_one_item ("sizet", "binary-size", "binary", POINTER_SIZE); print_one_item ("ptr", "binary-ptr", "binary", POINTER_SIZE); print_one_item ("ptr-diff", "binary-ptr-diff", "binary", POINTER_SIZE); print_one_item ("display", "display", "display", BITS_PER_UNIT); print_one_item ("binary", "binary", "binary", INT_TYPE_SIZE); print_one_item ("binary1", "binary1", "binary", 1 * BITS_PER_UNIT); print_one_item ("binary2", "binary2", "binary", 2 * BITS_PER_UNIT); print_one_item ("binary4", "binary4", "binary", 4 * BITS_PER_UNIT); print_one_item ("binary8", "binary8", "binary", 8 * BITS_PER_UNIT); print_one_item ("pointer", "binary-pointer", "pointer", POINTER_SIZE); print_one_item ("function-pointer", "function-pointer", "pointer", POINTER_SIZE); print_one_item ("program-pointer", "program-pointer", "pointer", POINTER_SIZE); printf ("(defconstant usage-attributes-ht\n" " (gcbc-utils:list2ht 'eql\n" " (mapcar #'(lambda (el) (list (gcb:usage-attributes-usage el) el))\n" " (list char-attributes\n" " short-attributes\n" " int-attributes\n" " long-attributes\n" " long-long-attributes\n" " sizet-attributes\n" " display-attributes\n" " binary-attributes\n" " binary1-attributes\n" " binary2-attributes \n" " binary4-attributes\n" " binary8-attributes\n" " pointer-attributes\n" " function-pointer-attributes\n" " program-pointer-attributes)))\n"); printf ("(defconstant max-unsigned-integral-value %llu)\n" "(defconstant max-positive-integral-value %lld)\n" "(defconstant min-negative-integral-value %lld)\n", (unsigned long long) UINTMAX_MAX, (long long) INTMAX_MAX, (long long) INTMAX_MIN); return 0; }