mirror of
https://github.com/frida/tinycc
synced 2024-11-28 02:29:38 +03:00
bitfields: fix PCC layout
Fixes some corner cases in PCC layout. Testcases coming up.
This commit is contained in:
parent
bd69bce20f
commit
ed680da951
51
tccgen.c
51
tccgen.c
@ -3267,6 +3267,7 @@ static void struct_add_offset (Sym *s, int offset)
|
||||
static void struct_layout(CType *type, AttributeDef *ad)
|
||||
{
|
||||
int align, maxalign, offset, c, bit_pos, bt, prevbt;
|
||||
int pcc = !tcc_state->ms_bitfields;
|
||||
Sym *f;
|
||||
if (ad->a.aligned)
|
||||
maxalign = ad->a.aligned;
|
||||
@ -3280,13 +3281,12 @@ static void struct_layout(CType *type, AttributeDef *ad)
|
||||
int extra_bytes = 0;
|
||||
int typealign, bit_size;
|
||||
int size = type_size(&f->type, &typealign);
|
||||
int pcc = !tcc_state->ms_bitfields;
|
||||
if (f->type.t & VT_BITFIELD) {
|
||||
bit_size = (f->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
|
||||
/* without ms-bitfields, allocate the
|
||||
* minimum number of bytes necessary,
|
||||
* adding single bytes as needed */
|
||||
if (!tcc_state->ms_bitfields) {
|
||||
if (0 && !tcc_state->ms_bitfields) {
|
||||
if (bit_pos == 0)
|
||||
/* minimum bytes for new bitfield */
|
||||
size = (bit_size + 7) / 8;
|
||||
@ -3311,55 +3311,59 @@ static void struct_layout(CType *type, AttributeDef *ad)
|
||||
} else {
|
||||
align = typealign;
|
||||
}
|
||||
/*if (extra_bytes) c += extra_bytes;
|
||||
else*/ if (bit_size < 0) {
|
||||
int addbytes = pcc ? (bit_pos + 7) >> 3 : 0;
|
||||
if (extra_bytes) c += extra_bytes;
|
||||
else if (bit_size < 0) {
|
||||
prevbt = VT_STRUCT;
|
||||
if (type->ref->type.t == TOK_STRUCT) {
|
||||
int addbytes = pcc ? (bit_pos + 7) >> 3 : 0;
|
||||
c = (c + addbytes + align - 1) & -align;
|
||||
offset = c;
|
||||
if (size > 0)
|
||||
c += size;
|
||||
} else {
|
||||
union_tail:
|
||||
offset = 0;
|
||||
if (addbytes > c)
|
||||
c = addbytes;
|
||||
if (size > c)
|
||||
c = size;
|
||||
}
|
||||
if (align > maxalign)
|
||||
maxalign = align;
|
||||
bit_pos = 0;
|
||||
prevbt = VT_STRUCT;
|
||||
} else if (type->ref->type.t != TOK_STRUCT) {
|
||||
if (pcc)
|
||||
size = (bit_size + 7) >> 3;
|
||||
f->type.t = (f->type.t & ~(0x3f << VT_STRUCT_SHIFT))
|
||||
| (0 << VT_STRUCT_SHIFT);
|
||||
goto union_tail;
|
||||
} else {
|
||||
/* A bit-field. Layout is more complicated. There are two
|
||||
options TCC implements: PCC compatible and MS compatible
|
||||
(PCC compatible is what GCC uses for almost all targets). */
|
||||
if (!bit_pos) {
|
||||
if (type->ref->type.t == TOK_STRUCT) {
|
||||
/* Don't align c here. That's only to be done
|
||||
in certain cases. */
|
||||
offset = c;
|
||||
} else {
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
if (pcc) {
|
||||
/* In PCC layout a non-packed bit-field is placed adjacent
|
||||
to the preceding bit-fields, except if it would overflow
|
||||
its container (depending on base type) or it's a zero-width
|
||||
bit-field. Packed non-zero-width bit-fields always are
|
||||
placed adjacent. */
|
||||
if ((typealign != 1 &&
|
||||
bit_pos + bit_size > size * 8) ||
|
||||
bit_size == 0) {
|
||||
int ofs = (c * 8 + bit_pos) % (typealign * 8);
|
||||
int ofs2 = ofs + bit_size + (typealign * 8) - 1;
|
||||
/*if ((typealign != 1 &&
|
||||
//bit_pos + bit_size > size * 8) ||
|
||||
(((c + ((bit_pos + 7) >> 3) + typealign - 1) & -typealign)
|
||||
!= ((c + ((bit_pos + bit_size + 7) >> 3) + typealign - 1) & -typealign))) ||
|
||||
bit_size == 0 ||
|
||||
(bit_pos + bit_size > size * 8)
|
||||
) {*/
|
||||
if (bit_size == 0 ||
|
||||
(typealign != 1 && (ofs2 / (typealign * 8)) > ((size*8)/(typealign*8)))) {
|
||||
c = (c + ((bit_pos + 7) >> 3) + typealign - 1) & -typealign;
|
||||
offset = c;
|
||||
bit_pos = 0;
|
||||
}
|
||||
offset = c;
|
||||
/* In PCC layout named bit-fields influence the alignment
|
||||
of the containing struct using the base types alignment,
|
||||
except for packed fields or zero-width fields. */
|
||||
if (bit_size > 0) {
|
||||
if (!(f->v & SYM_FIRST_ANOM)) {
|
||||
if (align > maxalign)
|
||||
maxalign = align;
|
||||
if (typealign > maxalign)
|
||||
@ -3444,7 +3448,8 @@ static void struct_layout(CType *type, AttributeDef *ad)
|
||||
f->r = 0;
|
||||
}
|
||||
/* store size and alignment */
|
||||
type->ref->c = (c + ((bit_pos + 7) >> 3) + maxalign - 1) & -maxalign;
|
||||
type->ref->c = (c + (pcc ? (bit_pos + 7) >> 3 : 0)
|
||||
+ maxalign - 1) & -maxalign;
|
||||
type->ref->r = maxalign;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user