History

refactor bitfields

Use 2 level strategy to access packed bitfields cleanly: 1) Allow to override the original declaration type with an auxilary "access type". This solves cases such as struct { ... unsigned f1:1; }; by using VT_BYTE to access f1. 2) Allow byte-wise split accesses using two new functions load/store_packed_bf. This solves any cases, also ones such as struct __attribute((packed)) _s { unsigned x : 12; unsigned char y : 7; unsigned z : 28; unsigned a: 3; unsigned b: 3; unsigned c: 3; }; where for field 'z': - VT_INT access from offset 2 would be unaligned - VT_LLONG from offset 0 would go past the total struct size (7) and for field 'a' because it is in two bytes and aligned access with VT_SHORT/INT is not possible. Also, static bitfield initializers are stored byte-wise always. Also, cleanup the struct_layout function a bit.

grischka committed 9 years ago

Commit a9e502c1 parent f87afa73 files · +384 −193Browse files

Unified · Split

3 files
  1. tcc.h +1 −0
  2. tccgen.c +379 −189
  3. tests/tcctest.c +4 −4
tcc.h+1−0
@@ -450,6 +450,7 @@ typedef struct Sym { · 449 unmodified lines
450450 int sym_scope; /* scope level for locals */
451451 int jnext; /* next jump label */
452452 struct FuncAttr f; /* function attributes */
453+ int auxtype; /* bitfield access type */
453454 };
454455 };
455456 long long enum_val; /* enum constant if IS_ENUM_VAL */
tccgen.c+379−189
@@ -93,6 +93,7 @@ ST_FUNC void vpush(CType *type); · 92 unmodified lines
9393 ST_FUNC int gvtst(int inv, int t);
9494 static void gen_inline_functions(TCCState *s);
9595 static void skip_or_save_block(TokenString **str);
96+static void gv_dup(void);
9697
9798 ST_INLN int is_float(int t)
9899 {
@@ -1065,38 +1066,142 @@ static void gbound(void) · 966 unmodified lines
10651066 }
10661067 #endif
10671068
1069+static void incr_bf_adr(int o)
1070+{
1071+ vtop->type = char_pointer_type;
1072+ gaddrof();
1073+ vpushi(o);
1074+ gen_op('+');
1075+ vtop->type.t = (vtop->type.t & ~(VT_BTYPE|VT_DEFSIGN))
1076+ | (VT_BYTE|VT_UNSIGNED);
1077+ vtop->r = (vtop->r & ~VT_LVAL_TYPE)
1078+ | (VT_LVAL_BYTE|VT_LVAL_UNSIGNED|VT_LVAL);
1079+}
1080+
1081+/* single-byte load mode for packed or otherwise unaligned bitfields */
1082+static void load_packed_bf(CType *type, int bit_pos, int bit_size)
1083+{
1084+ int n, o, bits;
1085+ save_reg_upstack(vtop->r, 1);
1086+ vpushi(0); // B X
1087+ vtop->type.t |= type->t;
1088+ bits = 0, o = bit_pos >> 3, bit_pos &= 7;
1089+ do {
1090+ vswap(); // X B
1091+ incr_bf_adr(o);
1092+ vdup(); // X B B
1093+ n = 8 - bit_pos;
1094+ if (n > bit_size)
1095+ n = bit_size;
1096+ if (bit_pos)
1097+ vpushi(bit_pos), gen_op(TOK_SHR), bit_pos = 0; // X B Y
1098+ if (n < 8)
1099+ vpushi((1 << n) - 1), gen_op('&');
1100+ gen_cast(type);
1101+ if (bits)
1102+ vpushi(bits), gen_op(TOK_SHL);
1103+ vrotb(3); // B Y X
1104+ gen_op('|'); // B X
1105+ bits += n, bit_size -= n, o = 1;
1106+ } while (bit_size);
1107+ vswap(), vpop();
1108+ if (!(type->t & VT_UNSIGNED)) {
1109+ n = ((type->t & VT_BTYPE) == VT_LLONG ? 64 : 32) - bits;
1110+ vpushi(n), gen_op(TOK_SHL);
1111+ vpushi(n), gen_op(TOK_SAR);
1112+ }
1113+}
1114+
1115+/* single-byte store mode for packed or otherwise unaligned bitfields */
1116+void store_packed_bf(int bit_pos, int bit_size)
1117+{
1118+ int bits, n, o, m, c;
1119+
1120+ c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
1121+ vswap(); // X B
1122+ save_reg_upstack(vtop->r, 1);
1123+ bits = 0, o = bit_pos >> 3, bit_pos &= 7;
1124+ do {
1125+ incr_bf_adr(o); // X B
1126+ vswap(); //B X
1127+ c ? vdup() : gv_dup(); // B V X
1128+ vrott(3); // X B V
1129+ if (bits)
1130+ vpushi(bits), gen_op(TOK_SHR);
1131+ if (bit_pos)
1132+ vpushi(bit_pos), gen_op(TOK_SHL);
1133+ n = 8 - bit_pos;
1134+ if (n > bit_size)
1135+ n = bit_size;
1136+ if (n < 8) {
1137+ m = ((1 << n) - 1) << bit_pos;
1138+ vpushi(m), gen_op('&'); // X B V1
1139+ vpushv(vtop-1); // X B V1 B
1140+ vpushi(m & 0x80 ? ~m & 0x7f : ~m);
1141+ gen_op('&'); // X B V1 B1
1142+ gen_op('|'); // X B V2
1143+ }
1144+ vdup(), vtop[-1] = vtop[-2]; // X B B V2
1145+ vstore(), vpop(); // X B
1146+ bits += n, bit_size -= n, bit_pos = 0, o = 1;
1147+ } while (bit_size);
1148+ vpop(), vpop();
1149+}
1150+
1151+int adjust_bf(SValue *sv, int bit_pos, int bit_size)
1152+{
1153+ int t;
1154+ if (0 == sv->type.ref)
1155+ return 0;
1156+ t = sv->type.ref->auxtype;
1157+ if (t != -1 && t != VT_STRUCT) {
1158+ sv->type.t = (sv->type.t & ~VT_BTYPE) | t;
1159+ sv->r = (sv->r & ~VT_LVAL_TYPE) | lvalue_type(sv->type.t);
1160+ }
1161+ return t;
1162+}
1163+
10681164 /* store vtop a register belonging to class 'rc'. lvalues are
10691165 converted to values. Cannot be used if cannot be converted to
10701166 register value (such as structures). */
10711167 ST_FUNC int gv(int rc)
10721168 {
1073− int r, bit_pos, bit_size, size, align;
1074− int rc2;
1169+ int r, bit_pos, bit_size, size, align, rc2;
10751170
10761171 /* NOTE: get_reg can modify vstack[] */
10771172 if (vtop->type.t & VT_BITFIELD) {
10781173 CType type;
1079− int bits = 32;
1080− bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
1081− bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
1174+
1175+ bit_pos = BIT_POS(vtop->type.t);
1176+ bit_size = BIT_SIZE(vtop->type.t);
10821177 /* remove bit field info to avoid loops */
1083− vtop->type.t &= ~VT_BITFIELD & ((1 << VT_STRUCT_SHIFT) - 1);
1084− /* cast to int to propagate signedness in following ops */
1085− if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
1086− type.t = VT_LLONG;
1087− bits = 64;
1088− } else
1089− type.t = VT_INT;
1090− if((vtop->type.t & VT_UNSIGNED)
1091− || (vtop->type.t & VT_BTYPE) == VT_BOOL)
1178+ vtop->type.t &= ~VT_STRUCT_MASK;
1179+
1180+ type.ref = NULL;
1181+ type.t = vtop->type.t & VT_UNSIGNED;
1182+ if ((vtop->type.t & VT_BTYPE) == VT_BOOL)
10921183 type.t |= VT_UNSIGNED;
1093− gen_cast(&type);
1094− /* generate shifts */
1095− vpushi(bits - (bit_pos + bit_size));
1096− gen_op(TOK_SHL);
1097− vpushi(bits - bit_size);
1098− /* NOTE: transformed to SHR if unsigned */
1099− gen_op(TOK_SAR);
1184+
1185+ r = adjust_bf(vtop, bit_pos, bit_size);
1186+
1187+ if ((vtop->type.t & VT_BTYPE) == VT_LLONG)
1188+ type.t |= VT_LLONG;
1189+ else
1190+ type.t |= VT_INT;
1191+
1192+ if (r == VT_STRUCT) {
1193+ load_packed_bf(&type, bit_pos, bit_size);
1194+ } else {
1195+ int bits = (type.t & VT_BTYPE) == VT_LLONG ? 64 : 32;
1196+ /* cast to int to propagate signedness in following ops */
1197+ gen_cast(&type);
1198+ /* generate shifts */
1199+ vpushi(bits - (bit_pos + bit_size));
1200+ gen_op(TOK_SHL);
1201+ vpushi(bits - bit_size);
1202+ /* NOTE: transformed to SHR if unsigned */
1203+ gen_op(TOK_SAR);
1204+ }
11001205 r = gv(rc);
11011206 } else {
11021207 if (is_float(vtop->type.t) &&
@@ -1362,6 +1467,10 @@ static void gv_dup(void) · 259 unmodified lines
13621467 t = vtop->type.t;
13631468 #if PTR_SIZE == 4
13641469 if ((t & VT_BTYPE) == VT_LLONG) {
1470+ if (t & VT_BITFIELD) {
1471+ gv(RC_INT);
1472+ t = vtop->type.t;
1473+ }
13651474 lexpand();
13661475 gv_dup();
13671476 vswap();
@@ -2920,45 +3029,49 @@ ST_FUNC void vstore(void) · 1552 unmodified lines
29203029 /* save lvalue as expression result (example: s.b = s.a = n;) */
29213030 vdup(), vtop[-1] = vtop[-2];
29223031
2923− bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
2924− bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
3032+ bit_pos = BIT_POS(ft);
3033+ bit_size = BIT_SIZE(ft);
29253034 /* remove bit field info to avoid loops */
2926− vtop[-1].type.t = ft & ~VT_BITFIELD & ((1 << VT_STRUCT_SHIFT) - 1);
3035+ vtop[-1].type.t = ft & ~VT_STRUCT_MASK;
29273036
2928− if((ft & VT_BTYPE) == VT_BOOL) {
3037+ if ((ft & VT_BTYPE) == VT_BOOL) {
29293038 gen_cast(&vtop[-1].type);
29303039 vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED);
29313040 }
29323041
2933− /* duplicate destination */
2934− vdup();
2935− vtop[-1] = vtop[-2];
2936−
2937− /* mask and shift source */
2938− if((ft & VT_BTYPE) != VT_BOOL) {
2939− if((ft & VT_BTYPE) == VT_LLONG) {
2940− vpushll((1ULL << bit_size) - 1ULL);
2941− } else {
2942− vpushi((1 << bit_size) - 1);
3042+ r = adjust_bf(vtop - 1, bit_pos, bit_size);
3043+ if (r == VT_STRUCT) {
3044+ gen_cast_s((ft & VT_BTYPE) == VT_LLONG ? VT_LLONG : VT_INT);
3045+ store_packed_bf(bit_pos, bit_size);
3046+ } else {
3047+ unsigned long long mask = (1ULL << bit_size) - 1;
3048+ if ((ft & VT_BTYPE) != VT_BOOL) {
3049+ /* mask source */
3050+ if ((vtop[-1].type.t & VT_BTYPE) == VT_LLONG)
3051+ vpushll(mask);
3052+ else
3053+ vpushi((unsigned)mask);
3054+ gen_op('&');
29433055 }
3056+ /* shift source */
3057+ vpushi(bit_pos);
3058+ gen_op(TOK_SHL);
3059+ vswap();
3060+ /* duplicate destination */
3061+ vdup();
3062+ vrott(3);
3063+ /* load destination, mask and or with source */
3064+ if ((vtop->type.t & VT_BTYPE) == VT_LLONG)
3065+ vpushll(~(mask << bit_pos));
3066+ else
3067+ vpushi(~((unsigned)mask << bit_pos));
29443068 gen_op('&');
3069+ gen_op('|');
3070+ /* store result */
3071+ vstore();
3072+ /* ... and discard */
3073+ vpop();
29453074 }
2946− vpushi(bit_pos);
2947− gen_op(TOK_SHL);
2948− /* load destination, mask and or with source */
2949− vswap();
2950− if((ft & VT_BTYPE) == VT_LLONG) {
2951− vpushll(~(((1ULL << bit_size) - 1ULL) << bit_pos));
2952− } else {
2953− vpushi(~(((1 << bit_size) - 1) << bit_pos));
2954− }
2955− gen_op('&');
2956− gen_op('|');
2957− /* store result */
2958− vstore();
2959− /* ... and discard */
2960− vpop();
2961−
29623075 } else {
29633076 #ifdef CONFIG_TCC_BCHECK
29643077 /* bound check case */
@@ -3276,112 +3389,114 @@ static void struct_add_offset (Sym *s, int offset) · 311 unmodified lines
32763389
32773390 static void struct_layout(CType *type, AttributeDef *ad)
32783391 {
3279− int align, maxalign, offset, c, bit_pos, bt, prevbt, prev_bit_size;
3392+ int size, align, maxalign, offset, c, bit_pos, bit_size;
3393+ int packed, a, bt, prevbt, prev_bit_size;
32803394 int pcc = !tcc_state->ms_bitfields;
3281− int packwarn = tcc_state->warn_gcc_compat;
3282− int typealign, bit_size, size;
3283−
3395+ int pragma_pack = *tcc_state->pack_stack_ptr;
32843396 Sym *f;
3285− if (ad->a.aligned)
3286− maxalign = 1 << (ad->a.aligned - 1);
3287− else
3288− maxalign = 1;
3397+
3398+ maxalign = 1;
32893399 offset = 0;
32903400 c = 0;
32913401 bit_pos = 0;
32923402 prevbt = VT_STRUCT; /* make it never match */
32933403 prev_bit_size = 0;
3294− size = 0;
3404+
3405+//#define BF_DEBUG
32953406
32963407 for (f = type->ref->next; f; f = f->next) {
3297− size = type_size(&f->type, &typealign);
3298− if (f->type.t & VT_BITFIELD)
3299− bit_size = (f->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
3300− else
3301− bit_size = -1;
3302− if (bit_size == 0 && pcc) {
3303− /* Zero-width bit-fields in PCC mode aren't affected
3304− by any packing (attribute or pragma). */
3305− align = typealign;
3306− } else if (f->r > 1) {
3307− align = f->r;
3308− } else if (ad->a.packed || f->r == 1) {
3309− align = 1;
3310− /* Packed fields or packed records don't let the base type
3311− influence the records type alignment. */
3312− typealign = 1;
3313− } else {
3314− align = typealign;
3315− }
3316− if (type->ref->type.t == VT_UNION) {
3408+ if (f->type.t & VT_BITFIELD)
3409+ bit_size = BIT_SIZE(f->type.t);
3410+ else
3411+ bit_size = -1;
3412+ size = type_size(&f->type, &align);
3413+ a = f->a.aligned ? 1 << (f->a.aligned - 1) : 0;
3414+ packed = 0;
3415+
3416+ if (pcc && bit_size == 0) {
3417+ /* in pcc mode, packing does not affect zero-width bitfields */
3418+
3419+ } else {
3420+ /* in pcc mode, attribute packed overrides if set. */
3421+ if (pcc && (f->a.packed || ad->a.packed))
3422+ align = packed = 1;
3423+
3424+ /* pragma pack overrides align if lesser and packs bitfields always */
3425+ if (pragma_pack) {
3426+ packed = 1;
3427+ if (pragma_pack < align)
3428+ align = pragma_pack;
3429+ /* in pcc mode pragma pack also overrides individual align */
3430+ if (pcc && pragma_pack < a)
3431+ a = 0;
3432+ }
3433+ }
3434+ /* some individual align was specified */
3435+ if (a)
3436+ align = a;
3437+
3438+ if (type->ref->type.t == VT_UNION) {
33173439 if (pcc && bit_size >= 0)
3318− size = (bit_size + 7) >> 3;
3319− /* Bit position is already zero from our caller. */
3440+ size = (bit_size + 7) >> 3;
33203441 offset = 0;
33213442 if (size > c)
3322− c = size;
3443+ c = size;
3444+
33233445 } else if (bit_size < 0) {
3324− int addbytes = pcc ? (bit_pos + 7) >> 3 : 0;
3325− prevbt = VT_STRUCT;
3326− prev_bit_size = 0;
3327− c = (c + addbytes + align - 1) & -align;
3446+ if (pcc)
3447+ c += (bit_pos + 7) >> 3;
3448+ c = (c + align - 1) & -align;
33283449 offset = c;
33293450 if (size > 0)
3330− c += size;
3451+ c += size;
33313452 bit_pos = 0;
3453+ prevbt = VT_STRUCT;
3454+ prev_bit_size = 0;
3455+
33323456 } else {
33333457 /* A bit-field. Layout is more complicated. There are two
3334− options TCC implements: PCC compatible and MS compatible
3335− (PCC compatible is what GCC uses for almost all targets).
3336− In PCC layout the overall size of the struct (in c) is
3337− _excluding_ the current run of bit-fields (that is,
3338− there's at least additional bit_pos bits after c). In
3339− MS layout c does include the current run of bit-fields.
3340−
3341− This matters for calculating the natural alignment buckets
3342− in PCC mode. */
3343−
3344− /* 'align' will be used to influence records alignment,
3345− so it's the max of specified and type alignment, except
3346− in certain cases that depend on the mode. */
3347− if (align < typealign)
3348− align = typealign;
3349− if (pcc) {
3350− /* In PCC layout a non-packed bit-field is placed adjacent
3351− to the preceding bit-fields, except if it would overflow
3352− its container (depending on base type) or it's a zero-width
3353− bit-field. Packed non-zero-width bit-fields always are
3354− placed adjacent. */
3355− int ofs = (c * 8 + bit_pos) % (typealign * 8);
3356− int ofs2 = ofs + bit_size + (typealign * 8) - 1;
3357− if (bit_size == 0 ||
3358− (typealign != 1 &&
3359− (ofs2 / (typealign * 8)) > (size/typealign))) {
3360− c = (c + ((bit_pos + 7) >> 3) + typealign - 1) & -typealign;
3458+ options: PCC (GCC) compatible and MS compatible */
3459+ if (pcc) {
3460+ /* In PCC layout a bit-field is placed adjacent to the
3461+ preceding bit-fields, except if:
3462+ - it has zero-width
3463+ - an individual alignment was given
3464+ - it would overflow its base type container and
3465+ there is no packing */
3466+ if (bit_size == 0) {
3467+ new_field:
3468+ c = (c + ((bit_pos + 7) >> 3) + align - 1) & -align;
33613469 bit_pos = 0;
3362− } else if (bit_pos + bit_size > size * 8) {
3363− c += bit_pos >> 3;
3364− bit_pos &= 7;
3365− if (bit_pos + bit_size > size * 8) {
3366− c += 1, bit_pos = 0;
3367− if ((ad->a.packed || f->r) && packwarn) {
3368− tcc_warning("struct layout not compatible with GCC (internal limitation)");
3369− packwarn = 0;
3370− }
3371− }
3372− }
3373− offset = c;
3470+ } else if (f->a.aligned) {
3471+ goto new_field;
3472+ } else if (!packed) {
3473+ int a8 = align * 8;
3474+ int ofs = ((c * 8 + bit_pos) % a8 + bit_size + a8 - 1) / a8;
3475+ if (ofs > size / align)
3476+ goto new_field;
3477+ }
3478+
3479+ /* in pcc mode, long long bitfields have type int if they fit */
3480+ if (size == 8 && bit_size <= 32) {
3481+ f->type.t = (f->type.t & ~VT_BTYPE) | VT_INT;
3482+ size = 4;
3483+ }
3484+ if (bit_pos >= size * 8) {
3485+ c += size;
3486+ bit_pos -= size * 8;
3487+ }
3488+ offset = c;
33743489 /* In PCC layout named bit-fields influence the alignment
33753490 of the containing struct using the base types alignment,
3376− except for packed fields (which here have correct
3377− align/typealign). */
3378− if ((f->v & SYM_FIRST_ANOM))
3379− align = 1;
3491+ except for packed fields (which here have correct align). */
3492+ if (f->v & SYM_FIRST_ANOM)
3493+ align = 1;
33803494 } else {
33813495 bt = f->type.t & VT_BTYPE;
3382− if ((bit_pos + bit_size > size * 8) ||
3383− (bit_size > 0) == (bt != prevbt)) {
3384− c = (c + typealign - 1) & -typealign;
3496+ if ((bit_pos + bit_size > size * 8)
3497+ || (bit_size > 0) == (bt != prevbt)
3498+ ) {
3499+ c = (c + align - 1) & -align;
33853500 offset = c;
33863501 bit_pos = 0;
33873502 /* In MS bitfield mode a bit-field run always uses
@@ -3389,34 +3504,33 @@ static void struct_layout(CType *type, AttributeDef *ad) · 1 unmodified line
33893504 To start a new run it's also required that this
33903505 or the last bit-field had non-zero width. */
33913506 if (bit_size || prev_bit_size)
3392− c += size;
3507+ c += size;
33933508 }
33943509 /* In MS layout the records alignment is normally
33953510 influenced by the field, except for a zero-width
33963511 field at the start of a run (but by further zero-width
33973512 fields it is again). */
33983513 if (bit_size == 0 && prevbt != bt)
3399− align = 1;
3514+ align = 1;
34003515 prevbt = bt;
3401− prev_bit_size = bit_size;
3516+ prev_bit_size = bit_size;
34023517 }
3518+
34033519 f->type.t = (f->type.t & ~(0x3f << VT_STRUCT_SHIFT))
34043520 | (bit_pos << VT_STRUCT_SHIFT);
34053521 bit_pos += bit_size;
3406− if (pcc && bit_pos >= size * 8) {
3407− c += size;
3408− bit_pos -= size * 8;
3409− }
34103522 }
34113523 if (align > maxalign)
3412− maxalign = align;
3413−#if 0
3414− printf("set field %s offset=%d",
3415− get_tok_str(f->v & ~SYM_FIELD, NULL), offset);
3524+ maxalign = align;
3525+
3526+#ifdef BF_DEBUG
3527+ printf("set field %s offset %-2d size %-2d align %-2d",
3528+ get_tok_str(f->v & ~SYM_FIELD, NULL), offset, size, align);
34163529 if (f->type.t & VT_BITFIELD) {
3417− printf(" pos=%d size=%d",
3418− (f->type.t >> VT_STRUCT_SHIFT) & 0x3f,
3419− (f->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
3530+ printf(" pos %-2d bits %-2d",
3531+ BIT_POS(f->type.t),
3532+ BIT_SIZE(f->type.t)
3533+ );
34203534 }
34213535 printf("\n");
34223536 #endif
@@ -3458,18 +3572,91 @@ static void struct_layout(CType *type, AttributeDef *ad) · 35 unmodified lines
34583572
34593573 f->r = 0;
34603574 }
3575+
3576+ if (pcc)
3577+ c += (bit_pos + 7) >> 3;
3578+
3579+ a = ad->a.aligned ? 1 << (ad->a.aligned - 1) : 0;
3580+ if (a < maxalign)
3581+ a = maxalign;
3582+ c = (c + a - 1) & -a;
3583+
34613584 /* store size and alignment */
3462− type->ref->c = (c + (pcc ? (bit_pos + 7) >> 3 : 0)
3463− + maxalign - 1) & -maxalign;
3464− type->ref->r = maxalign;
3465− if (offset + size > type->ref->c && type->ref->c)
3466− tcc_warning("will touch memory past end of the struct (internal limitation)");
3585+ type->ref->c = c;
3586+ type->ref->r = a;
3587+
3588+#ifdef BF_DEBUG
3589+ printf("struct size %-2d align %-2d\n\n", c, a), fflush(stdout);
3590+#endif
3591+
3592+ /* check whether we can access bitfields by their type */
3593+ for (f = type->ref->next; f; f = f->next) {
3594+ int s, px, cx, c0;
3595+ CType t;
3596+
3597+ if (0 == (f->type.t & VT_BITFIELD))
3598+ continue;
3599+ f->type.ref = f;
3600+ f->auxtype = -1;
3601+ bit_size = BIT_SIZE(f->type.t);
3602+ if (bit_size == 0)
3603+ continue;
3604+ bit_pos = BIT_POS(f->type.t);
3605+ size = type_size(&f->type, &align);
3606+
3607+ if (bit_pos + bit_size <= size * 8 && f->c + size <= c)
3608+ continue;
3609+
3610+ /* try to access the field using a differnt type */
3611+ c0 = -1, s = align = 1;
3612+ for (;;) {
3613+ px = f->c * 8 + bit_pos;
3614+ cx = (px >> 3) & -align;
3615+ px = px - (cx << 3);
3616+ if (c0 == cx)
3617+ break;
3618+ s = (px + bit_size + 7) >> 3;
3619+ if (s > 4) {
3620+ t.t = VT_LLONG;
3621+ } else if (s > 2) {
3622+ t.t = VT_INT;
3623+ } else if (s > 1) {
3624+ t.t = VT_SHORT;
3625+ } else {
3626+ t.t = VT_BYTE;
3627+ }
3628+ s = type_size(&t, &align);
3629+ c0 = cx;
3630+ }
3631+
3632+ if (px + bit_size <= s * 8 && cx + s <= c) {
3633+ /* update offset and bit position */
3634+ f->c = cx;
3635+ bit_pos = px;
3636+ f->type.t = (f->type.t & ~(0x3f << VT_STRUCT_SHIFT))
3637+ | (bit_pos << VT_STRUCT_SHIFT);
3638+ if (s != size)
3639+ f->auxtype = t.t;
3640+ } else {
3641+ /* fall back to load/store single-byte wise */
3642+ f->auxtype = VT_STRUCT;
3643+ }
3644+
3645+#ifdef BF_DEBUG
3646+ printf("FIX field %s offset %-2d size %-2d align %-2d "
3647+ "pos %-2d bits %-2d %s\n",
3648+ get_tok_str(f->v & ~SYM_FIELD, NULL),
3649+ cx, s, align, px, bit_size,
3650+ f->auxtype == VT_PTR ? " byte-wise" : ""
3651+ );
3652+#endif
3653+ }
34673654 }
34683655
34693656 /* enum/struct/union declaration. u is VT_ENUM/VT_STRUCT/VT_UNION */
34703657 static void struct_decl(CType *type, int u)
34713658 {
3472− int v, c, size, align, flexible, alignoverride;
3659+ int v, c, size, align, flexible;
34733660 int bit_size, bsize, bt;
34743661 Sym *s, *ss, **ps;
34753662 AttributeDef ad, ad1;
@@ -3623,17 +3810,6 @@ do_decl: · 147 unmodified lines
36233810 parse_attribute(&ad1);
36243811 }
36253812 size = type_size(&type1, &align);
3626− /* Only remember non-default alignment. */
3627− alignoverride = 0;
3628− if (ad1.a.aligned) {
3629− int speca = 1 << (ad1.a.aligned - 1);
3630− alignoverride = speca;
3631− } else if (ad1.a.packed || ad.a.packed) {
3632− alignoverride = 1;
3633− } else if (*tcc_state->pack_stack_ptr) {
3634− if (align >= *tcc_state->pack_stack_ptr)
3635− alignoverride = *tcc_state->pack_stack_ptr;
3636− }
36373813 if (bit_size >= 0) {
36383814 bt = type1.t & VT_BTYPE;
36393815 if (bt != VT_INT &&
@@ -3646,9 +3822,12 @@ do_decl: · 6 unmodified lines
36463822 if (bit_size > bsize) {
36473823 tcc_error("width of '%s' exceeds its type",
36483824 get_tok_str(v, NULL));
3649− } else if (bit_size == bsize) {
3825+ } else if (bit_size == bsize
3826+ && !ad.a.packed && !ad1.a.packed) {
36503827 /* no need for bit fields */
36513828 ;
3829+ } else if (bit_size == 64) {
3830+ tcc_error("field width 64 not implemented");
36523831 } else {
36533832 type1.t = (type1.t & ~VT_STRUCT_MASK)
36543833 | VT_BITFIELD
@@ -3668,7 +3847,8 @@ do_decl: · 13 unmodified lines
36683847 v = anon_sym++;
36693848 }
36703849 if (v) {
3671− ss = sym_push(v | SYM_FIELD, &type1, alignoverride, 0);
3850+ ss = sym_push(v | SYM_FIELD, &type1, 0, 0);
3851+ ss->a = ad1.a;
36723852 *ps = ss;
36733853 ps = &ss->next;
36743854 }
@@ -4495,7 +4675,10 @@ ST_FUNC void unary(void) · 820 unmodified lines
44954675 next();
44964676 in_sizeof++;
44974677 expr_type(&type, 1); // Perform a in_sizeof = 0;
4678+ s = vtop[1].sym; /* hack: accessing previous vtop */
44984679 size = type_size(&type, &align);
4680+ if (s && s->a.aligned)
4681+ align = 1 << (s->a.aligned - 1);
44994682 if (t == TOK_SIZEOF) {
45004683 if (!(type.t & VT_VLA)) {
45014684 if (size < 0)
@@ -6140,9 +6323,8 @@ static int decl_designator(CType *type, Section *sec, unsigned long c, · 1638 unmodified lines
61406323 /* store a value or an expression directly in global data or in local array */
61416324 static void init_putv(CType *type, Section *sec, unsigned long c)
61426325 {
6143− int bt, bit_pos, bit_size;
6326+ int bt;
61446327 void *ptr;
6145− unsigned long long bit_mask;
61466328 CType dtype;
61476329
61486330 dtype = *type;
@@ -6158,15 +6340,6 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 9 unmodified lines
61586340 section_reserve(sec, c + size);
61596341 ptr = sec->data + c;
61606342 /* XXX: make code faster ? */
6161− if (!(type->t & VT_BITFIELD)) {
6162− bit_pos = 0;
6163− bit_size = PTR_SIZE * 8;
6164− bit_mask = -1LL;
6165− } else {
6166− bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
6167− bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6168− bit_mask = (1LL << bit_size) - 1;
6169− }
61706343 if ((vtop->r & (VT_SYM|VT_CONST)) == (VT_SYM|VT_CONST) &&
61716344 vtop->sym->v >= SYM_FIRST_ANOM &&
61726345 /* XXX This rejects compound literals like
@@ -6219,31 +6392,48 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 46 unmodified lines
62196392 }
62206393 }
62216394 } else {
6222− if ((vtop->r & VT_SYM) &&
6395+ if ((vtop->r & VT_SYM) &&
62236396 (bt == VT_BYTE ||
62246397 bt == VT_SHORT ||
62256398 bt == VT_DOUBLE ||
62266399 bt == VT_LDOUBLE ||
62276400 #if PTR_SIZE == 8
6228− (bt == VT_LLONG && bit_size != 64) ||
6229− bt == VT_INT
6401+ bt == VT_INT ||
62306402 #else
62316403 bt == VT_LLONG ||
6232− (bt == VT_INT && bit_size != 32)
62336404 #endif
6405+ (type->t & VT_BITFIELD)
62346406 ))
62356407 tcc_error("initializer element is not computable at load time");
6236− switch(bt) {
6408+
6409+ if (type->t & VT_BITFIELD) {
6410+ int bit_pos, bit_size, bits, n;
6411+ unsigned char *p, v, m;
6412+ bit_pos = BIT_POS(vtop->type.t);
6413+ bit_size = BIT_SIZE(vtop->type.t);
6414+ p = (unsigned char*)ptr + (bit_pos >> 3);
6415+ bit_pos &= 7, bits = 0;
6416+ while (bit_size) {
6417+ n = 8 - bit_pos;
6418+ if (n > bit_size)
6419+ n = bit_size;
6420+ v = vtop->c.i >> bits << bit_pos;
6421+ m = ((1 << n) - 1) << bit_pos;
6422+ *p = (*p & ~m) | (v & m);
6423+ bits += n, bit_size -= n, bit_pos = 0, ++p;
6424+ }
6425+ } else
6426+ switch(bt) {
62376427 /* XXX: when cross-compiling we assume that each type has the
62386428 same representation on host and target, which is likely to
62396429 be wrong in the case of long double */
62406430 case VT_BOOL:
6241− vtop->c.i = (vtop->c.i != 0);
6431+ vtop->c.i = vtop->c.i != 0;
62426432 case VT_BYTE:
6243− *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
6433+ *(char *)ptr |= vtop->c.i;
62446434 break;
62456435 case VT_SHORT:
6246− *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
6436+ *(short *)ptr |= vtop->c.i;
62476437 break;
62486438 case VT_FLOAT:
62496439 *(float*)ptr = vtop->c.f;
@@ -6270,14 +6460,14 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 20 unmodified lines
62706460 break;
62716461 #if PTR_SIZE != 8
62726462 case VT_LLONG:
6273− *(long long *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
6463+ *(long long *)ptr |= vtop->c.i;
62746464 break;
62756465 #else
62766466 case VT_LLONG:
62776467 #endif
62786468 case VT_PTR:
62796469 {
6280− addr_t val = (vtop->c.i & bit_mask) << bit_pos;
6470+ addr_t val = vtop->c.i;
62816471 #if PTR_SIZE == 8
62826472 if (vtop->r & VT_SYM)
62836473 greloca(sec, vtop->sym, c, R_DATA_PTR, val);
@@ -6292,7 +6482,7 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 8 unmodified lines
62926482 }
62936483 default:
62946484 {
6295− int val = (vtop->c.i & bit_mask) << bit_pos;
6485+ int val = vtop->c.i;
62966486 #if PTR_SIZE == 8
62976487 if (vtop->r & VT_SYM)
62986488 greloca(sec, vtop->sym, c, R_DATA_PTR, val);
tests/tcctest.c+4−4
@@ -1050,8 +1050,8 @@ int pad1; · 1049 unmodified lines
10501050 but __alignof__ returns the wrong result (4) because we
10511051 can't store the alignment yet when specified on symbols
10521052 directly (it's stored in the type so we'd need to make
1053− a copy of it).
1054−struct aligntest7 altest7[2] __attribute__((aligned(16)));*/
1053+ a copy of it). -- FIXED */
1054+struct aligntest7 altest7[2] __attribute__((aligned(16)));
10551055
10561056 struct aligntest8
10571057 {
@@ -1161,8 +1161,8 @@ void struct_test() · 103 unmodified lines
11611161 sizeof(altest5), __alignof__(altest5));
11621162 printf("altest6 sizeof=%d alignof=%d\n",
11631163 sizeof(altest6), __alignof__(altest6));
1164− /*printf("altest7 sizeof=%d alignof=%d\n",
1165− sizeof(altest7), __alignof__(altest7));*/
1164+ printf("altest7 sizeof=%d alignof=%d\n",
1165+ sizeof(altest7), __alignof__(altest7));
11661166
11671167 /* empty structures (GCC extension) */
11681168 printf("sizeof(struct empty) = %d\n", sizeof(struct empty));

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