aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2023-06-13 10:55:35 +0200
committerlemon <lsof@mailbox.org>2023-06-13 11:04:31 +0200
commit3e5c11563f8cb7c843c71a0f761e5b644f39db46 (patch)
tree1192d4ba899b031ca99cf5a79fc814d98bed1e76
parent427d2298cd6f6e4da9a31c723a79a36267aebbc1 (diff)
lower allocas in isel() instead of emit() and misc fixes
-rw-r--r--abi0.c10
-rw-r--r--amd64/emit.c55
-rw-r--r--amd64/isel.c103
-rw-r--r--amd64/sysv.c8
-rw-r--r--common.h4
-rw-r--r--ir.c12
-rw-r--r--ir.h17
-rw-r--r--irdump.c6
-rw-r--r--mem.c24
-rw-r--r--parse.c42
-rw-r--r--regalloc.c37
11 files changed, 146 insertions, 172 deletions
diff --git a/abi0.c b/abi0.c
index 907ac12..314017b 100644
--- a/abi0.c
+++ b/abi0.c
@@ -71,10 +71,10 @@ copyparam(struct abiarg abi)
case KF4: ld = Oloadf4; break;
case KF8: ld = Oloadf8; break;
}
- vpush(&addrtab, ((struct addr) {.base = mkref(RREG, mctarg->fpr), .disp = abi.stk}));
+ vpush(&addrtab, ((struct addr) {.base = mkref(RREG, mctarg->bpr), .disp = -abi.stk}));
return mkinstr(ld, abi.ty.cls, mkref(RMORE, addrtab.n - 1));
} else { /* aggregate in stack */
- vpush(&addrtab, ((struct addr) {.base = mkref(RREG, mctarg->fpr), .disp = abi.stk}));
+ vpush(&addrtab, ((struct addr) {.base = mkref(RREG, mctarg->bpr), .disp = -abi.stk}));
return mkinstr(Ocopy, KPTR, mkref(RMORE, addrtab.n - 1));
}
}
@@ -361,7 +361,7 @@ abi0(struct function *fn)
union irtype typ = mkirtype(fn->retty);
insertinstr(blk, blk->ins.n, mkarginstr(typ, sret));
insertinstr(blk, blk->ins.n, mkarginstr(typ, blk->jmp.arg[0]));
- insertinstr(blk, blk->ins.n, mkintrin(fn, INstructcopy, 0, 2));
+ insertinstr(blk, blk->ins.n, mkintrin(INstructcopy, 0, 2));
} else assert(blk->jmp.arg[0].bits == mkref(RTMP, rvovar).bits);
if (fn->abiret[0].ty.cls) blk->jmp.arg[0] = rvovar == -1 ? sret : mkref(RTMP, rvovar);
else memset(blk->jmp.arg, 0, sizeof blk->jmp.arg);
@@ -383,8 +383,8 @@ abi0(struct function *fn)
} while ((blk = blk->lnext) != fn->entry);
if (ccopt.dbg.a) {
- efmt("after abi0:\n");
- irdump(fn, fn->name);
+ efmt("<< After abi0 >>\n");
+ irdump(fn);
}
}
diff --git a/amd64/emit.c b/amd64/emit.c
index d7847f5..6be080e 100644
--- a/amd64/emit.c
+++ b/amd64/emit.c
@@ -478,20 +478,14 @@ gencopy(uchar **pcode, enum irclass cls, struct oper dst, union ref val)
}
static void
-emitinstr(uchar **pcode, uint *stktop, struct function *fn, struct block *blk, int ii, struct instr *ins)
+emitinstr(uchar **pcode, struct function *fn, struct block *blk, int ii, struct instr *ins)
{
struct oper dst, src;
uchar ksiz = cls2siz[ins->cls];
void (*X)(uchar **, uint, struct oper, struct oper) = NULL;
void (*X1)(uchar **, uint, struct oper) = NULL;
- if (oisalloca(ins->op)) {
- uint alignlog2 = ins->op - Oalloca1;
- uint siz = ins->l.i << alignlog2;
- *stktop += siz;
- *stktop = alignup(*stktop, 1 << alignlog2);
- ioper[ins - instrtab] = mkoper(OMEM, .base = RBP, .index = NOINDEX, .disp = -*stktop);
- } else switch (ins->op) {
+ switch (ins->op) {
default: assert(!"nyi ins");
case Onop: break;
case Ostore1: case Ostore2: case Ostore4: case Ostore8:
@@ -581,25 +575,6 @@ calleerestore(uchar **pcode, struct function *fn)
if (bstest(fn->regusage, RBX)) Xpop(pcode, RBX);
}
-static bool /* stack frame size <= 128? */
-smallstack(struct function *fn)
-{
- uint stktop = 0;
- struct block *blk = fn->entry;
- do {
- for (int i = 0; i < blk->ins.n; ++i) {
- struct instr *ins = &instrtab[blk->ins.p[i]];
- if (oisalloca(ins->op)) {
- uint align = 1 << (ins->op - Oalloca1);
- uint siz = ins->l.i * align;
- stktop = alignup(stktop + siz, align);
- if (alignup(stktop, 16) > 128) return 0;
- }
- }
- } while ((blk = blk->lnext) != fn->entry);
- return 1;
-}
-
/* align code using NOPs */
static void
aligncode(uchar **pcode, int align)
@@ -625,9 +600,6 @@ static void
emitbin(struct function *fn)
{
struct block *blk;
- uchar *rspdisp;
- uint stktop = 0;
- bool stack8 = smallstack(fn);
uchar **pcode = &objout.code;
aligncode(pcode, 16);
@@ -637,15 +609,17 @@ emitbin(struct function *fn)
DS("\x55\x48\x89\xE5");
calleesave(pcode, fn);
/* sub rsp, <stack size> */
- if (stack8)
- DS("\x48\x83\xEC"), rspdisp = *pcode, DS("\xAA");
+ if (fn->stksiz < 128)
+ DS("\x48\x83\xEC"), B(fn->stksiz);
+ else if (fn->stksiz == 128)
+ DS("\x48\x83\xC4\x80"); /* add rsp, -128 */
else
- DS("\x48\x81\xEC"), rspdisp = *pcode, DS("\xAA\xAA\xAA\xAA");
+ DS("\x48\x81\xEC"), I32(fn->stksiz);
blk = fn->entry;
do {
for (int i = 0; i < blk->ins.n; ++i) {
- emitinstr(pcode, &stktop, fn, blk, i, &instrtab[blk->ins.p[i]]);
+ emitinstr(pcode, fn, blk, i, &instrtab[blk->ins.p[i]]);
}
if (blk->jmp.t == Jret) {
/* epilogue */
@@ -653,19 +627,6 @@ emitbin(struct function *fn)
DS("\xC9\xC3"); /* leave; ret */
}
} while ((blk = blk->lnext) != fn->entry);
-
- stktop = alignup(stktop, 16);
- if (stack8) {
- assert(stktop <= 128);
- if (stktop < 128) *rspdisp = stktop;
- else {
- /* cannot encode `sub rsp, 128` with 8bit imm, turn into `add rsp, -128` */
- rspdisp[-1] = 0xC4;
- *rspdisp = -128;
- }
- } else {
- wr32le(rspdisp, alignup(stktop, 16));
- }
}
void
diff --git a/amd64/isel.c b/amd64/isel.c
index 858dfbc..3734143 100644
--- a/amd64/isel.c
+++ b/amd64/isel.c
@@ -1,7 +1,5 @@
#include "all.h"
-static bool fuseaddr(struct function *fn, union ref *r);
-
static void
fixarg(struct function *fn, union ref *r, struct instr *ins, struct block *blk, int *curi)
{
@@ -16,7 +14,7 @@ fixarg(struct function *fn, union ref *r, struct instr *ins, struct block *blk,
} else if (in_range(op, Oadd, Osub) && con->i8 == 2147483648) {
/* add X, INT32MAX+1 -> sub X, INT32MIN */
ins->op = Oadd + (op == Oadd);
- *r = mkintcon(fn, KI4, -2147483648);
+ *r = mkintcon(KI4, -2147483648);
} else if (in_range(op, Ocopy, Omove) && kisflt(con->cls)
&& (con->cls == KF4 ? con->fs == 0.0f : con->fd == 0.0))
{
@@ -28,7 +26,7 @@ fixarg(struct function *fn, union ref *r, struct instr *ins, struct block *blk,
uint siz = cls2siz[con->cls];
if (con->cls == KI4 || con->cls == KF4) wr32le(data, con->i4);
else wr64le(data, con->i8);
- *r = mkdatref(fn, siz, /*align*/siz, data, siz, /*deref*/1);
+ *r = mkdatref(siz, /*align*/siz, data, siz, /*deref*/1);
} else if (in_range(op, Odiv, Ourem) && kisint(ins->cls))
goto DivImm;
} else if (r->t == RICON && in_range(op, Odiv, Ourem) && kisint(ins->cls)) {
@@ -46,7 +44,7 @@ fixarg(struct function *fn, union ref *r, struct instr *ins, struct block *blk,
#define rswap(a,b) do { union ref _t = (a); (a) = (b); (b) = _t; } while (0)
static bool
-acon(struct function *fn, struct addr *addr, union ref r)
+acon(struct addr *addr, union ref r)
{
vlong a = addr->disp;
if (r.t == RICON) {
@@ -63,7 +61,7 @@ acon(struct function *fn, struct addr *addr, union ref r)
}
static bool
-ascale(struct function *fn, struct addr *addr, union ref a, union ref b)
+ascale(struct addr *addr, union ref a, union ref b)
{
if (b.t != RICON) return 0;
if (addr->index.t) return 0;
@@ -75,33 +73,41 @@ ascale(struct function *fn, struct addr *addr, union ref a, union ref b)
}
static bool
-aadd(struct function *fn, struct addr *addr, union ref r, bool rec)
+aadd(struct addr *addr, union ref r, bool rec)
{
- struct instr *ins = &instrtab[r.i];
- if (r.t == RTMP && ins->op == Oadd) {
- if (!aadd(fn, addr, ins->l, rec)) return 0;
- if (!aadd(fn, addr, ins->r, rec)) return 0;
- ins->skip = 1;
- } else if (r.t == RTMP && ins->op == Oshl) {
- if (!ascale(fn, addr, ins->l, ins->r)) return 0;
- ins->skip = 1;
- } else if (!rec && r.t == RTMP && ins->op == Ocopy && ins->l.t == RMORE) {
- struct addr save = *addr, *addr2 = &addrtab.p[ins->l.i];
- if ((!addr2->base.t || aadd(fn, addr, addr2->base, 1))
- && aadd(fn, addr, mkintcon(fn, KI4, addr2->disp), 1)
- && (!addr2->index.t || ascale(fn, addr, addr2->index, mkref(RICON, addr2->shift))))
- {
+ if (r.t == RTMP) {
+ struct instr *ins = &instrtab[r.i];
+
+ if (ins->op == Oadd) {
+ if (!aadd(addr, ins->l, rec)) return 0;
+ if (!aadd(addr, ins->r, rec)) return 0;
ins->skip = 1;
- } else {
- *addr = save;
- goto Ref;
- }
- } else if (iscon(r)) return acon(fn, addr, r);
- else Ref: {
+ } else if (ins->op == Oshl) {
+ if (!ascale(addr, ins->l, ins->r)) return 0;
+ ins->skip = 1;
+ } else if (!rec && ins->op == Ocopy && ins->l.t == RMORE) {
+ struct addr save = *addr, *addr2 = &addrtab.p[ins->l.i];
+ if ((!addr2->base.t || aadd(addr, addr2->base, 1))
+ && aadd(addr, mkintcon(KI4, addr2->disp), 1)
+ && (!addr2->index.t || ascale(addr, addr2->index, mkref(RICON, addr2->shift))))
+ {
+ ins->skip = 1;
+ } else {
+ *addr = save;
+ goto Ref;
+ }
+ } else goto Ref;
+ } else if (iscon(r)) {
+ return acon(addr, r);
+ } else if (r.t == RREG) {
+ /* temporaries are single assignment, but register aren't, so they can't be *
+ * safely hoisted into an address value, unless they have global lifetime */
+ if (!bstest(mctarg->rglob, r.i)) return 0;
+ Ref:
if (!addr->base.t) addr->base = r;
else if (!addr->index.t) addr->index = r;
else return 0;
- }
+ } else return 0;
return 1;
}
@@ -109,21 +115,12 @@ static bool
fuseaddr(struct function *fn, union ref *r)
{
struct addr addr = { 0 };
- struct instr *ins = &instrtab[r->i];
+
if (r->t == RMORE) return 1;
- else if (r->t != RTMP) return 0;
- else if (ins->op == Oadd) {
- if (ins->l.t == RTMP && instrtab[ins->l.i].op == Ocopy && instrtab[ins->l.i].l.t == RMORE)
- /* put ADDR in rhs because this code is dumb and it might be better */
- rswap(ins->l, ins->r);
- if (!aadd(fn, &addr, ins->l, 0)) return 0;
- if (!aadd(fn, &addr, ins->r, 0)) return 0;
- ins->skip = 1;
- } else if (ins->op == Oshl) {
- if (!ascale(fn, &addr, ins->l, ins->r)) return 0;
- ins->skip = 1;
- }
- else return 0;
+ if (r->t != RTMP) return 0;
+
+ if (!aadd(&addr, *r, 0)) return 0;
+
vpush(&addrtab, addr);
*r = mkref(RMORE, addrtab.n-1);
return 1;
@@ -141,6 +138,7 @@ addarg4addrp(union ref r)
static void
sel(struct function *fn, struct instr *ins, struct block *blk, int *curi)
{
+ uint siz, alignlog2;
struct instr temp = {0};
enum op op = ins->op;
@@ -148,6 +146,13 @@ sel(struct function *fn, struct instr *ins, struct block *blk, int *curi)
default: assert(0);
case Onop: break;
case Oalloca1: case Oalloca2: case Oalloca4: case Oalloca8: case Oalloca16:
+ alignlog2 = ins->op - Oalloca1;
+ siz = ins->l.i << alignlog2;
+ fn->stksiz += siz;
+ fn->stksiz = alignup(fn->stksiz, 1 << alignlog2);
+ if (fn->stksiz > 1<<24) error(NULL, "'%s' stack frame too big", fn->name);
+ *ins = mkinstr(Oadd, KPTR, mkref(RREG, mctarg->bpr), mkref(RICON, -fn->stksiz));
+ break;
case Ocall: case Ointrin:
break;
case Oshl: case Osar: case Oslr:
@@ -206,8 +211,7 @@ sel(struct function *fn, struct instr *ins, struct block *blk, int *curi)
ins->op = Oxinc;
ins->r = NOREF;
goto ALU;
- }
- if (kisint(ins->cls) && (addarg4addrp(ins->l) || addarg4addrp(ins->r))) {
+ } else if (kisint(ins->cls) && (addarg4addrp(ins->l) || addarg4addrp(ins->r))) {
temp.op = Ocopy;
temp.cls = ins->cls;
temp.l = mkref(RTMP, ins - instrtab);
@@ -258,8 +262,9 @@ amd64_isel(struct function *fn)
{
struct block *blk = fn->entry;
+ fn->stksiz = 0;
+
do {
- struct instr *ins;
for (int i = 0; i < blk->phi.n; ++i) {
struct phi *phi = &phitab.p[instrtab[blk->phi.p[i]].l.i];
for (int i = 0; i < phi->n; ++i) {
@@ -267,14 +272,14 @@ amd64_isel(struct function *fn)
}
}
for (int i = 0; i < blk->ins.n; ++i) {
- ins = &instrtab[blk->ins.p[i]];
- sel(fn, ins, blk, &i);
+ sel(fn, &instrtab[blk->ins.p[i]], blk, &i);
}
} while ((blk = blk->lnext) != fn->entry);
+ fn->stksiz = alignup(fn->stksiz, 16);
if (ccopt.dbg.i) {
- efmt("after isel:\n");
- irdump(fn, fn->name);
+ efmt("<< After isel >>\n");
+ irdump(fn);
}
}
diff --git a/amd64/sysv.c b/amd64/sysv.c
index 7d391dc..1c84909 100644
--- a/amd64/sysv.c
+++ b/amd64/sysv.c
@@ -68,7 +68,7 @@ abiarg(short r[2], uchar cls[2], int *ni, int *nf, int *ns, union irtype typ)
} else if (*ni < NINT) {
r[0] = intregs[(*ni)++];
} else {
- r[0] = -*ns - 8;
+ r[0] = -*ns - 16;
*ns += 8;
return 0; /* MEMORY */
}
@@ -77,7 +77,7 @@ abiarg(short r[2], uchar cls[2], int *ni, int *nf, int *ns, union irtype typ)
cls[0] = cls[1] = 0;
ret = classify(cls, &typedata[typ.dat], 0);
if (!ret) { /*MEMORY*/
- r[0] = -*ns - 8;
+ r[0] = -*ns - 16;
*ns = alignup(*ns + typedata[typ.dat].siz, 8);
return 0;
}
@@ -91,7 +91,7 @@ abiarg(short r[2], uchar cls[2], int *ni, int *nf, int *ns, union irtype typ)
r[i] = intregs[(*ni)++];
else { /* MEMORY */
*ni = ni_save, *nf = nf_save;
- r[0] = -*ns - 8;
+ r[0] = -*ns - 16;
*ns = alignup(*ns + typedata[typ.dat].siz, 8);
r[1] = -1;
return cls[0] = cls[1] = 0;
@@ -139,7 +139,7 @@ const char amd64_rnames[][6] = {
const struct mctarg t_amd64_sysv = {
.gpr0 = RAX, .ngpr = R15 - RAX + 1,
- .fpr = RBP,
+ .bpr = RBP,
.fpr0 = XMM0, .nfpr = XMM15 - XMM0 + 1,
.rcallee = {{1<<RBX | 1<<R12 | 1<<R13 | 1<<R14 | 1<<R15}},
.rglob = {{1<<RSP | 1<<RBP}},
diff --git a/common.h b/common.h
index 45d50d5..3628c89 100644
--- a/common.h
+++ b/common.h
@@ -314,6 +314,10 @@ struct arena {
#define vec_of(T) struct { T *p; int _cap; uint n; }
+extern void *xcalloc(size_t n, const char *);
+extern void *xrealloc(void *, size_t n, const char *);
+#define xcalloc(n) xcalloc(n, __func__)
+#define xrealloc(p,n) xrealloc(p, n, __func__)
struct arena *newarena(uint chunksiz);
void *alloc(struct arena **, uint siz, uint align);
static inline void *
diff --git a/ir.c b/ir.c
index 28391ad..d887fab 100644
--- a/ir.c
+++ b/ir.c
@@ -5,7 +5,7 @@ uchar cls2siz[KF8+1];
const uchar siz2intcls[] = { [1] = KI4, [2] = KI4, [4] = KI4, [8] = KI8 };
struct instr instrtab[MAXINSTR];
-static int ninstr;
+int ninstr;
static int instrfreelist;
struct calltab calltab;
struct phitab phitab;
@@ -130,7 +130,7 @@ mkirtype(union type t)
}
union ref
-mkintcon(struct function *fn, enum irclass k, vlong i)
+mkintcon(enum irclass k, vlong i)
{
if (i < 1l << 28 && i >= -(1l << 28)) {
return mkref(RICON, i);
@@ -144,7 +144,7 @@ mkintcon(struct function *fn, enum irclass k, vlong i)
}
union ref
-mkfltcon(struct function *fn, enum irclass k, double f)
+mkfltcon(enum irclass k, double f)
{
struct xcon con = { .cls = k };
if (k == KF4) con.fs = f;
@@ -153,14 +153,14 @@ mkfltcon(struct function *fn, enum irclass k, double f)
}
union ref
-mksymref(struct function *fn, const char *s)
+mksymref(const char *s)
{
struct xcon con = { .issym = 1, .sym = s };
return mkref(RXCON, addcon(&con));
}
union ref
-mkdatref(struct function *fn, uint siz, uint align, const void *bytes, uint n, bool deref)
+mkdatref(uint siz, uint align, const void *bytes, uint n, bool deref)
{
struct irdat dat = { align, 0, siz };
if (siz <= 8) memcpy(dat.sdat, bytes, n < siz ? n : siz);
@@ -183,7 +183,7 @@ mkalloca(uint siz, uint align)
}
union ref
-mkcallarg(struct function *fn, union irtype ret, uint narg, int vararg)
+mkcallarg(union irtype ret, uint narg, int vararg)
{
struct call call = { .ret=ret, .narg=narg, .vararg=vararg };
assert((long) vararg <= narg);
diff --git a/ir.h b/ir.h
index 3561397..e1f9fba 100644
--- a/ir.h
+++ b/ir.h
@@ -134,6 +134,7 @@ struct function {
union type fnty, retty;
struct abiarg *abiarg, abiret[2];
uint nblk;
+ int stksiz;
ushort nabiarg, nabiret;
bool globl;
struct bitset regusage[1];
@@ -142,7 +143,7 @@ struct function {
struct mctarg {
short gpr0, /* first gpr */
ngpr, /* gpr count */
- fpr, /* frame pointer reg */
+ bpr, /* frame/base pointer reg */
fpr0, /* first fpr */
nfpr; /* fpr count */
struct bitset rcallee[1], /* callee-saved */
@@ -194,14 +195,14 @@ void irinit(struct function *);
void irfini(struct function *);
#define cls2type(k) ((union irtype){.cls=(k)})
union irtype mkirtype(union type);
-union ref mkintcon(struct function *, enum irclass, vlong);
-union ref mkfltcon(struct function *, enum irclass, double);
-union ref mksymref(struct function *, const char *);
-union ref mkdatref(struct function *, uint siz, uint align, const void *, uint n, bool deref);
+union ref mkintcon(enum irclass, vlong);
+union ref mkfltcon(enum irclass, double);
+union ref mksymref(const char *);
+union ref mkdatref(uint siz, uint align, const void *, uint n, bool deref);
struct instr mkalloca(uint siz, uint align);
void conputdat(struct irdat *, uint off, enum typetag t, const void *dat);
-union ref mkcallarg(struct function *, union irtype ret, uint narg, int vararg);
-#define mkintrin(F, B, C, N) mkinstr(Ointrin, C, {.t=RICON,B}, mkcallarg(F,(union irtype){{0}},N,-1))
+union ref mkcallarg(union irtype ret, uint narg, int vararg);
+#define mkintrin(B, C, N) mkinstr(Ointrin, C, {.t=RICON,B}, mkcallarg((union irtype){{0}},N,-1))
union ref addinstr(struct function *, struct instr);
union ref insertinstr(struct block *, int idx, struct instr);
void delinstr(struct block *, int idx);
@@ -215,7 +216,7 @@ void putcondbranch(struct function *, union ref arg, struct block *t, struct blo
void putreturn(struct function *, union ref r0, union ref r1);
void replref(struct function *, struct block *, int, union ref from, union ref to);
-void irdump(struct function *, const char *fname);
+void irdump(struct function *);
void abi0(struct function *);
void regalloc(struct function *);
diff --git a/irdump.c b/irdump.c
index 5ee817a..c41a196 100644
--- a/irdump.c
+++ b/irdump.c
@@ -180,7 +180,7 @@ dumpinst(const struct instr *ins)
if (ins->cls)
efmt("%s ", clsname[ins->cls]);
efmt("%s = ", mctarg->rnames[ins->reg - 1]);
- } else if (ins->cls && !ins->skip) {
+ } else if (ins->cls) {
efmt("%s %%%d", clsname[ins->cls], ins - instrtab);
efmt(" = ");
}
@@ -222,14 +222,14 @@ dumpblk(struct function *fn, struct block *blk)
}
void
-irdump(struct function *fn, const char *fname)
+irdump(struct function *fn)
{
struct block *blk;
/* print datas that have never been printed before */
while (nextdat < dattab.n) pridat(&dattab.p[nextdat++]);
- efmt("function %s : %ty\n", fname, fn->fnty);
+ efmt("function %s : %ty\n", fn->name, fn->fnty);
if (fn->abiarg || fn->nabiret) {
efmt("abi: (");
for (int i = 0; i < fn->nabiarg; ++i) {
diff --git a/mem.c b/mem.c
index 43029ac..4817b7d 100644
--- a/mem.c
+++ b/mem.c
@@ -10,16 +10,16 @@
abort(); \
} while (0)
-static void *
-xcalloc(size_t n, const char *f)
+void *
+(xcalloc)(size_t n, const char *f)
{
void *p = calloc(n, 1);
if (!p) ALLOCERR(f);
return p;
}
-static void *
-xrealloc(void *p, size_t n, const char *f)
+void *
+(xrealloc)(void *p, size_t n, const char *f)
{
p = p ? realloc(p, n) : malloc(n);
if (!p) ALLOCERR(f);
@@ -36,7 +36,7 @@ vinit_(void **p, int *pcap, void *inlbuf, int cap, uint siz)
if (inlbuf) {
*p = inlbuf;
} else if (cap) {
- *p = xrealloc(0, cap*siz, "vinit");
+ *p = xrealloc(0, cap*siz);
*pcap = -cap;
}
}
@@ -46,10 +46,10 @@ vpush_(void **p, int *pcap, uint *pn, uint siz)
{
if (*pn == *pcap) { /* empty or inline buffer */
int cap = *pcap ? *pcap * 2 : 8;
- *p = xrealloc(NULL, cap * siz, "vpush");
+ *p = xrealloc(NULL, cap * siz);
*pcap = -cap;
} else if (*pn == -*pcap) { /* dyn buf */
- *p = xrealloc(*p, -(*pcap *= 2) * siz, "vpush");
+ *p = xrealloc(*p, -(*pcap *= 2) * siz);
}
assert(-(volatile int)*pcap > *pn && "overflow");
}
@@ -78,7 +78,7 @@ vresize_(void **p, int *pcap, uint *pn, uint siz, uint N)
struct arena *
newarena(uint chunksiz)
{
- struct arena *ar = xcalloc(offsetof(struct arena, mem) + chunksiz, "newarena");
+ struct arena *ar = xcalloc(offsetof(struct arena, mem) + chunksiz);
assert(chunksiz < 1u<<31 && "toobig");
ar->cap = chunksiz;
ar->dyn = 1;
@@ -134,7 +134,7 @@ imap_init_(struct imapbase *m, void **v, uint vsiz, uint N)
sizbs = BSSIZE(N)*sizeof(struct bitset);
assert(ispo2(N));
- m->k = xcalloc(sizk + sizv + sizbs, "imap_init");
+ m->k = xcalloc(sizk + sizv + sizbs);
*v = (char *)m->k + sizk;
m->bs = (struct bitset *)((char *)*v + sizv);
m->N = N;
@@ -164,7 +164,7 @@ imap_rehash(struct imapbase *m, void **v, uint vsiz)
sizbs = BSSIZE(N2)*sizeof(struct bitset);
assert(N2);
- newk = xcalloc(sizk + sizv + sizbs, "imap_rehash");
+ newk = xcalloc(sizk + sizv + sizbs);
memset(newk, 0, sizk + sizv + sizbs);
newv = (char *)newk + sizk;
newbs = (struct bitset *)((char *)newv + sizv);
@@ -216,7 +216,7 @@ pmap_init_(struct pmapbase *m, void **v, uint vsiz, uint N)
sizv = N*vsiz;
assert(ispo2(N));
- m->k = xcalloc(sizk + sizv, "pmap_init");
+ m->k = xcalloc(sizk + sizv);
*v = (char *)m->k + sizk;
m->N = N;
}
@@ -244,7 +244,7 @@ pmap_rehash(struct pmapbase *m, void **v, uint vsiz)
sizv = N2*vsiz;
assert(N2);
- newk = xcalloc(sizk + sizv, "pmap_rehash");
+ newk = xcalloc(sizk + sizv);
newv = (char *)newk + sizk;
for (i = 0; i < m->N; ++i) {
if (!m->k[i])
diff --git a/parse.c b/parse.c
index b488b36..022ef8a 100644
--- a/parse.c
+++ b/parse.c
@@ -991,7 +991,7 @@ structcopy(struct function *fn, union type ty, union ref dst, union ref src)
union irtype typ = mkirtype(ty);
addinstr(fn, mkarginstr(typ, dst));
addinstr(fn, mkarginstr(typ, src));
- addinstr(fn, mkintrin(fn, INstructcopy, 0, 2));
+ addinstr(fn, mkintrin(INstructcopy, 0, 2));
}
static union ref
@@ -1017,7 +1017,7 @@ expraddr(struct function *fn, const struct expr *ex)
case SCAUTO: case SCREGISTER:
return mkref(RTMP, decl->id);
case SCEXTERN: case SCNONE:
- return mksymref(fn, decl->name);
+ return mksymref(decl->name);
case SCSTATIC:
assert(!"nyi");
break;
@@ -1026,7 +1026,7 @@ expraddr(struct function *fn, const struct expr *ex)
}
break;
case ESTRLIT:
- return mkdatref(fn, ex->s.n+1, /*align*/ 1, ex->s.p, ex->s.n, /*deref*/0);
+ return mkdatref(ex->s.n+1, /*align*/ 1, ex->s.p, ex->s.n, /*deref*/0);
case EDEREF:
return exprvalue(fn, ex->sub);
case EGETF:
@@ -1036,7 +1036,7 @@ expraddr(struct function *fn, const struct expr *ex)
ins.cls = KPTR;
ins.op = Oadd;
ins.l = r;
- ins.r = mkintcon(fn, KI4, ex->fld.off);
+ ins.r = mkintcon(KI4, ex->fld.off);
return addinstr(fn, ins);
case ESET:
assert(isagg(ex->ty));
@@ -1104,10 +1104,10 @@ cvt(struct function *fn, enum typetag to, enum typetag from, union ref ref)
if (kisflt(kto) || kisflt(kfrom)) {
if (ref.t == RICON) {
assert(kisflt(kto) && kisint(kfrom));
- return mkfltcon(fn, kto, kto == KF4 ? (float)ref.i : (double)ref.i);
+ return mkfltcon(kto, kto == KF4 ? (float)ref.i : (double)ref.i);
}
if (kisflt(kto) && kfrom == KI4) ins.op = issignedt(from) ? Ocvts4f : Ocvtu4f;
- else if (to == TYBOOL && kisflt(kfrom)) ins.op = Oneq, ins.r = mkfltcon(fn, kfrom, 0.0);
+ else if (to == TYBOOL && kisflt(kfrom)) ins.op = Oneq, ins.r = mkfltcon(kfrom, 0.0);
else if (kisflt(kto) && kfrom == KI8) ins.op = issignedt(from) ? Ocvts8f : Ocvtu8f;
else if (kto == KF8 && kfrom == KF4) ins.op = Ocvtf4f8;
else if (kto == KF4 && kfrom == KF8) ins.op = Ocvtf8f4;
@@ -1125,7 +1125,7 @@ cvt(struct function *fn, enum typetag to, enum typetag from, union ref ref)
}
else if (kfrom == KI4 && issignedt(from)) ins.op = Oexts4;
else if (kfrom == KI4) ins.op = Oextu4;
- else if (ref.t == RXCON && kfrom == KI8) return mkintcon(fn, KI4, (int)(conht[ref.i].i8));
+ else if (ref.t == RXCON && kfrom == KI8) return mkintcon(KI4, (int)(conht[ref.i].i8));
else ins.op = Ocopy;
}
return addinstr(fn, ins);
@@ -1162,13 +1162,13 @@ genptroff(struct function *fn, enum op op, uint siz, union ref ptr,
idx = cvt(fn, targ_sizetype, tt, idx);
if (siz == 1) off = idx;
else if (idx.t == RICON)
- off = mkintcon(fn, cls, idx.i * siz);
+ off = mkintcon(cls, idx.i * siz);
else if (ispo2(siz))
off = addinstr(fn,
- mkinstr(Oshl, cls, .l = idx, .r = mkintcon(fn, cls, ilog2(siz))));
+ mkinstr(Oshl, cls, .l = idx, .r = mkintcon(cls, ilog2(siz))));
else
off = addinstr(fn,
- mkinstr(Omul, cls, .l = idx, .r = mkintcon(fn, cls, siz)));
+ mkinstr(Omul, cls, .l = idx, .r = mkintcon(cls, siz)));
assert(in_range(op, Oadd, Osub));
return addinstr(fn, mkinstr(op, KPTR, .l = ptr, .r = off));
}
@@ -1181,9 +1181,9 @@ genptrdiff(struct function *fn, uint siz, union ref a, union ref b)
a = addinstr(fn, mkinstr(Osub, cls, .l = a, .r = b));
if (siz == 1) return a;
else if ((siz & (siz-1)) == 0) /* is power of 2 */
- return addinstr(fn, mkinstr(Osar, cls, a, mkintcon(fn, cls, ilog2(siz))));
+ return addinstr(fn, mkinstr(Osar, cls, a, mkintcon(cls, ilog2(siz))));
else
- return addinstr(fn, mkinstr(Odiv, cls, a, mkintcon(fn, cls, siz)));
+ return addinstr(fn, mkinstr(Odiv, cls, a, mkintcon(cls, siz)));
}
/* used to emit the jumps in an in if (), while (), etc condition */
@@ -1273,7 +1273,7 @@ condexprrec(struct function *fn, const struct expr *ex, struct condphis *phis,
if (boolcon == -2)
r = cvt(fn, TYBOOL, ex->ty.t, r);
if (boolcon >= 0)
- vpush(&phis->ref, mkintcon(fn, KI4, boolcon));
+ vpush(&phis->ref, mkintcon(KI4, boolcon));
else
vpush(&phis->ref, r);
if (zero) {
@@ -1311,7 +1311,7 @@ compilecall(struct function *fn, const struct expr *ex)
for (int i = 0; i < insns.n; ++i)
addinstr(fn, insns.p[i]);
vfree(&insns);
- ins.r = mkcallarg(fn, mkirtype(ex->ty), ex->narg, td->variadic ? td->nmemb : td->kandr ? 0 : -1);
+ ins.r = mkcallarg(mkirtype(ex->ty), ex->narg, td->variadic ? td->nmemb : td->kandr ? 0 : -1);
return addinstr(fn, ins);
}
@@ -1355,8 +1355,8 @@ compileexpr(struct function *fn, const struct expr *ex, bool discard)
case ENUMLIT:
if (discard) return NOREF;
if (isflt(ex->ty))
- return mkfltcon(fn, cls, ex->f);
- return mkintcon(fn, cls, ex->i);
+ return mkfltcon(cls, ex->f);
+ return mkintcon(cls, ex->i);
case ESYM:
if (discard && !(ex->qual & QVOLATILE)) return NOREF;
return genload(fn, ex->ty, expraddr(fn, ex));
@@ -1391,7 +1391,7 @@ compileexpr(struct function *fn, const struct expr *ex, bool discard)
ins.l = compileexpr(fn, sub, discard);
if (discard) return NOREF;
ins.l = cvt(fn, ex->ty.t, sub->ty.t, ins.l);
- ins.r = mkintcon(fn, cls, 0);
+ ins.r = mkintcon(cls, 0);
ins.cls = cls;
return addinstr(fn, ins);
case EDEREF:
@@ -1455,7 +1455,7 @@ compileexpr(struct function *fn, const struct expr *ex, bool discard)
r = expraddr(fn, sub);
ins.l = genload(fn, sub->ty, r);
if (ex->ty.t == TYPTR)
- ins.r = mkintcon(fn, KI4, typesize(typechild(ex->ty)));
+ ins.r = mkintcon(KI4, typesize(typechild(ex->ty)));
else
ins.r = mkref(RICON, 1);
genstore(fn, sub->ty, r, addinstr(fn, ins));
@@ -1467,7 +1467,7 @@ compileexpr(struct function *fn, const struct expr *ex, bool discard)
r = expraddr(fn, sub);
ins.l = genload(fn, sub->ty, r);
if (ex->ty.t == TYPTR)
- ins.r = mkintcon(fn, KI4, typesize(typechild(ex->ty)));
+ ins.r = mkintcon(KI4, typesize(typechild(ex->ty)));
else
ins.r = mkref(RICON, 1);
q = addinstr(fn, ins);
@@ -1505,8 +1505,8 @@ compileexpr(struct function *fn, const struct expr *ex, bool discard)
return addinstr(fn, ins);
case ESET:
assert(isscalar(ex->ty));
- r = expraddr(fn, &sub[0]);
q = cvt(fn, sub[0].ty.t, sub[1].ty.t, exprvalue(fn, &sub[1]));
+ r = expraddr(fn, &sub[0]);
genstore(fn, ex->ty, r, q);
if (discard) return NOREF;
return narrow(fn, cls, sub[0].ty.t, q);
@@ -2601,7 +2601,7 @@ parse(struct parser *pr)
irinit(&fn);
function(pr, &fn, st.pnames, st.pspans);
if (!nerror && ccopt.dbg.p)
- irdump(&fn, decl.name);
+ irdump(&fn);
irfini(&fn);
} else if (decl.name) {
putdecl(pr, &decl);
diff --git a/regalloc.c b/regalloc.c
index f001fee..bf7bac6 100644
--- a/regalloc.c
+++ b/regalloc.c
@@ -15,7 +15,7 @@ struct alloc { ushort t : 2, a : 14; };
struct rega {
union ref regs[MAXREGS]; /* map reg -> value holding reg */
- imap_of(struct alloc) allocs; /* map tmpidx -> allocation */
+ struct alloc *allocs; /* map tmpidx -> allocation */
int nfreegpr, nfreefpr;
};
@@ -27,14 +27,15 @@ def(struct rega *ra, struct instr *ins)
if (ins->op != Omove) {
var = ins - instrtab;
// efmt("def %%%d\n",var);
- if ((alloc = imap_get(&ra->allocs, var))) {
- if (alloc->t == AREG) {
- reg = alloc->a;
- // efmt("-- free %s for %%%d\n", mctarg->rnames[alloc->a], var);
- assert(ra->regs[reg].bits == mkref(RTMP, var).bits);
- } else assert(0);
- *alloc = afree();
- }
+ alloc = &ra->allocs[var];
+ if (alloc->t == ADEAD) {
+ return;
+ } else if (alloc->t == AREG) {
+ reg = alloc->a;
+ // efmt("-- free %s for %%%d\n", mctarg->rnames[alloc->a], var);
+ assert(ra->regs[reg].bits == mkref(RTMP, var).bits);
+ } else assert(0);
+ *alloc = afree();
} else {
reg = ins->l.i;
assert(ins->l.t == RREG);
@@ -52,7 +53,7 @@ take(struct rega *ra, int reg, union ref ref) {
// efmt("-- take %s for %d %d\n", mctarg->rnames[reg], ref.t, ref.i);
assert(!ra->regs[reg].t && "taken");
if (ref.t == RTMP)
- imap_set(&ra->allocs, ref.i, areg(reg));
+ ra->allocs[ref.i] = areg(reg);
ra->regs[reg] = ref;
bsset(globusage, reg);
if (isfpr(reg)) --ra->nfreefpr;
@@ -96,8 +97,8 @@ forcetake(struct rega *ra, int reg, union ref ref, struct block *blk, int curi)
}
assert(ra->regs[reg].t == RTMP);
var = ra->regs[reg].i;
- alloc = imap_get(&ra->allocs, var);
- assert(alloc && alloc->a == reg);
+ alloc = &ra->allocs[var];
+ assert(alloc->a == reg);
*alloc = afree();
/* try to move temp to another register */
if (isgpr(reg) ? ra->nfreegpr > 0 : ra->nfreefpr > 0) {
@@ -113,7 +114,7 @@ forcetake(struct rega *ra, int reg, union ref ref, struct block *blk, int curi)
instrtab[var].reg = rename+1;
ra->regs[rename] = mkref(RTMP, var);
bsset(globusage, rename);
- imap_set(&ra->allocs, var, areg(rename));
+ *alloc = areg(rename);
ra->regs[reg].bits = 0;
} else {
assert(!"spill");
@@ -163,11 +164,12 @@ use(struct rega *ra, struct block *blk, int curi, enum op op, int hint, union re
void
regalloc(struct function *fn)
{
+ extern int ninstr;
struct instr *ins;
struct block *last = fn->entry->lprev, *blk;
- struct rega ra = {0};
+ struct rega ra = {.allocs = xcalloc(ninstr * sizeof(struct alloc))};
ra.nfreegpr = mctarg->ngpr - popcnt(mctarg->rglob->u);
- ra.nfreefpr = mctarg->fpr;
+ ra.nfreefpr = mctarg->nfpr;
for (int i = 0; i < MAXREGS; ++i)
if (in_range(i, mctarg->fpr0, mctarg->fpr0 + mctarg->nfpr - 1))
bsset(floatregs, i);
@@ -243,10 +245,11 @@ regalloc(struct function *fn)
do vfree(&blk->phi); while ((blk = blk->lprev) != last);
if (ccopt.dbg.r) {
- efmt("after regalloc:\n");
- irdump(fn, fn->name);
+ efmt("<< After regalloc >>\n");
+ irdump(fn);
}
bscopy(fn->regusage, globusage, 1);
+ free(ra.allocs);
}
/* vim:set ts=3 sw=3 expandtab: */