History

Fix struct layout some more

Anonymous sub-sub-members weren't handled correctly. Bit-fields neither: this implements PCC layout for now. It temporarily disables MS-compatible bit-field layout.

Michael Matz committed 10 years ago

Commit 78c70961 parent ddecb0e2 files · +199 −40Browse files

Unified · Split

2 files
  1. tccgen.c +113 −40
  2. tests/tcctest.c +86 −0
tccgen.c+113−40
@@ -3239,7 +3239,9 @@ static Sym * find_field (CType *type, int v) · 3238 unmodified lines
3239 Sym *s = type->ref;3239 Sym *s = type->ref;
3240 v |= SYM_FIELD;3240 v |= SYM_FIELD;
3241 while ((s = s->next) != NULL) {3241 while ((s = s->next) != NULL) {
3242 if ((s->v & SYM_FIELD) && (s->v & ~SYM_FIELD) >= SYM_FIRST_ANOM) {3242 if ((s->v & SYM_FIELD) &&
3243 (s->type.t & VT_BTYPE) == VT_STRUCT &&
3244 (s->v & ~SYM_FIELD) >= SYM_FIRST_ANOM) {
3243 Sym *ret = find_field (&s->type, v);3245 Sym *ret = find_field (&s->type, v);
3244 if (ret)3246 if (ret)
3245 return ret;3247 return ret;
@@ -3250,44 +3252,131 @@ static Sym * find_field (CType *type, int v) · 4 unmodified lines
3250 return s;3252 return s;
3251}3253}
3252 3254
3255static void struct_add_offset (Sym *s, int offset)
3256{
3257 while ((s = s->next) != NULL) {
3258 if ((s->v & SYM_FIELD) &&
3259 (s->type.t & VT_BTYPE) == VT_STRUCT &&
3260 (s->v & ~SYM_FIELD) >= SYM_FIRST_ANOM) {
3261 struct_add_offset(s->type.ref, offset);
3262 } else
3263 s->c += offset;
3264 }
3265}
3266
3253static void struct_layout(CType *type, AttributeDef *ad)3267static void struct_layout(CType *type, AttributeDef *ad)
3254{3268{
3255 int align, maxalign, offset, c;3269 int align, maxalign, offset, c, bit_pos;
3256 Sym *f;3270 Sym *f;
3257 maxalign = 1;3271 if (ad->a.aligned)
3272 maxalign = ad->a.aligned;
3273 else
3274 maxalign = 1;
3258 offset = 0;3275 offset = 0;
3259 c = 0;3276 c = 0;
3277 bit_pos = 0;
3260 for (f = type->ref->next; f; f = f->next) {3278 for (f = type->ref->next; f; f = f->next) {
3261 int extra_bytes = f->c;3279 int extra_bytes = 0;
3262 int bit_pos;3280 int typealign, bit_size;
3263 int size = type_size(&f->type, &align);3281 int size = type_size(&f->type, &typealign);
3264 if (f->type.t & VT_BITFIELD)3282 int pcc = !tcc_state->ms_bitfields;
3265 bit_pos = (f->type.t >> VT_STRUCT_SHIFT) & 0x3f;3283 if (f->type.t & VT_BITFIELD) {
3266 else3284 bit_size = (f->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
3267 bit_pos = 0;3285 /* without ms-bitfields, allocate the
3268 if (f->r) {3286 * minimum number of bytes necessary,
3287 * adding single bytes as needed */
3288 if (!tcc_state->ms_bitfields) {
3289 if (bit_pos == 0)
3290 /* minimum bytes for new bitfield */
3291 size = (bit_size + 7) / 8;
3292 else {
3293 /* enough spare bits already allocated? */
3294 int add_size = (bit_pos - 1) % 8 + 1 + bit_size;
3295 if (add_size > 8) /* doesn't fit */
3296 extra_bytes = (add_size - 1) / 8;
3297 }
3298 }
3299 } else
3300 bit_size = -1;
3301 if (bit_size == 0 && pcc) {
3302 /* Zero-width bit-fields in PCC mode aren't affected
3303 by any packing (attribute or pragma). */
3304 align = typealign;
3305 } else if (f->r > 1) {
3269 align = f->r;3306 align = f->r;
3270 } else if (ad->a.packed) {3307 } else if (ad->a.packed || f->r == 1) {
3271 align = 1;3308 align = 1;
3309 typealign = 1;
3310 } else {
3311 align = typealign;
3272 }3312 }
3273 if (extra_bytes) c += extra_bytes;3313 /*if (extra_bytes) c += extra_bytes;
3274 else if (bit_pos == 0) {3314 else*/ if (bit_size < 0) {
3315 int addbytes = (bit_pos + 7) >> 3;
3275 if (type->ref->type.t == TOK_STRUCT) {3316 if (type->ref->type.t == TOK_STRUCT) {
3276 c = (c + align - 1) & -align;3317 c = (c + addbytes + align - 1) & -align;
3277 offset = c;3318 offset = c;
3278 if (size > 0)3319 if (size > 0)
3279 c += size;3320 c += size;
3280 } else {3321 } else {
3281 offset = 0;3322 offset = 0;
3323 if (addbytes > c)
3324 c = addbytes;
3282 if (size > c)3325 if (size > c)
3283 c = size;3326 c = size;
3284 }3327 }
3285 if (align > maxalign)3328 if (align > maxalign)
3286 maxalign = align;3329 maxalign = align;
3330 bit_pos = 0;
3331 } else {
3332 /* A bit-field. Layout is more complicated. There are two
3333 options TCC implements: PCC compatible and MS compatible
3334 (PCC compatible is what GCC uses for almost all targets). */
3335 if (!bit_pos) {
3336 if (type->ref->type.t == TOK_STRUCT) {
3337 /* Don't align c here. That's only to be done
3338 in certain cases. */
3339 offset = c;
3340 } else {
3341 offset = 0;
3342 }
3343 }
3344 if (pcc) {
3345 /* In PCC layout a non-packed bit-field is placed adjacent
3346 to the preceding bit-fields, except if it would overflow
3347 its container (depending on base type) or it's a zero-width
3348 bit-field. Packed non-zero-width bit-fields always are
3349 placed adjacent. */
3350 if (typealign != 1 &&
3351 (bit_pos + bit_size > size * 8 ||
3352 bit_size == 0)) {
3353 c = (c + ((bit_pos + 7) >> 3) + typealign - 1) & -typealign;
3354 offset = c;
3355 bit_pos = 0;
3356 }
3357 /* In PCC layout named bit-fields influence the alignment
3358 of the containing struct using the base types alignment,
3359 except for packed fields or zero-width fields. */
3360 if (bit_size > 0) {
3361 if (align > maxalign)
3362 maxalign = align;
3363 if (typealign > maxalign)
3364 maxalign = typealign;
3365 }
3366 } else {
3367 tcc_error("ms bit-field layout not implemented");
3368 }
3369 f->type.t = (f->type.t & ~(0x3f << VT_STRUCT_SHIFT))
3370 | (bit_pos << VT_STRUCT_SHIFT);
3371 bit_pos += bit_size;
3372 if (bit_pos >= size * 8) {
3373 c += size;
3374 bit_pos -= size * 8;
3375 }
3287 }3376 }
3288#if 03377#if 0
3289 printf("set field %s offset=%d",3378 printf("set field %s offset=%d c=%d",
3290 get_tok_str(f->v & ~SYM_FIELD, NULL), offset);3379 get_tok_str(f->v & ~SYM_FIELD, NULL), offset, c);
3291 if (f->type.t & VT_BITFIELD) {3380 if (f->type.t & VT_BITFIELD) {
3292 printf(" pos=%d size=%d",3381 printf(" pos=%d size=%d",
3293 (f->type.t >> VT_STRUCT_SHIFT) & 0x3f,3382 (f->type.t >> VT_STRUCT_SHIFT) & 0x3f,
@@ -3325,9 +3414,7 @@ static void struct_layout(CType *type, AttributeDef *ad) · 31 unmodified lines
3325 }3414 }
3326 *pps = NULL;3415 *pps = NULL;
3327 }3416 }
3328 ass = f->type.ref;3417 struct_add_offset(f->type.ref, offset);
3329 while ((ass = ass->next) != NULL)
3330 ass->c += offset;
3331 f->c = 0;3418 f->c = 0;
3332 } else {3419 } else {
3333 f->c = offset;3420 f->c = offset;
@@ -3336,7 +3423,7 @@ static void struct_layout(CType *type, AttributeDef *ad) · 2 unmodified lines
3336 f->r = 0;3423 f->r = 0;
3337 }3424 }
3338 /* store size and alignment */3425 /* store size and alignment */
3339 type->ref->c = (c + maxalign - 1) & -maxalign;3426 type->ref->c = (c + ((bit_pos + 7) >> 3) + maxalign - 1) & -maxalign;
3340 type->ref->r = maxalign;3427 type->ref->r = maxalign;
3341}3428}
3342 3429
@@ -3515,11 +3602,6 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) · 172 unmodified lines
3515 } else if (bit_size == bsize) {3602 } else if (bit_size == bsize) {
3516 /* no need for bit fields */3603 /* no need for bit fields */
3517 bit_pos = 0;3604 bit_pos = 0;
3518 } else if (bit_size == 0) {
3519 /* XXX: what to do if only padding in a
3520 structure ? */
3521 /* zero size: means to pad */
3522 bit_pos = 0;
3523 } else {3605 } else {
3524 /* if type change, union, or will overrun3606 /* if type change, union, or will overrun
3525 * allignment slot, start at a newly3607 * allignment slot, start at a newly
@@ -3531,20 +3613,6 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) · 5 unmodified lines
3531 type1.t |= VT_BITFIELD | 3613 type1.t |= VT_BITFIELD |
3532 (bit_pos << VT_STRUCT_SHIFT) |3614 (bit_pos << VT_STRUCT_SHIFT) |
3533 (bit_size << (VT_STRUCT_SHIFT + 6));3615 (bit_size << (VT_STRUCT_SHIFT + 6));
3534 /* without ms-bitfields, allocate the
3535 * minimum number of bytes necessary,
3536 * adding single bytes as needed */
3537 if (!tcc_state->ms_bitfields) {
3538 if (bit_pos == 0)
3539 /* minimum bytes for new bitfield */
3540 size = (bit_size + 7) / 8;
3541 else {
3542 /* enough spare bits already allocated? */
3543 int add_size = (bit_pos - 1) % 8 + 1 + bit_size;
3544 if (add_size > 8) /* doesn't fit */
3545 extra_bytes = (add_size - 1) / 8;
3546 }
3547 }
3548 bit_pos += bit_size;3616 bit_pos += bit_size;
3549 }3617 }
3550 prevbt = bt;3618 prevbt = bt;
@@ -3561,6 +3629,11 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) · 10 unmodified lines
3561 anonymous member of struct type. */3629 anonymous member of struct type. */
3562 v = anon_sym++;3630 v = anon_sym++;
3563 }3631 }
3632 if (v == 0 && bit_size >= 0) {
3633 /* Need to remember anon bit-fields as well.
3634 They influence layout. */
3635 v = anon_sym++;
3636 }
3564 if (v) {3637 if (v) {
3565 ss = sym_push(v | SYM_FIELD, &type1, alignoverride, extra_bytes);3638 ss = sym_push(v | SYM_FIELD, &type1, alignoverride, extra_bytes);
3566 *ps = ss;3639 *ps = ss;
tests/tcctest.c+86−0
@@ -1026,10 +1026,67 @@ struct aligntest4 { · 1025 unmodified lines
1026 double a[0];1026 double a[0];
1027};1027};
1028 1028
1029struct __attribute__((aligned(16))) aligntest5
1030{
1031 int i;
1032};
1033struct aligntest6
1034{
1035 int i;
1036} __attribute__((aligned(16)));
1037struct aligntest7
1038{
1039 int i;
1040};
1041struct aligntest5 altest5[2];
1042struct aligntest6 altest6[2];
1043int pad1;
1044/* altest7 is correctly aligned to 16 bytes also with TCC,
1045 but __alignof__ returns the wrong result (4) because we
1046 can't store the alignment yet when specified on symbols
1047 directly (it's stored in the type so we'd need to make
1048 a copy of it).
1049struct aligntest7 altest7[2] __attribute__((aligned(16)));*/
1050
1051struct Large {
1052 unsigned long flags;
1053 union {
1054 void *u1;
1055 int *u2;
1056 };
1057
1058 struct {
1059 union {
1060 unsigned long index;
1061 void *freelist;
1062 };
1063 union {
1064 unsigned long counters;
1065 struct {
1066 int bla;
1067 };
1068 };
1069 };
1070
1071 union {
1072 struct {
1073 long u3;
1074 long u4;
1075 };
1076 void *u5;
1077 struct {
1078 unsigned long compound_head;
1079 unsigned int compound_dtor;
1080 unsigned int compound_order;
1081 };
1082 };
1083} __attribute__((aligned(2 * sizeof(long))));
1084
1029void struct_test()1085void struct_test()
1030{1086{
1031 struct1 *s;1087 struct1 *s;
1032 union union2 u;1088 union union2 u;
1089 struct Large ls;
1033 1090
1034 printf("struct:\n");1091 printf("struct:\n");
1035 printf("sizes: %d %d %d %d\n",1092 printf("sizes: %d %d %d %d\n",
@@ -1037,6 +1094,7 @@ void struct_test() · 1 unmodified line
1037 sizeof(struct struct2),1094 sizeof(struct struct2),
1038 sizeof(union union1),1095 sizeof(union union1),
1039 sizeof(union union2));1096 sizeof(union union2));
1097 printf("offsets: %d\n", (int)((char*)&st1.u.v1 - (char*)&st1));
1040 st1.f1 = 1;1098 st1.f1 = 1;
1041 st1.f2 = 2;1099 st1.f2 = 2;
1042 st1.f3 = 3;1100 st1.f3 = 3;
@@ -1065,10 +1123,27 @@ void struct_test() · 22 unmodified lines
1065 sizeof(struct aligntest3), __alignof__(struct aligntest3));1123 sizeof(struct aligntest3), __alignof__(struct aligntest3));
1066 printf("aligntest4 sizeof=%d alignof=%d\n",1124 printf("aligntest4 sizeof=%d alignof=%d\n",
1067 sizeof(struct aligntest4), __alignof__(struct aligntest4));1125 sizeof(struct aligntest4), __alignof__(struct aligntest4));
1126 printf("aligntest5 sizeof=%d alignof=%d\n",
1127 sizeof(struct aligntest5), __alignof__(struct aligntest5));
1128 printf("aligntest6 sizeof=%d alignof=%d\n",
1129 sizeof(struct aligntest6), __alignof__(struct aligntest6));
1130 printf("aligntest7 sizeof=%d alignof=%d\n",
1131 sizeof(struct aligntest7), __alignof__(struct aligntest7));
1132 printf("altest5 sizeof=%d alignof=%d\n",
1133 sizeof(altest5), __alignof__(altest5));
1134 printf("altest6 sizeof=%d alignof=%d\n",
1135 sizeof(altest6), __alignof__(altest6));
1136 /*printf("altest7 sizeof=%d alignof=%d\n",
1137 sizeof(altest7), __alignof__(altest7));*/
1068 1138
1069 /* empty structures (GCC extension) */1139 /* empty structures (GCC extension) */
1070 printf("sizeof(struct empty) = %d\n", sizeof(struct empty));1140 printf("sizeof(struct empty) = %d\n", sizeof(struct empty));
1071 printf("alignof(struct empty) = %d\n", __alignof__(struct empty));1141 printf("alignof(struct empty) = %d\n", __alignof__(struct empty));
1142
1143 printf("Large: sizeof=%d\n", sizeof(ls));
1144 memset(&ls, 0, sizeof(ls));
1145 ls.compound_head = 42;
1146 printf("Large: offsetof(compound_head)=%d\n", (int)((char*)&ls.compound_head - (char*)&ls));
1072}1147}
1073 1148
1074/* XXX: depend on endianness */1149/* XXX: depend on endianness */
@@ -3547,11 +3622,22 @@ typedef struct Spacked3_s { · 2472 unmodified lines
3547 int c;3622 int c;
3548} __attribute__((__packed__)) Spacked3;3623} __attribute__((__packed__)) Spacked3;
3549Spacked3 spacked3;3624Spacked3 spacked3;
3625struct gate_struct64 {
3626 unsigned short offset_low;
3627 unsigned short segment;
3628 unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1;
3629 unsigned short offset_middle;
3630 unsigned offset_high;
3631 unsigned zero1;
3632} __attribute__((packed));
3633typedef struct gate_struct64 gate_desc;
3634gate_desc a_gate_desc;
3550void attrib_test(void)3635void attrib_test(void)
3551{3636{
3552 printf("attr: %d %d %d %d\n", sizeof(struct Spacked),3637 printf("attr: %d %d %d %d\n", sizeof(struct Spacked),
3553 sizeof(spacked), sizeof(Spacked2), sizeof(spacked2));3638 sizeof(spacked), sizeof(Spacked2), sizeof(spacked2));
3554 printf("attr: %d %d\n", sizeof(Spacked3), sizeof(spacked3));3639 printf("attr: %d %d\n", sizeof(Spacked3), sizeof(spacked3));
3640 printf("attr: %d %d\n", sizeof(gate_desc), sizeof(a_gate_desc));
3555}3641}
3556extern __attribute__((__unused__)) char * __attribute__((__unused__)) *3642extern __attribute__((__unused__)) char * __attribute__((__unused__)) *
3557strange_attrib_placement (void);3643strange_attrib_placement (void);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t