From e345d6fc4e3223e2d2655114c8829538276a0bb9 Mon Sep 17 00:00:00 2001 From: Michael Forney Date: Mon, 25 Oct 2021 16:58:15 -0700 Subject: decl: Allow alignment > 16 of locals This is not yet supported by QBE, so for now we allocate a bit extra and choose the address in the allocated region with an aligned address. --- decl.c | 4 +--- qbe.c | 12 ++++++++++-- test/alignas-local-32.c | 4 ++++ test/alignas-local-32.qbe | 11 +++++++++++ 4 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 test/alignas-local-32.c create mode 100644 test/alignas-local-32.qbe diff --git a/decl.c b/decl.c index 50fe1c6..268ee01 100644 --- a/decl.c +++ b/decl.c @@ -960,10 +960,8 @@ decl(struct scope *s, struct func *f) if (init || d->linkage == LINKNONE) { if (d->linkage != LINKNONE || sc & SCSTATIC) emitdata(d, init); - else if (d->align <= 16) - funcinit(f, d, init); else - error(&tok.loc, "unsupported alignment %d for object with automatic storage duration", d->align); + funcinit(f, d, init); d->defined = true; if (d->tentative.next) listremove(&d->tentative); diff --git a/qbe.c b/qbe.c index 88cd97b..264bdac 100644 --- a/qbe.c +++ b/qbe.c @@ -259,6 +259,7 @@ funcalloc(struct func *f, struct decl *d) { enum instkind op; struct inst *inst; + unsigned long long size; assert(!d->type->incomplete); assert(d->type->size > 0); @@ -266,17 +267,24 @@ funcalloc(struct func *f, struct decl *d) d->align = d->type->align; else if (d->align < d->type->align) error(&tok.loc, "object requires alignment %d, which is stricter than %d", d->type->align, d->align); + size = d->type->size; switch (d->align) { case 1: case 2: case 4: op = IALLOC4; break; case 8: op = IALLOC8; break; + default: size += d->align - 16; /* fallthrough */ case 16: op = IALLOC16; break; - default: - fatal("internal error: invalid alignment: %d\n", d->align); } inst = mkinst(f, op, ptrclass, mkintconst(size), NULL); arrayaddptr(&f->start->insts, inst); + if (d->align > 16) { + /* TODO: implement alloc32 in QBE and use that instead */ + inst = mkinst(f, IADD, ptrclass, &inst->res, mkintconst(d->align - 16)); + arrayaddptr(&f->start->insts, inst); + inst = mkinst(f, IAND, ptrclass, &inst->res, mkintconst(-d->align)); + arrayaddptr(&f->start->insts, inst); + } d->value = &inst->res; } diff --git a/test/alignas-local-32.c b/test/alignas-local-32.c new file mode 100644 index 0000000..e69a105 --- /dev/null +++ b/test/alignas-local-32.c @@ -0,0 +1,4 @@ +int main(void) { + _Alignas(32) char x; + return (unsigned long)&x % 32; +} diff --git a/test/alignas-local-32.qbe b/test/alignas-local-32.qbe new file mode 100644 index 0000000..53bfab3 --- /dev/null +++ b/test/alignas-local-32.qbe @@ -0,0 +1,11 @@ +export +function w $main() { +@start.1 + %.1 =l alloc16 17 + %.2 =l add %.1, 16 + %.3 =l and %.2, 18446744073709551584 +@body.2 + %.4 =l extsw 32 + %.5 =l urem %.3, %.4 + ret %.5 +} -- cgit v1.2.3