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
450 int sym_scope; /* scope level for locals */450 int sym_scope; /* scope level for locals */
451 int jnext; /* next jump label */451 int jnext; /* next jump label */
452 struct FuncAttr f; /* function attributes */452 struct FuncAttr f; /* function attributes */
453 int auxtype; /* bitfield access type */
453 };454 };
454 };455 };
455 long long enum_val; /* enum constant if IS_ENUM_VAL */456 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
93ST_FUNC int gvtst(int inv, int t);93ST_FUNC int gvtst(int inv, int t);
94static void gen_inline_functions(TCCState *s);94static void gen_inline_functions(TCCState *s);
95static void skip_or_save_block(TokenString **str);95static void skip_or_save_block(TokenString **str);
96static void gv_dup(void);
96 97
97ST_INLN int is_float(int t)98ST_INLN int is_float(int t)
98{99{
@@ -1065,38 +1066,142 @@ static void gbound(void) · 966 unmodified lines
1065}1066}
1066#endif1067#endif
1067 1068
1069static 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 */
1082static 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 */
1116void 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
1151int 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
1068/* store vtop a register belonging to class 'rc'. lvalues are1164/* store vtop a register belonging to class 'rc'. lvalues are
1069 converted to values. Cannot be used if cannot be converted to1165 converted to values. Cannot be used if cannot be converted to
1070 register value (such as structures). */1166 register value (such as structures). */
1071ST_FUNC int gv(int rc)1167ST_FUNC int gv(int rc)
1072{1168{
1073 int r, bit_pos, bit_size, size, align;1169 int r, bit_pos, bit_size, size, align, rc2;
1074 int rc2;
1075 1170
1076 /* NOTE: get_reg can modify vstack[] */1171 /* NOTE: get_reg can modify vstack[] */
1077 if (vtop->type.t & VT_BITFIELD) {1172 if (vtop->type.t & VT_BITFIELD) {
1078 CType type;1173 CType type;
1079 int bits = 32;1174
1080 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;1175 bit_pos = BIT_POS(vtop->type.t);
1081 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;1176 bit_size = BIT_SIZE(vtop->type.t);
1082 /* remove bit field info to avoid loops */1177 /* remove bit field info to avoid loops */
1083 vtop->type.t &= ~VT_BITFIELD & ((1 << VT_STRUCT_SHIFT) - 1);1178 vtop->type.t &= ~VT_STRUCT_MASK;
1084 /* cast to int to propagate signedness in following ops */1179
1085 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {1180 type.ref = NULL;
1086 type.t = VT_LLONG;1181 type.t = vtop->type.t & VT_UNSIGNED;
1087 bits = 64;1182 if ((vtop->type.t & VT_BTYPE) == VT_BOOL)
1088 } else
1089 type.t = VT_INT;
1090 if((vtop->type.t & VT_UNSIGNED)
1091 || (vtop->type.t & VT_BTYPE) == VT_BOOL)
1092 type.t |= VT_UNSIGNED;1183 type.t |= VT_UNSIGNED;
1093 gen_cast(&type);1184
1094 /* generate shifts */1185 r = adjust_bf(vtop, bit_pos, bit_size);
1095 vpushi(bits - (bit_pos + bit_size));1186
1096 gen_op(TOK_SHL);1187 if ((vtop->type.t & VT_BTYPE) == VT_LLONG)
1097 vpushi(bits - bit_size);1188 type.t |= VT_LLONG;
1098 /* NOTE: transformed to SHR if unsigned */1189 else
1099 gen_op(TOK_SAR);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 }
1100 r = gv(rc);1205 r = gv(rc);
1101 } else {1206 } else {
1102 if (is_float(vtop->type.t) && 1207 if (is_float(vtop->type.t) &&
@@ -1362,6 +1467,10 @@ static void gv_dup(void) · 259 unmodified lines
1362 t = vtop->type.t;1467 t = vtop->type.t;
1363#if PTR_SIZE == 41468#if PTR_SIZE == 4
1364 if ((t & VT_BTYPE) == VT_LLONG) {1469 if ((t & VT_BTYPE) == VT_LLONG) {
1470 if (t & VT_BITFIELD) {
1471 gv(RC_INT);
1472 t = vtop->type.t;
1473 }
1365 lexpand();1474 lexpand();
1366 gv_dup();1475 gv_dup();
1367 vswap();1476 vswap();
@@ -2920,45 +3029,49 @@ ST_FUNC void vstore(void) · 1552 unmodified lines
2920 /* save lvalue as expression result (example: s.b = s.a = n;) */3029 /* save lvalue as expression result (example: s.b = s.a = n;) */
2921 vdup(), vtop[-1] = vtop[-2];3030 vdup(), vtop[-1] = vtop[-2];
2922 3031
2923 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;3032 bit_pos = BIT_POS(ft);
2924 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;3033 bit_size = BIT_SIZE(ft);
2925 /* remove bit field info to avoid loops */3034 /* 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;
2927 3036
2928 if((ft & VT_BTYPE) == VT_BOOL) {3037 if ((ft & VT_BTYPE) == VT_BOOL) {
2929 gen_cast(&vtop[-1].type);3038 gen_cast(&vtop[-1].type);
2930 vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED);3039 vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED);
2931 }3040 }
2932 3041
2933 /* duplicate destination */3042 r = adjust_bf(vtop - 1, bit_pos, bit_size);
2934 vdup();3043 if (r == VT_STRUCT) {
2935 vtop[-1] = vtop[-2];3044 gen_cast_s((ft & VT_BTYPE) == VT_LLONG ? VT_LLONG : VT_INT);
2936 3045 store_packed_bf(bit_pos, bit_size);
2937 /* mask and shift source */3046 } else {
2938 if((ft & VT_BTYPE) != VT_BOOL) {3047 unsigned long long mask = (1ULL << bit_size) - 1;
2939 if((ft & VT_BTYPE) == VT_LLONG) {3048 if ((ft & VT_BTYPE) != VT_BOOL) {
2940 vpushll((1ULL << bit_size) - 1ULL);3049 /* mask source */
2941 } else {3050 if ((vtop[-1].type.t & VT_BTYPE) == VT_LLONG)
2942 vpushi((1 << bit_size) - 1);3051 vpushll(mask);
3052 else
3053 vpushi((unsigned)mask);
3054 gen_op('&');
2943 }3055 }
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));
2944 gen_op('&');3068 gen_op('&');
3069 gen_op('|');
3070 /* store result */
3071 vstore();
3072 /* ... and discard */
3073 vpop();
2945 }3074 }
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
2962 } else {3075 } else {
2963#ifdef CONFIG_TCC_BCHECK3076#ifdef CONFIG_TCC_BCHECK
2964 /* bound check case */3077 /* bound check case */
@@ -3276,112 +3389,114 @@ static void struct_add_offset (Sym *s, int offset) · 311 unmodified lines
3276 3389
3277static void struct_layout(CType *type, AttributeDef *ad)3390static void struct_layout(CType *type, AttributeDef *ad)
3278{3391{
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;
3280 int pcc = !tcc_state->ms_bitfields;3394 int pcc = !tcc_state->ms_bitfields;
3281 int packwarn = tcc_state->warn_gcc_compat;3395 int pragma_pack = *tcc_state->pack_stack_ptr;
3282 int typealign, bit_size, size;
3283
3284 Sym *f;3396 Sym *f;
3285 if (ad->a.aligned)3397
3286 maxalign = 1 << (ad->a.aligned - 1);3398 maxalign = 1;
3287 else
3288 maxalign = 1;
3289 offset = 0;3399 offset = 0;
3290 c = 0;3400 c = 0;
3291 bit_pos = 0;3401 bit_pos = 0;
3292 prevbt = VT_STRUCT; /* make it never match */3402 prevbt = VT_STRUCT; /* make it never match */
3293 prev_bit_size = 0;3403 prev_bit_size = 0;
3294 size = 0;3404
3405//#define BF_DEBUG
3295 3406
3296 for (f = type->ref->next; f; f = f->next) {3407 for (f = type->ref->next; f; f = f->next) {
3297 size = type_size(&f->type, &typealign);3408 if (f->type.t & VT_BITFIELD)
3298 if (f->type.t & VT_BITFIELD)3409 bit_size = BIT_SIZE(f->type.t);
3299 bit_size = (f->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;3410 else
3300 else3411 bit_size = -1;
3301 bit_size = -1;3412 size = type_size(&f->type, &align);
3302 if (bit_size == 0 && pcc) {3413 a = f->a.aligned ? 1 << (f->a.aligned - 1) : 0;
3303 /* Zero-width bit-fields in PCC mode aren't affected3414 packed = 0;
3304 by any packing (attribute or pragma). */3415
3305 align = typealign;3416 if (pcc && bit_size == 0) {
3306 } else if (f->r > 1) {3417 /* in pcc mode, packing does not affect zero-width bitfields */
3307 align = f->r;3418
3308 } else if (ad->a.packed || f->r == 1) {3419 } else {
3309 align = 1;3420 /* in pcc mode, attribute packed overrides if set. */
3310 /* Packed fields or packed records don't let the base type3421 if (pcc && (f->a.packed || ad->a.packed))
3311 influence the records type alignment. */3422 align = packed = 1;
3312 typealign = 1;3423
3313 } else {3424 /* pragma pack overrides align if lesser and packs bitfields always */
3314 align = typealign;3425 if (pragma_pack) {
3315 }3426 packed = 1;
3316 if (type->ref->type.t == VT_UNION) {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) {
3317 if (pcc && bit_size >= 0)3439 if (pcc && bit_size >= 0)
3318 size = (bit_size + 7) >> 3;3440 size = (bit_size + 7) >> 3;
3319 /* Bit position is already zero from our caller. */
3320 offset = 0;3441 offset = 0;
3321 if (size > c)3442 if (size > c)
3322 c = size;3443 c = size;
3444
3323 } else if (bit_size < 0) {3445 } else if (bit_size < 0) {
3324 int addbytes = pcc ? (bit_pos + 7) >> 3 : 0;3446 if (pcc)
3325 prevbt = VT_STRUCT;3447 c += (bit_pos + 7) >> 3;
3326 prev_bit_size = 0;3448 c = (c + align - 1) & -align;
3327 c = (c + addbytes + align - 1) & -align;
3328 offset = c;3449 offset = c;
3329 if (size > 0)3450 if (size > 0)
3330 c += size;3451 c += size;
3331 bit_pos = 0;3452 bit_pos = 0;
3453 prevbt = VT_STRUCT;
3454 prev_bit_size = 0;
3455
3332 } else {3456 } else {
3333 /* A bit-field. Layout is more complicated. There are two3457 /* A bit-field. Layout is more complicated. There are two
3334 options TCC implements: PCC compatible and MS compatible3458 options: PCC (GCC) compatible and MS compatible */
3335 (PCC compatible is what GCC uses for almost all targets).3459 if (pcc) {
3336 In PCC layout the overall size of the struct (in c) is3460 /* In PCC layout a bit-field is placed adjacent to the
3337 _excluding_ the current run of bit-fields (that is,3461 preceding bit-fields, except if:
3338 there's at least additional bit_pos bits after c). In3462 - it has zero-width
3339 MS layout c does include the current run of bit-fields.3463 - an individual alignment was given
3340 3464 - it would overflow its base type container and
3341 This matters for calculating the natural alignment buckets3465 there is no packing */
3342 in PCC mode. */3466 if (bit_size == 0) {
3343 3467 new_field:
3344 /* 'align' will be used to influence records alignment,3468 c = (c + ((bit_pos + 7) >> 3) + align - 1) & -align;
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;
3361 bit_pos = 0;3469 bit_pos = 0;
3362 } else if (bit_pos + bit_size > size * 8) {3470 } else if (f->a.aligned) {
3363 c += bit_pos >> 3;3471 goto new_field;
3364 bit_pos &= 7;3472 } else if (!packed) {
3365 if (bit_pos + bit_size > size * 8) {3473 int a8 = align * 8;
3366 c += 1, bit_pos = 0;3474 int ofs = ((c * 8 + bit_pos) % a8 + bit_size + a8 - 1) / a8;
3367 if ((ad->a.packed || f->r) && packwarn) {3475 if (ofs > size / align)
3368 tcc_warning("struct layout not compatible with GCC (internal limitation)");3476 goto new_field;
3369 packwarn = 0;3477 }
3370 }3478
3371 }3479 /* in pcc mode, long long bitfields have type int if they fit */
3372 }3480 if (size == 8 && bit_size <= 32) {
3373 offset = c;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;
3374 /* In PCC layout named bit-fields influence the alignment3489 /* In PCC layout named bit-fields influence the alignment
3375 of the containing struct using the base types alignment,3490 of the containing struct using the base types alignment,
3376 except for packed fields (which here have correct3491 except for packed fields (which here have correct align). */
3377 align/typealign). */3492 if (f->v & SYM_FIRST_ANOM)
3378 if ((f->v & SYM_FIRST_ANOM))3493 align = 1;
3379 align = 1;
3380 } else {3494 } else {
3381 bt = f->type.t & VT_BTYPE;3495 bt = f->type.t & VT_BTYPE;
3382 if ((bit_pos + bit_size > size * 8) ||3496 if ((bit_pos + bit_size > size * 8)
3383 (bit_size > 0) == (bt != prevbt)) {3497 || (bit_size > 0) == (bt != prevbt)
3384 c = (c + typealign - 1) & -typealign;3498 ) {
3499 c = (c + align - 1) & -align;
3385 offset = c;3500 offset = c;
3386 bit_pos = 0;3501 bit_pos = 0;
3387 /* In MS bitfield mode a bit-field run always uses3502 /* 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
3389 To start a new run it's also required that this3504 To start a new run it's also required that this
3390 or the last bit-field had non-zero width. */3505 or the last bit-field had non-zero width. */
3391 if (bit_size || prev_bit_size)3506 if (bit_size || prev_bit_size)
3392 c += size;3507 c += size;
3393 }3508 }
3394 /* In MS layout the records alignment is normally3509 /* In MS layout the records alignment is normally
3395 influenced by the field, except for a zero-width3510 influenced by the field, except for a zero-width
3396 field at the start of a run (but by further zero-width3511 field at the start of a run (but by further zero-width
3397 fields it is again). */3512 fields it is again). */
3398 if (bit_size == 0 && prevbt != bt)3513 if (bit_size == 0 && prevbt != bt)
3399 align = 1;3514 align = 1;
3400 prevbt = bt;3515 prevbt = bt;
3401 prev_bit_size = bit_size;3516 prev_bit_size = bit_size;
3402 }3517 }
3518
3403 f->type.t = (f->type.t & ~(0x3f << VT_STRUCT_SHIFT))3519 f->type.t = (f->type.t & ~(0x3f << VT_STRUCT_SHIFT))
3404 | (bit_pos << VT_STRUCT_SHIFT);3520 | (bit_pos << VT_STRUCT_SHIFT);
3405 bit_pos += bit_size;3521 bit_pos += bit_size;
3406 if (pcc && bit_pos >= size * 8) {
3407 c += size;
3408 bit_pos -= size * 8;
3409 }
3410 }3522 }
3411 if (align > maxalign)3523 if (align > maxalign)
3412 maxalign = align;3524 maxalign = align;
3413#if 03525
3414 printf("set field %s offset=%d",3526#ifdef BF_DEBUG
3415 get_tok_str(f->v & ~SYM_FIELD, NULL), offset);3527 printf("set field %s offset %-2d size %-2d align %-2d",
3528 get_tok_str(f->v & ~SYM_FIELD, NULL), offset, size, align);
3416 if (f->type.t & VT_BITFIELD) {3529 if (f->type.t & VT_BITFIELD) {
3417 printf(" pos=%d size=%d",3530 printf(" pos %-2d bits %-2d",
3418 (f->type.t >> VT_STRUCT_SHIFT) & 0x3f,3531 BIT_POS(f->type.t),
3419 (f->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);3532 BIT_SIZE(f->type.t)
3533 );
3420 }3534 }
3421 printf("\n");3535 printf("\n");
3422#endif3536#endif
@@ -3458,18 +3572,91 @@ static void struct_layout(CType *type, AttributeDef *ad) · 35 unmodified lines
3458 3572
3459 f->r = 0;3573 f->r = 0;
3460 }3574 }
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
3461 /* store size and alignment */3584 /* store size and alignment */
3462 type->ref->c = (c + (pcc ? (bit_pos + 7) >> 3 : 0)3585 type->ref->c = c;
3463 + maxalign - 1) & -maxalign;3586 type->ref->r = a;
3464 type->ref->r = maxalign;3587
3465 if (offset + size > type->ref->c && type->ref->c)3588#ifdef BF_DEBUG
3466 tcc_warning("will touch memory past end of the struct (internal limitation)");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 }
3467}3654}
3468 3655
3469/* enum/struct/union declaration. u is VT_ENUM/VT_STRUCT/VT_UNION */3656/* enum/struct/union declaration. u is VT_ENUM/VT_STRUCT/VT_UNION */
3470static void struct_decl(CType *type, int u)3657static void struct_decl(CType *type, int u)
3471{3658{
3472 int v, c, size, align, flexible, alignoverride;3659 int v, c, size, align, flexible;
3473 int bit_size, bsize, bt;3660 int bit_size, bsize, bt;
3474 Sym *s, *ss, **ps;3661 Sym *s, *ss, **ps;
3475 AttributeDef ad, ad1;3662 AttributeDef ad, ad1;
@@ -3623,17 +3810,6 @@ do_decl: · 147 unmodified lines
3623 parse_attribute(&ad1);3810 parse_attribute(&ad1);
3624 }3811 }
3625 size = type_size(&type1, &align);3812 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 }
3637 if (bit_size >= 0) {3813 if (bit_size >= 0) {
3638 bt = type1.t & VT_BTYPE;3814 bt = type1.t & VT_BTYPE;
3639 if (bt != VT_INT && 3815 if (bt != VT_INT &&
@@ -3646,9 +3822,12 @@ do_decl: · 6 unmodified lines
3646 if (bit_size > bsize) {3822 if (bit_size > bsize) {
3647 tcc_error("width of '%s' exceeds its type",3823 tcc_error("width of '%s' exceeds its type",
3648 get_tok_str(v, NULL));3824 get_tok_str(v, NULL));
3649 } else if (bit_size == bsize) {3825 } else if (bit_size == bsize
3826 && !ad.a.packed && !ad1.a.packed) {
3650 /* no need for bit fields */3827 /* no need for bit fields */
3651 ;3828 ;
3829 } else if (bit_size == 64) {
3830 tcc_error("field width 64 not implemented");
3652 } else {3831 } else {
3653 type1.t = (type1.t & ~VT_STRUCT_MASK)3832 type1.t = (type1.t & ~VT_STRUCT_MASK)
3654 | VT_BITFIELD3833 | VT_BITFIELD
@@ -3668,7 +3847,8 @@ do_decl: · 13 unmodified lines
3668 v = anon_sym++;3847 v = anon_sym++;
3669 }3848 }
3670 if (v) {3849 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;
3672 *ps = ss;3852 *ps = ss;
3673 ps = &ss->next;3853 ps = &ss->next;
3674 }3854 }
@@ -4495,7 +4675,10 @@ ST_FUNC void unary(void) · 820 unmodified lines
4495 next();4675 next();
4496 in_sizeof++;4676 in_sizeof++;
4497 expr_type(&type, 1); // Perform a in_sizeof = 0;4677 expr_type(&type, 1); // Perform a in_sizeof = 0;
4678 s = vtop[1].sym; /* hack: accessing previous vtop */
4498 size = type_size(&type, &align);4679 size = type_size(&type, &align);
4680 if (s && s->a.aligned)
4681 align = 1 << (s->a.aligned - 1);
4499 if (t == TOK_SIZEOF) {4682 if (t == TOK_SIZEOF) {
4500 if (!(type.t & VT_VLA)) {4683 if (!(type.t & VT_VLA)) {
4501 if (size < 0)4684 if (size < 0)
@@ -6140,9 +6323,8 @@ static int decl_designator(CType *type, Section *sec, unsigned long c, · 1638 unmodified lines
6140/* store a value or an expression directly in global data or in local array */6323/* store a value or an expression directly in global data or in local array */
6141static void init_putv(CType *type, Section *sec, unsigned long c)6324static void init_putv(CType *type, Section *sec, unsigned long c)
6142{6325{
6143 int bt, bit_pos, bit_size;6326 int bt;
6144 void *ptr;6327 void *ptr;
6145 unsigned long long bit_mask;
6146 CType dtype;6328 CType dtype;
6147 6329
6148 dtype = *type;6330 dtype = *type;
@@ -6158,15 +6340,6 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 9 unmodified lines
6158 section_reserve(sec, c + size);6340 section_reserve(sec, c + size);
6159 ptr = sec->data + c;6341 ptr = sec->data + c;
6160 /* XXX: make code faster ? */6342 /* 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 }
6170 if ((vtop->r & (VT_SYM|VT_CONST)) == (VT_SYM|VT_CONST) &&6343 if ((vtop->r & (VT_SYM|VT_CONST)) == (VT_SYM|VT_CONST) &&
6171 vtop->sym->v >= SYM_FIRST_ANOM &&6344 vtop->sym->v >= SYM_FIRST_ANOM &&
6172 /* XXX This rejects compound literals like6345 /* XXX This rejects compound literals like
@@ -6219,31 +6392,48 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 46 unmodified lines
6219 }6392 }
6220 }6393 }
6221 } else {6394 } else {
6222 if ((vtop->r & VT_SYM) &&6395 if ((vtop->r & VT_SYM) &&
6223 (bt == VT_BYTE ||6396 (bt == VT_BYTE ||
6224 bt == VT_SHORT ||6397 bt == VT_SHORT ||
6225 bt == VT_DOUBLE ||6398 bt == VT_DOUBLE ||
6226 bt == VT_LDOUBLE ||6399 bt == VT_LDOUBLE ||
6227#if PTR_SIZE == 86400#if PTR_SIZE == 8
6228 (bt == VT_LLONG && bit_size != 64) ||6401 bt == VT_INT ||
6229 bt == VT_INT
6230#else6402#else
6231 bt == VT_LLONG ||6403 bt == VT_LLONG ||
6232 (bt == VT_INT && bit_size != 32)
6233#endif6404#endif
6405 (type->t & VT_BITFIELD)
6234 ))6406 ))
6235 tcc_error("initializer element is not computable at load time");6407 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) {
6237 /* XXX: when cross-compiling we assume that each type has the6427 /* XXX: when cross-compiling we assume that each type has the
6238 same representation on host and target, which is likely to6428 same representation on host and target, which is likely to
6239 be wrong in the case of long double */6429 be wrong in the case of long double */
6240 case VT_BOOL:6430 case VT_BOOL:
6241 vtop->c.i = (vtop->c.i != 0);6431 vtop->c.i = vtop->c.i != 0;
6242 case VT_BYTE:6432 case VT_BYTE:
6243 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;6433 *(char *)ptr |= vtop->c.i;
6244 break;6434 break;
6245 case VT_SHORT:6435 case VT_SHORT:
6246 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;6436 *(short *)ptr |= vtop->c.i;
6247 break;6437 break;
6248 case VT_FLOAT:6438 case VT_FLOAT:
6249 *(float*)ptr = vtop->c.f;6439 *(float*)ptr = vtop->c.f;
@@ -6270,14 +6460,14 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 20 unmodified lines
6270 break;6460 break;
6271#if PTR_SIZE != 86461#if PTR_SIZE != 8
6272 case VT_LLONG:6462 case VT_LLONG:
6273 *(long long *)ptr |= (vtop->c.i & bit_mask) << bit_pos;6463 *(long long *)ptr |= vtop->c.i;
6274 break;6464 break;
6275#else6465#else
6276 case VT_LLONG:6466 case VT_LLONG:
6277#endif6467#endif
6278 case VT_PTR:6468 case VT_PTR:
6279 {6469 {
6280 addr_t val = (vtop->c.i & bit_mask) << bit_pos;6470 addr_t val = vtop->c.i;
6281#if PTR_SIZE == 86471#if PTR_SIZE == 8
6282 if (vtop->r & VT_SYM)6472 if (vtop->r & VT_SYM)
6283 greloca(sec, vtop->sym, c, R_DATA_PTR, val);6473 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
6292 }6482 }
6293 default:6483 default:
6294 {6484 {
6295 int val = (vtop->c.i & bit_mask) << bit_pos;6485 int val = vtop->c.i;
6296#if PTR_SIZE == 86486#if PTR_SIZE == 8
6297 if (vtop->r & VT_SYM)6487 if (vtop->r & VT_SYM)
6298 greloca(sec, vtop->sym, c, R_DATA_PTR, val);6488 greloca(sec, vtop->sym, c, R_DATA_PTR, val);
tests/tcctest.c+4−4
@@ -1050,8 +1050,8 @@ int pad1; · 1049 unmodified lines
1050 but __alignof__ returns the wrong result (4) because we1050 but __alignof__ returns the wrong result (4) because we
1051 can't store the alignment yet when specified on symbols1051 can't store the alignment yet when specified on symbols
1052 directly (it's stored in the type so we'd need to make1052 directly (it's stored in the type so we'd need to make
1053 a copy of it).1053 a copy of it). -- FIXED */
1054struct aligntest7 altest7[2] __attribute__((aligned(16)));*/1054struct aligntest7 altest7[2] __attribute__((aligned(16)));
1055 1055
1056struct aligntest81056struct aligntest8
1057{1057{
@@ -1161,8 +1161,8 @@ void struct_test() · 103 unmodified lines
1161 sizeof(altest5), __alignof__(altest5));1161 sizeof(altest5), __alignof__(altest5));
1162 printf("altest6 sizeof=%d alignof=%d\n",1162 printf("altest6 sizeof=%d alignof=%d\n",
1163 sizeof(altest6), __alignof__(altest6));1163 sizeof(altest6), __alignof__(altest6));
1164 /*printf("altest7 sizeof=%d alignof=%d\n",1164 printf("altest7 sizeof=%d alignof=%d\n",
1165 sizeof(altest7), __alignof__(altest7));*/1165 sizeof(altest7), __alignof__(altest7));
1166 1166
1167 /* empty structures (GCC extension) */1167 /* empty structures (GCC extension) */
1168 printf("sizeof(struct empty) = %d\n", sizeof(struct empty));1168 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