Bit-fields are layed out differently in visual C, this implements a compatible mode. Checked against Visual C/C++ 2016. Unfortunately the GCC implementation of MS layout (behind -mms-bitfields) actually is different, and hence not compatible with MS in all cases :-/
Unified · Split
| @@ -3266,7 +3266,7 @@ static void struct_add_offset (Sym *s, int offset) · 3265 unmodified lines | |||
| 3266 | 3266 | ||
| 3267 | static void struct_layout(CType *type, AttributeDef *ad) | 3267 | static void struct_layout(CType *type, AttributeDef *ad) |
| 3268 | { | 3268 | { |
| 3269 | int align, maxalign, offset, c, bit_pos; | 3269 | int align, maxalign, offset, c, bit_pos, bt, prevbt; |
| 3270 | Sym *f; | 3270 | Sym *f; |
| 3271 | if (ad->a.aligned) | 3271 | if (ad->a.aligned) |
| 3272 | maxalign = ad->a.aligned; | 3272 | maxalign = ad->a.aligned; |
| @@ -3275,6 +3275,7 @@ static void struct_layout(CType *type, AttributeDef *ad) · 2 unmodified lines | |||
| 3275 | offset = 0; | 3275 | offset = 0; |
| 3276 | c = 0; | 3276 | c = 0; |
| 3277 | bit_pos = 0; | 3277 | bit_pos = 0; |
| 3278 | prevbt = VT_STRUCT; /* make it never match */ | ||
| 3278 | for (f = type->ref->next; f; f = f->next) { | 3279 | for (f = type->ref->next; f; f = f->next) { |
| 3279 | int extra_bytes = 0; | 3280 | int extra_bytes = 0; |
| 3280 | int typealign, bit_size; | 3281 | int typealign, bit_size; |
| @@ -3312,7 +3313,7 @@ static void struct_layout(CType *type, AttributeDef *ad) · 31 unmodified lines | |||
| 3312 | } | 3313 | } |
| 3313 | /*if (extra_bytes) c += extra_bytes; | 3314 | /*if (extra_bytes) c += extra_bytes; |
| 3314 | else*/ if (bit_size < 0) { | 3315 | else*/ if (bit_size < 0) { |
| 3315 | int addbytes = (bit_pos + 7) >> 3; | 3316 | int addbytes = pcc ? (bit_pos + 7) >> 3 : 0; |
| 3316 | if (type->ref->type.t == TOK_STRUCT) { | 3317 | if (type->ref->type.t == TOK_STRUCT) { |
| 3317 | c = (c + addbytes + align - 1) & -align; | 3318 | c = (c + addbytes + align - 1) & -align; |
| 3318 | offset = c; | 3319 | offset = c; |
| @@ -3328,6 +3329,7 @@ static void struct_layout(CType *type, AttributeDef *ad) · 9 unmodified lines | |||
| 3328 | if (align > maxalign) | 3329 | if (align > maxalign) |
| 3329 | maxalign = align; | 3330 | maxalign = align; |
| 3330 | bit_pos = 0; | 3331 | bit_pos = 0; |
| 3332 | prevbt = VT_STRUCT; | ||
| 3331 | } else { | 3333 | } else { |
| 3332 | /* A bit-field. Layout is more complicated. There are two | 3334 | /* A bit-field. Layout is more complicated. There are two |
| 3333 | options TCC implements: PCC compatible and MS compatible | 3335 | options TCC implements: PCC compatible and MS compatible |
| @@ -3347,9 +3349,9 @@ static void struct_layout(CType *type, AttributeDef *ad) · 13 unmodified lines | |||
| 3347 | its container (depending on base type) or it's a zero-width | 3349 | its container (depending on base type) or it's a zero-width |
| 3348 | bit-field. Packed non-zero-width bit-fields always are | 3350 | bit-field. Packed non-zero-width bit-fields always are |
| 3349 | placed adjacent. */ | 3351 | placed adjacent. */ |
| 3350 | if (typealign != 1 && | 3352 | if ((typealign != 1 && |
| 3351 | (bit_pos + bit_size > size * 8 || | 3353 | bit_pos + bit_size > size * 8) || |
| 3352 | bit_size == 0)) { | 3354 | bit_size == 0) { |
| 3353 | c = (c + ((bit_pos + 7) >> 3) + typealign - 1) & -typealign; | 3355 | c = (c + ((bit_pos + 7) >> 3) + typealign - 1) & -typealign; |
| 3354 | offset = c; | 3356 | offset = c; |
| 3355 | bit_pos = 0; | 3357 | bit_pos = 0; |
| @@ -3364,12 +3366,31 @@ static void struct_layout(CType *type, AttributeDef *ad) · 8 unmodified lines | |||
| 3364 | maxalign = typealign; | 3366 | maxalign = typealign; |
| 3365 | } | 3367 | } |
| 3366 | } else { | 3368 | } else { |
| 3367 | tcc_error("ms bit-field layout not implemented"); | 3369 | bt = f->type.t & VT_BTYPE; |
| 3370 | if ( | ||
| 3371 | (( | ||
| 3372 | bit_pos + bit_size > size * 8) || | ||
| 3373 | (bit_size == 0 && prevbt == bt) || | ||
| 3374 | (bit_size > 0 && bt != prevbt))) { | ||
| 3375 | c = (c + typealign - 1) & -typealign; | ||
| 3376 | offset = c; | ||
| 3377 | bit_pos = 0; | ||
| 3378 | /* In MS bitfield mode a bit-field run always uses | ||
| 3379 | at least as many bits as the underlying type. */ | ||
| 3380 | c += size; | ||
| 3381 | } | ||
| 3382 | if (bit_size > 0 || prevbt == bt) { | ||
| 3383 | if (align > maxalign) | ||
| 3384 | maxalign = align; | ||
| 3385 | if (typealign > maxalign) | ||
| 3386 | maxalign = typealign; | ||
| 3387 | } | ||
| 3388 | prevbt = bt; | ||
| 3368 | } | 3389 | } |
| 3369 | f->type.t = (f->type.t & ~(0x3f << VT_STRUCT_SHIFT)) | 3390 | f->type.t = (f->type.t & ~(0x3f << VT_STRUCT_SHIFT)) |
| 3370 | | (bit_pos << VT_STRUCT_SHIFT); | 3391 | | (bit_pos << VT_STRUCT_SHIFT); |
| 3371 | bit_pos += bit_size; | 3392 | bit_pos += bit_size; |
| 3372 | if (bit_pos >= size * 8) { | 3393 | if (pcc && bit_pos >= size * 8) { |
| 3373 | c += size; | 3394 | c += size; |
| 3374 | bit_pos -= size * 8; | 3395 | bit_pos -= size * 8; |
| 3375 | } | 3396 | } |
| @@ -3573,6 +3594,8 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) · 197 unmodified lines | |||
| 3573 | if (v && bit_size == 0) | 3594 | if (v && bit_size == 0) |
| 3574 | tcc_error("zero width for bit-field '%s'", | 3595 | tcc_error("zero width for bit-field '%s'", |
| 3575 | get_tok_str(v, NULL)); | 3596 | get_tok_str(v, NULL)); |
| 3597 | if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) | ||
| 3598 | parse_attribute(&ad1); | ||
| 3576 | } | 3599 | } |
| 3577 | size = type_size(&type1, &align); | 3600 | size = type_size(&type1, &align); |
| 3578 | /* Only remember non-default alignment. */ | 3601 | /* Only remember non-default alignment. */ |