History

bitfields: one more hack and a "-Wgcc-compat" switch

bit_pos + bit_size > type_size * 8 must NEVER happen because the code generator can read/write only the basic integral types. Warn if tcc has to break GCC compatibility for that reason and if -Wgcc-compat is given. Example: struct __attribute__((packed)) _s { unsigned int x : 12; unsigned char y : 7; unsigned int z : 28; }; Expected (GCC) layout (sizeof struct = 6) .xxxxxxxx.xxxxyyyy.yyyzzzzz.zzzzzzzz.zzzzzzzz.zzzzzzz0. But we cannot read/write 'char y'from 2 bytes in memory. So we have to adjust: .xxxxxxxx.xxxx0000.yyyyyyyz.zzzzzzzz.zzzzzzzz.zzzzzzzz.zzz00000 Now 'int z' cannot be accessed from 5 bytes. So we arrive at this (sizeof struct = 7): .xxxxxxxx.xxxx0000.yyyyyyy0.zzzzzzzz.zzzzzzzz.zzzzzzzz.zzzz0000 Otherwise the bitfield load/store generator needs to be changed to allow byte-wise accesses. Also we may touch memory past the struct in some cases currently. The patch adds a warning for that too. 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: 81 ec 04 00 00 00 sub $0x4,%esp 9: 90 nop struct __attribute__((packed)) { unsigned x : 5; } b = {0} ; a: 8b 45 ff mov -0x1(%ebp),%eax d: 83 e0 e0 and $0xffffffe0,%eax 10: 89 45 ff mov %eax,-0x1(%ebp) This touches -0x1 ... +0x3(%ebp), hence 3 bytes beyond stack space. Since the data is not changed, nothing else happens here.

grischka committed 9 years ago

Commit d2427061 parent 3f5fd303 files · +21 −6Browse files

Unified · Split

3 files
  1. libtcc.c +1 −0
  2. tcc.h +1 −0
  3. tccgen.c +19 −6
libtcc.c+1−0
@@ -1578,6 +1578,7 @@ static const FlagDef options_W[] = { · 1577 unmodified lines
1578 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },1578 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
1579 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },1579 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
1580 { offsetof(TCCState, warn_error), 0, "error" },1580 { offsetof(TCCState, warn_error), 0, "error" },
1581 { offsetof(TCCState, warn_gcc_compat), 0, "gcc-compat" },
1581 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,1582 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
1582 "implicit-function-declaration" },1583 "implicit-function-declaration" },
1583 { 0, 0, NULL }1584 { 0, 0, NULL }
tcc.h+1−0
@@ -660,6 +660,7 @@ struct TCCState { · 659 unmodified lines
660 int warn_error;660 int warn_error;
661 int warn_none;661 int warn_none;
662 int warn_implicit_function_declaration;662 int warn_implicit_function_declaration;
663 int warn_gcc_compat;
663 664
664 /* compile with debug symbol (and use them if error during execution) */665 /* compile with debug symbol (and use them if error during execution) */
665 int do_debug;666 int do_debug;
tccgen.c+19−6
@@ -3285,6 +3285,9 @@ static void struct_layout(CType *type, AttributeDef *ad) · 3284 unmodified lines
3285{3285{
3286 int align, maxalign, offset, c, bit_pos, bt, prevbt, prev_bit_size;3286 int align, maxalign, offset, c, bit_pos, bt, prevbt, prev_bit_size;
3287 int pcc = !tcc_state->ms_bitfields;3287 int pcc = !tcc_state->ms_bitfields;
3288 int packwarn = tcc_state->warn_gcc_compat;
3289 int typealign, bit_size, size;
3290
3288 Sym *f;3291 Sym *f;
3289 if (ad->a.aligned)3292 if (ad->a.aligned)
3290 maxalign = 1 << (ad->a.aligned - 1);3293 maxalign = 1 << (ad->a.aligned - 1);
@@ -3295,9 +3298,10 @@ static void struct_layout(CType *type, AttributeDef *ad) · 4 unmodified lines
3295 bit_pos = 0;3298 bit_pos = 0;
3296 prevbt = VT_STRUCT; /* make it never match */3299 prevbt = VT_STRUCT; /* make it never match */
3297 prev_bit_size = 0;3300 prev_bit_size = 0;
3301 size = 0;
3302
3298 for (f = type->ref->next; f; f = f->next) {3303 for (f = type->ref->next; f; f = f->next) {
3299 int typealign, bit_size;3304 size = type_size(&f->type, &typealign);
3300 int size = type_size(&f->type, &typealign);
3301 if (f->type.t & VT_BITFIELD)3305 if (f->type.t & VT_BITFIELD)
3302 bit_size = (f->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;3306 bit_size = (f->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
3303 else3307 else
@@ -3358,13 +3362,20 @@ static void struct_layout(CType *type, AttributeDef *ad) · 54 unmodified lines
3358 int ofs = (c * 8 + bit_pos) % (typealign * 8);3362 int ofs = (c * 8 + bit_pos) % (typealign * 8);
3359 int ofs2 = ofs + bit_size + (typealign * 8) - 1;3363 int ofs2 = ofs + bit_size + (typealign * 8) - 1;
3360 if (bit_size == 0 ||3364 if (bit_size == 0 ||
3361 ((typealign != 1 || size == 1) &&3365 (typealign != 1 &&
3362 (ofs2 / (typealign * 8)) > (size/typealign))) {3366 (ofs2 / (typealign * 8)) > (size/typealign))) {
3363 c = (c + ((bit_pos + 7) >> 3) + typealign - 1) & -typealign;3367 c = (c + ((bit_pos + 7) >> 3) + typealign - 1) & -typealign;
3364 bit_pos = 0;3368 bit_pos = 0;
3365 } else if (bit_pos + bit_size > size * 8) {3369 } else if (bit_pos + bit_size > size * 8) {
3366 c += bit_pos >> 3;3370 c += bit_pos >> 3;
3367 bit_pos &= 7;3371 bit_pos &= 7;
3372 if (bit_pos + bit_size > size * 8) {
3373 c += 1, bit_pos = 0;
3374 if ((ad->a.packed || f->r) && packwarn) {
3375 tcc_warning("struct layout not compatible with GCC (internal limitation)");
3376 packwarn = 0;
3377 }
3378 }
3368 }3379 }
3369 offset = c;3380 offset = c;
3370 /* In PCC layout named bit-fields influence the alignment3381 /* In PCC layout named bit-fields influence the alignment
@@ -3407,8 +3418,8 @@ static void struct_layout(CType *type, AttributeDef *ad) · 36 unmodified lines
3407 if (align > maxalign)3418 if (align > maxalign)
3408 maxalign = align;3419 maxalign = align;
3409#if 03420#if 0
3410 printf("set field %s offset=%d c=%d",3421 printf("set field %s offset=%d",
3411 get_tok_str(f->v & ~SYM_FIELD, NULL), offset, c);3422 get_tok_str(f->v & ~SYM_FIELD, NULL), offset);
3412 if (f->type.t & VT_BITFIELD) {3423 if (f->type.t & VT_BITFIELD) {
3413 printf(" pos=%d size=%d",3424 printf(" pos=%d size=%d",
3414 (f->type.t >> VT_STRUCT_SHIFT) & 0x3f,3425 (f->type.t >> VT_STRUCT_SHIFT) & 0x3f,
@@ -3458,6 +3469,8 @@ static void struct_layout(CType *type, AttributeDef *ad) · 43 unmodified lines
3458 type->ref->c = (c + (pcc ? (bit_pos + 7) >> 3 : 0)3469 type->ref->c = (c + (pcc ? (bit_pos + 7) >> 3 : 0)
3459 + maxalign - 1) & -maxalign;3470 + maxalign - 1) & -maxalign;
3460 type->ref->r = maxalign;3471 type->ref->r = maxalign;
3472 if (offset + size > type->ref->c)
3473 tcc_warning("will touch memory past end of the struct (internal limitation)");
3461}3474}
3462 3475
3463/* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */3476/* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
@@ -3615,7 +3628,7 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) · 151 unmodified lines
3615 } else if (ad1.a.packed || ad->a.packed) {3628 } else if (ad1.a.packed || ad->a.packed) {
3616 alignoverride = 1;3629 alignoverride = 1;
3617 } else if (*tcc_state->pack_stack_ptr) {3630 } else if (*tcc_state->pack_stack_ptr) {
3618 if (align > *tcc_state->pack_stack_ptr)3631 if (align >= *tcc_state->pack_stack_ptr)
3619 alignoverride = *tcc_state->pack_stack_ptr;3632 alignoverride = *tcc_state->pack_stack_ptr;
3620 }3633 }
3621 if (bit_size >= 0) {3634 if (bit_size >= 0) {

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