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 | 3239 | Sym *s = type->ref; |
| 3240 | 3240 | v |= SYM_FIELD; |
| 3241 | 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 | 3245 | Sym *ret = find_field (&s->type, v); |
| 3244 | 3246 | if (ret) |
| 3245 | 3247 | return ret; |
| @@ -3250,44 +3252,131 @@ static Sym * find_field (CType *type, int v) · 4 unmodified lines | ||
| 3250 | 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 | 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 | 3270 | Sym *f; |
| 3257 | − maxalign = 1; | |
| 3271 | + if (ad->a.aligned) | |
| 3272 | + maxalign = ad->a.aligned; | |
| 3273 | + else | |
| 3274 | + maxalign = 1; | |
| 3258 | 3275 | offset = 0; |
| 3259 | 3276 | c = 0; |
| 3277 | + bit_pos = 0; | |
| 3260 | 3278 | for (f = type->ref->next; f; f = f->next) { |
| 3261 | − int extra_bytes = f->c; | |
| 3262 | − int bit_pos; | |
| 3263 | − int size = type_size(&f->type, &align); | |
| 3264 | − if (f->type.t & VT_BITFIELD) | |
| 3265 | − bit_pos = (f->type.t >> VT_STRUCT_SHIFT) & 0x3f; | |
| 3266 | − else | |
| 3267 | − bit_pos = 0; | |
| 3268 | − if (f->r) { | |
| 3279 | + int extra_bytes = 0; | |
| 3280 | + int typealign, bit_size; | |
| 3281 | + int size = type_size(&f->type, &typealign); | |
| 3282 | + int pcc = !tcc_state->ms_bitfields; | |
| 3283 | + if (f->type.t & VT_BITFIELD) { | |
| 3284 | + bit_size = (f->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f; | |
| 3285 | + /* without ms-bitfields, allocate the | |
| 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 | 3306 | align = f->r; |
| 3270 | − } else if (ad->a.packed) { | |
| 3307 | + } else if (ad->a.packed || f->r == 1) { | |
| 3271 | 3308 | align = 1; |
| 3309 | + typealign = 1; | |
| 3310 | + } else { | |
| 3311 | + align = typealign; | |
| 3272 | 3312 | } |
| 3273 | − if (extra_bytes) c += extra_bytes; | |
| 3274 | − else if (bit_pos == 0) { | |
| 3313 | + /*if (extra_bytes) c += extra_bytes; | |
| 3314 | + else*/ if (bit_size < 0) { | |
| 3315 | + int addbytes = (bit_pos + 7) >> 3; | |
| 3275 | 3316 | if (type->ref->type.t == TOK_STRUCT) { |
| 3276 | − c = (c + align - 1) & -align; | |
| 3317 | + c = (c + addbytes + align - 1) & -align; | |
| 3277 | 3318 | offset = c; |
| 3278 | 3319 | if (size > 0) |
| 3279 | 3320 | c += size; |
| 3280 | 3321 | } else { |
| 3281 | 3322 | offset = 0; |
| 3323 | + if (addbytes > c) | |
| 3324 | + c = addbytes; | |
| 3282 | 3325 | if (size > c) |
| 3283 | 3326 | c = size; |
| 3284 | 3327 | } |
| 3285 | 3328 | if (align > maxalign) |
| 3286 | 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 | 3377 | #if 0 |
| 3289 | − printf("set field %s offset=%d", | |
| 3290 | − get_tok_str(f->v & ~SYM_FIELD, NULL), offset); | |
| 3378 | + printf("set field %s offset=%d c=%d", | |
| 3379 | + get_tok_str(f->v & ~SYM_FIELD, NULL), offset, c); | |
| 3291 | 3380 | if (f->type.t & VT_BITFIELD) { |
| 3292 | 3381 | printf(" pos=%d size=%d", |
| 3293 | 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 | 3415 | *pps = NULL; |
| 3327 | 3416 | } |
| 3328 | − ass = f->type.ref; | |
| 3329 | − while ((ass = ass->next) != NULL) | |
| 3330 | − ass->c += offset; | |
| 3417 | + struct_add_offset(f->type.ref, offset); | |
| 3331 | 3418 | f->c = 0; |
| 3332 | 3419 | } else { |
| 3333 | 3420 | f->c = offset; |
| @@ -3336,7 +3423,7 @@ static void struct_layout(CType *type, AttributeDef *ad) · 2 unmodified lines | ||
| 3336 | 3423 | f->r = 0; |
| 3337 | 3424 | } |
| 3338 | 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 | 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 | 3602 | } else if (bit_size == bsize) { |
| 3516 | 3603 | /* no need for bit fields */ |
| 3517 | 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 | 3605 | } else { |
| 3524 | 3606 | /* if type change, union, or will overrun |
| 3525 | 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 | 3613 | type1.t |= VT_BITFIELD | |
| 3532 | 3614 | (bit_pos << VT_STRUCT_SHIFT) | |
| 3533 | 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 | 3616 | bit_pos += bit_size; |
| 3549 | 3617 | } |
| 3550 | 3618 | prevbt = bt; |
| @@ -3561,6 +3629,11 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) · 10 unmodified lines | ||
| 3561 | 3629 | anonymous member of struct type. */ |
| 3562 | 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 | 3637 | if (v) { |
| 3565 | 3638 | ss = sym_push(v | SYM_FIELD, &type1, alignoverride, extra_bytes); |
| 3566 | 3639 | *ps = ss; |
| @@ -1026,10 +1026,67 @@ struct aligntest4 { · 1025 unmodified lines | ||
| 1026 | 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 | 1085 | void struct_test() |
| 1030 | 1086 | { |
| 1031 | 1087 | struct1 *s; |
| 1032 | 1088 | union union2 u; |
| 1089 | + struct Large ls; | |
| 1033 | 1090 | |
| 1034 | 1091 | printf("struct:\n"); |
| 1035 | 1092 | printf("sizes: %d %d %d %d\n", |
| @@ -1037,6 +1094,7 @@ void struct_test() · 1 unmodified line | ||
| 1037 | 1094 | sizeof(struct struct2), |
| 1038 | 1095 | sizeof(union union1), |
| 1039 | 1096 | sizeof(union union2)); |
| 1097 | + printf("offsets: %d\n", (int)((char*)&st1.u.v1 - (char*)&st1)); | |
| 1040 | 1098 | st1.f1 = 1; |
| 1041 | 1099 | st1.f2 = 2; |
| 1042 | 1100 | st1.f3 = 3; |
| @@ -1065,10 +1123,27 @@ void struct_test() · 22 unmodified lines | ||
| 1065 | 1123 | sizeof(struct aligntest3), __alignof__(struct aligntest3)); |
| 1066 | 1124 | printf("aligntest4 sizeof=%d alignof=%d\n", |
| 1067 | 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 | 1139 | /* empty structures (GCC extension) */ |
| 1070 | 1140 | printf("sizeof(struct empty) = %d\n", sizeof(struct empty)); |
| 1071 | 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 | 1149 | /* XXX: depend on endianness */ |
| @@ -3547,11 +3622,22 @@ typedef struct Spacked3_s { · 2472 unmodified lines | ||
| 3547 | 3622 | int c; |
| 3548 | 3623 | } __attribute__((__packed__)) Spacked3; |
| 3549 | 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 | 3635 | void attrib_test(void) |
| 3551 | 3636 | { |
| 3552 | 3637 | printf("attr: %d %d %d %d\n", sizeof(struct Spacked), |
| 3553 | 3638 | sizeof(spacked), sizeof(Spacked2), sizeof(spacked2)); |
| 3554 | 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 | 3642 | extern __attribute__((__unused__)) char * __attribute__((__unused__)) * |
| 3557 | 3643 | strange_attrib_placement (void); |