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;
}


Reply via email to