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 1d47a3f01bd5ea43ce798fa6624b65dfdc6a37c0
parent f326044f9fc4ef7e182603e8686dde3f12da42dd
Author: Michael Forney <mforney@mforney.org>
Date:   Wed, 20 Feb 2019 13:22:44 -0800

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).

Diffstat:
Mqbe.c | 79+++++++++++++++++++++++++++++++++++++------------------------------------------
Mtests/struct-passing.qbe | 3++-
2 files changed, 39 insertions(+), 43 deletions(-)

diff --git a/qbe.c b/qbe.c @@ -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 @@ -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