cproc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/cproc
Log | Files | Refs | Submodules | README | LICENSE

commit 7569343621ce0257a239e24290557e11e31dc119
parent 2833c0041d669bc1ba7a6d13e7f92c23b84e04ae
Author: Michael Forney <mforney@mforney.org>
Date:   Wed, 17 Apr 2019 19:13:08 -0700

Fix bit-field offsets in unions

Diffstat:
Mdecl.c | 38++++++++++++++++++++++++--------------
Atest/bitfield-union.c | 4++++
Atest/bitfield-union.qbe | 1+
3 files changed, 29 insertions(+), 14 deletions(-)

diff --git a/decl.c b/decl.c @@ -684,21 +684,31 @@ addmember(struct structbuilder *b, struct qualtype mt, char *name, int align, ui error(&tok.loc, "bit-field with zero width must not have declarator"); if (width > mt.type->size * 8) error(&tok.loc, "bit-field exceeds width of underlying type"); - /* calculate end of the storage-unit for this bit-field */ - end = ALIGNUP(t->size, mt.type->size); - if (!width || width > (end - t->size) * 8 + b->bits) { - /* no room, allocate a new storage-unit */ - t->size = end; - b->bits = 0; - } - if (m) { - m->offset = ALIGNDOWN(t->size - !!b->bits, mt.type->size); - m->bits.before = (t->size - m->offset) * 8 - b->bits; - m->bits.after = mt.type->size * 8 - width - m->bits.before; - } - t->size += (width - b->bits + 7) / 8; - b->bits = (b->bits - width) % 8; align = mt.type->align; + if (t->kind == TYPESTRUCT) { + /* calculate end of the storage-unit for this bit-field */ + end = ALIGNUP(t->size, mt.type->size); + if (!width || width > (end - t->size) * 8 + b->bits) { + /* no room, allocate a new storage-unit */ + t->size = end; + b->bits = 0; + } + if (m) { + m->offset = ALIGNDOWN(t->size - !!b->bits, mt.type->size); + m->bits.before = (t->size - m->offset) * 8 - b->bits; + m->bits.after = mt.type->size * 8 - width - m->bits.before; + } + t->size += (width - b->bits + 7) / 8; + b->bits = (b->bits - width) % 8; + } else { + if (m) { + m->offset = 0; + m->bits.before = 0; + m->bits.after = mt.type->size * 8 - width; + } + if (t->size < mt.type->size) + t->size = mt.type->size; + } } if (t->align < align) t->align = align; diff --git a/test/bitfield-union.c b/test/bitfield-union.c @@ -0,0 +1,4 @@ +union { + int x : 5; + int y : 10; +} u = {.y = 123}; diff --git a/test/bitfield-union.qbe b/test/bitfield-union.qbe @@ -0,0 +1 @@ +export data $u = align 4 { b 123, z 3 }