qbe

Internal scc patchset buffer for QBE
Log | Files | Refs | README | LICENSE

commit c5769f62b4912e429a332c9aa0bead3a383fe966
parent 329a18a30b9f8db598db39b7326fc4149bcc1431
Author: Quentin Carbonneaux <quentin@c9x.me>
Date:   Mon, 14 Mar 2022 23:10:39 +0100

dynamic stack allocs for arm64

I also moved some isel logic
that would have been repeated
a third time in util.c.

Diffstat:
Mall.h | 1+
Mamd64/isel.c | 30++++--------------------------
Marm64/emit.c | 9++++++++-
Marm64/isel.c | 10+++++++++-
Mrv64/isel.c | 48+++++++++++-------------------------------------
Mutil.c | 30++++++++++++++++++++++++++++++
6 files changed, 63 insertions(+), 65 deletions(-)

diff --git a/all.h b/all.h @@ -444,6 +444,7 @@ Ref getcon(int64_t, Fn *); int addcon(Con *, Con *); void blit(Ref, uint, Ref, uint, uint, Fn *); void blit0(Ref, Ref, uint, Fn *); +void salloc(Ref, Ref, Fn *); void dumpts(BSet *, Tmp *, FILE *); void bsinit(BSet *, uint); diff --git a/amd64/isel.c b/amd64/isel.c @@ -203,7 +203,6 @@ sel(Ins i, ANum *an, Fn *fn) { Ref r0, r1, tmp[7]; int x, j, k, kc, sh, swap; - int64_t sz; Ins *i0, *i1; if (rtype(i.to) == RTmp) @@ -375,31 +374,10 @@ Emit: fixarg(&i1->arg[0], argcls(&i, 0), i1, fn); fixarg(&i1->arg[1], argcls(&i, 1), i1, fn); break; - case Oalloc: - case Oalloc+1: - case Oalloc+2: /* == Oalloc1 */ - /* we need to make sure - * the stack remains aligned - * (rsp = 0) mod 16 - */ - fn->dynalloc = 1; - if (rtype(i.arg[0]) == RCon) { - sz = fn->con[i.arg[0].val].bits.i; - if (sz < 0 || sz >= INT_MAX-15) - err("invalid alloc size %"PRId64, sz); - sz = (sz + 15) & -16; - emit(Osalloc, Kl, i.to, getcon(sz, fn), R); - } else { - /* r0 = (i.arg[0] + 15) & -16 */ - r0 = newtmp("isel", Kl, fn); - r1 = newtmp("isel", Kl, fn); - emit(Osalloc, Kl, i.to, r0, R); - emit(Oand, Kl, r0, r1, getcon(-16, fn)); - emit(Oadd, Kl, r1, i.arg[0], getcon(15, fn)); - if (fn->tmp[i.arg[0].val].slot != -1) - err("unlikely argument %%%s in %s", - fn->tmp[i.arg[0].val].name, optab[i.op].name); - } + case Oalloc4: + case Oalloc8: + case Oalloc16: + salloc(i.to, i.arg[0], fn); break; default: if (isext(i.op)) diff --git a/arm64/emit.c b/arm64/emit.c @@ -385,6 +385,11 @@ emitins(Ins *i, E *e) rn, s & 0xFFFF, rn, s >> 16, rn, rn ); break; + case Osalloc: + emitf("sub sp, sp, %0", i, e); + if (!req(i->to, R)) + emitf("mov %=, sp", i, e); + break; } } @@ -483,7 +488,7 @@ arm64_emitfn(Fn *fn, FILE *out) "\tstp\tx29, x30, [sp, -16]!\n", e->frame & 0xFFFF, e->frame >> 16 ); - fputs("\tadd\tx29, sp, 0\n", e->f); + fputs("\tmov\tx29, sp\n", e->f); s = (e->frame - e->padding) / 4; for (r=arm64_rclob; *r>=0; r++) if (e->fn->reg & BIT(*r)) { @@ -509,6 +514,8 @@ arm64_emitfn(Fn *fn, FILE *out) i->cls = *r >= V0 ? Kd : Kl; emitins(i, e); } + if (e->fn->dynalloc) + fputs("\tmov sp, x29\n", e->f); o = e->frame + 16; if (e->fn->vararg) o += 192; diff --git a/arm64/isel.c b/arm64/isel.c @@ -163,6 +163,12 @@ sel(Ins i, Fn *fn) Ins *i0; int ck, cc; + if (INRANGE(i.op, Oalloc, Oalloc1)) { + i0 = curi - 1; + salloc(i.to, i.arg[0], fn); + fixarg(&i0->arg[0], Kl, 0, fn); + return; + } if (iscmp(i.op, &ck, &cc)) { emit(Oflag, i.cls, i.to, R, R); i0 = curi; @@ -170,7 +176,9 @@ sel(Ins i, Fn *fn) i0->op += cmpop(cc); else i0->op += cc; - } else if (i.op != Onop) { + return; + } + if (i.op != Onop) { emiti(i); iarg = curi->arg; /* fixarg() can change curi */ fixarg(&iarg[0], argcls(&i, 0), 0, fn); diff --git a/rv64/isel.c b/rv64/isel.c @@ -174,46 +174,20 @@ selcmp(Ins i, int k, int op, Fn *fn) static void sel(Ins i, Fn *fn) { - Ref r0, r1; Ins *i0; int ck, cc; - int64_t sz; - switch (i.op) { - case Onop: - break; - case Oalloc4: - case Oalloc8: - case Oalloc16: - /* we need to make sure - * the stack remains aligned - * (rsp = 0) mod 16 - */ - fn->dynalloc = 1; - if (rtype(i.arg[0]) == RCon) { - sz = fn->con[i.arg[0].val].bits.i; - if (sz < 0) - err("invalid alloc size %"PRId64, sz); - sz = (sz + 15) & -16; - emit(Osalloc, Kl, i.to, getcon(sz, fn), R); - fixarg(&curi->arg[0], Kl, curi, fn); - } else { - /* r0 = (i.arg[0] + 15) & -16 */ - r0 = newtmp("isel", Kl, fn); - r1 = newtmp("isel", Kl, fn); - emit(Osalloc, Kl, i.to, r0, R); - emit(Oand, Kl, r0, r1, getcon(-16, fn)); - emit(Oadd, Kl, r1, i.arg[0], getcon(15, fn)); - if (fn->tmp[i.arg[0].val].slot != -1) - err("unlikely argument %%%s in %s", - fn->tmp[i.arg[0].val].name, optab[i.op].name); - } - break; - default: - if (iscmp(i.op, &ck, &cc)) { - selcmp(i, ck, cc, fn); - break; - } + if (INRANGE(i.op, Oalloc, Oalloc1)) { + i0 = curi - 1; + salloc(i.to, i.arg[0], fn); + fixarg(&i0->arg[0], Kl, i0, fn); + return; + } + if (iscmp(i.op, &ck, &cc)) { + selcmp(i, ck, cc, fn); + return; + } + if (i.op != Onop) { emiti(i); i0 = curi; /* fixarg() can change curi */ fixarg(&i0->arg[0], argcls(&i, 0), i0, fn); diff --git a/util.c b/util.c @@ -429,6 +429,36 @@ blit0(Ref rdst, Ref rsrc, uint sz, Fn *fn) } void +salloc(Ref rt, Ref rs, Fn *fn) +{ + Ref r0, r1; + int64_t sz; + + /* we need to make sure + * the stack remains aligned + * (rsp = 0) mod 16 + */ + fn->dynalloc = 1; + if (rtype(rs) == RCon) { + sz = fn->con[rs.val].bits.i; + if (sz < 0 || sz >= INT_MAX-15) + err("invalid alloc size %"PRId64, sz); + sz = (sz + 15) & -16; + emit(Osalloc, Kl, rt, getcon(sz, fn), R); + } else { + /* r0 = (r + 15) & -16 */ + r0 = newtmp("isel", Kl, fn); + r1 = newtmp("isel", Kl, fn); + emit(Osalloc, Kl, rt, r0, R); + emit(Oand, Kl, r0, r1, getcon(-16, fn)); + emit(Oadd, Kl, r1, rs, getcon(15, fn)); + if (fn->tmp[rs.val].slot != -1) + err("unlikely alloc argument %%%s for %%%s", + fn->tmp[rs.val].name, fn->tmp[rt.val].name); + } +} + +void bsinit(BSet *bs, uint n) { n = (n + NBit-1) / NBit;