diff options
Diffstat (limited to 'ir')
| -rw-r--r-- | ir/abi0.c | 16 | ||||
| -rw-r--r-- | ir/builder.c | 8 | ||||
| -rw-r--r-- | ir/dump.c | 4 | ||||
| -rw-r--r-- | ir/ir.c | 53 | ||||
| -rw-r--r-- | ir/ir.h | 9 | ||||
| -rw-r--r-- | ir/op.def | 3 |
6 files changed, 68 insertions, 25 deletions
@@ -32,6 +32,7 @@ abiret(struct abiarg abiret[2], struct abiargsvec *abiargs, int *ni, union irtyp } for (int i = 0; i < retreg; ++i) { abiret[i].ty = cls2type(cls[i]); + abiret[i].isstk = 0; abiret[i].reg = r[i]; } return retreg; @@ -44,7 +45,7 @@ abiarg(struct abiargsvec *abiargs, int *ni, int *nf, int *ns, union irtype ty) uchar cls[2]; int ret = mctarg->abiarg(r, cls, ni, nf, ns, ty); if (!ret) { /* in stack */ - vpush(abiargs, ((struct abiarg) { ty, .stk = r[0] })); + vpush(abiargs, ((struct abiarg) { ty, .isstk = 1, .stk = r[0] })); } else if (ret == 1 && ty.isagg && cls[0] == KPTR) { /* aggregate by pointer */ vpush(abiargs, ((struct abiarg) { cls2type(cls[0]), .reg = r[0] })); } else { /* by regs */ @@ -59,7 +60,7 @@ static struct instr copyparam(struct function *fn, int *curi, int param, struct abiarg abi) { struct instr par = mkinstr(Oparam, abi.ty.cls, mkref(RICON, param), mktyperef(abi.ty)); - if (abi.reg >= 0) { /* reg */ + if (!abi.isstk) { /* reg */ assert(!abi.ty.isagg); return par; } else if (!abi.ty.isagg) { /* scalar in stack */ @@ -237,7 +238,6 @@ abi0_call(struct function *fn, struct instr *ins, struct block *blk, int *curi) struct call *call = &calltab.p[ins->r.i]; vararg = call->vararg; - vinit(&abiargs, abiargsbuf, arraylength(abiargsbuf)); ni = nf = ns = 0; assert(!ins->cls == !call->ret.bits); nret = abiret(call->abiret, &abiargs, &ni, call->ret); @@ -282,7 +282,7 @@ abi0_call(struct function *fn, struct instr *ins, struct block *blk, int *curi) ins->cls = 0; if (!nret) { /* hidden pointer argument */ ins->cls = 0; - if (call->abiret[0].reg >= 0) { + if (!call->abiret[0].isstk) { /* the result location pointer is also returned by the callee, e.g. in x86 */ ins->cls = KPTR; ++nret; @@ -401,11 +401,12 @@ abi0(struct function *fn) blk = fn->entry->lnext; do { - /* adjust calls */ + /* adjust vaargs and calls */ for (int iinstr = 0; iinstr < blk->ins.n; ++iinstr) { struct instr *ins = &instrtab[blk->ins.p[iinstr]]; - if (ins->op != Ocall) continue; - abi0_call(fn, ins, blk, &iinstr); + if (ins->op == Ovastart) mctarg->vastart(fn, blk, &iinstr); + else if (ins->op == Ovaarg) mctarg->vaarg(fn, blk, &iinstr); + else if (ins->op == Ocall) abi0_call(fn, ins, blk, &iinstr); } /* adjust returns */ @@ -432,6 +433,7 @@ abi0(struct function *fn) } } while ((blk = blk->lnext) != fn->entry); + sortrpo(fn); if (ccopt.dbg.a) { efmt("<< After abi0 >>\n"); irdump(fn); diff --git a/ir/builder.c b/ir/builder.c index 964099a..640c1fd 100644 --- a/ir/builder.c +++ b/ir/builder.c @@ -124,12 +124,12 @@ irunop(struct function *fn, enum op op, enum irclass k, union ref a) return addinstr(fn, mkinstr(op, k, a)); } -int newinstr(void); +int allocinstr(void); union ref addinstr(struct function *fn, struct instr ins) { - int new = newinstr(); + int new = allocinstr(); assert(fn->curblk != NULL); instrtab[new] = ins; adduse(fn->curblk, new, ins.l); @@ -168,8 +168,8 @@ addphi(struct function *fn, enum irclass cls, union ref *r) ins.l = mkref(RXXX, phitab.n-1); assert(fn->curblk != NULL); - assert(fn->curblk->ins.n == 0); - new = newinstr(); + /*assert(fn->curblk->ins.n == 0);*/ + new = allocinstr(); instrtab[new] = ins; for (int i = 0; i < fn->curblk->npred; ++i) { adduse(fn->curblk, new, r[i]); @@ -173,7 +173,7 @@ dumpinst(const struct instr *ins) efmt("\n"); } -static void +void dumpblk(struct function *fn, struct block *blk) { static const char *jnames[] = { 0, "b", "ret" }; @@ -228,7 +228,7 @@ irdump(struct function *fn) efmt("abi: ("); for (int i = 0; i < fn->nabiarg; ++i) { if (i > 0) efmt(", "); - if (fn->abiarg[i].reg >= 0) { + if (!fn->abiarg[i].isstk) { efmt("%s", mctarg->rnames[fn->abiarg[i].reg]); } else { prityp(fn->abiarg[i].ty); @@ -234,8 +234,7 @@ delpred(struct block *blk, struct block *p) struct block * newblk(struct function *fn) { - struct block *blk = alloc(fn->arena, sizeof(struct block), 0); - memset(blk, 0, sizeof *blk); + struct block *blk = allocz(fn->arena, sizeof(struct block), 0); blk->id = -1; return blk; } @@ -297,8 +296,36 @@ insertblk(struct function *fn, struct block *pred, struct block *subst) assert(0); } +struct block * +blksplitafter(struct function *fn, struct block *blk, int idx) +{ + struct block *new = newblk(fn); + ++fn->nblk; + new->lprev = blk; + new->lnext = blk->lnext; + blk->lnext = new; + new->lnext->lprev = new; + if (idx < blk->ins.n-1) + vpushn(&new->ins, &blk->ins.p[idx+1], blk->ins.n-idx-1); + blk->ins.n -= new->ins.n; + new->jmp = blk->jmp; + blk->jmp.t = Jb; + memset(blk->jmp.arg, 0, sizeof blk->jmp.arg); + for (int i = 0; i < 2; ++i) { + struct block *s = (&blk->s1)[i]; + for (int i = 0; i < s->npred; ++i) { + if (blkpred(s, i) == blk) + blkpred(s, i) = new; + } + } + new->s1 = blk->s1, new->s2 = blk->s2; + blk->s1 = new, blk->s2 = NULL; + addpred(new, blk); + return new; +} + int -newinstr(void) +allocinstr(void) { int t; if (instrfreelist != -1) { @@ -358,12 +385,22 @@ Shrink: return 1; } +int +newinstr(struct block *at, struct instr ins) +{ + int new = allocinstr(); + instrtab[new] = ins; + if (at) { + adduse(at, new, ins.l); + adduse(at, new, ins.r); + } + return new; +} + union ref insertinstr(struct block *blk, int idx, struct instr ins) { - int new = newinstr(); - - instrtab[new] = ins; + int new = newinstr(blk, ins); if (idx == blk->ins.n) vpush(&blk->ins, new); else { assert(idx >= 0 && idx < blk->ins.n); @@ -373,15 +410,13 @@ insertinstr(struct block *blk, int idx, struct instr ins) blk->ins.p[i] = blk->ins.p[i - 1]; blk->ins.p[idx] = new; } - adduse(blk, new, ins.l); - adduse(blk, new, ins.r); return mkref(RTMP, new); } union ref insertphi(struct block *blk, enum irclass cls) { - int new = newinstr(); + int new = allocinstr(); union ref *refs = NULL; assert(blk->npred > 0); xbgrowz(&refs, blk->npred); @@ -37,8 +37,8 @@ struct xcon { struct abiarg { union irtype ty; union { - short reg; /* >= 0 */ - short stk; /* < 0 */ + struct { ushort _ : 1, reg : 15; }; + struct { ushort isstk : 1, stk : 15; }; }; }; @@ -188,7 +188,8 @@ struct mctarg { * or negative SP offset if stack */ int (*abiarg)(short r[2], uchar cls[2], int *ni, int *nf, int *ns, union irtype); - + void (*vastart)(struct function *, struct block *, int *curi); + void (*vaarg)(struct function *, struct block *, int *curi); void (*isel)(struct function *); void (*emit)(struct function *); }; @@ -236,7 +237,9 @@ void addpred(struct block *blk, struct block *p); struct block *newblk(struct function *); void freeblk(struct function *, struct block *); struct block *insertblk(struct function *, struct block *pred, struct block *subst); +struct block *blksplitafter(struct function *, struct block *, int idx); void adduse(struct block *ublk, int ui, union ref r); +int newinstr(struct block *at, struct instr ins); union ref insertinstr(struct block *, int idx, struct instr); union ref insertphi(struct block *, enum irclass cls); void replcuses(union ref from, union ref to); @@ -69,6 +69,9 @@ _(call2r, 1) _(intrin, 2) _(phi, 1) _(swap, 2) +_(vastart, 1) +_(vaarg, 2) /* machine-specific instructions */ +_(xvaprologue, 1) _(xsave, 1) _(xrestore, 1) |