diff options
author | Michael Forney <mforney@mforney.org> | 2019-02-20 13:22:44 -0800 |
---|---|---|
committer | Michael Forney <mforney@mforney.org> | 2019-02-20 13:27:35 -0800 |
commit | 1d47a3f01bd5ea43ce798fa6624b65dfdc6a37c0 (patch) | |
tree | b55646706a2ce9c4569f0bb9b38eebabba1d1b07 | |
parent | f326044f9fc4ef7e182603e8686dde3f12da42dd (diff) | |
download | cproc-1d47a3f01bd5ea43ce798fa6624b65dfdc6a37c0.tar.xz |
Fix definitions for nested structs
The QBE documentation suggested that the subtypes in an aggregate must
be simple types, but they can actually be any type (this is necessary
for getting the alignment and padding right between fields adjacent to
the nested struct).
-rw-r--r-- | qbe.c | 79 | ||||
-rw-r--r-- | tests/struct-passing.qbe | 3 |
2 files changed, 39 insertions, 43 deletions
@@ -966,61 +966,56 @@ emitvalue(struct value *v) } static void -aggr(struct type *t) +emitrepr(struct representation *r, bool abi, bool ext) { - uint64_t i; - struct member *m; - - switch (t->kind) { - case TYPEARRAY: - if (typeprop(t->base) & PROPAGGR) { - for (i = 0; i < t->array.length; ++i) - aggr(t->base); - } else { - printf("%c %" PRIu64 ", ", t->base->repr->ext, t->array.length); - } - break; - case TYPESTRUCT: - for (m = t->structunion.members; m; m = m->next) { - if (typeprop(m->type) & PROPAGGR) - aggr(m->type); - else - printf("%c, ", m->type->repr->ext); - } - break; - default: - fatal("internal error; not an aggregate type"); + if (abi && r->abi.id) { + putchar(':'); + emitname(&r->abi); + } else if (ext) { + putchar(r->ext); + } else { + putchar(r->base); } } +/* XXX: need to consider _Alignas on struct members */ +/* XXX: this might not be right for something like +union { + struct { long long x; double y; }; + struct { double z; long long w; }; +}; +*/ static void emittype(struct type *t) { static uint64_t id; + struct member *m; + struct type *sub; + uint64_t i; - if (!t->repr || t->repr->abi.id || !(typeprop(t) & PROPAGGR)) + if (!t->repr || t->repr->abi.id || t->kind != TYPESTRUCT && t->kind != TYPEUNION) return; t->repr = xmalloc(sizeof(*t->repr)); t->repr->base = 'l'; - if (t->kind == TYPESTRUCT || t->kind == TYPEUNION) - t->repr->abi.str = t->structunion.tag; + t->repr->abi.str = t->structunion.tag; t->repr->abi.id = ++id; + for (m = t->structunion.members; m; m = m->next) { + for (sub = m->type; sub->kind == TYPEARRAY; sub = sub->base) + ; + emittype(sub); + } fputs("type :", stdout); emitname(&t->repr->abi); fputs(" = { ", stdout); - aggr(t); - puts("}"); -} - -static void -emitrepr(struct representation *r, bool abi) -{ - if (abi && r->abi.id) { - putchar(':'); - emitname(&r->abi); - } else { - putchar(r->base); + for (m = t->structunion.members; m && t->kind == TYPESTRUCT; m = m->next) { + 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); + fputs(", ", stdout); } + puts("}"); } static void @@ -1033,7 +1028,7 @@ emitinst(struct instruction *inst) if (instdesc[inst->kind].ret && inst->res.kind) { emitvalue(&inst->res); fputs(" =", stdout); - emitrepr(inst->res.repr, inst->kind == ICALL); + emitrepr(inst->res.repr, inst->kind == ICALL, false); putchar(' '); } fputs(instdesc[inst->kind].str, stdout); @@ -1046,7 +1041,7 @@ emitinst(struct instruction *inst) if (arg != &inst->arg[1]) fputs(", ", stdout); if ((*arg)->kind != VALELLIPSIS) { - emitrepr((*arg)->repr, true); + emitrepr((*arg)->repr, true, false); putchar(' '); } emitvalue(*arg); @@ -1096,14 +1091,14 @@ emitfunc(struct function *f, bool global) puts("export"); fputs("function ", stdout); if (f->type->base != &typevoid) { - emitrepr(f->type->base->repr, true); + emitrepr(f->type->base->repr, true, false); putchar(' '); } printf("$%s(", f->name); for (p = f->type->func.params; p; p = p->next) { if (p != f->type->func.params) fputs(", ", stdout); - emitrepr(p->type->repr, true); + emitrepr(p->type->repr, true, false); putchar(' '); emitvalue(p->value); } diff --git a/tests/struct-passing.qbe b/tests/struct-passing.qbe index a01bda2..07bd483 100644 --- a/tests/struct-passing.qbe +++ b/tests/struct-passing.qbe @@ -1,4 +1,5 @@ -type :s.1 = { w, b 3, h, b 3, h, d, } +type :.2 = { b 3, h, } +type :s.1 = { w, :.2 2, d, } export function $f(:s.1 %.1) { @start.1 |