#include <u.h>#include <libc.h>#include <bio.h>#include <ctype.h>#define Extern extern#include "parl.h"#include "globl.h" voidgendata(Node *n){ Type *t; Inst *i; ulong s; if(n == ZeroN) return; switch(n->type) { default: gendata(n->left); gendata(n->right); break; case OAGDECL: case OUNDECL: case OADTDECL: case OSETDECL: case OFUNC: break; case ONAME: switch(n->t->class) { case Internal: case Global: iline = n->srcline; t = n->t; if(n->init) doinit(n, t, n->init, 0); s = t->size; if(s == 0) break; if(s & (Align_data-1)) s += Align_data-(s&(Align_data-1)); i = ai(); i->op = AGLOBL; mkaddr(con(s), &i->dst, 0); mkaddr(n, &i->src1, 0); ilink(i); break; } break; }} /* Load/store instructions by type TXXX TINT TUINT TSINT TSUINT TCHAR TFLOAT TIND TCHAN TARY TAGG TUNI TFUNC TVOID*/int ostore[] ={ AGOK, AMOVW, AMOVW, AMOVH, AMOVH, AMOVB, AMOVD, AMOVW, AMOVW, AGOK, AGOK, AGOK, AGOK, AGOK }; int oload[] = { AGOK, AMOVW, AMOVW, AMOVH, AMOVHU,AMOVBU,AMOVD, AMOVW, AMOVW,AGOK, AGOK, AGOK, AGOK, AGOK }; voidload(Node *from, Node *to){ Node n1; int op; op = oload[from->t->type]; reg(&n1, from->t, to); instruction(op, from, ZeroN, &n1); assign(&n1, to); regfree(&n1);} voidstore(Node *from, Node *to){ Node n1; int op, t; op = ostore[to->t->type]; t = from->t->type; if(t != TFLOAT) if(vconst(from) == 0) { instruction(op, from, ZeroN, to); return; } if(t == to->t->type) reg(&n1, to->t, from); else reg(&n1, to->t, ZeroN); assign(from, &n1); instruction(op, &n1, ZeroN, to); regfree(&n1);} /* * Compile code for moves */voidassign(Node *src, Node *dst){ Node n1; int op, dt; if(opt('a')) print("assign: %N = %N\n", dst, src); if(dst == ZeroN) return; switch(src->type) { case ONAME: case OINDREG: case OIND: load(src, dst); return; } switch(dst->type) { case ONAME: case OINDREG: case OIND: store(src, dst); return; } /* delete register/register nop moves */ if(src->type == OREGISTER) if(dst->type == OREGISTER) if(dst->reg == src->reg) if(dst->type == src->type) return; op = AGOK; dt = dst->t->type; switch(src->t->type) { case TINT: case TUINT: case TIND: case TCHANNEL: switch(dt) { case TINT: case TUINT: case TCHAR: case TSUINT: case TSINT: case TIND: case TCHANNEL: op = AMOVW; break; case TFLOAT: instruction(AMOVW, src, ZeroN, dst); instruction(AMOVWD, dst, ZeroN, dst); return; } break; case TSUINT: switch(dt) { case TINT: case TUINT: case TIND: op = AMOVHU; break; case TSUINT: case TCHAR: case TSINT: op = AMOVW; break; case TFLOAT: reg(&n1, src->t, ZeroN); instruction(AMOVHU, src, ZeroN, &n1); instruction(AMOVW, &n1, ZeroN, dst); instruction(AMOVWD, dst, ZeroN, dst); regfree(&n1); return; } break; case TSINT: switch(dt) { case TINT: case TUINT: case TIND: op = AMOVH; break; case TSUINT: case TCHAR: case TSINT: op = AMOVW; break; case TFLOAT: reg(&n1, src->t, ZeroN); instruction(AMOVH, src, ZeroN, &n1); instruction(AMOVW, &n1, ZeroN, dst); instruction(AMOVWD, dst, ZeroN, dst); regfree(&n1); return; } break; case TFLOAT: switch(dt) { case TINT: case TUINT: case TIND: instruction(AMOVDW, src, ZeroN, src); instruction(AMOVW, src, ZeroN, dst); return; case TCHAR: reg(&n1, dst->t, ZeroN); instruction(AMOVDW, src, ZeroN, src); instruction(AMOVW, src, ZeroN, &n1); instruction(AMOVBU, &n1, ZeroN, dst); regfree(&n1); return; case TSINT: reg(&n1, dst->t, ZeroN); instruction(AMOVDW, src, ZeroN, src); instruction(AMOVW, src, ZeroN, &n1); instruction(AMOVH, &n1, ZeroN, dst); regfree(&n1); return; case TSUINT: reg(&n1, dst->t, ZeroN); instruction(AMOVDW, src, ZeroN, src); instruction(AMOVW, src, ZeroN, &n1); instruction(AMOVHU, &n1, ZeroN, dst); regfree(&n1); return; case TFLOAT: op = AMOVD; break; } break; case TCHAR: switch(dt) { case TINT: case TUINT: case TIND: op = AMOVBU; break; case TSUINT: case TSINT: case TCHAR: op = AMOVW; break; case TFLOAT: reg(&n1, src->t, ZeroN); instruction(AMOVBU, src, ZeroN, &n1); instruction(AMOVW, &n1, ZeroN, dst); instruction(AMOVWD, dst, ZeroN, dst); regfree(&n1); return; } break; } instruction(op, src, ZeroN, dst);} /* * Generate the address of an expression */voidgenaddr(Node *expr, Node *dst){ Node n, *tmp; if(opt('g')) print("genaddr: %N\n", expr); if(expr->type == OIND) { genexp(expr->left, dst); return; } n.srcline = expr->srcline; if(isaddr(expr) == 0) { tmp = stknode(expr->t); n.type = OASGN; n.t = tmp->t; n.left = tmp; n.right = expr; n.islval = 0; genexp(&n, ZeroN); expr = tmp; } n = *expr; reg(&n, builtype[TIND], dst); n.type = OADDR; n.left = expr; n.right = ZeroN; n.t = builtype[TIND]; assign(&n, dst); regfree(&n);} /* * generate an l-value into a register */voidrgenaddr(Node *t, Node *rval, Node *lval){ Node *r; ulong v; *t = *rval; t->t = builtype[TIND]; reg(t, t->t, lval); if(rval->type == OIND) { r = rval->left; while(r->type == OADD) r = r->right; if(immed(r)) { v = r->ival; r->ival = 0; genaddr(rval, t); t->ival += v; r->ival = v; t->type = OINDREG; t->t = rval->t; return; } } genaddr(rval, t); t->type = OINDREG; t->t = rval->t;} /* * pre and post increment generation */voidpostop(Node *rval, Node *lval){ Node *l, *nconst; Node n1, n2, n3, n4; l = rval->left; nconst = con(1); if(l->t->type == TIND) nconst->ival = l->t->next->size; if(rval->type == OPDEC) nconst->ival = -nconst->ival; if(l->islval < Sucompute) rgenaddr(&n2, l, ZeroN); else n2 = *l; n3.type = OADD; n3.t = builtype[TINT]; /* Easy if we dont need the value after the inc */ if(lval == ZeroN) { reg(&n1, l->t, lval); assign(&n2, &n1); codmop(&n3, nconst, &n1, &n1); assign(&n1, &n2); goto out; } reg(&n4, l->t, lval); assign(&n2, &n4); reg(&n1, l->t, ZeroN); /* Thank RISC for three address ! */ codmop(&n3, nconst, &n4, &n1); assign(&n1, &n2); regfree(&n4);out: regfree(&n1); if(l->islval < Sucompute) regfree(&n2);} voidpreop(Node *rval, Node *lval){ Node n1, n2, n3; Node *l, *nconst; l = rval->left; nconst = con(1); if(l->t->type == TIND) nconst->ival = l->t->next->size; if(rval->type == OEDEC) nconst->ival = -nconst->ival; if(l->islval < Sucompute) rgenaddr(&n2, l, ZeroN); else n2 = *l; reg(&n1, l->t, lval); assign(&n2, &n1); n3.type = OADD; n3.t = builtype[TINT]; codmop(&n3, nconst, &n1, &n1); assign(&n1, &n2); regfree(&n1); if(l->islval < Sucompute) regfree(&n2);} voiddocall(Node *n){ Node *rsp; if(atv == ZeroN) { instruction(AJAL, ZeroN, ZeroN, n); return; } /* * if calling through an activation, link * to the new stack */ ratv.ival = atv->atvsafe; rsp = regn(RegSP); instruction(AMOVW, rsp, ZeroN, &ratv); ratv.type = OREGISTER; assign(&ratv, rsp); instruction(AJAL, ZeroN, ZeroN, n); rsp->type = OINDREG; rsp->ival = atv->atvsafe; instruction(AMOVW, rsp, ZeroN, regn(RegSP)); regfree(&ratv);} voidbecome(Node *rval){ Node nl; Node *l, *r, *ns, *tmp; tmp = rval->left; r = tmp->right; l = tmp->left; if(opt('b')) { print("BECOME:\n"); ptree(rval, 0); } tmp = ZeroN; if(!isaddr(l)) { tmp = stknode(builtype[TIND]); genaddr(l, tmp); } /* Generate the alias saves */ genelist(rval->right); evalarg(r, 0); /* * Write out tail recursion */ if(l->type == ONAME && curfunc->sym == l->sym) { tip = block[Scope]; evalarg(r, 4); instruction(AJMP, ZeroN, ZeroN, ZeroN); label(ipc, becomentry->pc+1); return; } ns = an(ONAME, ZeroN, ZeroN);Lines 1–500 of 1543. Load more
#include <u.h> #include <libc.h> #include <bio.h> #include <ctype.h> #define Extern extern #include "parl.h" #include "globl.h" void gendata(Node *n) { Type *t; Inst *i; ulong s; if(n == ZeroN) return; switch(n->type) { default: gendata(n->left); gendata(n->right); break; case OAGDECL: case OUNDECL: case OADTDECL: case OSETDECL: case OFUNC: break; case ONAME: switch(n->t->class) { case Internal: case Global: iline = n->srcline; t = n->t; if(n->init) doinit(n, t, n->init, 0); s = t->size; if(s == 0) break; if(s & (Align_data-1)) s += Align_data-(s&(Align_data-1)); i = ai(); i->op = AGLOBL; mkaddr(con(s), &i->dst, 0); mkaddr(n, &i->src1, 0); ilink(i); break; } break; } } /* Load/store instructions by type TXXX TINT TUINT TSINT TSUINT TCHAR TFLOAT TIND TCHAN TARY TAGG TUNI TFUNC TVOID */ int ostore[] ={ AGOK, AMOVW, AMOVW, AMOVH, AMOVH, AMOVB, AMOVD, AMOVW, AMOVW, AGOK, AGOK, AGOK, AGOK, AGOK }; int oload[] = { AGOK, AMOVW, AMOVW, AMOVH, AMOVHU,AMOVBU,AMOVD, AMOVW, AMOVW,AGOK, AGOK, AGOK, AGOK, AGOK }; void load(Node *from, Node *to) { Node n1; int op; op = oload[from->t->type]; reg(&n1, from->t, to); instruction(op, from, ZeroN, &n1); assign(&n1, to); regfree(&n1); } void store(Node *from, Node *to) { Node n1; int op, t; op = ostore[to->t->type]; t = from->t->type; if(t != TFLOAT) if(vconst(from) == 0) { instruction(op, from, ZeroN, to); return; } if(t == to->t->type) reg(&n1, to->t, from); else reg(&n1, to->t, ZeroN); assign(from, &n1); instruction(op, &n1, ZeroN, to); regfree(&n1); } /* * Compile code for moves */ void assign(Node *src, Node *dst) { Node n1; int op, dt; if(opt('a')) print("assign: %N = %N\n", dst, src); if(dst == ZeroN) return; switch(src->type) { case ONAME: case OINDREG: case OIND: load(src, dst); return; } switch(dst->type) { case ONAME: case OINDREG: case OIND: store(src, dst); return; } /* delete register/register nop moves */ if(src->type == OREGISTER) if(dst->type == OREGISTER) if(dst->reg == src->reg) if(dst->type == src->type) return; op = AGOK; dt = dst->t->type; switch(src->t->type) { case TINT: case TUINT: case TIND: case TCHANNEL: switch(dt) { case TINT: case TUINT: case TCHAR: case TSUINT: case TSINT: case TIND: case TCHANNEL: op = AMOVW; break; case TFLOAT: instruction(AMOVW, src, ZeroN, dst); instruction(AMOVWD, dst, ZeroN, dst); return; } break; case TSUINT: switch(dt) { case TINT: case TUINT: case TIND: op = AMOVHU; break; case TSUINT: case TCHAR: case TSINT: op = AMOVW; break; case TFLOAT: reg(&n1, src->t, ZeroN); instruction(AMOVHU, src, ZeroN, &n1); instruction(AMOVW, &n1, ZeroN, dst); instruction(AMOVWD, dst, ZeroN, dst); regfree(&n1); return; } break; case TSINT: switch(dt) { case TINT: case TUINT: case TIND: op = AMOVH; break; case TSUINT: case TCHAR: case TSINT: op = AMOVW; break; case TFLOAT: reg(&n1, src->t, ZeroN); instruction(AMOVH, src, ZeroN, &n1); instruction(AMOVW, &n1, ZeroN, dst); instruction(AMOVWD, dst, ZeroN, dst); regfree(&n1); return; } break; case TFLOAT: switch(dt) { case TINT: case TUINT: case TIND: instruction(AMOVDW, src, ZeroN, src); instruction(AMOVW, src, ZeroN, dst); return; case TCHAR: reg(&n1, dst->t, ZeroN); instruction(AMOVDW, src, ZeroN, src); instruction(AMOVW, src, ZeroN, &n1); instruction(AMOVBU, &n1, ZeroN, dst); regfree(&n1); return; case TSINT: reg(&n1, dst->t, ZeroN); instruction(AMOVDW, src, ZeroN, src); instruction(AMOVW, src, ZeroN, &n1); instruction(AMOVH, &n1, ZeroN, dst); regfree(&n1); return; case TSUINT: reg(&n1, dst->t, ZeroN); instruction(AMOVDW, src, ZeroN, src); instruction(AMOVW, src, ZeroN, &n1); instruction(AMOVHU, &n1, ZeroN, dst); regfree(&n1); return; case TFLOAT: op = AMOVD; break; } break; case TCHAR: switch(dt) { case TINT: case TUINT: case TIND: op = AMOVBU; break; case TSUINT: case TSINT: case TCHAR: op = AMOVW; break; case TFLOAT: reg(&n1, src->t, ZeroN); instruction(AMOVBU, src, ZeroN, &n1); instruction(AMOVW, &n1, ZeroN, dst); instruction(AMOVWD, dst, ZeroN, dst); regfree(&n1); return; } break; } instruction(op, src, ZeroN, dst); } /* * Generate the address of an expression */ void genaddr(Node *expr, Node *dst) { Node n, *tmp; if(opt('g')) print("genaddr: %N\n", expr); if(expr->type == OIND) { genexp(expr->left, dst); return; } n.srcline = expr->srcline; if(isaddr(expr) == 0) { tmp = stknode(expr->t); n.type = OASGN; n.t = tmp->t; n.left = tmp; n.right = expr; n.islval = 0; genexp(&n, ZeroN); expr = tmp; } n = *expr; reg(&n, builtype[TIND], dst); n.type = OADDR; n.left = expr; n.right = ZeroN; n.t = builtype[TIND]; assign(&n, dst); regfree(&n); } /* * generate an l-value into a register */ void rgenaddr(Node *t, Node *rval, Node *lval) { Node *r; ulong v; *t = *rval; t->t = builtype[TIND]; reg(t, t->t, lval); if(rval->type == OIND) { r = rval->left; while(r->type == OADD) r = r->right; if(immed(r)) { v = r->ival; r->ival = 0; genaddr(rval, t); t->ival += v; r->ival = v; t->type = OINDREG; t->t = rval->t; return; } } genaddr(rval, t); t->type = OINDREG; t->t = rval->t; } /* * pre and post increment generation */ void postop(Node *rval, Node *lval) { Node *l, *nconst; Node n1, n2, n3, n4; l = rval->left; nconst = con(1); if(l->t->type == TIND) nconst->ival = l->t->next->size; if(rval->type == OPDEC) nconst->ival = -nconst->ival; if(l->islval < Sucompute) rgenaddr(&n2, l, ZeroN); else n2 = *l; n3.type = OADD; n3.t = builtype[TINT]; /* Easy if we dont need the value after the inc */ if(lval == ZeroN) { reg(&n1, l->t, lval); assign(&n2, &n1); codmop(&n3, nconst, &n1, &n1); assign(&n1, &n2); goto out; } reg(&n4, l->t, lval); assign(&n2, &n4); reg(&n1, l->t, ZeroN); /* Thank RISC for three address ! */ codmop(&n3, nconst, &n4, &n1); assign(&n1, &n2); regfree(&n4); out: regfree(&n1); if(l->islval < Sucompute) regfree(&n2); } void preop(Node *rval, Node *lval) { Node n1, n2, n3; Node *l, *nconst; l = rval->left; nconst = con(1); if(l->t->type == TIND) nconst->ival = l->t->next->size; if(rval->type == OEDEC) nconst->ival = -nconst->ival; if(l->islval < Sucompute) rgenaddr(&n2, l, ZeroN); else n2 = *l; reg(&n1, l->t, lval); assign(&n2, &n1); n3.type = OADD; n3.t = builtype[TINT]; codmop(&n3, nconst, &n1, &n1); assign(&n1, &n2); regfree(&n1); if(l->islval < Sucompute) regfree(&n2); } void docall(Node *n) { Node *rsp; if(atv == ZeroN) { instruction(AJAL, ZeroN, ZeroN, n); return; } /* * if calling through an activation, link * to the new stack */ ratv.ival = atv->atvsafe; rsp = regn(RegSP); instruction(AMOVW, rsp, ZeroN, &ratv); ratv.type = OREGISTER; assign(&ratv, rsp); instruction(AJAL, ZeroN, ZeroN, n); rsp->type = OINDREG; rsp->ival = atv->atvsafe; instruction(AMOVW, rsp, ZeroN, regn(RegSP)); regfree(&ratv); } void become(Node *rval) { Node nl; Node *l, *r, *ns, *tmp; tmp = rval->left; r = tmp->right; l = tmp->left; if(opt('b')) { print("BECOME:\n"); ptree(rval, 0); } tmp = ZeroN; if(!isaddr(l)) { tmp = stknode(builtype[TIND]); genaddr(l, tmp); } /* Generate the alias saves */ genelist(rval->right); evalarg(r, 0); /* * Write out tail recursion */ if(l->type == ONAME && curfunc->sym == l->sym) { tip = block[Scope]; evalarg(r, 4); instruction(AJMP, ZeroN, ZeroN, ZeroN); label(ipc, becomentry->pc+1); return; } ns = an(ONAME, ZeroN, ZeroN);