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.
Unified · Split
| @@ -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 | ||
| 3255 | static 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 | |||
| 3253 | static void struct_layout(CType *type, AttributeDef *ad) | 3267 | static 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 | else | 3284 | 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 0 | 3377 | #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 overrun | 3606 | /* if type change, union, or will overrun |
| 3525 | * allignment slot, start at a newly | 3607 | * 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; |
| @@ -1026,10 +1026,67 @@ struct aligntest4 { · 1025 unmodified lines | |||
| 1026 | double a[0]; | 1026 | double a[0]; |
| 1027 | }; | 1027 | }; |
| 1028 | 1028 | ||
| 1029 | struct __attribute__((aligned(16))) aligntest5 | ||
| 1030 | { | ||
| 1031 | int i; | ||
| 1032 | }; | ||
| 1033 | struct aligntest6 | ||
| 1034 | { | ||
| 1035 | int i; | ||
| 1036 | } __attribute__((aligned(16))); | ||
| 1037 | struct aligntest7 | ||
| 1038 | { | ||
| 1039 | int i; | ||
| 1040 | }; | ||
| 1041 | struct aligntest5 altest5[2]; | ||
| 1042 | struct aligntest6 altest6[2]; | ||
| 1043 | int 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). | ||
| 1049 | struct aligntest7 altest7[2] __attribute__((aligned(16)));*/ | ||
| 1050 | |||
| 1051 | struct 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 | |||
| 1029 | void struct_test() | 1085 | void 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; |
| 3549 | Spacked3 spacked3; | 3624 | Spacked3 spacked3; |
| 3625 | struct 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)); | ||
| 3633 | typedef struct gate_struct64 gate_desc; | ||
| 3634 | gate_desc a_gate_desc; | ||
| 3550 | void attrib_test(void) | 3635 | void 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 | } |
| 3556 | extern __attribute__((__unused__)) char * __attribute__((__unused__)) * | 3642 | extern __attribute__((__unused__)) char * __attribute__((__unused__)) * |
| 3557 | strange_attrib_placement (void); | 3643 | strange_attrib_placement (void); |