| @@ -93,6 +93,7 @@ ST_FUNC void vpush(CType *type); · 92 unmodified lines |
| 93 | 93 | ST_FUNC int gvtst(int inv, int t); |
| 94 | 94 | static void gen_inline_functions(TCCState *s); |
| 95 | 95 | static void skip_or_save_block(TokenString **str); |
| 96 | +static void gv_dup(void); |
| 96 | 97 | |
| 97 | 98 | ST_INLN int is_float(int t) |
| 98 | 99 | { |
| @@ -1065,38 +1066,142 @@ static void gbound(void) · 966 unmodified lines |
| 1065 | 1066 | } |
| 1066 | 1067 | #endif |
| 1067 | 1068 | |
| 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 | + |
| 1068 | 1164 | /* store vtop a register belonging to class 'rc'. lvalues are |
| 1069 | 1165 | converted to values. Cannot be used if cannot be converted to |
| 1070 | 1166 | register value (such as structures). */ |
| 1071 | 1167 | ST_FUNC int gv(int rc) |
| 1072 | 1168 | { |
| 1073 | | − int r, bit_pos, bit_size, size, align; |
| 1074 | | − int rc2; |
| 1169 | + int r, bit_pos, bit_size, size, align, rc2; |
| 1075 | 1170 | |
| 1076 | 1171 | /* NOTE: get_reg can modify vstack[] */ |
| 1077 | 1172 | if (vtop->type.t & VT_BITFIELD) { |
| 1078 | 1173 | 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); |
| 1082 | 1177 | /* 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) |
| 1092 | 1183 | 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 | + } |
| 1100 | 1205 | r = gv(rc); |
| 1101 | 1206 | } else { |
| 1102 | 1207 | if (is_float(vtop->type.t) && |
| @@ -1362,6 +1467,10 @@ static void gv_dup(void) · 259 unmodified lines |
| 1362 | 1467 | t = vtop->type.t; |
| 1363 | 1468 | #if PTR_SIZE == 4 |
| 1364 | 1469 | if ((t & VT_BTYPE) == VT_LLONG) { |
| 1470 | + if (t & VT_BITFIELD) { |
| 1471 | + gv(RC_INT); |
| 1472 | + t = vtop->type.t; |
| 1473 | + } |
| 1365 | 1474 | lexpand(); |
| 1366 | 1475 | gv_dup(); |
| 1367 | 1476 | vswap(); |
| @@ -2920,45 +3029,49 @@ ST_FUNC void vstore(void) · 1552 unmodified lines |
| 2920 | 3029 | /* save lvalue as expression result (example: s.b = s.a = n;) */ |
| 2921 | 3030 | vdup(), vtop[-1] = vtop[-2]; |
| 2922 | 3031 | |
| 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); |
| 2925 | 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 | 3038 | gen_cast(&vtop[-1].type); |
| 2930 | 3039 | vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED); |
| 2931 | 3040 | } |
| 2932 | 3041 | |
| 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('&'); |
| 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 | 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 | 3075 | } else { |
| 2963 | 3076 | #ifdef CONFIG_TCC_BCHECK |
| 2964 | 3077 | /* bound check case */ |
| @@ -3276,112 +3389,114 @@ static void struct_add_offset (Sym *s, int offset) · 311 unmodified lines |
| 3276 | 3389 | |
| 3277 | 3390 | static 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 | 3394 | 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; |
| 3284 | 3396 | Sym *f; |
| 3285 | | − if (ad->a.aligned) |
| 3286 | | − maxalign = 1 << (ad->a.aligned - 1); |
| 3287 | | − else |
| 3288 | | − maxalign = 1; |
| 3397 | + |
| 3398 | + maxalign = 1; |
| 3289 | 3399 | offset = 0; |
| 3290 | 3400 | c = 0; |
| 3291 | 3401 | bit_pos = 0; |
| 3292 | 3402 | prevbt = VT_STRUCT; /* make it never match */ |
| 3293 | 3403 | prev_bit_size = 0; |
| 3294 | | − size = 0; |
| 3404 | + |
| 3405 | +//#define BF_DEBUG |
| 3295 | 3406 | |
| 3296 | 3407 | 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) { |
| 3317 | 3439 | 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; |
| 3320 | 3441 | offset = 0; |
| 3321 | 3442 | if (size > c) |
| 3322 | | − c = size; |
| 3443 | + c = size; |
| 3444 | + |
| 3323 | 3445 | } 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; |
| 3328 | 3449 | offset = c; |
| 3329 | 3450 | if (size > 0) |
| 3330 | | − c += size; |
| 3451 | + c += size; |
| 3331 | 3452 | bit_pos = 0; |
| 3453 | + prevbt = VT_STRUCT; |
| 3454 | + prev_bit_size = 0; |
| 3455 | + |
| 3332 | 3456 | } else { |
| 3333 | 3457 | /* 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; |
| 3361 | 3469 | 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; |
| 3374 | 3489 | /* In PCC layout named bit-fields influence the alignment |
| 3375 | 3490 | 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; |
| 3380 | 3494 | } else { |
| 3381 | 3495 | 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; |
| 3385 | 3500 | offset = c; |
| 3386 | 3501 | bit_pos = 0; |
| 3387 | 3502 | /* 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 | 3504 | To start a new run it's also required that this |
| 3390 | 3505 | or the last bit-field had non-zero width. */ |
| 3391 | 3506 | if (bit_size || prev_bit_size) |
| 3392 | | − c += size; |
| 3507 | + c += size; |
| 3393 | 3508 | } |
| 3394 | 3509 | /* In MS layout the records alignment is normally |
| 3395 | 3510 | influenced by the field, except for a zero-width |
| 3396 | 3511 | field at the start of a run (but by further zero-width |
| 3397 | 3512 | fields it is again). */ |
| 3398 | 3513 | if (bit_size == 0 && prevbt != bt) |
| 3399 | | − align = 1; |
| 3514 | + align = 1; |
| 3400 | 3515 | prevbt = bt; |
| 3401 | | − prev_bit_size = bit_size; |
| 3516 | + prev_bit_size = bit_size; |
| 3402 | 3517 | } |
| 3518 | + |
| 3403 | 3519 | f->type.t = (f->type.t & ~(0x3f << VT_STRUCT_SHIFT)) |
| 3404 | 3520 | | (bit_pos << VT_STRUCT_SHIFT); |
| 3405 | 3521 | bit_pos += bit_size; |
| 3406 | | − if (pcc && bit_pos >= size * 8) { |
| 3407 | | − c += size; |
| 3408 | | − bit_pos -= size * 8; |
| 3409 | | − } |
| 3410 | 3522 | } |
| 3411 | 3523 | 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); |
| 3416 | 3529 | 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 | + ); |
| 3420 | 3534 | } |
| 3421 | 3535 | printf("\n"); |
| 3422 | 3536 | #endif |
| @@ -3458,18 +3572,91 @@ static void struct_layout(CType *type, AttributeDef *ad) · 35 unmodified lines |
| 3458 | 3572 | |
| 3459 | 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 | 3584 | /* 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 | + } |
| 3467 | 3654 | } |
| 3468 | 3655 | |
| 3469 | 3656 | /* enum/struct/union declaration. u is VT_ENUM/VT_STRUCT/VT_UNION */ |
| 3470 | 3657 | static 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 | 3660 | int bit_size, bsize, bt; |
| 3474 | 3661 | Sym *s, *ss, **ps; |
| 3475 | 3662 | AttributeDef ad, ad1; |
| @@ -3623,17 +3810,6 @@ do_decl: · 147 unmodified lines |
| 3623 | 3810 | parse_attribute(&ad1); |
| 3624 | 3811 | } |
| 3625 | 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 | 3813 | if (bit_size >= 0) { |
| 3638 | 3814 | bt = type1.t & VT_BTYPE; |
| 3639 | 3815 | if (bt != VT_INT && |
| @@ -3646,9 +3822,12 @@ do_decl: · 6 unmodified lines |
| 3646 | 3822 | if (bit_size > bsize) { |
| 3647 | 3823 | tcc_error("width of '%s' exceeds its type", |
| 3648 | 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 | 3827 | /* no need for bit fields */ |
| 3651 | 3828 | ; |
| 3829 | + } else if (bit_size == 64) { |
| 3830 | + tcc_error("field width 64 not implemented"); |
| 3652 | 3831 | } else { |
| 3653 | 3832 | type1.t = (type1.t & ~VT_STRUCT_MASK) |
| 3654 | 3833 | | VT_BITFIELD |
| @@ -3668,7 +3847,8 @@ do_decl: · 13 unmodified lines |
| 3668 | 3847 | v = anon_sym++; |
| 3669 | 3848 | } |
| 3670 | 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 | 3852 | *ps = ss; |
| 3673 | 3853 | ps = &ss->next; |
| 3674 | 3854 | } |
| @@ -4495,7 +4675,10 @@ ST_FUNC void unary(void) · 820 unmodified lines |
| 4495 | 4675 | next(); |
| 4496 | 4676 | in_sizeof++; |
| 4497 | 4677 | expr_type(&type, 1); // Perform a in_sizeof = 0; |
| 4678 | + s = vtop[1].sym; /* hack: accessing previous vtop */ |
| 4498 | 4679 | size = type_size(&type, &align); |
| 4680 | + if (s && s->a.aligned) |
| 4681 | + align = 1 << (s->a.aligned - 1); |
| 4499 | 4682 | if (t == TOK_SIZEOF) { |
| 4500 | 4683 | if (!(type.t & VT_VLA)) { |
| 4501 | 4684 | if (size < 0) |
| @@ -6140,9 +6323,8 @@ static int decl_designator(CType *type, Section *sec, unsigned long c, · 1638 unmodified lines |
| 6140 | 6323 | /* store a value or an expression directly in global data or in local array */ |
| 6141 | 6324 | static void init_putv(CType *type, Section *sec, unsigned long c) |
| 6142 | 6325 | { |
| 6143 | | − int bt, bit_pos, bit_size; |
| 6326 | + int bt; |
| 6144 | 6327 | void *ptr; |
| 6145 | | − unsigned long long bit_mask; |
| 6146 | 6328 | CType dtype; |
| 6147 | 6329 | |
| 6148 | 6330 | dtype = *type; |
| @@ -6158,15 +6340,6 @@ static void init_putv(CType *type, Section *sec, unsigned long c) · 9 unmodified lines |
| 6158 | 6340 | section_reserve(sec, c + size); |
| 6159 | 6341 | ptr = sec->data + c; |
| 6160 | 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 | 6343 | if ((vtop->r & (VT_SYM|VT_CONST)) == (VT_SYM|VT_CONST) && |
| 6171 | 6344 | vtop->sym->v >= SYM_FIRST_ANOM && |
| 6172 | 6345 | /* 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 | 6394 | } else { |
| 6222 | | − if ((vtop->r & VT_SYM) && |
| 6395 | + if ((vtop->r & VT_SYM) && |
| 6223 | 6396 | (bt == VT_BYTE || |
| 6224 | 6397 | bt == VT_SHORT || |
| 6225 | 6398 | bt == VT_DOUBLE || |
| 6226 | 6399 | bt == VT_LDOUBLE || |
| 6227 | 6400 | #if PTR_SIZE == 8 |
| 6228 | | − (bt == VT_LLONG && bit_size != 64) || |
| 6229 | | − bt == VT_INT |
| 6401 | + bt == VT_INT || |
| 6230 | 6402 | #else |
| 6231 | 6403 | bt == VT_LLONG || |
| 6232 | | − (bt == VT_INT && bit_size != 32) |
| 6233 | 6404 | #endif |
| 6405 | + (type->t & VT_BITFIELD) |
| 6234 | 6406 | )) |
| 6235 | 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 | 6427 | /* XXX: when cross-compiling we assume that each type has the |
| 6238 | 6428 | same representation on host and target, which is likely to |
| 6239 | 6429 | be wrong in the case of long double */ |
| 6240 | 6430 | case VT_BOOL: |
| 6241 | | − vtop->c.i = (vtop->c.i != 0); |
| 6431 | + vtop->c.i = vtop->c.i != 0; |
| 6242 | 6432 | case VT_BYTE: |
| 6243 | | − *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos; |
| 6433 | + *(char *)ptr |= vtop->c.i; |
| 6244 | 6434 | break; |
| 6245 | 6435 | case VT_SHORT: |
| 6246 | | − *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos; |
| 6436 | + *(short *)ptr |= vtop->c.i; |
| 6247 | 6437 | break; |
| 6248 | 6438 | case VT_FLOAT: |
| 6249 | 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 | 6460 | break; |
| 6271 | 6461 | #if PTR_SIZE != 8 |
| 6272 | 6462 | case VT_LLONG: |
| 6273 | | − *(long long *)ptr |= (vtop->c.i & bit_mask) << bit_pos; |
| 6463 | + *(long long *)ptr |= vtop->c.i; |
| 6274 | 6464 | break; |
| 6275 | 6465 | #else |
| 6276 | 6466 | case VT_LLONG: |
| 6277 | 6467 | #endif |
| 6278 | 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 | 6471 | #if PTR_SIZE == 8 |
| 6282 | 6472 | if (vtop->r & VT_SYM) |
| 6283 | 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 | 6483 | default: |
| 6294 | 6484 | { |
| 6295 | | − int val = (vtop->c.i & bit_mask) << bit_pos; |
| 6485 | + int val = vtop->c.i; |
| 6296 | 6486 | #if PTR_SIZE == 8 |
| 6297 | 6487 | if (vtop->r & VT_SYM) |
| 6298 | 6488 | greloca(sec, vtop->sym, c, R_DATA_PTR, val); |