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 923f6d78056f1d287565bcf491c38f654ae9f7be
parent e76bd99a3f6963de58f661ca9141cd1a723db004
Author: Michael Forney <mforney@mforney.org>
Date:   Fri, 10 May 2019 14:40:51 -0700

qbe: Fix QBE types for structs containing bit-fields

Diffstat:
Mqbe.c | 27++++++++++++++++++++-------
Atest/struct-passing-bitfield.c | 7+++++++
Atest/struct-passing-bitfield.qbe | 7+++++++
3 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/qbe.c b/qbe.c @@ -1063,9 +1063,9 @@ static void emittype(struct type *t) { static uint64_t id; - struct member *m; + struct member *m, *other; struct type *sub; - uint64_t i; + uint64_t i, off; if (!t->repr || t->repr->abi.id || t->kind != TYPESTRUCT && t->kind != TYPEUNION) return; @@ -1081,18 +1081,31 @@ emittype(struct type *t) fputs("type :", stdout); emitname(&t->repr->abi); fputs(" = { ", stdout); - for (m = t->structunion.members; m; m = m->next) { - if (t->kind == TYPEUNION) + for (m = t->structunion.members, off = 0; m;) { + if (t->kind == TYPESTRUCT) { + /* look for a subsequent member with a larger storage unit */ + for (other = m->next; other && other->offset < ALIGNUP(m->offset + 1, 8); other = other->next) { + if (other->offset <= m->offset) + m = other; + } + off = m->offset + m->type->size; + } else { fputs("{ ", stdout); + } for (i = 1, sub = m->type; sub->kind == TYPEARRAY; sub = sub->base) i *= sub->array.length; emitrepr(sub->repr, true, true); if (i > 1) printf(" %" PRIu64, i); - if (t->kind == TYPEUNION) - fputs(" } ", stdout); - else + if (t->kind == TYPESTRUCT) { fputs(", ", stdout); + /* skip subsequent members contained within the same storage unit */ + do m = m->next; + while (m && m->offset < off); + } else { + fputs(" } ", stdout); + m = m->next; + } } puts("}"); } diff --git a/test/struct-passing-bitfield.c b/test/struct-passing-bitfield.c @@ -0,0 +1,7 @@ +struct s { + char x, y; + long long z : 48; +}; + +void f(struct s s) { +} diff --git a/test/struct-passing-bitfield.qbe b/test/struct-passing-bitfield.qbe @@ -0,0 +1,7 @@ +type :s.1 = { l, } +export +function $f(:s.1 %.1) { +@start.1 +@body.2 + ret +}