#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, AMOVL, AMOVL, AMOVW, AMOVW, AMOVB, AFMOVDP, AMOVL, AMOVL, AGOK, AGOK, AGOK, AGOK, AGOK }; int oload[] = { AGOK, AMOVL, AMOVL, AMOVWLSX,AMOVWLZX,AMOVBLZX,AFMOVD, AMOVL, AMOVL, AGOK, AGOK, AGOK, AGOK, AGOK }; voidload(Node *from, Node *to){ Node n1; int op; op = from->t->type; switch(op) { case TFLOAT: instruction(oload[op], from, to); break; default: reg(&n1, from->t, to); instruction(oload[op], from, &n1); assign(&n1, to); regfree(&n1); }} voidstore(Node *from, Node *to){ Node n1, *tmp; int op, t; op = ostore[to->t->type]; t = from->t->type; switch(t) { case TFLOAT: if(to->t->type == TFLOAT) { instruction(op, from, to); break; } tmp = stknode(builtype[TINT]); instruction(AFMOVLP, from, tmp); assign(tmp, to); break; default: if(vconst(from) == 0) { instruction(op, from, to); return; } if(t == to->t->type) reg(&n1, to->t, from); else reg(&n1, to->t, ZeroN); assign(from, &n1); instruction(op, &n1, to); regfree(&n1); }} /* * Compile code for moves */voidassign(Node *src, Node *dst){ Node *tmp; int op, dt; Inst *nofix; 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 = AMOVL; break; case TFLOAT: tmp = stknode(builtype[TINT]); assign(src, tmp); instruction(AFMOVL, tmp, F0); if(src->t->type != TUINT) return; instruction(ACMPL, src, con(0)); instruction(AJGE, ZeroN, ZeroN); nofix = ipc; instruction(AFADDD, conf(4294967296.), F0); label(nofix, ipc->pc+1); return; } break; case TSUINT: switch(dt) { case TINT: case TUINT: case TIND: op = AMOVWLZX; break; case TSUINT: case TCHAR: case TSINT: op = AMOVL; break; case TFLOAT: tmp = stknode(builtype[TINT]); assign(src, tmp); instruction(AFMOVL, tmp, F0); return; } break; case TSINT: switch(dt) { case TINT: case TUINT: case TIND: op = AMOVW; break; case TSUINT: case TCHAR: case TSINT: op = AMOVL; break; case TFLOAT: tmp = stknode(builtype[TINT]); assign(src, tmp); instruction(AFMOVL, tmp, F0); return; } break; case TFLOAT: switch(dt) { case TINT: case TUINT: case TIND: case TCHAR: case TSINT: case TSUINT: tmp = stknode(builtype[TINT]); instruction(AFMOVLP, src, tmp); assign(tmp, dst); return; case TFLOAT: op = AFMOVD; break; } break; case TCHAR: switch(dt) { case TINT: case TUINT: case TIND: op = AMOVBLZX; break; case TSUINT: case TSINT: case TCHAR: op = AMOVL; break; case TFLOAT: tmp = stknode(builtype[TINT]); assign(src, tmp); instruction(AFMOVL, tmp, F0); return; } break; } instruction(op, src, dst);} /* * This routine makes anything addressable */voidgenaddr(Node *expr, Node *dst){ Node n, *tmp; if(opt('g')) { print("genaddr:\n"); ptree(expr, 0); } switch(expr->type) { case OIND: genexp(expr->left, dst); return; default: if(!isaddr(expr)) { 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; } switch(dst->type) { case OINDREG: case OREGISTER: instruction(ALEAL, expr, dst); break; default: reg(&n, builtype[TIND], ZeroN); instruction(ALEAL, expr, &n); assign(&n, dst); regfree(&n); break; } }} /* * 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;} voidtoaddr(Node *l, Node *dst){ if(isaddr(l)) { *dst = *l; return; } rgenaddr(dst, l, ZeroN);} /* * pre and post increment generation */voidpostop(Node *rval, Node *lval){ Node *l, *nconst, n1, nop; 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; toaddr(l, &n1); nop.type = OADD; nop.t = builtype[TINT]; assign(&n1, lval); codmop(&nop, nconst, &n1, &n1); if(!isaddr(l)) regfree(&n1);} voidpreop(Node *rval, Node *lval){ Node *l, *nconst, n1, nop; 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; toaddr(l, &n1); nop.type = OADD; nop.t = builtype[TINT]; codmop(&nop, nconst, &n1, &n1); assign(&n1, lval); if(!isaddr(l)) regfree(&n1);} voiddocall(Node *n){ Node *rsp; if(atv == ZeroN) { instruction(ACALL, ZeroN, n); return; } /* * if calling through an activation, link * to the new stack */ ratv.ival = atv->atvsafe; rsp = regn(RegSP); instruction(AMOVL, rsp, &ratv); ratv.type = OREGISTER; assign(&ratv, rsp); instruction(ACALL, ZeroN, n); rsp->type = OINDREG; rsp->ival = atv->atvsafe; instruction(AMOVL, rsp, regn(RegSP)); regfree(&ratv);} /* * make reg free so we can use it as an implied register for things * like IDIV and SALL */intneed(int reg, Node *rnod, Node *rval, Node *lval){ int ref; Node *safe, *r, *l, n; l = rval->left; r = rval->right; if(needreg(reg, rnod, lval) == 0) return 0; safe = stknode(builtype[TINT]); assign(rnod, safe); ref = regsave(reg); /* * If the destination is the safe register generate an * assign into the safe stack location and let the optimiser * figure the redundant moves */ if(l->type == OREGISTER && l->reg == reg) { n = *rval; n.left = safe; genexp(&n, lval); } else if(r->type == OREGISTER && r->reg == reg) { n = *rval; n.right = safe; genexp(&n, lval); } else genexp(rval, lval); assign(safe, regn(reg)); regrest(reg, ref); return 1;} 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)) {Lines 1–500 of 1779. 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, AMOVL, AMOVL, AMOVW, AMOVW, AMOVB, AFMOVDP, AMOVL, AMOVL, AGOK, AGOK, AGOK, AGOK, AGOK }; int oload[] = { AGOK, AMOVL, AMOVL, AMOVWLSX,AMOVWLZX,AMOVBLZX,AFMOVD, AMOVL, AMOVL, AGOK, AGOK, AGOK, AGOK, AGOK }; void load(Node *from, Node *to) { Node n1; int op; op = from->t->type; switch(op) { case TFLOAT: instruction(oload[op], from, to); break; default: reg(&n1, from->t, to); instruction(oload[op], from, &n1); assign(&n1, to); regfree(&n1); } } void store(Node *from, Node *to) { Node n1, *tmp; int op, t; op = ostore[to->t->type]; t = from->t->type; switch(t) { case TFLOAT: if(to->t->type == TFLOAT) { instruction(op, from, to); break; } tmp = stknode(builtype[TINT]); instruction(AFMOVLP, from, tmp); assign(tmp, to); break; default: if(vconst(from) == 0) { instruction(op, from, to); return; } if(t == to->t->type) reg(&n1, to->t, from); else reg(&n1, to->t, ZeroN); assign(from, &n1); instruction(op, &n1, to); regfree(&n1); } } /* * Compile code for moves */ void assign(Node *src, Node *dst) { Node *tmp; int op, dt; Inst *nofix; 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 = AMOVL; break; case TFLOAT: tmp = stknode(builtype[TINT]); assign(src, tmp); instruction(AFMOVL, tmp, F0); if(src->t->type != TUINT) return; instruction(ACMPL, src, con(0)); instruction(AJGE, ZeroN, ZeroN); nofix = ipc; instruction(AFADDD, conf(4294967296.), F0); label(nofix, ipc->pc+1); return; } break; case TSUINT: switch(dt) { case TINT: case TUINT: case TIND: op = AMOVWLZX; break; case TSUINT: case TCHAR: case TSINT: op = AMOVL; break; case TFLOAT: tmp = stknode(builtype[TINT]); assign(src, tmp); instruction(AFMOVL, tmp, F0); return; } break; case TSINT: switch(dt) { case TINT: case TUINT: case TIND: op = AMOVW; break; case TSUINT: case TCHAR: case TSINT: op = AMOVL; break; case TFLOAT: tmp = stknode(builtype[TINT]); assign(src, tmp); instruction(AFMOVL, tmp, F0); return; } break; case TFLOAT: switch(dt) { case TINT: case TUINT: case TIND: case TCHAR: case TSINT: case TSUINT: tmp = stknode(builtype[TINT]); instruction(AFMOVLP, src, tmp); assign(tmp, dst); return; case TFLOAT: op = AFMOVD; break; } break; case TCHAR: switch(dt) { case TINT: case TUINT: case TIND: op = AMOVBLZX; break; case TSUINT: case TSINT: case TCHAR: op = AMOVL; break; case TFLOAT: tmp = stknode(builtype[TINT]); assign(src, tmp); instruction(AFMOVL, tmp, F0); return; } break; } instruction(op, src, dst); } /* * This routine makes anything addressable */ void genaddr(Node *expr, Node *dst) { Node n, *tmp; if(opt('g')) { print("genaddr:\n"); ptree(expr, 0); } switch(expr->type) { case OIND: genexp(expr->left, dst); return; default: if(!isaddr(expr)) { 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; } switch(dst->type) { case OINDREG: case OREGISTER: instruction(ALEAL, expr, dst); break; default: reg(&n, builtype[TIND], ZeroN); instruction(ALEAL, expr, &n); assign(&n, dst); regfree(&n); break; } } } /* * 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; } void toaddr(Node *l, Node *dst) { if(isaddr(l)) { *dst = *l; return; } rgenaddr(dst, l, ZeroN); } /* * pre and post increment generation */ void postop(Node *rval, Node *lval) { Node *l, *nconst, n1, nop; 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; toaddr(l, &n1); nop.type = OADD; nop.t = builtype[TINT]; assign(&n1, lval); codmop(&nop, nconst, &n1, &n1); if(!isaddr(l)) regfree(&n1); } void preop(Node *rval, Node *lval) { Node *l, *nconst, n1, nop; 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; toaddr(l, &n1); nop.type = OADD; nop.t = builtype[TINT]; codmop(&nop, nconst, &n1, &n1); assign(&n1, lval); if(!isaddr(l)) regfree(&n1); } void docall(Node *n) { Node *rsp; if(atv == ZeroN) { instruction(ACALL, ZeroN, n); return; } /* * if calling through an activation, link * to the new stack */ ratv.ival = atv->atvsafe; rsp = regn(RegSP); instruction(AMOVL, rsp, &ratv); ratv.type = OREGISTER; assign(&ratv, rsp); instruction(ACALL, ZeroN, n); rsp->type = OINDREG; rsp->ival = atv->atvsafe; instruction(AMOVL, rsp, regn(RegSP)); regfree(&ratv); } /* * make reg free so we can use it as an implied register for things * like IDIV and SALL */ int need(int reg, Node *rnod, Node *rval, Node *lval) { int ref; Node *safe, *r, *l, n; l = rval->left; r = rval->right; if(needreg(reg, rnod, lval) == 0) return 0; safe = stknode(builtype[TINT]); assign(rnod, safe); ref = regsave(reg); /* * If the destination is the safe register generate an * assign into the safe stack location and let the optimiser * figure the redundant moves */ if(l->type == OREGISTER && l->reg == reg) { n = *rval; n.left = safe; genexp(&n, lval); } else if(r->type == OREGISTER && r->reg == reg) { n = *rval; n.right = safe; genexp(&n, lval); } else genexp(rval, lval); assign(safe, regn(reg)); regrest(reg, ref); return 1; } 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)) {