#include "limbo.h" static int addrmode[Rend] ={ /* Rreg */ Afp, /* Rmreg */ Amp, /* Roff */ Aoff, /* Rnoff */ Anoff, /* Rdesc */ Adesc, /* Rdescp */ Adesc, /* Rconst */ Aimm, /* Ralways */ Aerr, /* Radr */ Afpind, /* Rmadr */ Ampind, /* Rcant */ Aerr, /* Rpc */ Apc, /* Rmpc */ Aerr, /* Rareg */ Aerr, /* Ramreg */ Aerr, /* Raadr */ Aerr, /* Ramadr */ Aerr, /* Rldt */ Aldt,}; static Decl *wtemp;static Decl *bigtemp;static int ntemp;static Node retnode;static Inst zinst; int *blockstack; int blockdep; int nblocks;static int lenblockstack;static Node *ntoz; static Inst* genfixop(Src *src, int op, Node *s, Node *m, Node *d); voidgenstart(void){ Decl *d; d = mkdecl(&nosrc, Dlocal, tint); d->sym = enter(".ret", 0); d->offset = IBY2WD * REGRET; retnode = znode; retnode.op = Oname; retnode.addable = Rreg; retnode.decl = d; retnode.ty = tint; zinst.op = INOP; zinst.sm = Anone; zinst.dm = Anone; zinst.mm = Anone; firstinst = allocmem(sizeof *firstinst); *firstinst = zinst; lastinst = firstinst; blocks = -1; blockdep = 0; nblocks = 0;} /* * manage nested control flow blocks */intpushblock(void){ if(blockdep >= lenblockstack){ lenblockstack = blockdep + 32; blockstack = reallocmem(blockstack, lenblockstack * sizeof *blockstack); } blockstack[blockdep++] = blocks; return blocks = nblocks++;} voidrepushblock(int b){ blockstack[blockdep++] = blocks; blocks = b;} voidpopblock(void){ blocks = blockstack[blockdep -= 1];} voidtinit(void){ wtemp = nil; bigtemp = nil;} Decl*tdecls(void){ Decl *d; for(d = wtemp; d != nil; d = d->next){ if(d->tref != 1) fatal("temporary %s has %d references", d->sym->name, d->tref-1); } for(d = bigtemp; d != nil; d = d->next){ if(d->tref != 1) fatal("temporary %s has %d references", d->sym->name, d->tref-1); } return appdecls(wtemp, bigtemp);} Node*talloc(Node *n, Type *t, Node *nok){ Decl *d, *ok; Desc *desc; char buf[StrSize]; ok = nil; if(nok != nil) ok = nok->decl; if(ok == nil || ok->tref == 0 || tattr[ok->ty->kind].big != tattr[t->kind].big || ok->ty->align != t->align) ok = nil; *n = znode; n->op = Oname; n->addable = Rreg; n->ty = t; if(tattr[t->kind].big){ desc = mktdesc(t); if(ok != nil && ok->desc == desc){ ok->tref++; ok->refs++; n->decl = ok; return n; } for(d = bigtemp; d != nil; d = d->next){ if(d->tref == 1 && d->desc == desc && d->ty->align == t->align){ d->tref++; d->refs++; n->decl = d; return n; } } d = mkdecl(&nosrc, Dlocal, t); d->desc = desc; d->tref = 2; d->refs = 1; n->decl = d; seprint(buf, buf+sizeof(buf), ".b%d", ntemp++); d->sym = enter(buf, 0); d->next = bigtemp; bigtemp = d; return n; } if(ok != nil && tattr[ok->ty->kind].isptr == tattr[t->kind].isptr && ok->ty->size == t->size){ ok->tref++; n->decl = ok; return n; } for(d = wtemp; d != nil; d = d->next){ if(d->tref == 1 && tattr[d->ty->kind].isptr == tattr[t->kind].isptr && d->ty->size == t->size && d->ty->align == t->align){ d->tref++; n->decl = d; return n; } } d = mkdecl(&nosrc, Dlocal, t); d->tref = 2; d->refs = 1; n->decl = d; seprint(buf, buf+sizeof(buf), ".t%d", ntemp++); d->sym = enter(buf, 0); d->next = wtemp; wtemp = d; return n;} voidtfree(Node *n){ if(n == nil || n->decl == nil || n->decl->tref == 0) return; if(n->decl->tref == 1) fatal("double free of temporary %s", n->decl->sym->name); if (--n->decl->tref == 1) zcom1(n, nil);} voidtfreelater(Node *n){ if(n == nil || n->decl == nil || n->decl->tref == 0) return; if(n->decl->tref == 1) fatal("double free of temporary %s", n->decl->sym->name); if(--n->decl->tref == 1){ Node *nn = mkn(Oname, nil, nil); *nn = *n; nn->left = ntoz; ntoz = nn; n->decl->tref++; }} voidtfreenow(){ Node *n, *nn; for(n = ntoz; n != nil; n = nn){ nn = n->left; n->left = nil; if(n->decl->tref != 2) fatal("bad free of temporary %s", n->decl->sym->name); --n->decl->tref; zcom1(n, nil); } ntoz = nil;} /* * realloc a temporary after it's been freed */Node*tacquire(Node *n){ if(n == nil || n->decl == nil || n->decl->tref == 0) return n;/* if(n->decl->tref != 1) fatal("tacquire ref != 1: %d", n->decl->tref);*/ n->decl->tref++; return n;} voidtrelease(Node *n){ if(n == nil || n->decl == nil || n->decl->tref == 0) return; if(n->decl->tref == 1) fatal("double release of temporary %s", n->decl->sym->name); n->decl->tref--;} Inst*mkinst(void){ Inst *in; in = lastinst->next; if(in == nil){ in = allocmem(sizeof *in); *in = zinst; lastinst->next = in; } lastinst = in; in->block = blocks; if(blocks < 0) fatal("mkinst no block"); return in;} Inst*nextinst(void){ Inst *in; in = lastinst->next; if(in != nil) return in; in = allocmem(sizeof(*in)); *in = zinst; lastinst->next = in; return in;} /* * allocate a node for returning */Node*retalloc(Node *n, Node *nn){ if(nn->ty == tnone) return nil; *n = znode; n->op = Oind; n->addable = Radr; n->left = dupn(1, &n->src, &retnode); n->ty = nn->ty; return n;} Inst*genrawop(Src *src, int op, Node *s, Node *m, Node *d){ Inst *in; in = mkinst(); in->op = op; in->src = *src;if(in->sm != Anone || in->mm != Anone || in->dm != Anone)fatal("bogus mkinst in genrawop: %I\n", in); if(s != nil){ in->s = genaddr(s); in->sm = addrmode[s->addable]; } if(m != nil){ in->m = genaddr(m); in->mm = addrmode[m->addable]; if(in->mm == Ampind || in->mm == Afpind) fatal("illegal addressing mode in register %n", m); } if(d != nil){ in->d = genaddr(d); in->dm = addrmode[d->addable]; } return in;} Inst*genop(Src *src, int op, Node *s, Node *m, Node *d){ Inst *in; int iop; iop = disoptab[op][opind[d->ty->kind]]; if(iop == 0) fatal("can't deal with op %s on %n %n %n in genop", opname[op], s, m, d); if(iop == IMULX || iop == IDIVX) return genfixop(src, iop, s, m, d); in = mkinst(); in->op = iop; in->src = *src; if(s != nil){ in->s = genaddr(s); in->sm = addrmode[s->addable]; } if(m != nil){ in->m = genaddr(m); in->mm = addrmode[m->addable]; if(in->mm == Ampind || in->mm == Afpind) fatal("illegal addressing mode in register %n", m); } if(d != nil){ in->d = genaddr(d); in->dm = addrmode[d->addable]; } return in;} Inst*genbra(Src *src, int op, Node *s, Node *m){ Type *t; Inst *in; int iop; t = s->ty; if(t == tany) t = m->ty; iop = disoptab[op][opind[t->kind]]; if(iop == 0) fatal("can't deal with op %s on %n %n in genbra", opname[op], s, m); in = mkinst(); in->op = iop; in->src = *src; if(s != nil){ in->s = genaddr(s); in->sm = addrmode[s->addable]; } if(m != nil){ in->m = genaddr(m); in->mm = addrmode[m->addable]; if(in->mm == Ampind || in->mm == Afpind) fatal("illegal addressing mode in register %n", m); } return in;} Inst*genchan(Src *src, Node *sz, Type *mt, Node *d){ Inst *in; Desc *td; Addr reg; int op, regm; regm = Anone; reg.decl = nil; reg.reg = 0; reg.offset = 0; op = chantab[mt->kind]; if(op == 0) fatal("can't deal with op %d in genchan", mt->kind); switch(mt->kind){ case Tadt: case Tadtpick: case Ttuple: td = mktdesc(mt); if(td->nmap != 0){ op++; /* sleazy */ usedesc(td); regm = Adesc; reg.decl = mt->decl; }else{ regm = Aimm; reg.offset = mt->size; } break; } in = mkinst(); in->op = op; in->src = *src; in->s = reg; in->sm = regm; if(sz != nil){ in->m = genaddr(sz); in->mm = addrmode[sz->addable]; } if(d != nil){ in->d = genaddr(d); in->dm = addrmode[d->addable]; } return in;} Inst*genmove(Src *src, int how, Type *mt, Node *s, Node *d){ Inst *in; Desc *td; Addr reg; int op, regm; regm = Anone; reg.decl = nil; reg.reg = 0; reg.offset = 0; op = movetab[how][mt->kind]; if(op == 0) fatal("can't deal with op %d on %n %n in genmove", how, s, d); switch(mt->kind){ case Tadt: case Tadtpick: case Ttuple: case Texception: if(mt->size == 0 && how == Mas) return nil; td = mktdesc(mt); if(td->nmap != 0){ op++; /* sleazy */ usedesc(td); regm = Adesc; reg.decl = mt->decl; }else{ regm = Aimm; reg.offset = mt->size; } break; } in = mkinst(); in->op = op; in->src = *src; if(s != nil){ in->s = genaddr(s); in->sm = addrmode[s->addable]; } in->m = reg; in->mm = regm; if(d != nil){ in->d = genaddr(d); in->dm = addrmode[d->addable]; } if(s->addable == Rpc) in->op = IMOVPC; return in;} voidpatch(Inst *b, Inst *dst){ Inst *n;Lines 1–500 of 1096. Load more
#include "limbo.h" static int addrmode[Rend] = { /* Rreg */ Afp, /* Rmreg */ Amp, /* Roff */ Aoff, /* Rnoff */ Anoff, /* Rdesc */ Adesc, /* Rdescp */ Adesc, /* Rconst */ Aimm, /* Ralways */ Aerr, /* Radr */ Afpind, /* Rmadr */ Ampind, /* Rcant */ Aerr, /* Rpc */ Apc, /* Rmpc */ Aerr, /* Rareg */ Aerr, /* Ramreg */ Aerr, /* Raadr */ Aerr, /* Ramadr */ Aerr, /* Rldt */ Aldt, }; static Decl *wtemp; static Decl *bigtemp; static int ntemp; static Node retnode; static Inst zinst; int *blockstack; int blockdep; int nblocks; static int lenblockstack; static Node *ntoz; static Inst* genfixop(Src *src, int op, Node *s, Node *m, Node *d); void genstart(void) { Decl *d; d = mkdecl(&nosrc, Dlocal, tint); d->sym = enter(".ret", 0); d->offset = IBY2WD * REGRET; retnode = znode; retnode.op = Oname; retnode.addable = Rreg; retnode.decl = d; retnode.ty = tint; zinst.op = INOP; zinst.sm = Anone; zinst.dm = Anone; zinst.mm = Anone; firstinst = allocmem(sizeof *firstinst); *firstinst = zinst; lastinst = firstinst; blocks = -1; blockdep = 0; nblocks = 0; } /* * manage nested control flow blocks */ int pushblock(void) { if(blockdep >= lenblockstack){ lenblockstack = blockdep + 32; blockstack = reallocmem(blockstack, lenblockstack * sizeof *blockstack); } blockstack[blockdep++] = blocks; return blocks = nblocks++; } void repushblock(int b) { blockstack[blockdep++] = blocks; blocks = b; } void popblock(void) { blocks = blockstack[blockdep -= 1]; } void tinit(void) { wtemp = nil; bigtemp = nil; } Decl* tdecls(void) { Decl *d; for(d = wtemp; d != nil; d = d->next){ if(d->tref != 1) fatal("temporary %s has %d references", d->sym->name, d->tref-1); } for(d = bigtemp; d != nil; d = d->next){ if(d->tref != 1) fatal("temporary %s has %d references", d->sym->name, d->tref-1); } return appdecls(wtemp, bigtemp); } Node* talloc(Node *n, Type *t, Node *nok) { Decl *d, *ok; Desc *desc; char buf[StrSize]; ok = nil; if(nok != nil) ok = nok->decl; if(ok == nil || ok->tref == 0 || tattr[ok->ty->kind].big != tattr[t->kind].big || ok->ty->align != t->align) ok = nil; *n = znode; n->op = Oname; n->addable = Rreg; n->ty = t; if(tattr[t->kind].big){ desc = mktdesc(t); if(ok != nil && ok->desc == desc){ ok->tref++; ok->refs++; n->decl = ok; return n; } for(d = bigtemp; d != nil; d = d->next){ if(d->tref == 1 && d->desc == desc && d->ty->align == t->align){ d->tref++; d->refs++; n->decl = d; return n; } } d = mkdecl(&nosrc, Dlocal, t); d->desc = desc; d->tref = 2; d->refs = 1; n->decl = d; seprint(buf, buf+sizeof(buf), ".b%d", ntemp++); d->sym = enter(buf, 0); d->next = bigtemp; bigtemp = d; return n; } if(ok != nil && tattr[ok->ty->kind].isptr == tattr[t->kind].isptr && ok->ty->size == t->size){ ok->tref++; n->decl = ok; return n; } for(d = wtemp; d != nil; d = d->next){ if(d->tref == 1 && tattr[d->ty->kind].isptr == tattr[t->kind].isptr && d->ty->size == t->size && d->ty->align == t->align){ d->tref++; n->decl = d; return n; } } d = mkdecl(&nosrc, Dlocal, t); d->tref = 2; d->refs = 1; n->decl = d; seprint(buf, buf+sizeof(buf), ".t%d", ntemp++); d->sym = enter(buf, 0); d->next = wtemp; wtemp = d; return n; } void tfree(Node *n) { if(n == nil || n->decl == nil || n->decl->tref == 0) return; if(n->decl->tref == 1) fatal("double free of temporary %s", n->decl->sym->name); if (--n->decl->tref == 1) zcom1(n, nil); } void tfreelater(Node *n) { if(n == nil || n->decl == nil || n->decl->tref == 0) return; if(n->decl->tref == 1) fatal("double free of temporary %s", n->decl->sym->name); if(--n->decl->tref == 1){ Node *nn = mkn(Oname, nil, nil); *nn = *n; nn->left = ntoz; ntoz = nn; n->decl->tref++; } } void tfreenow() { Node *n, *nn; for(n = ntoz; n != nil; n = nn){ nn = n->left; n->left = nil; if(n->decl->tref != 2) fatal("bad free of temporary %s", n->decl->sym->name); --n->decl->tref; zcom1(n, nil); } ntoz = nil; } /* * realloc a temporary after it's been freed */ Node* tacquire(Node *n) { if(n == nil || n->decl == nil || n->decl->tref == 0) return n; /* if(n->decl->tref != 1) fatal("tacquire ref != 1: %d", n->decl->tref); */ n->decl->tref++; return n; } void trelease(Node *n) { if(n == nil || n->decl == nil || n->decl->tref == 0) return; if(n->decl->tref == 1) fatal("double release of temporary %s", n->decl->sym->name); n->decl->tref--; } Inst* mkinst(void) { Inst *in; in = lastinst->next; if(in == nil){ in = allocmem(sizeof *in); *in = zinst; lastinst->next = in; } lastinst = in; in->block = blocks; if(blocks < 0) fatal("mkinst no block"); return in; } Inst* nextinst(void) { Inst *in; in = lastinst->next; if(in != nil) return in; in = allocmem(sizeof(*in)); *in = zinst; lastinst->next = in; return in; } /* * allocate a node for returning */ Node* retalloc(Node *n, Node *nn) { if(nn->ty == tnone) return nil; *n = znode; n->op = Oind; n->addable = Radr; n->left = dupn(1, &n->src, &retnode); n->ty = nn->ty; return n; } Inst* genrawop(Src *src, int op, Node *s, Node *m, Node *d) { Inst *in; in = mkinst(); in->op = op; in->src = *src; if(in->sm != Anone || in->mm != Anone || in->dm != Anone) fatal("bogus mkinst in genrawop: %I\n", in); if(s != nil){ in->s = genaddr(s); in->sm = addrmode[s->addable]; } if(m != nil){ in->m = genaddr(m); in->mm = addrmode[m->addable]; if(in->mm == Ampind || in->mm == Afpind) fatal("illegal addressing mode in register %n", m); } if(d != nil){ in->d = genaddr(d); in->dm = addrmode[d->addable]; } return in; } Inst* genop(Src *src, int op, Node *s, Node *m, Node *d) { Inst *in; int iop; iop = disoptab[op][opind[d->ty->kind]]; if(iop == 0) fatal("can't deal with op %s on %n %n %n in genop", opname[op], s, m, d); if(iop == IMULX || iop == IDIVX) return genfixop(src, iop, s, m, d); in = mkinst(); in->op = iop; in->src = *src; if(s != nil){ in->s = genaddr(s); in->sm = addrmode[s->addable]; } if(m != nil){ in->m = genaddr(m); in->mm = addrmode[m->addable]; if(in->mm == Ampind || in->mm == Afpind) fatal("illegal addressing mode in register %n", m); } if(d != nil){ in->d = genaddr(d); in->dm = addrmode[d->addable]; } return in; } Inst* genbra(Src *src, int op, Node *s, Node *m) { Type *t; Inst *in; int iop; t = s->ty; if(t == tany) t = m->ty; iop = disoptab[op][opind[t->kind]]; if(iop == 0) fatal("can't deal with op %s on %n %n in genbra", opname[op], s, m); in = mkinst(); in->op = iop; in->src = *src; if(s != nil){ in->s = genaddr(s); in->sm = addrmode[s->addable]; } if(m != nil){ in->m = genaddr(m); in->mm = addrmode[m->addable]; if(in->mm == Ampind || in->mm == Afpind) fatal("illegal addressing mode in register %n", m); } return in; } Inst* genchan(Src *src, Node *sz, Type *mt, Node *d) { Inst *in; Desc *td; Addr reg; int op, regm; regm = Anone; reg.decl = nil; reg.reg = 0; reg.offset = 0; op = chantab[mt->kind]; if(op == 0) fatal("can't deal with op %d in genchan", mt->kind); switch(mt->kind){ case Tadt: case Tadtpick: case Ttuple: td = mktdesc(mt); if(td->nmap != 0){ op++; /* sleazy */ usedesc(td); regm = Adesc; reg.decl = mt->decl; }else{ regm = Aimm; reg.offset = mt->size; } break; } in = mkinst(); in->op = op; in->src = *src; in->s = reg; in->sm = regm; if(sz != nil){ in->m = genaddr(sz); in->mm = addrmode[sz->addable]; } if(d != nil){ in->d = genaddr(d); in->dm = addrmode[d->addable]; } return in; } Inst* genmove(Src *src, int how, Type *mt, Node *s, Node *d) { Inst *in; Desc *td; Addr reg; int op, regm; regm = Anone; reg.decl = nil; reg.reg = 0; reg.offset = 0; op = movetab[how][mt->kind]; if(op == 0) fatal("can't deal with op %d on %n %n in genmove", how, s, d); switch(mt->kind){ case Tadt: case Tadtpick: case Ttuple: case Texception: if(mt->size == 0 && how == Mas) return nil; td = mktdesc(mt); if(td->nmap != 0){ op++; /* sleazy */ usedesc(td); regm = Adesc; reg.decl = mt->decl; }else{ regm = Aimm; reg.offset = mt->size; } break; } in = mkinst(); in->op = op; in->src = *src; if(s != nil){ in->s = genaddr(s); in->sm = addrmode[s->addable]; } in->m = reg; in->mm = regm; if(d != nil){ in->d = genaddr(d); in->dm = addrmode[d->addable]; } if(s->addable == Rpc) in->op = IMOVPC; return in; } void patch(Inst *b, Inst *dst) { Inst *n;