#include "gc.h" voidginit(void){ int i; Type *t; thechar = '6'; thestring = "amd64"; exregoffset = REGEXT; exfregoffset = FREGEXT; listinit(); nstring = 0; mnstring = 0; nrathole = 0; pc = 0; breakpc = -1; continpc = -1; cases = C; firstp = P; lastp = P; tfield = types[TINT]; typeword = typechlvp; typecmplx = typesu; /* TO DO */ memmove(typechlpv, typechlp, sizeof(typechlpv)); typechlpv[TVLONG] = 1; typechlpv[TUVLONG] = 1; zprog.link = P; zprog.as = AGOK; zprog.from.type = D_NONE; zprog.from.index = D_NONE; zprog.from.scale = 0; zprog.to = zprog.from; lregnode.op = OREGISTER; lregnode.class = CEXREG; lregnode.reg = REGTMP; lregnode.complex = 0; lregnode.addable = 11; lregnode.type = types[TLONG]; qregnode = lregnode; qregnode.type = types[TVLONG]; constnode.op = OCONST; constnode.class = CXXX; constnode.complex = 0; constnode.addable = 20; constnode.type = types[TLONG]; vconstnode = constnode; vconstnode.type = types[TVLONG]; fconstnode.op = OCONST; fconstnode.class = CXXX; fconstnode.complex = 0; fconstnode.addable = 20; fconstnode.type = types[TDOUBLE]; nodsafe = new(ONAME, Z, Z); nodsafe->sym = slookup(".safe"); nodsafe->type = types[TINT]; nodsafe->etype = types[TINT]->etype; nodsafe->class = CAUTO; complex(nodsafe); t = typ(TARRAY, types[TCHAR]); symrathole = slookup(".rathole"); symrathole->class = CGLOBL; symrathole->type = t; nodrat = new(ONAME, Z, Z); nodrat->sym = symrathole; nodrat->type = types[TIND]; nodrat->etype = TVOID; nodrat->class = CGLOBL; complex(nodrat); nodrat->type = t; nodret = new(ONAME, Z, Z); nodret->sym = slookup(".ret"); nodret->type = types[TIND]; nodret->etype = TIND; nodret->class = CPARAM; nodret = new(OIND, nodret, Z); complex(nodret); if(0) com64init(); for(i=0; i<nelem(reg); i++) { reg[i] = 1; if(i >= D_AX && i <= D_R15 && i != D_SP) reg[i] = 0; if(i >= D_X0 && i <= D_X7) reg[i] = 0; }} voidgclean(void){ int i; Sym *s; reg[D_SP]--; for(i=D_AX; i<=D_R15; i++) if(reg[i]) diag(Z, "reg %R left allocated", i); for(i=D_X0; i<=D_X7; i++) if(reg[i]) diag(Z, "reg %R left allocated", i); while(mnstring) outstring("", 1L); symstring->type->width = nstring; symrathole->type->width = nrathole; for(i=0; i<NHASH; i++) for(s = hash[i]; s != S; s = s->link) { if(s->type == T) continue; if(s->type->width == 0) continue; if(s->class != CGLOBL && s->class != CSTATIC) continue; if(s->type == types[TENUM]) continue; gpseudo(AGLOBL, s, nodconst(s->type->width)); } nextpc(); p->as = AEND; outcode();} voidnextpc(void){ p = alloc(sizeof(*p)); *p = zprog; p->lineno = nearln; pc++; if(firstp == P) { firstp = p; lastp = p; return; } lastp->link = p; lastp = p;} voidgargs(Node *n, Node *tn1, Node *tn2){ long regs; Node fnxargs[20], *fnxp; regs = cursafe; fnxp = fnxargs; garg1(n, tn1, tn2, 0, &fnxp); /* compile fns to temps */ curarg = 0; fnxp = fnxargs; garg1(n, tn1, tn2, 1, &fnxp); /* compile normal args and temps */ cursafe = regs;} intnareg(void){ int i, n; n = 0; for(i=D_AX; i<=D_R15; i++) if(reg[i] == 0) n++; return n;} voidgarg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp){ Node nod; if(n == Z) return; if(n->op == OLIST) { garg1(n->left, tn1, tn2, f, fnxp); garg1(n->right, tn1, tn2, f, fnxp); return; } if(f == 0) { if(n->complex >= FNX) { regsalloc(*fnxp, n); nod = znode; nod.op = OAS; nod.left = *fnxp; nod.right = n; nod.type = n->type; cgen(&nod, Z); (*fnxp)++; } return; } if(typesu[n->type->etype]) { regaalloc(tn2, n); if(n->complex >= FNX) { sugen(*fnxp, tn2, n->type->width); (*fnxp)++; } else sugen(n, tn2, n->type->width); return; } if(REGARG && curarg == 0 && typechlpv[n->type->etype]) { regaalloc1(tn1, n); if(n->complex >= FNX) { cgen(*fnxp, tn1); (*fnxp)++; } else cgen(n, tn1); return; } if(vconst(n) == 0) { regaalloc(tn2, n); gmove(n, tn2); return; } regalloc(tn1, n, Z); if(n->complex >= FNX) { cgen(*fnxp, tn1); (*fnxp)++; } else cgen(n, tn1); regaalloc(tn2, n); gmove(tn1, tn2); regfree(tn1);} Node*nodgconst(vlong v, Type *t){ if(!typev[t->etype]) return nodconst((long)v); vconstnode.vconst = v; return &vconstnode;} Node*nodconst(long v){ constnode.vconst = v; return &constnode;} Node*nodfconst(double d){ fconstnode.fconst = d; return &fconstnode;} intisreg(Node *n, int r){ if(n->op == OREGISTER) if(n->reg == r) return 1; return 0;} intnodreg(Node *n, Node *nn, int r){ int et; *n = qregnode; n->reg = r; if(nn != Z){ et = nn->type->etype; if(!typefd[et] && nn->type->width <= SZ_LONG && 0) n->type = typeu[et]? types[TUINT]: types[TINT]; else n->type = nn->type;//print("nodreg %s [%s]\n", tnames[et], tnames[n->type->etype]); n->lineno = nn->lineno; } if(reg[r] == 0) return 0; if(nn != Z) { if(nn->op == OREGISTER) if(nn->reg == r) return 0; } return 1;} voidregret(Node *n, Node *nn){ int r; r = REGRET; if(typefd[nn->type->etype]) r = FREGRET; nodreg(n, nn, r); reg[r]++;} voidregalloc(Node *n, Node *tn, Node *o){ int i; switch(tn->type->etype) { case TCHAR: case TUCHAR: case TSHORT: case TUSHORT: case TINT: case TUINT: case TLONG: case TULONG: case TVLONG: case TUVLONG: case TIND: if(o != Z && o->op == OREGISTER) { i = o->reg; if(i >= D_AX && i <= D_R15) goto out; } for(i=D_AX; i<=D_R15; i++) if(reg[i] == 0) goto out; diag(tn, "out of fixed registers"); goto err; case TFLOAT: case TDOUBLE: if(o != Z && o->op == OREGISTER) { i = o->reg; if(i >= D_X0 && i <= D_X7) goto out; } for(i=D_X0; i<=D_X7; i++) if(reg[i] == 0) goto out; diag(tn, "out of float registers"); goto out; } diag(tn, "unknown type in regalloc: %T", tn->type);err: i = 0;out: if(i) reg[i]++; nodreg(n, tn, i);} voidregialloc(Node *n, Node *tn, Node *o){ Node nod; nod = *tn; nod.type = types[TIND]; regalloc(n, &nod, o);} voidregfree(Node *n){ int i; i = 0; if(n->op != OREGISTER && n->op != OINDREG) goto err; i = n->reg; if(i < 0 || i >= sizeof(reg)) goto err; if(reg[i] <= 0) goto err; reg[i]--; return;err: diag(n, "error in regfree: %R", i);} voidregsalloc(Node *n, Node *nn){ cursafe = align(cursafe, nn->type, Aaut3); maxargsafe = maxround(maxargsafe, cursafe+curarg); *n = *nodsafe; n->xoffset = -(stkoff + cursafe); n->type = nn->type; n->etype = nn->type->etype; n->lineno = nn->lineno;} voidregaalloc1(Node *n, Node *nn){ nodreg(n, nn, REGARG); reg[REGARG]++; curarg = align(curarg, nn->type, Aarg1); curarg = align(curarg, nn->type, Aarg2); maxargsafe = maxround(maxargsafe, cursafe+curarg);} voidregaalloc(Node *n, Node *nn){ curarg = align(curarg, nn->type, Aarg1); *n = *nn; n->op = OINDREG; n->reg = REGSP; n->xoffset = curarg; n->complex = 0; n->addable = 20; curarg = align(curarg, nn->type, Aarg2); maxargsafe = maxround(maxargsafe, cursafe+curarg);} voidregind(Node *n, Node *nn){ if(n->op != OREGISTER) { diag(n, "regind not OREGISTER"); return; } n->op = OINDREG; n->type = nn->type;} voidnaddr(Node *n, Adr *a){ long v; a->type = D_NONE; if(n == Z) return; switch(n->op) { default: bad: diag(n, "bad in naddr: %O %D", n->op, a); break; case OREGISTER: a->type = n->reg; a->sym = S; break; case OIND: naddr(n->left, a); if(a->type >= D_AX && a->type <= D_R15) a->type += D_INDIR; else if(a->type == D_CONST) a->type = D_NONE+D_INDIR; else if(a->type == D_ADDR) { a->type = a->index; a->index = D_NONE; } else goto bad; break; case OINDEX: a->type = idx.ptr; if(n->left->op == OADDR || n->left->op == OCONST) naddr(n->left, a); if(a->type >= D_AX && a->type <= D_R15) a->type += D_INDIR; else if(a->type == D_CONST) a->type = D_NONE+D_INDIR; else if(a->type == D_ADDR) { a->type = a->index; a->index = D_NONE; } else goto bad; a->index = idx.reg; a->scale = n->scale; a->offset += n->xoffset; break; case OINDREG: a->type = n->reg+D_INDIR; a->sym = S;Lines 1–500 of 1514. Load more
#include "gc.h" void ginit(void) { int i; Type *t; thechar = '6'; thestring = "amd64"; exregoffset = REGEXT; exfregoffset = FREGEXT; listinit(); nstring = 0; mnstring = 0; nrathole = 0; pc = 0; breakpc = -1; continpc = -1; cases = C; firstp = P; lastp = P; tfield = types[TINT]; typeword = typechlvp; typecmplx = typesu; /* TO DO */ memmove(typechlpv, typechlp, sizeof(typechlpv)); typechlpv[TVLONG] = 1; typechlpv[TUVLONG] = 1; zprog.link = P; zprog.as = AGOK; zprog.from.type = D_NONE; zprog.from.index = D_NONE; zprog.from.scale = 0; zprog.to = zprog.from; lregnode.op = OREGISTER; lregnode.class = CEXREG; lregnode.reg = REGTMP; lregnode.complex = 0; lregnode.addable = 11; lregnode.type = types[TLONG]; qregnode = lregnode; qregnode.type = types[TVLONG]; constnode.op = OCONST; constnode.class = CXXX; constnode.complex = 0; constnode.addable = 20; constnode.type = types[TLONG]; vconstnode = constnode; vconstnode.type = types[TVLONG]; fconstnode.op = OCONST; fconstnode.class = CXXX; fconstnode.complex = 0; fconstnode.addable = 20; fconstnode.type = types[TDOUBLE]; nodsafe = new(ONAME, Z, Z); nodsafe->sym = slookup(".safe"); nodsafe->type = types[TINT]; nodsafe->etype = types[TINT]->etype; nodsafe->class = CAUTO; complex(nodsafe); t = typ(TARRAY, types[TCHAR]); symrathole = slookup(".rathole"); symrathole->class = CGLOBL; symrathole->type = t; nodrat = new(ONAME, Z, Z); nodrat->sym = symrathole; nodrat->type = types[TIND]; nodrat->etype = TVOID; nodrat->class = CGLOBL; complex(nodrat); nodrat->type = t; nodret = new(ONAME, Z, Z); nodret->sym = slookup(".ret"); nodret->type = types[TIND]; nodret->etype = TIND; nodret->class = CPARAM; nodret = new(OIND, nodret, Z); complex(nodret); if(0) com64init(); for(i=0; i<nelem(reg); i++) { reg[i] = 1; if(i >= D_AX && i <= D_R15 && i != D_SP) reg[i] = 0; if(i >= D_X0 && i <= D_X7) reg[i] = 0; } } void gclean(void) { int i; Sym *s; reg[D_SP]--; for(i=D_AX; i<=D_R15; i++) if(reg[i]) diag(Z, "reg %R left allocated", i); for(i=D_X0; i<=D_X7; i++) if(reg[i]) diag(Z, "reg %R left allocated", i); while(mnstring) outstring("", 1L); symstring->type->width = nstring; symrathole->type->width = nrathole; for(i=0; i<NHASH; i++) for(s = hash[i]; s != S; s = s->link) { if(s->type == T) continue; if(s->type->width == 0) continue; if(s->class != CGLOBL && s->class != CSTATIC) continue; if(s->type == types[TENUM]) continue; gpseudo(AGLOBL, s, nodconst(s->type->width)); } nextpc(); p->as = AEND; outcode(); } void nextpc(void) { p = alloc(sizeof(*p)); *p = zprog; p->lineno = nearln; pc++; if(firstp == P) { firstp = p; lastp = p; return; } lastp->link = p; lastp = p; } void gargs(Node *n, Node *tn1, Node *tn2) { long regs; Node fnxargs[20], *fnxp; regs = cursafe; fnxp = fnxargs; garg1(n, tn1, tn2, 0, &fnxp); /* compile fns to temps */ curarg = 0; fnxp = fnxargs; garg1(n, tn1, tn2, 1, &fnxp); /* compile normal args and temps */ cursafe = regs; } int nareg(void) { int i, n; n = 0; for(i=D_AX; i<=D_R15; i++) if(reg[i] == 0) n++; return n; } void garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp) { Node nod; if(n == Z) return; if(n->op == OLIST) { garg1(n->left, tn1, tn2, f, fnxp); garg1(n->right, tn1, tn2, f, fnxp); return; } if(f == 0) { if(n->complex >= FNX) { regsalloc(*fnxp, n); nod = znode; nod.op = OAS; nod.left = *fnxp; nod.right = n; nod.type = n->type; cgen(&nod, Z); (*fnxp)++; } return; } if(typesu[n->type->etype]) { regaalloc(tn2, n); if(n->complex >= FNX) { sugen(*fnxp, tn2, n->type->width); (*fnxp)++; } else sugen(n, tn2, n->type->width); return; } if(REGARG && curarg == 0 && typechlpv[n->type->etype]) { regaalloc1(tn1, n); if(n->complex >= FNX) { cgen(*fnxp, tn1); (*fnxp)++; } else cgen(n, tn1); return; } if(vconst(n) == 0) { regaalloc(tn2, n); gmove(n, tn2); return; } regalloc(tn1, n, Z); if(n->complex >= FNX) { cgen(*fnxp, tn1); (*fnxp)++; } else cgen(n, tn1); regaalloc(tn2, n); gmove(tn1, tn2); regfree(tn1); } Node* nodgconst(vlong v, Type *t) { if(!typev[t->etype]) return nodconst((long)v); vconstnode.vconst = v; return &vconstnode; } Node* nodconst(long v) { constnode.vconst = v; return &constnode; } Node* nodfconst(double d) { fconstnode.fconst = d; return &fconstnode; } int isreg(Node *n, int r) { if(n->op == OREGISTER) if(n->reg == r) return 1; return 0; } int nodreg(Node *n, Node *nn, int r) { int et; *n = qregnode; n->reg = r; if(nn != Z){ et = nn->type->etype; if(!typefd[et] && nn->type->width <= SZ_LONG && 0) n->type = typeu[et]? types[TUINT]: types[TINT]; else n->type = nn->type; //print("nodreg %s [%s]\n", tnames[et], tnames[n->type->etype]); n->lineno = nn->lineno; } if(reg[r] == 0) return 0; if(nn != Z) { if(nn->op == OREGISTER) if(nn->reg == r) return 0; } return 1; } void regret(Node *n, Node *nn) { int r; r = REGRET; if(typefd[nn->type->etype]) r = FREGRET; nodreg(n, nn, r); reg[r]++; } void regalloc(Node *n, Node *tn, Node *o) { int i; switch(tn->type->etype) { case TCHAR: case TUCHAR: case TSHORT: case TUSHORT: case TINT: case TUINT: case TLONG: case TULONG: case TVLONG: case TUVLONG: case TIND: if(o != Z && o->op == OREGISTER) { i = o->reg; if(i >= D_AX && i <= D_R15) goto out; } for(i=D_AX; i<=D_R15; i++) if(reg[i] == 0) goto out; diag(tn, "out of fixed registers"); goto err; case TFLOAT: case TDOUBLE: if(o != Z && o->op == OREGISTER) { i = o->reg; if(i >= D_X0 && i <= D_X7) goto out; } for(i=D_X0; i<=D_X7; i++) if(reg[i] == 0) goto out; diag(tn, "out of float registers"); goto out; } diag(tn, "unknown type in regalloc: %T", tn->type); err: i = 0; out: if(i) reg[i]++; nodreg(n, tn, i); } void regialloc(Node *n, Node *tn, Node *o) { Node nod; nod = *tn; nod.type = types[TIND]; regalloc(n, &nod, o); } void regfree(Node *n) { int i; i = 0; if(n->op != OREGISTER && n->op != OINDREG) goto err; i = n->reg; if(i < 0 || i >= sizeof(reg)) goto err; if(reg[i] <= 0) goto err; reg[i]--; return; err: diag(n, "error in regfree: %R", i); } void regsalloc(Node *n, Node *nn) { cursafe = align(cursafe, nn->type, Aaut3); maxargsafe = maxround(maxargsafe, cursafe+curarg); *n = *nodsafe; n->xoffset = -(stkoff + cursafe); n->type = nn->type; n->etype = nn->type->etype; n->lineno = nn->lineno; } void regaalloc1(Node *n, Node *nn) { nodreg(n, nn, REGARG); reg[REGARG]++; curarg = align(curarg, nn->type, Aarg1); curarg = align(curarg, nn->type, Aarg2); maxargsafe = maxround(maxargsafe, cursafe+curarg); } void regaalloc(Node *n, Node *nn) { curarg = align(curarg, nn->type, Aarg1); *n = *nn; n->op = OINDREG; n->reg = REGSP; n->xoffset = curarg; n->complex = 0; n->addable = 20; curarg = align(curarg, nn->type, Aarg2); maxargsafe = maxround(maxargsafe, cursafe+curarg); } void regind(Node *n, Node *nn) { if(n->op != OREGISTER) { diag(n, "regind not OREGISTER"); return; } n->op = OINDREG; n->type = nn->type; } void naddr(Node *n, Adr *a) { long v; a->type = D_NONE; if(n == Z) return; switch(n->op) { default: bad: diag(n, "bad in naddr: %O %D", n->op, a); break; case OREGISTER: a->type = n->reg; a->sym = S; break; case OIND: naddr(n->left, a); if(a->type >= D_AX && a->type <= D_R15) a->type += D_INDIR; else if(a->type == D_CONST) a->type = D_NONE+D_INDIR; else if(a->type == D_ADDR) { a->type = a->index; a->index = D_NONE; } else goto bad; break; case OINDEX: a->type = idx.ptr; if(n->left->op == OADDR || n->left->op == OCONST) naddr(n->left, a); if(a->type >= D_AX && a->type <= D_R15) a->type += D_INDIR; else if(a->type == D_CONST) a->type = D_NONE+D_INDIR; else if(a->type == D_ADDR) { a->type = a->index; a->index = D_NONE; } else goto bad; a->index = idx.reg; a->scale = n->scale; a->offset += n->xoffset; break; case OINDREG: a->type = n->reg+D_INDIR; a->sym = S;