#include "gc.h" voidcodgen(Node *n, Node *nn){ Prog *sp; argoff = 0; inargs = 0; for(;; nn = nn->left) { if(nn == Z) { diag(Z, "cant find function name"); return; } if(nn->op == ONAME) break; } nearln = nn->lineno; gpseudo(ATEXT, nn->sym, D_CONST, stkoff); sp = p; retok = 0; gen(n); if(!retok) if(thisfn->link->etype != TVOID) warn(Z, "no return at end of function: %s", nn->sym->name); noretval(3); gbranch(ORETURN); if(!debug['N'] || debug['R'] || debug['P']) regopt(sp);} voidgen(Node *n){ Node *l; Prog *sp, *spc, *spb; Case *cn; long sbc, scc; int g, o; loop: if(n == Z) return; nearln = n->lineno; o = n->op; if(debug['G']) if(o != OLIST) print("%L %O\n", nearln, o); retok = 0; switch(o) { default: complex(n); doinc(n, PRE); cgen(n, D_NONE, n); doinc(n, POST); break; case OLIST: gen(n->left); rloop: n = n->right; goto loop; case ORETURN: retok = 1; complex(n); if(n->type == T) break; l = n->left; if(l == Z) { noretval(3); gbranch(ORETURN); break; } doinc(l, PRE); if(typesuv[n->type->etype]) { sugen(l, D_TREE, nodret, n->type->width); doinc(l, POST); noretval(3); gbranch(ORETURN); break; } g = regalloc(n->type, regret(n->type)); cgen(l, g, n); doinc(l, POST); if(typefd[n->type->etype]) noretval(1); else noretval(2); gbranch(ORETURN); regfree(g); break; case OLABEL: l = n->left; if(l) { l->xoffset = pc; if(l->label) patch(l->label, pc); } gbranch(OGOTO); /* prevent self reference in reg */ patch(p, pc); goto rloop; case OGOTO: retok = 1; n = n->left; if(n == Z) return; if(n->complex == 0) { diag(Z, "label undefined: %s", n->sym->name); return; } gbranch(OGOTO); if(n->xoffset) { patch(p, n->xoffset); return; } if(n->label) patch(n->label, pc-1); n->label = p; return; case OCASE: l = n->left; if(cases == C) diag(n, "case/default outside a switch"); if(l == Z) { cas(); cases->val = 0; cases->def = 1; cases->label = pc; setsp();; goto rloop; } complex(l); if(l->type == T) goto rloop; if(l->op == OCONST) if(typechl[l->type->etype]) { cas(); cases->val = l->vconst; cases->def = 0; cases->label = pc; setsp(); goto rloop; } diag(n, "case expression must be integer constant"); goto rloop; case OSWITCH: l = n->left; complex(l); doinc(l, PRE); if(l->type == T) break; if(!typechl[l->type->etype]) { diag(n, "switch expression must be integer"); break; } g = regalloc(types[TLONG], D_NONE); n->type = types[TLONG]; cgen(l, g, n); regfree(g); doinc(l, POST); setsp(); gbranch(OGOTO); /* entry */ sp = p; cn = cases; cases = C; cas(); sbc = breakpc; breakpc = pc; gbranch(OGOTO); spb = p; gen(n->right); gbranch(OGOTO); patch(p, breakpc); patch(sp, pc); doswit(g, l); patch(spb, pc); cases = cn; breakpc = sbc; setsp(); break; case OWHILE: case ODWHILE: l = n->left; gbranch(OGOTO); /* entry */ sp = p; scc = continpc; continpc = pc; gbranch(OGOTO); spc = p; sbc = breakpc; breakpc = pc; gbranch(OGOTO); spb = p; patch(spc, pc); if(n->op == OWHILE) patch(sp, pc); bcomplex(l); /* test */ patch(p, breakpc); if(n->op == ODWHILE) patch(sp, pc); gen(n->right); /* body */ gbranch(OGOTO); patch(p, continpc); patch(spb, pc); continpc = scc; breakpc = sbc; break; case OFOR: l = n->left; gen(l->right->left); /* init */ gbranch(OGOTO); /* entry */ sp = p; scc = continpc; continpc = pc; gbranch(OGOTO); spc = p; sbc = breakpc; breakpc = pc; gbranch(OGOTO); spb = p; patch(spc, pc); gen(l->right->right); /* inc */ patch(sp, pc); if(l->left != Z) { /* test */ bcomplex(l->left); patch(p, breakpc); } gen(n->right); /* body */ gbranch(OGOTO); patch(p, continpc); patch(spb, pc); continpc = scc; breakpc = sbc; break; case OCONTINUE: if(continpc < 0) { diag(n, "continue not in a loop"); break; } gbranch(OGOTO); patch(p, continpc); break; case OBREAK: if(breakpc < 0) { diag(n, "break not in a loop"); break; } gbranch(OGOTO); patch(p, breakpc); break; case OIF: l = n->left; bcomplex(l); sp = p; if(n->right->left != Z) gen(n->right->left); if(n->right->right != Z) { gbranch(OGOTO); patch(sp, pc); sp = p; gen(n->right->right); } patch(sp, pc); break; case OSET: case OUSED: usedset(n->left, o); break; }} voidusedset(Node *n, int o){ if(n->op == OLIST) { usedset(n->left, o); usedset(n->right, o); return; } complex(n); switch(n->op) { case OADDR: /* volatile */ gopcode(OTST, types[TINT], D_TREE, n, D_NONE, Z); p->as = ANOP; break; case ONAME: if(o == OSET) gopcode(OTST, types[TINT], D_NONE, Z, D_TREE, n); else gopcode(OTST, types[TINT], D_TREE, n, D_NONE, Z); p->as = ANOP; break; }} voidnoretval(int n){ if(n & 1) { gopcode(OTST, types[TINT], D_NONE, Z, regret(types[TLONG]), Z); p->as = ANOP; } if(n & 2) { gopcode(OTST, types[TINT], D_NONE, Z, regret(types[TDOUBLE]), Z); p->as = ANOP; }} /* * calculate addressability as follows * REGISTER ==> 12 register * NAME ==> 10/11 name+value(SB/SP) * CONST ==> 20 $value * *(20) ==> 21 value * &(10) ==> 12 $name+value(SB) * &(11) ==> 1 $name+value(SP) * (12) + (20) ==> 12 fold constants * (1) + (20) ==> 1 fold constants * *(12) ==> 10 back to name * *(1) ==> 11 back to name * * (2,10,11) + (20) ==> 2 indirect w offset * (2) ==> &13 * *(10,11) ==> 13 indirect, no index * * (20) * (X) ==> 7 multiplier in indexing * (X,7) + (12,1) ==> 8 adder in indexing (addresses) * (X,7) + (10,11,2) ==> 8 adder in indexing (names) * (8) ==> &9 index, almost addressable * * (X)++ ==> X fake addressability * * calculate complexity (number of registers) */voidxcom(Node *n){ Node *l, *r; int g; if(n == Z) return; l = n->left; r = n->right; n->complex = 0; n->addable = 0; switch(n->op) { case OCONST: n->addable = 20; break; case ONAME: n->addable = 10; if(n->class == CPARAM || n->class == CAUTO) n->addable = 11; break; case OREGISTER: n->addable = 12; break; case OADDR: xcom(l); if(l->addable == 10) n->addable = 12; else if(l->addable == 11) n->addable = 1; break; case OADD: xcom(l); xcom(r); if(n->type->etype != TIND) break; if(l->addable == 20) switch(r->addable) { case 12: case 1: n->addable = r->addable; goto brk; case 10: case 11: case 2: goto addr13; } if(r->addable == 20) switch(l->addable) { case 12: case 1: n->addable = l->addable; goto brk; case 10: case 11: case 2: addr13: n->addable = 2; l = new1(OXXX, Z, Z); *l = *n; n->op = OIND; n->left = l; n->right = Z; n->addable = 13; l = new1(OXXX, Z, Z); *l = *n; n->op = OADDR; n->left = l; n->right = Z; n->addable = 2; goto brk; } switch(r->addable) { case 10: case 11: case 12: case 1: n->addable = 8; } switch(l->addable) { case 10: case 11: case 12: case 1: n->addable = 8; } if(n->addable == 8) { indx(n); l = new1(OINDEX, idx.basetree, idx.regtree); l->scale = idx.scale; l->addable = 9; l->complex = l->right->complex; l->type = l->left->type; n->op = OADDR; n->left = l; n->right = Z; n->addable = 0; break; } break; case OIND: xcom(l); if(l->op == OADDR) { l = l->left; l->type = n->type; *n = *l; return; } switch(l->addable) { case 20: n->addable = 21; break; case 1: n->addable = 11; break; case 12: n->addable = 10; break; case 10: case 11: case 2: n->addable = 13; break; } break; case OASHL:Lines 1–500 of 819. Load more
#include "gc.h" void codgen(Node *n, Node *nn) { Prog *sp; argoff = 0; inargs = 0; for(;; nn = nn->left) { if(nn == Z) { diag(Z, "cant find function name"); return; } if(nn->op == ONAME) break; } nearln = nn->lineno; gpseudo(ATEXT, nn->sym, D_CONST, stkoff); sp = p; retok = 0; gen(n); if(!retok) if(thisfn->link->etype != TVOID) warn(Z, "no return at end of function: %s", nn->sym->name); noretval(3); gbranch(ORETURN); if(!debug['N'] || debug['R'] || debug['P']) regopt(sp); } void gen(Node *n) { Node *l; Prog *sp, *spc, *spb; Case *cn; long sbc, scc; int g, o; loop: if(n == Z) return; nearln = n->lineno; o = n->op; if(debug['G']) if(o != OLIST) print("%L %O\n", nearln, o); retok = 0; switch(o) { default: complex(n); doinc(n, PRE); cgen(n, D_NONE, n); doinc(n, POST); break; case OLIST: gen(n->left); rloop: n = n->right; goto loop; case ORETURN: retok = 1; complex(n); if(n->type == T) break; l = n->left; if(l == Z) { noretval(3); gbranch(ORETURN); break; } doinc(l, PRE); if(typesuv[n->type->etype]) { sugen(l, D_TREE, nodret, n->type->width); doinc(l, POST); noretval(3); gbranch(ORETURN); break; } g = regalloc(n->type, regret(n->type)); cgen(l, g, n); doinc(l, POST); if(typefd[n->type->etype]) noretval(1); else noretval(2); gbranch(ORETURN); regfree(g); break; case OLABEL: l = n->left; if(l) { l->xoffset = pc; if(l->label) patch(l->label, pc); } gbranch(OGOTO); /* prevent self reference in reg */ patch(p, pc); goto rloop; case OGOTO: retok = 1; n = n->left; if(n == Z) return; if(n->complex == 0) { diag(Z, "label undefined: %s", n->sym->name); return; } gbranch(OGOTO); if(n->xoffset) { patch(p, n->xoffset); return; } if(n->label) patch(n->label, pc-1); n->label = p; return; case OCASE: l = n->left; if(cases == C) diag(n, "case/default outside a switch"); if(l == Z) { cas(); cases->val = 0; cases->def = 1; cases->label = pc; setsp();; goto rloop; } complex(l); if(l->type == T) goto rloop; if(l->op == OCONST) if(typechl[l->type->etype]) { cas(); cases->val = l->vconst; cases->def = 0; cases->label = pc; setsp(); goto rloop; } diag(n, "case expression must be integer constant"); goto rloop; case OSWITCH: l = n->left; complex(l); doinc(l, PRE); if(l->type == T) break; if(!typechl[l->type->etype]) { diag(n, "switch expression must be integer"); break; } g = regalloc(types[TLONG], D_NONE); n->type = types[TLONG]; cgen(l, g, n); regfree(g); doinc(l, POST); setsp(); gbranch(OGOTO); /* entry */ sp = p; cn = cases; cases = C; cas(); sbc = breakpc; breakpc = pc; gbranch(OGOTO); spb = p; gen(n->right); gbranch(OGOTO); patch(p, breakpc); patch(sp, pc); doswit(g, l); patch(spb, pc); cases = cn; breakpc = sbc; setsp(); break; case OWHILE: case ODWHILE: l = n->left; gbranch(OGOTO); /* entry */ sp = p; scc = continpc; continpc = pc; gbranch(OGOTO); spc = p; sbc = breakpc; breakpc = pc; gbranch(OGOTO); spb = p; patch(spc, pc); if(n->op == OWHILE) patch(sp, pc); bcomplex(l); /* test */ patch(p, breakpc); if(n->op == ODWHILE) patch(sp, pc); gen(n->right); /* body */ gbranch(OGOTO); patch(p, continpc); patch(spb, pc); continpc = scc; breakpc = sbc; break; case OFOR: l = n->left; gen(l->right->left); /* init */ gbranch(OGOTO); /* entry */ sp = p; scc = continpc; continpc = pc; gbranch(OGOTO); spc = p; sbc = breakpc; breakpc = pc; gbranch(OGOTO); spb = p; patch(spc, pc); gen(l->right->right); /* inc */ patch(sp, pc); if(l->left != Z) { /* test */ bcomplex(l->left); patch(p, breakpc); } gen(n->right); /* body */ gbranch(OGOTO); patch(p, continpc); patch(spb, pc); continpc = scc; breakpc = sbc; break; case OCONTINUE: if(continpc < 0) { diag(n, "continue not in a loop"); break; } gbranch(OGOTO); patch(p, continpc); break; case OBREAK: if(breakpc < 0) { diag(n, "break not in a loop"); break; } gbranch(OGOTO); patch(p, breakpc); break; case OIF: l = n->left; bcomplex(l); sp = p; if(n->right->left != Z) gen(n->right->left); if(n->right->right != Z) { gbranch(OGOTO); patch(sp, pc); sp = p; gen(n->right->right); } patch(sp, pc); break; case OSET: case OUSED: usedset(n->left, o); break; } } void usedset(Node *n, int o) { if(n->op == OLIST) { usedset(n->left, o); usedset(n->right, o); return; } complex(n); switch(n->op) { case OADDR: /* volatile */ gopcode(OTST, types[TINT], D_TREE, n, D_NONE, Z); p->as = ANOP; break; case ONAME: if(o == OSET) gopcode(OTST, types[TINT], D_NONE, Z, D_TREE, n); else gopcode(OTST, types[TINT], D_TREE, n, D_NONE, Z); p->as = ANOP; break; } } void noretval(int n) { if(n & 1) { gopcode(OTST, types[TINT], D_NONE, Z, regret(types[TLONG]), Z); p->as = ANOP; } if(n & 2) { gopcode(OTST, types[TINT], D_NONE, Z, regret(types[TDOUBLE]), Z); p->as = ANOP; } } /* * calculate addressability as follows * REGISTER ==> 12 register * NAME ==> 10/11 name+value(SB/SP) * CONST ==> 20 $value * *(20) ==> 21 value * &(10) ==> 12 $name+value(SB) * &(11) ==> 1 $name+value(SP) * (12) + (20) ==> 12 fold constants * (1) + (20) ==> 1 fold constants * *(12) ==> 10 back to name * *(1) ==> 11 back to name * * (2,10,11) + (20) ==> 2 indirect w offset * (2) ==> &13 * *(10,11) ==> 13 indirect, no index * * (20) * (X) ==> 7 multiplier in indexing * (X,7) + (12,1) ==> 8 adder in indexing (addresses) * (X,7) + (10,11,2) ==> 8 adder in indexing (names) * (8) ==> &9 index, almost addressable * * (X)++ ==> X fake addressability * * calculate complexity (number of registers) */ void xcom(Node *n) { Node *l, *r; int g; if(n == Z) return; l = n->left; r = n->right; n->complex = 0; n->addable = 0; switch(n->op) { case OCONST: n->addable = 20; break; case ONAME: n->addable = 10; if(n->class == CPARAM || n->class == CAUTO) n->addable = 11; break; case OREGISTER: n->addable = 12; break; case OADDR: xcom(l); if(l->addable == 10) n->addable = 12; else if(l->addable == 11) n->addable = 1; break; case OADD: xcom(l); xcom(r); if(n->type->etype != TIND) break; if(l->addable == 20) switch(r->addable) { case 12: case 1: n->addable = r->addable; goto brk; case 10: case 11: case 2: goto addr13; } if(r->addable == 20) switch(l->addable) { case 12: case 1: n->addable = l->addable; goto brk; case 10: case 11: case 2: addr13: n->addable = 2; l = new1(OXXX, Z, Z); *l = *n; n->op = OIND; n->left = l; n->right = Z; n->addable = 13; l = new1(OXXX, Z, Z); *l = *n; n->op = OADDR; n->left = l; n->right = Z; n->addable = 2; goto brk; } switch(r->addable) { case 10: case 11: case 12: case 1: n->addable = 8; } switch(l->addable) { case 10: case 11: case 12: case 1: n->addable = 8; } if(n->addable == 8) { indx(n); l = new1(OINDEX, idx.basetree, idx.regtree); l->scale = idx.scale; l->addable = 9; l->complex = l->right->complex; l->type = l->left->type; n->op = OADDR; n->left = l; n->right = Z; n->addable = 0; break; } break; case OIND: xcom(l); if(l->op == OADDR) { l = l->left; l->type = n->type; *n = *l; return; } switch(l->addable) { case 20: n->addable = 21; break; case 1: n->addable = 11; break; case 12: n->addable = 10; break; case 10: case 11: case 2: n->addable = 13; break; } break; case OASHL: