📄 struct-layout-encoding-1_generate.c
字号:
/* Structure layout test generator. Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. Contributed by Jakub Jelinek <jakub@redhat.com>.This file is part of GCC.GCC is free software; you can redistribute it and/or modify it underthe terms of the GNU General Public License as published by the FreeSoftware Foundation; either version 3, or (at your option) any laterversion.GCC is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY; without even the implied warranty of MERCHANTABILITY orFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licensefor more details.You should have received a copy of the GNU General Public Licensealong with GCC; see the file COPYING3. If not see<http://www.gnu.org/licenses/>. *//* Compile with gcc -o struct-layout-1_generate{,.c} generate_random{,_r}.c *//* N.B. -- This program cannot use libiberty as that will not work when testing an installed compiler. */#include <limits.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stddef.h>/* We use our own pseudo-random number generator, so that it gives the same values on all hosts. */#include "generate-random.h"#if LLONG_MAX != 9223372036854775807LL && __LONG_LONG_MAX__ != 9223372036854775807LL# error Need 64-bit long long#endiftypedef unsigned int hashval_t;enum TYPE{ TYPE_INT, TYPE_UINT, TYPE_CINT, TYPE_CUINT, TYPE_FLOAT, TYPE_CFLOAT, TYPE_SENUM, TYPE_UENUM, TYPE_PTR, TYPE_FNPTR, TYPE_OTHER};struct types{ const char *name; enum TYPE type; unsigned long long int maxval; char bitfld;};struct types base_types[] = {/* As we don't know whether char will be signed or not, just limit ourselves to unsigned values less than maximum signed char value. */{ "char", TYPE_UINT, 127, 'C' },{ "signed char", TYPE_INT, 127, 'C' },{ "unsigned char", TYPE_UINT, 255, 'C' },{ "short int", TYPE_INT, 32767, 'S' },{ "unsigned short int", TYPE_UINT, 65535, 'S' },{ "int", TYPE_INT, 2147483647, 'I' },{ "unsigned int", TYPE_UINT, 4294967295U, 'I' },{ "long int", TYPE_INT, 9223372036854775807LL, 'L' },{ "unsigned long int", TYPE_UINT, 18446744073709551615ULL, 'L' },{ "long long int", TYPE_INT, 9223372036854775807LL, 'Q' },{ "unsigned long long int", TYPE_UINT, 18446744073709551615ULL, 'Q' },{ "bool", TYPE_UINT, 1, 'B' },{ "void *", TYPE_PTR, 0, 0 },{ "char *", TYPE_PTR, 0, 0 },{ "int *", TYPE_PTR, 0, 0 },{ "float", TYPE_FLOAT, 0, 0 },{ "double", TYPE_FLOAT, 0, 0 },/*{ "long double", TYPE_FLOAT, 0, 0 },*//* Disabled as double and long double are encoded thee same, currently */#define NTYPES1 16#if 0/* enums are disabled for now as it seems like their encoding is broken, we should just encode them using their underlaying type but we don't. */{ "enum E0", TYPE_UENUM, 0, ' ' },{ "enum E1", TYPE_UENUM, 1, ' ' },{ "enum E2", TYPE_SENUM, 3, ' ' },{ "enum E3", TYPE_SENUM, 127, ' ' },{ "enum E4", TYPE_UENUM, 255, ' ' },{ "enum E5", TYPE_SENUM, 32767, ' ' },{ "enum E6", TYPE_UENUM, 65535, ' ' },{ "enum E7", TYPE_SENUM, 2147483647, ' ' },{ "enum E8", TYPE_UENUM, 4294967295U, ' ' },{ "enum E9", TYPE_SENUM, 1099511627775LL, ' ' },#endif#define NTYPES2 (sizeof (base_types) / sizeof (base_types[0]))};struct types complex_types[] = {{ "_Complex char", TYPE_CUINT, 127, 0 },{ "_Complex signed char", TYPE_CINT, 127, 0 },{ "_Complex unsigned char", TYPE_CUINT, 255, 0 },{ "_Complex short int", TYPE_CINT, 32767, 0 },{ "_Complex unsigned short int", TYPE_CUINT, 65535, 0 },{ "_Complex int", TYPE_CINT, 2147483647, 0 },{ "_Complex unsigned int", TYPE_CUINT, 4294967295U, 0 },{ "_Complex long int", TYPE_CINT, 9223372036854775807LL, 0 },{ "_Complex unsigned long int", TYPE_CUINT, 18446744073709551615ULL, 0 },{ "_Complex long long int", TYPE_CINT, 9223372036854775807LL, 0 },{ "_Complex unsigned long long int", TYPE_CUINT, 18446744073709551615ULL, 0 },{ "_Complex float", TYPE_CFLOAT, 0, 0 },{ "_Complex double", TYPE_CFLOAT, 0, 0 },/*{ "_Complex long double", TYPE_CFLOAT, 0, 0 }, *//* Disable until long doubles are encoded correctly. */#define NCTYPES2 (sizeof (complex_types) / sizeof (complex_types[0]))};struct types vector_types[] = {/* vector-defs.h typedefs */{ "v8qi", TYPE_OTHER, 0, 0 },{ "v16qi", TYPE_OTHER, 0, 0 },{ "v2hi", TYPE_OTHER, 0, 0 },{ "v4hi", TYPE_OTHER, 0, 0 },{ "v8hi", TYPE_OTHER, 0, 0 },{ "v2si", TYPE_OTHER, 0, 0 },{ "v4si", TYPE_OTHER, 0, 0 },{ "v1di", TYPE_OTHER, 0, 0 },{ "v2di", TYPE_OTHER, 0, 0 },{ "v2sf", TYPE_OTHER, 0, 0 },{ "v4sf", TYPE_OTHER, 0, 0 },{ "v16sf", TYPE_OTHER, 0, 0 },{ "v2df", TYPE_OTHER, 0, 0 },{ "u8qi", TYPE_OTHER, 0, 0 },{ "u16qi", TYPE_OTHER, 0, 0 },{ "u2hi", TYPE_OTHER, 0, 0 },{ "u4hi", TYPE_OTHER, 0, 0 },{ "u8hi", TYPE_OTHER, 0, 0 },{ "u2si", TYPE_OTHER, 0, 0 },{ "u4si", TYPE_OTHER, 0, 0 },{ "u1di", TYPE_OTHER, 0, 0 },{ "u2di", TYPE_OTHER, 0, 0 },{ "u2sf", TYPE_OTHER, 0, 0 },{ "u4sf", TYPE_OTHER, 0, 0 },{ "u16sf", TYPE_OTHER, 0, 0 },{ "u2df", TYPE_OTHER, 0, 0 },{ "__m64", TYPE_OTHER, 0, 0 },{ "__m128", TYPE_OTHER, 0, 0 }#define NVTYPES2 (sizeof (vector_types) / sizeof (vector_types[0]))};struct types bitfld_types[NTYPES2];int n_bitfld_types;enum ETYPE{ ETYPE_TYPE, ETYPE_ARRAY, ETYPE_BITFLD, ETYPE_STRUCT, ETYPE_UNION, ETYPE_STRUCT_ARRAY, ETYPE_UNION_ARRAY};struct entry{#ifdef __GNUC__ enum ETYPE etype : 8;#else unsigned char etype;#endif unsigned short len; unsigned char arr_len; struct types *type; const char *attrib; /* Used to chain together entries in the hash table. */ struct entry *next;};/* A prime number giving the number of slots in the hash table. */ #define HASH_SIZE 32749 static struct entry *hash_table[HASH_SIZE];static int idx, limidx, output_one;static const char *destdir;static const char *srcdir;FILE *outfile;voidswitchfiles (int fields){ static int filecnt; static char *destbuf, *destptr; ++filecnt; if (outfile) fclose (outfile); if (output_one) { outfile = stdout; return; } if (destbuf == NULL) { size_t len = strlen (destdir); destbuf = malloc (len + 20); if (!destbuf) abort (); memcpy (destbuf, destdir, len); if (!len || destbuf[len - 1] != '/') destbuf[len++] = '/'; destptr = destbuf + len; } sprintf (destptr, "t%03d_main.m", filecnt); outfile = fopen (destbuf, "w"); if (outfile == NULL) { fail: fputs ("failed to create test files\n", stderr); exit (1); } /* FIXME: these tests should not be xfailed on PowerPC darwin or aix but they are because libobjc uses GCC's headers for trying to find the struct layout but it gets it wrong. */ if (filecnt == 2 || filecnt == 3 || filecnt == 4 || filecnt == 6 || filecnt == 7 || filecnt == 8 || filecnt == 11 || filecnt == 12 || filecnt == 15 || filecnt == 22) { fprintf (outfile, "\/* { dg-do run { xfail powerpc*-*-darwin* powerpc*-*-aix* } } */\n\/* { dg-options \"-w -I%s -fgnu-runtime\" } */\n", srcdir); } /* FIXME: these should not be xfailed but they are because of bugs in libobjc and the objc front-end. 25 is because vectors are not encoded. The rest are because or zero sized arrays are encoded as pointers. */ else if (filecnt >= 25) { fprintf (outfile, "\/* { dg-do run { xfail *-*-* } } */\n\/* { dg-options \"-w -I%s -fgnu-runtime\" } */\n", srcdir); } else { fprintf (outfile, "\/* { dg-do run } */\n\/* { dg-options \"-w -I%s -fgnu-runtime\" } */\n", srcdir); } fprintf(outfile, "#include <objc/encoding.h> \n\#include \"struct-layout-1.h\"\n\\n\int fails; \n\#define TX(n, type, attrs, fields, ops) \\\n\type S##n { fields } attrs; \\\n\void test##n (void) \\\n\{ \\\n\ char *encoding = @encode (type S##n); \\\n\ if (objc_sizeof_type (encoding) != sizeof(type S##n)) \\\n\ { \\\n\ fails ++; \\\n\ printf(#type \" { \" #fields \"} size is %%u, but is calulated as %%u\\n\", \\\n\ sizeof(type S##n), objc_sizeof_type (encoding)); \\\n\ } \\\n\ if (objc_alignof_type (encoding) != __alignof__ (type S##n)) \\\n\ { \\\n\ fails ++; \\\n\ printf(#type \" { \" #fields \"} align is %%u, but is calulated as %%u\\n\", \\\n\ __alignof__ (type S##n), objc_alignof_type (encoding)); \\\n\ } \\\n\}\n\#include \"t%03d_test.h\"\n\#undef TX\n\\n\int main (void)\n\{\n\#define TX(n, type, attrs, fields, ops) test##n ();\n\#include \"t%03d_test.h\"\n\#undef TX\n\ if (fails)\n\ {\n\ fflush (stdout);\n\ abort ();\n\ }\n\ exit (0);\n\}\n", filecnt, filecnt); fclose (outfile); sprintf (destptr, "t%03d_test.h", filecnt); outfile = fopen (destbuf, "w"); if (outfile == NULL) goto fail; if (fields <= 2) limidx = idx + 300; else if (fields <= 4) limidx = idx + 200; else if (fields <= 6) limidx = idx + 100; else limidx = idx + 50;}unsigned long long intgetrandll (void){ unsigned long long int ret; ret = generate_random () & 0xffffff; ret |= (generate_random () & 0xffffffLL) << 24; ret |= ((unsigned long long int) generate_random ()) << 48; return ret;}intsubfield (struct entry *e, char *letter){ int i, type; char buf[20]; const char *p; switch (e[0].etype) { case ETYPE_STRUCT: case ETYPE_UNION: case ETYPE_STRUCT_ARRAY: case ETYPE_UNION_ARRAY: type = e[0].attrib ? 1 + (generate_random () & 3) : 0; if (e[0].etype == ETYPE_STRUCT || e[0].etype == ETYPE_STRUCT_ARRAY) p = "struct"; else p = "union"; if (e[0].etype == ETYPE_STRUCT_ARRAY || e[0].etype == ETYPE_UNION_ARRAY) { if (e[0].arr_len == 255) snprintf (buf, 20, "%c[]", *letter); else snprintf (buf, 20, "%c[%d]", *letter, e[0].arr_len); } else { buf[0] = *letter; buf[1] = '\0'; } ++*letter; switch (type) { case 0: case 3: case 4: fprintf (outfile, "%s{", p); break; case 1: fprintf (outfile, "%s %s{", e[0].attrib, p); break; case 2: fprintf (outfile, "%s %s{", p, e[0].attrib); break; } for (i = 1; i <= e[0].len; ) i += subfield (e + i, letter); switch (type) { case 0: case 1: case 2: fprintf (outfile, "}%s;", buf); break; case 3: fprintf (outfile, "}%s %s;", e[0].attrib, buf); break; case 4: fprintf (outfile, "}%s %s;", buf, e[0].attrib); break; } return 1 + e[0].len; case ETYPE_TYPE: case ETYPE_ARRAY: if (e[0].etype == ETYPE_ARRAY) { if (e[0].arr_len == 255) snprintf (buf, 20, "%c[]", *letter); else snprintf (buf, 20, "%c[%d]", *letter, e[0].arr_len); } else { buf[0] = *letter; buf[1] = '\0'; } ++*letter; if (e[0].attrib) switch (generate_random () % 3) { case 0: fprintf (outfile, "%s %s %s;", e[0].attrib, e[0].type->name, buf); break; case 1: fprintf (outfile, "%s %s %s;", e[0].type->name, e[0].attrib, buf); break; case 2: fprintf (outfile, "%s %s %s;", e[0].type->name, buf, e[0].attrib); break; } else fprintf (outfile, "%s %s;", e[0].type->name, buf); return 1; case ETYPE_BITFLD: if (e[0].len == 0) { if (e[0].attrib) switch (generate_random () % 3) { case 0: fprintf (outfile, "%s %s:0;", e[0].attrib, e[0].type->name); break; case 1: fprintf (outfile, "%s %s:0;", e[0].type->name, e[0].attrib); break; case 2: fprintf (outfile, "%s:0 %s;", e[0].type->name, e[0].attrib); break; } else fprintf (outfile, "%s:0;", e[0].type->name); ++*letter; return 1; } switch (e[0].type->bitfld) { case 'C': case 'S': case 'I': case 'L': case 'Q': snprintf (buf, 20, "B%cN(%d)", e[0].type->bitfld, e[0].len); break; case 'B': case ' ': snprintf (buf, 20, "%d", e[0].len); break; default: abort (); } if (e[0].attrib) switch (generate_random () % 3) { case 0: fprintf (outfile, "%s %s %c:%s;", e[0].attrib, e[0].type->name, *letter, buf); break; case 1: fprintf (outfile, "%s %s %c:%s;", e[0].type->name, e[0].attrib,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -