aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--qbe.c27
-rw-r--r--test/struct-passing-bitfield.c7
-rw-r--r--test/struct-passing-bitfield.qbe7
3 files changed, 34 insertions, 7 deletions
diff --git a/qbe.c b/qbe.c
index e707942..4389e27 100644
--- 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
new file mode 100644
index 0000000..fbda34a
--- /dev/null
+++ 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
new file mode 100644
index 0000000..2bd9a3c
--- /dev/null
+++ 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
+}