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:
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;