diff options
| -rw-r--r-- | abi0.c | 10 | ||||
| -rw-r--r-- | amd64/emit.c | 55 | ||||
| -rw-r--r-- | amd64/isel.c | 103 | ||||
| -rw-r--r-- | amd64/sysv.c | 8 | ||||
| -rw-r--r-- | common.h | 4 | ||||
| -rw-r--r-- | ir.c | 12 | ||||
| -rw-r--r-- | ir.h | 17 | ||||
| -rw-r--r-- | irdump.c | 6 | ||||
| -rw-r--r-- | mem.c | 24 | ||||
| -rw-r--r-- | parse.c | 42 | ||||
| -rw-r--r-- | regalloc.c | 37 |
11 files changed, 146 insertions, 172 deletions
@@ -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}}, @@ -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 * @@ -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); @@ -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 *); @@ -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) { @@ -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]) @@ -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); @@ -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: */ |