void prtree(FILE *out, Node *n, int lvl) { switch (n->what) { case nNUM: { indent(out, lvl), fprintf(out, "%lld", n->n); break; } case nFP: { indent(out, lvl), fprintf(out, "%g", n->fp); break; } case nSTR: { indent(out, lvl), fprintf(out, "\"%s\"", n->s); break; } case nVOID: { indent(out, lvl), fprintf(out, "void"); break; } default: { if (n->s) indent(out, lvl), fprintf(out, "%s", n->s); else { indent(out, lvl), fprintf(out, "(%s\n", what_tab[n->what].name); if (n->l) prtree(out, n->l, lvl + 2); if (n->r) prtree(out, n->r, lvl + 2); indent(out, lvl), fprintf(out, ")"); } } } fprintf(out, "\n"); }
void lcgen(Node *n, Node *nn) { Prog *p1; Node nod; if(debug['g']) { prtree(nn, "lcgen lhs"); prtree(n, "lcgen"); } if(n == Z || n->type == T) return; if(nn == Z) { nn = &nod; regalloc(&nod, n, Z); } switch(n->op) { default: if(n->addable < INDEXED) { diag(n, "unknown op in lcgen: %O", n->op); break; } nod = *n; nod.op = OADDR; nod.left = n; nod.right = Z; nod.type = types[TIND]; gopcode(OAS, &nod, Z, nn); break; case OCOMMA: cgen(n->left, n->left); lcgen(n->right, nn); break; case OIND: cgen(n->left, nn); break; case OCOND: bcgen(n->left, 1); p1 = p; lcgen(n->right->left, nn); gbranch(OGOTO); patch(p1, pc); p1 = p; lcgen(n->right->right, nn); patch(p1, pc); break; } }
static void prpc(struct imap_refmsgtable *mt) { struct imap_refmsg *root=rfc822_threadgetroot(mt), *m; if (!root) return; for (m=root->firstchild; m; m=m->nextsib) prtree(m); printf("\n\n"); }
void prsym(Sym *s) { int i, n; if (s < wall && fflag) flatten(s->exp); if (n = s->inst) { if (n < 1) return; for (s++, i = 0; i < n; i++, s++) if (s->lval) { fprintf(stdout, "%s.%s = ", s->name, s->pin); prtree(s->exp); fprintf(stdout, "\n"); } } if (!s->lval) return; fprintf(stdout,"%s = ",s->name); prtree(s->exp); fprintf(stdout,"\n"); }
static void prtree(struct imap_refmsg *m) { printf("<%s>", m->msgid ? m->msgid:""); if (m->isdummy) { printf(" (dummy)"); } printf(".parent="); if (m->parent) printf("<%s>", m->parent->msgid ? m->parent->msgid:""); else printf("ROOT"); printf("\n"); for (m=m->firstchild; m; m=m->nextsib) prtree(m); }
int main(int argc, char** argv) { int arg, i; char *mfile = NULL; for (arg = 1; arg < argc; ++arg) if (*argv[arg] == '-') { if ('f'==clower(argv[arg][1])) { if (++arg >= argc) { fprintf(stderr, "-f needs filename argument.\n"); return 1; } mfile = argv[arg]; } else opt_char(argv[arg][1]); } else if (modcount < MAXMODS) { if (argv[arg][0]) /* ignore trailing whitespace */ modnames[modcount++] = argv[arg]; } else { fprintf(stderr, "Too many module names.\n"); return 1; } if (mfile != NULL) { arg = fmake(mfile); if (arg == -1) fprintf(stderr, "\nCannot open makefile\n"); } else { for (i = 0; *mfiles[i]; ++i) if ((arg=fmake(mfiles[i])) != -1) break; if (!*mfiles[i]) fprintf(stderr, "\nCannot open makefile\n"); } if (debug) prtree(); return arg; }
void cgen(Node *n, Node *nn) { Node *l, *r; Prog *p1; Node nod, nod1, nod2, nod3, nod4; int o; long v, curs; if(debug['g']) { prtree(nn, "cgen lhs"); prtree(n, "cgen"); } if(n == Z || n->type == T) return; if(typesuv[n->type->etype]) { sugen(n, nn, n->type->width); return; } l = n->left; r = n->right; o = n->op; if(n->addable >= INDEXED) { if(nn == Z) { switch(o) { default: nullwarn(Z, Z); break; case OINDEX: nullwarn(l, r); break; } return; } gmove(n, nn); return; } curs = cursafe; if(n->complex >= FNX) if(l->complex >= FNX) if(r != Z && r->complex >= FNX) switch(o) { default: regret(&nod, r); cgen(r, &nod); regsalloc(&nod1, r); gopcode(OAS, &nod, Z, &nod1); regfree(&nod); nod = *n; nod.right = &nod1; cgen(&nod, nn); return; case OFUNC: case OCOMMA: case OANDAND: case OOROR: case OCOND: case ODOT: break; } switch(o) { default: diag(n, "unknown op in cgen: %O", o); break; case OAS: if(l->op == OBIT) goto bitas; if(l->addable >= INDEXED && l->complex < FNX) { if(nn != Z || r->addable < INDEXED) { if(r->complex >= FNX && nn == Z) regret(&nod, r); else regalloc(&nod, r, nn); cgen(r, &nod); gmove(&nod, l); if(nn != Z) gmove(&nod, nn); regfree(&nod); } else gmove(r, l); break; } if(l->complex >= r->complex) { reglcgen(&nod1, l, Z); if(r->addable >= INDEXED) { gmove(r, &nod1); if(nn != Z) gmove(r, nn); regfree(&nod1); break; } regalloc(&nod, r, nn); cgen(r, &nod); } else { regalloc(&nod, r, nn); cgen(r, &nod); reglcgen(&nod1, l, Z); } gmove(&nod, &nod1); regfree(&nod); regfree(&nod1); break; bitas: n = l->left; regalloc(&nod, r, nn); if(l->complex >= r->complex) { reglcgen(&nod1, n, Z); cgen(r, &nod); } else { cgen(r, &nod); reglcgen(&nod1, n, Z); } regalloc(&nod2, n, Z); gopcode(OAS, &nod1, Z, &nod2); bitstore(l, &nod, &nod1, &nod2, nn); break; case OBIT: if(nn == Z) { nullwarn(l, Z); break; } bitload(n, &nod, Z, Z, nn); gopcode(OAS, &nod, Z, nn); regfree(&nod); break; case OADD: case OSUB: case OAND: case OOR: case OXOR: case OLSHR: case OASHL: case OASHR: /* * immediate operands */ if(nn != Z) if(r->op == OCONST) if(!typefd[n->type->etype]) { cgen(l, nn); if(r->vconst == 0) if(o != OAND) break; if(nn != Z) gopcode(o, r, Z, nn); break; } case OLMUL: case OLDIV: case OLMOD: case OMUL: case ODIV: case OMOD: if(nn == Z) { nullwarn(l, r); break; } if(o == OMUL || o == OLMUL) { if(mulcon(n, nn)) break; } if(l->complex >= r->complex) { regalloc(&nod, l, nn); cgen(l, &nod); regalloc(&nod1, r, Z); cgen(r, &nod1); gopcode(o, &nod1, Z, &nod); } else { regalloc(&nod, r, nn); cgen(r, &nod); regalloc(&nod1, l, Z); cgen(l, &nod1); gopcode(o, &nod, &nod1, &nod); } gopcode(OAS, &nod, Z, nn); regfree(&nod); regfree(&nod1); break; case OASLSHR: case OASASHL: case OASASHR: case OASAND: case OASADD: case OASSUB: case OASXOR: case OASOR: if(l->op == OBIT) goto asbitop; if(r->op == OCONST) if(!typefd[r->type->etype]) if(!typefd[n->type->etype]) { if(l->addable < INDEXED) reglcgen(&nod2, l, Z); else nod2 = *l; regalloc(&nod, r, nn); gopcode(OAS, &nod2, Z, &nod); gopcode(o, r, Z, &nod); gopcode(OAS, &nod, Z, &nod2); regfree(&nod); if(l->addable < INDEXED) regfree(&nod2); break; } case OASLMUL: case OASLDIV: case OASLMOD: case OASMUL: case OASDIV: case OASMOD: if(l->op == OBIT) goto asbitop; if(l->complex >= r->complex) { if(l->addable < INDEXED) reglcgen(&nod2, l, Z); else nod2 = *l; regalloc(&nod1, r, Z); cgen(r, &nod1); } else { regalloc(&nod1, r, Z); cgen(r, &nod1); if(l->addable < INDEXED) reglcgen(&nod2, l, Z); else nod2 = *l; } regalloc(&nod, n, nn); gmove(&nod2, &nod); gopcode(o, &nod1, Z, &nod); gmove(&nod, &nod2); if(nn != Z) gopcode(OAS, &nod, Z, nn); regfree(&nod); regfree(&nod1); if(l->addable < INDEXED) regfree(&nod2); break; asbitop: regalloc(&nod4, n, nn); if(l->complex >= r->complex) { bitload(l, &nod, &nod1, &nod2, &nod4); regalloc(&nod3, r, Z); cgen(r, &nod3); } else { regalloc(&nod3, r, Z); cgen(r, &nod3); bitload(l, &nod, &nod1, &nod2, &nod4); } gmove(&nod, &nod4); gopcode(o, &nod3, Z, &nod4); regfree(&nod3); gmove(&nod4, &nod); regfree(&nod4); bitstore(l, &nod, &nod1, &nod2, nn); break; case OADDR: if(nn == Z) { nullwarn(l, Z); break; } lcgen(l, nn); break; case OFUNC: if(l->complex >= FNX) { if(l->op != OIND) diag(n, "bad function call"); regret(&nod, l->left); cgen(l->left, &nod); regsalloc(&nod1, l->left); gopcode(OAS, &nod, Z, &nod1); regfree(&nod); nod = *n; nod.left = &nod2; nod2 = *l; nod2.left = &nod1; nod2.complex = 1; cgen(&nod, nn); return; } o = reg[REGARG]; gargs(r, &nod, &nod1); if(l->addable < INDEXED) { reglcgen(&nod, l, Z); gopcode(OFUNC, Z, Z, &nod); regfree(&nod); } else gopcode(OFUNC, Z, Z, l); if(REGARG) if(o != reg[REGARG]) reg[REGARG]--; if(nn != Z) { regret(&nod, n); gopcode(OAS, &nod, Z, nn); regfree(&nod); } break; case OIND: if(nn == Z) { nullwarn(l, Z); break; } regialloc(&nod, n, nn); r = l; while(r->op == OADD) r = r->right; if(sconst(r)) { v = r->vconst; r->vconst = 0; cgen(l, &nod); nod.xoffset += v; r->vconst = v; } else cgen(l, &nod); regind(&nod, n); gopcode(OAS, &nod, Z, nn); regfree(&nod); break; case OEQ: case ONE: case OLE: case OLT: case OGE: case OGT: case OLO: case OLS: case OHI: case OHS: if(nn == Z) { nullwarn(l, r); break; } boolgen(n, 1, nn); break; case OANDAND: case OOROR: boolgen(n, 1, nn); if(nn == Z) patch(p, pc); break; case ONOT: if(nn == Z) { nullwarn(l, Z); break; } boolgen(n, 1, nn); break; case OCOMMA: cgen(l, Z); cgen(r, nn); break; case OCAST: if(nn == Z) { nullwarn(l, Z); break; } /* * convert from types l->n->nn */ if(nocast(l->type, n->type)) { if(nocast(n->type, nn->type)) { cgen(l, nn); break; } } regalloc(&nod, l, nn); cgen(l, &nod); regalloc(&nod1, n, &nod); gopcode(OAS, &nod, Z, &nod1); gopcode(OAS, &nod1, Z, nn); regfree(&nod1); regfree(&nod); break; case ODOT: sugen(l, nodrat, l->type->width); if(nn != Z) { warn(n, "non-interruptable temporary"); nod = *nodrat; if(!r || r->op != OCONST) { diag(n, "DOT and no offset"); break; } nod.xoffset += (long)r->vconst; nod.type = n->type; cgen(&nod, nn); } break; case OCOND: bcgen(l, 1); p1 = p; cgen(r->left, nn); gbranch(OGOTO); patch(p1, pc); p1 = p; cgen(r->right, nn); patch(p1, pc); break; case OPOSTINC: case OPOSTDEC: v = 1; if(l->type->etype == TIND) v = l->type->link->width; if(o == OPOSTDEC) v = -v; if(l->op == OBIT) goto bitinc; if(nn == Z) goto pre; if(l->addable < INDEXED) reglcgen(&nod2, l, Z); else nod2 = *l; regalloc(&nod, l, nn); gopcode(OAS, &nod2, Z, &nod); regalloc(&nod1, l, Z); if(typefd[l->type->etype]) { regalloc(&nod3, l, Z); if(v < 0) { gopcode(OAS, nodfconst(-v), Z, &nod3); gopcode(OSUB, &nod3, &nod, &nod1); } else { gopcode(OAS, nodfconst(v), Z, &nod3); gopcode(OADD, &nod3, &nod, &nod1); } regfree(&nod3); } else gopcode(OADD, nodconst(v), &nod, &nod1); gopcode(OAS, &nod1, Z, &nod2); regfree(&nod); regfree(&nod1); if(l->addable < INDEXED) regfree(&nod2); break; case OPREINC: case OPREDEC: v = 1; if(l->type->etype == TIND) v = l->type->link->width; if(o == OPREDEC) v = -v; if(l->op == OBIT) goto bitinc; pre: if(l->addable < INDEXED) reglcgen(&nod2, l, Z); else nod2 = *l; regalloc(&nod, l, nn); gopcode(OAS, &nod2, Z, &nod); if(typefd[l->type->etype]) { regalloc(&nod3, l, Z); if(v < 0) { gopcode(OAS, nodfconst(-v), Z, &nod3); gopcode(OSUB, &nod3, Z, &nod); } else { gopcode(OAS, nodfconst(v), Z, &nod3); gopcode(OADD, &nod3, Z, &nod); } regfree(&nod3); } else gopcode(OADD, nodconst(v), Z, &nod); gopcode(OAS, &nod, Z, &nod2); if(nn && l->op == ONAME) /* in x=++i, emit USED(i) */ gins(ANOP, l, Z); regfree(&nod); if(l->addable < INDEXED) regfree(&nod2); break; bitinc: if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) { bitload(l, &nod, &nod1, &nod2, Z); gopcode(OAS, &nod, Z, nn); gopcode(OADD, nodconst(v), Z, &nod); bitstore(l, &nod, &nod1, &nod2, Z); break; } bitload(l, &nod, &nod1, &nod2, nn); gopcode(OADD, nodconst(v), Z, &nod); bitstore(l, &nod, &nod1, &nod2, nn); break; } cursafe = curs; }
void cgen(Node *n, Node *nn) { Node *l, *r, *t; Prog *p1; Node nod, nod1, nod2, nod3, nod4; int o, hardleft; int32 v, curs; vlong c; if(debug['g']) { prtree(nn, "cgen lhs"); prtree(n, "cgen"); } if(n == Z || n->type == T) return; if(typesu[n->type->etype]) { sugen(n, nn, n->type->width); return; } l = n->left; r = n->right; o = n->op; if(n->op == OEXREG || (nn != Z && nn->op == OEXREG)) { gmove(n, nn); return; } if(n->addable >= INDEXED) { if(nn == Z) { switch(o) { default: nullwarn(Z, Z); break; case OINDEX: nullwarn(l, r); break; } return; } gmove(n, nn); return; } curs = cursafe; if(l->complex >= FNX) if(r != Z && r->complex >= FNX) switch(o) { default: if(cond(o) && typesu[l->type->etype]) break; regret(&nod, r); cgen(r, &nod); regsalloc(&nod1, r); gmove(&nod, &nod1); regfree(&nod); nod = *n; nod.right = &nod1; cgen(&nod, nn); return; case OFUNC: case OCOMMA: case OANDAND: case OOROR: case OCOND: case ODOT: break; } hardleft = l->addable < INDEXED || l->complex >= FNX; switch(o) { default: diag(n, "unknown op in cgen: %O", o); break; case ONEG: case OCOM: if(nn == Z) { nullwarn(l, Z); break; } regalloc(&nod, l, nn); cgen(l, &nod); gopcode(o, n->type, Z, &nod); gmove(&nod, nn); regfree(&nod); break; case OAS: if(l->op == OBIT) goto bitas; if(!hardleft) { if(nn != Z || r->addable < INDEXED || hardconst(r)) { if(r->complex >= FNX && nn == Z) regret(&nod, r); else regalloc(&nod, r, nn); cgen(r, &nod); gmove(&nod, l); if(nn != Z) gmove(&nod, nn); regfree(&nod); } else gmove(r, l); break; } if(l->complex >= r->complex) { if(l->op == OINDEX && immconst(r)) { gmove(r, l); break; } reglcgen(&nod1, l, Z); if(r->addable >= INDEXED && !hardconst(r)) { gmove(r, &nod1); if(nn != Z) gmove(r, nn); regfree(&nod1); break; } regalloc(&nod, r, nn); cgen(r, &nod); } else { regalloc(&nod, r, nn); cgen(r, &nod); reglcgen(&nod1, l, Z); } gmove(&nod, &nod1); regfree(&nod); regfree(&nod1); break; bitas: n = l->left; regalloc(&nod, r, nn); if(l->complex >= r->complex) { reglcgen(&nod1, n, Z); cgen(r, &nod); } else { cgen(r, &nod); reglcgen(&nod1, n, Z); } regalloc(&nod2, n, Z); gmove(&nod1, &nod2); bitstore(l, &nod, &nod1, &nod2, nn); break; case OBIT: if(nn == Z) { nullwarn(l, Z); break; } bitload(n, &nod, Z, Z, nn); gmove(&nod, nn); regfree(&nod); break; case OLSHR: case OASHL: case OASHR: if(nn == Z) { nullwarn(l, r); break; } if(r->op == OCONST) { if(r->vconst == 0) { cgen(l, nn); break; } regalloc(&nod, l, nn); cgen(l, &nod); if(o == OASHL && r->vconst == 1) gopcode(OADD, n->type, &nod, &nod); else gopcode(o, n->type, r, &nod); gmove(&nod, nn); regfree(&nod); break; } /* * get nod to be D_CX */ if(nodreg(&nod, nn, D_CX)) { regsalloc(&nod1, n); gmove(&nod, &nod1); cgen(n, &nod); /* probably a bug */ gmove(&nod, nn); gmove(&nod1, &nod); break; } reg[D_CX]++; if(nn->op == OREGISTER && nn->reg == D_CX) regalloc(&nod1, l, Z); else regalloc(&nod1, l, nn); if(r->complex >= l->complex) { cgen(r, &nod); cgen(l, &nod1); } else { cgen(l, &nod1); cgen(r, &nod); } gopcode(o, n->type, &nod, &nod1); gmove(&nod1, nn); regfree(&nod); regfree(&nod1); break; case OADD: case OSUB: case OOR: case OXOR: case OAND: if(nn == Z) { nullwarn(l, r); break; } if(typefd[n->type->etype]) goto fop; if(r->op == OCONST) { if(r->vconst == 0 && o != OAND) { cgen(l, nn); break; } } if(n->op == OADD && l->op == OASHL && l->right->op == OCONST && (r->op != OCONST || r->vconst < -128 || r->vconst > 127)) { c = l->right->vconst; if(c > 0 && c <= 3) { if(l->left->complex >= r->complex) { regalloc(&nod, l->left, nn); cgen(l->left, &nod); if(r->addable < INDEXED) { regalloc(&nod1, r, Z); cgen(r, &nod1); genmuladd(&nod, &nod, 1 << c, &nod1); regfree(&nod1); } else genmuladd(&nod, &nod, 1 << c, r); } else { regalloc(&nod, r, nn); cgen(r, &nod); regalloc(&nod1, l->left, Z); cgen(l->left, &nod1); genmuladd(&nod, &nod1, 1 << c, &nod); regfree(&nod1); } gmove(&nod, nn); regfree(&nod); break; } } if(r->addable >= INDEXED && !hardconst(r)) { regalloc(&nod, l, nn); cgen(l, &nod); gopcode(o, n->type, r, &nod); gmove(&nod, nn); regfree(&nod); break; } if(l->complex >= r->complex) { regalloc(&nod, l, nn); cgen(l, &nod); regalloc(&nod1, r, Z); cgen(r, &nod1); gopcode(o, n->type, &nod1, &nod); } else { regalloc(&nod1, r, nn); cgen(r, &nod1); regalloc(&nod, l, Z); cgen(l, &nod); gopcode(o, n->type, &nod1, &nod); } gmove(&nod, nn); regfree(&nod); regfree(&nod1); break; case OLMOD: case OMOD: case OLMUL: case OLDIV: case OMUL: case ODIV: if(nn == Z) { nullwarn(l, r); break; } if(typefd[n->type->etype]) goto fop; if(r->op == OCONST && typechl[n->type->etype]) { /* TO DO */ SET(v); switch(o) { case ODIV: case OMOD: c = r->vconst; if(c < 0) c = -c; v = xlog2(c); if(v < 0) break; /* fall thru */ case OMUL: case OLMUL: regalloc(&nod, l, nn); cgen(l, &nod); switch(o) { case OMUL: case OLMUL: mulgen(n->type, r, &nod); break; case ODIV: sdiv2(r->vconst, v, l, &nod); break; case OMOD: smod2(r->vconst, v, l, &nod); break; } gmove(&nod, nn); regfree(&nod); goto done; case OLDIV: c = r->vconst; if((c & 0x80000000) == 0) break; regalloc(&nod1, l, Z); cgen(l, &nod1); regalloc(&nod, l, nn); zeroregm(&nod); gins(ACMPL, &nod1, nodconst(c)); gins(ASBBL, nodconst(-1), &nod); regfree(&nod1); gmove(&nod, nn); regfree(&nod); goto done; } } if(o == OMUL) { if(l->addable >= INDEXED) { t = l; l = r; r = t; } /* should favour AX */ regalloc(&nod, l, nn); cgen(l, &nod); if(r->addable < INDEXED || hardconst(r)) { regalloc(&nod1, r, Z); cgen(r, &nod1); gopcode(OMUL, n->type, &nod1, &nod); regfree(&nod1); }else gopcode(OMUL, n->type, r, &nod); /* addressible */ gmove(&nod, nn); regfree(&nod); break; } /* * get nod to be D_AX * get nod1 to be D_DX */ if(nodreg(&nod, nn, D_AX)) { regsalloc(&nod2, n); gmove(&nod, &nod2); v = reg[D_AX]; reg[D_AX] = 0; if(isreg(l, D_AX)) { nod3 = *n; nod3.left = &nod2; cgen(&nod3, nn); } else if(isreg(r, D_AX)) { nod3 = *n; nod3.right = &nod2; cgen(&nod3, nn); } else cgen(n, nn); gmove(&nod2, &nod); reg[D_AX] = v; break; } if(nodreg(&nod1, nn, D_DX)) { regsalloc(&nod2, n); gmove(&nod1, &nod2); v = reg[D_DX]; reg[D_DX] = 0; if(isreg(l, D_DX)) { nod3 = *n; nod3.left = &nod2; cgen(&nod3, nn); } else if(isreg(r, D_DX)) { nod3 = *n; nod3.right = &nod2; cgen(&nod3, nn); } else cgen(n, nn); gmove(&nod2, &nod1); reg[D_DX] = v; break; } reg[D_AX]++; if(r->op == OCONST && (o == ODIV || o == OLDIV) && immconst(r) && typechl[r->type->etype]) { reg[D_DX]++; if(l->addable < INDEXED) { regalloc(&nod2, l, Z); cgen(l, &nod2); l = &nod2; } if(o == ODIV) sdivgen(l, r, &nod, &nod1); else udivgen(l, r, &nod, &nod1); gmove(&nod1, nn); if(l == &nod2) regfree(l); goto freeaxdx; } if(l->complex >= r->complex) { cgen(l, &nod); reg[D_DX]++; if(o == ODIV || o == OMOD) gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z); if(o == OLDIV || o == OLMOD) zeroregm(&nod1); if(r->addable < INDEXED || r->op == OCONST) { regsalloc(&nod3, r); cgen(r, &nod3); gopcode(o, n->type, &nod3, Z); } else gopcode(o, n->type, r, Z); } else { regsalloc(&nod3, r); cgen(r, &nod3); cgen(l, &nod); reg[D_DX]++; if(o == ODIV || o == OMOD) gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z); if(o == OLDIV || o == OLMOD) zeroregm(&nod1); gopcode(o, n->type, &nod3, Z); } if(o == OMOD || o == OLMOD) gmove(&nod1, nn); else gmove(&nod, nn); freeaxdx: regfree(&nod); regfree(&nod1); break; case OASLSHR: case OASASHL: case OASASHR: if(r->op == OCONST) goto asand; if(l->op == OBIT) goto asbitop; if(typefd[n->type->etype]) goto asand; /* can this happen? */ /* * get nod to be D_CX */ if(nodreg(&nod, nn, D_CX)) { regsalloc(&nod1, n); gmove(&nod, &nod1); cgen(n, &nod); if(nn != Z) gmove(&nod, nn); gmove(&nod1, &nod); break; } reg[D_CX]++; if(r->complex >= l->complex) { cgen(r, &nod); if(hardleft) reglcgen(&nod1, l, Z); else nod1 = *l; } else { if(hardleft) reglcgen(&nod1, l, Z); else nod1 = *l; cgen(r, &nod); } gopcode(o, l->type, &nod, &nod1); regfree(&nod); if(nn != Z) gmove(&nod1, nn); if(hardleft) regfree(&nod1); break; case OASAND: case OASADD: case OASSUB: case OASXOR: case OASOR: asand: if(l->op == OBIT) goto asbitop; if(typefd[l->type->etype] || typefd[r->type->etype]) goto asfop; if(l->complex >= r->complex) { if(hardleft) reglcgen(&nod, l, Z); else nod = *l; if(!immconst(r)) { regalloc(&nod1, r, nn); cgen(r, &nod1); gopcode(o, l->type, &nod1, &nod); regfree(&nod1); } else gopcode(o, l->type, r, &nod); } else { regalloc(&nod1, r, nn); cgen(r, &nod1); if(hardleft) reglcgen(&nod, l, Z); else nod = *l; gopcode(o, l->type, &nod1, &nod); regfree(&nod1); } if(nn != Z) gmove(&nod, nn); if(hardleft) regfree(&nod); break; asfop: if(l->complex >= r->complex) { if(hardleft) reglcgen(&nod, l, Z); else nod = *l; if(r->addable < INDEXED){ regalloc(&nod1, r, nn); cgen(r, &nod1); }else nod1 = *r; regalloc(&nod2, r, Z); gmove(&nod, &nod2); gopcode(o, r->type, &nod1, &nod2); gmove(&nod2, &nod); regfree(&nod2); if(r->addable < INDEXED) regfree(&nod1); } else { regalloc(&nod1, r, nn); cgen(r, &nod1); if(hardleft) reglcgen(&nod, l, Z); else nod = *l; if(o != OASMUL && o != OASADD) { regalloc(&nod2, r, Z); gmove(&nod, &nod2); gopcode(o, r->type, &nod1, &nod2); regfree(&nod1); gmove(&nod2, &nod); regfree(&nod2); } else { gopcode(o, r->type, &nod, &nod1); gmove(&nod1, &nod); regfree(&nod1); } } if(nn != Z) gmove(&nod, nn); if(hardleft) regfree(&nod); break; case OASLMUL: case OASLDIV: case OASLMOD: case OASMUL: case OASDIV: case OASMOD: if(l->op == OBIT) goto asbitop; if(typefd[n->type->etype] || typefd[r->type->etype]) goto asfop; if(r->op == OCONST && typechl[n->type->etype]) { SET(v); switch(o) { case OASDIV: case OASMOD: c = r->vconst; if(c < 0) c = -c; v = xlog2(c); if(v < 0) break; /* fall thru */ case OASMUL: case OASLMUL: if(hardleft) reglcgen(&nod2, l, Z); else nod2 = *l; regalloc(&nod, l, nn); cgen(&nod2, &nod); switch(o) { case OASMUL: case OASLMUL: mulgen(n->type, r, &nod); break; case OASDIV: sdiv2(r->vconst, v, l, &nod); break; case OASMOD: smod2(r->vconst, v, l, &nod); break; } havev: gmove(&nod, &nod2); if(nn != Z) gmove(&nod, nn); if(hardleft) regfree(&nod2); regfree(&nod); goto done; case OASLDIV: c = r->vconst; if((c & 0x80000000) == 0) break; if(hardleft) reglcgen(&nod2, l, Z); else nod2 = *l; regalloc(&nod1, l, nn); cgen(&nod2, &nod1); regalloc(&nod, l, nn); zeroregm(&nod); gins(ACMPL, &nod1, nodconst(c)); gins(ASBBL, nodconst(-1), &nod); regfree(&nod1); goto havev; } } if(o == OASMUL) { /* should favour AX */ regalloc(&nod, l, nn); if(r->complex >= FNX) { regalloc(&nod1, r, Z); cgen(r, &nod1); r = &nod1; } if(hardleft) reglcgen(&nod2, l, Z); else nod2 = *l; cgen(&nod2, &nod); if(r->addable < INDEXED || hardconst(r)) { if(r->complex < FNX) { regalloc(&nod1, r, Z); cgen(r, &nod1); } gopcode(OASMUL, n->type, &nod1, &nod); regfree(&nod1); } else gopcode(OASMUL, n->type, r, &nod); if(r == &nod1) regfree(r); gmove(&nod, &nod2); if(nn != Z) gmove(&nod, nn); regfree(&nod); if(hardleft) regfree(&nod2); break; } /* * get nod to be D_AX * get nod1 to be D_DX */ if(nodreg(&nod, nn, D_AX)) { regsalloc(&nod2, n); gmove(&nod, &nod2); v = reg[D_AX]; reg[D_AX] = 0; if(isreg(l, D_AX)) { nod3 = *n; nod3.left = &nod2; cgen(&nod3, nn); } else if(isreg(r, D_AX)) { nod3 = *n; nod3.right = &nod2; cgen(&nod3, nn); } else cgen(n, nn); gmove(&nod2, &nod); reg[D_AX] = v; break; } if(nodreg(&nod1, nn, D_DX)) { regsalloc(&nod2, n); gmove(&nod1, &nod2); v = reg[D_DX]; reg[D_DX] = 0; if(isreg(l, D_DX)) { nod3 = *n; nod3.left = &nod2; cgen(&nod3, nn); } else if(isreg(r, D_DX)) { nod3 = *n; nod3.right = &nod2; cgen(&nod3, nn); } else cgen(n, nn); gmove(&nod2, &nod1); reg[D_DX] = v; break; } reg[D_AX]++; reg[D_DX]++; if(l->complex >= r->complex) { if(hardleft) reglcgen(&nod2, l, Z); else nod2 = *l; cgen(&nod2, &nod); if(r->op == OCONST && typechl[r->type->etype]) { switch(o) { case OASDIV: sdivgen(&nod2, r, &nod, &nod1); goto divdone; case OASLDIV: udivgen(&nod2, r, &nod, &nod1); divdone: gmove(&nod1, &nod2); if(nn != Z) gmove(&nod1, nn); goto freelxaxdx; } } if(o == OASDIV || o == OASMOD) gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z); if(o == OASLDIV || o == OASLMOD) zeroregm(&nod1); if(r->addable < INDEXED || r->op == OCONST || !typeil[r->type->etype]) { regalloc(&nod3, r, Z); cgen(r, &nod3); gopcode(o, l->type, &nod3, Z); regfree(&nod3); } else gopcode(o, n->type, r, Z); } else { regalloc(&nod3, r, Z); cgen(r, &nod3); if(hardleft) reglcgen(&nod2, l, Z); else nod2 = *l; cgen(&nod2, &nod); if(o == OASDIV || o == OASMOD) gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z); if(o == OASLDIV || o == OASLMOD) zeroregm(&nod1); gopcode(o, l->type, &nod3, Z); regfree(&nod3); } if(o == OASMOD || o == OASLMOD) { gmove(&nod1, &nod2); if(nn != Z) gmove(&nod1, nn); } else { gmove(&nod, &nod2); if(nn != Z) gmove(&nod, nn); } freelxaxdx: if(hardleft) regfree(&nod2); regfree(&nod); regfree(&nod1); break; fop: if(l->complex >= r->complex) { regalloc(&nod, l, nn); cgen(l, &nod); if(r->addable < INDEXED) { regalloc(&nod1, r, Z); cgen(r, &nod1); gopcode(o, n->type, &nod1, &nod); regfree(&nod1); } else gopcode(o, n->type, r, &nod); } else { /* TO DO: could do better with r->addable >= INDEXED */ regalloc(&nod1, r, Z); cgen(r, &nod1); regalloc(&nod, l, nn); cgen(l, &nod); gopcode(o, n->type, &nod1, &nod); regfree(&nod1); } gmove(&nod, nn); regfree(&nod); break; asbitop: regalloc(&nod4, n, nn); if(l->complex >= r->complex) { bitload(l, &nod, &nod1, &nod2, &nod4); regalloc(&nod3, r, Z); cgen(r, &nod3); } else { regalloc(&nod3, r, Z); cgen(r, &nod3); bitload(l, &nod, &nod1, &nod2, &nod4); } gmove(&nod, &nod4); { /* TO DO: check floating point source */ Node onod; /* incredible grot ... */ onod = nod3; onod.op = o; onod.complex = 2; onod.addable = 0; onod.type = tfield; onod.left = &nod4; onod.right = &nod3; cgen(&onod, Z); } regfree(&nod3); gmove(&nod4, &nod); regfree(&nod4); bitstore(l, &nod, &nod1, &nod2, nn); break; case OADDR: if(nn == Z) { nullwarn(l, Z); break; } lcgen(l, nn); break; case OFUNC: if(l->complex >= FNX) { if(l->op != OIND) diag(n, "bad function call"); regret(&nod, l->left); cgen(l->left, &nod); regsalloc(&nod1, l->left); gmove(&nod, &nod1); regfree(&nod); nod = *n; nod.left = &nod2; nod2 = *l; nod2.left = &nod1; nod2.complex = 1; cgen(&nod, nn); return; } o = 0; if(REGARG >= 0) o = reg[REGARG]; gargs(r, &nod, &nod1); if(l->addable < INDEXED) { reglcgen(&nod, l, nn); nod.op = OREGISTER; gopcode(OFUNC, n->type, Z, &nod); regfree(&nod); } else gopcode(OFUNC, n->type, Z, l); if(REGARG >= 0) if(o != reg[REGARG]) reg[REGARG]--; if(nn != Z) { regret(&nod, n); gmove(&nod, nn); regfree(&nod); } break; case OIND: if(nn == Z) { nullwarn(l, Z); break; } regialloc(&nod, n, nn); r = l; while(r->op == OADD) r = r->right; if(sconst(r)) { v = r->vconst; r->vconst = 0; cgen(l, &nod); nod.xoffset += v; r->vconst = v; } else cgen(l, &nod); regind(&nod, n); gmove(&nod, nn); regfree(&nod); break; case OEQ: case ONE: case OLE: case OLT: case OGE: case OGT: case OLO: case OLS: case OHI: case OHS: if(nn == Z) { nullwarn(l, r); break; } boolgen(n, 1, nn); break; case OANDAND: case OOROR: boolgen(n, 1, nn); if(nn == Z) patch(p, pc); break; case ONOT: if(nn == Z) { nullwarn(l, Z); break; } boolgen(n, 1, nn); break; case OCOMMA: cgen(l, Z); cgen(r, nn); break; case OCAST: if(nn == Z) { nullwarn(l, Z); break; } /* * convert from types l->n->nn */ if(nocast(l->type, n->type) && nocast(n->type, nn->type)) { /* both null, gen l->nn */ cgen(l, nn); break; } if(ewidth[n->type->etype] < ewidth[l->type->etype]){ if(l->type->etype == TIND && typechlp[n->type->etype]) warn(n, "conversion of pointer to shorter integer"); }else if(0){ if(nocast(n->type, nn->type) || castup(n->type, nn->type)){ if(typefd[l->type->etype] != typefd[nn->type->etype]) regalloc(&nod, l, nn); else regalloc(&nod, nn, nn); cgen(l, &nod); gmove(&nod, nn); regfree(&nod); break; } } regalloc(&nod, l, nn); cgen(l, &nod); regalloc(&nod1, n, &nod); gmove(&nod, &nod1); gmove(&nod1, nn); regfree(&nod1); regfree(&nod); break; case ODOT: sugen(l, nodrat, l->type->width); if(nn == Z) break; warn(n, "non-interruptable temporary"); nod = *nodrat; if(!r || r->op != OCONST) { diag(n, "DOT and no offset"); break; } nod.xoffset += (int32)r->vconst; nod.type = n->type; cgen(&nod, nn); break; case OCOND: bcgen(l, 1); p1 = p; cgen(r->left, nn); gbranch(OGOTO); patch(p1, pc); p1 = p; cgen(r->right, nn); patch(p1, pc); break; case OPOSTINC: case OPOSTDEC: v = 1; if(l->type->etype == TIND) v = l->type->link->width; if(o == OPOSTDEC) v = -v; if(l->op == OBIT) goto bitinc; if(nn == Z) goto pre; if(hardleft) reglcgen(&nod, l, Z); else nod = *l; gmove(&nod, nn); if(typefd[n->type->etype]) { regalloc(&nod1, l, Z); gmove(&nod, &nod1); if(v < 0) gopcode(OSUB, n->type, nodfconst(-v), &nod1); else gopcode(OADD, n->type, nodfconst(v), &nod1); gmove(&nod1, &nod); regfree(&nod1); } else gopcode(OADD, n->type, nodconst(v), &nod); if(hardleft) regfree(&nod); break; case OPREINC: case OPREDEC: v = 1; if(l->type->etype == TIND) v = l->type->link->width; if(o == OPREDEC) v = -v; if(l->op == OBIT) goto bitinc; pre: if(hardleft) reglcgen(&nod, l, Z); else nod = *l; if(typefd[n->type->etype]) { regalloc(&nod1, l, Z); gmove(&nod, &nod1); if(v < 0) gopcode(OSUB, n->type, nodfconst(-v), &nod1); else gopcode(OADD, n->type, nodfconst(v), &nod1); gmove(&nod1, &nod); regfree(&nod1); } else gopcode(OADD, n->type, nodconst(v), &nod); if(nn != Z) gmove(&nod, nn); if(hardleft) regfree(&nod); break; bitinc: if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) { bitload(l, &nod, &nod1, &nod2, Z); gmove(&nod, nn); gopcode(OADD, tfield, nodconst(v), &nod); bitstore(l, &nod, &nod1, &nod2, Z); break; } bitload(l, &nod, &nod1, &nod2, nn); gopcode(OADD, tfield, nodconst(v), &nod); bitstore(l, &nod, &nod1, &nod2, nn); break; } done: cursafe = curs; }
/*-----------------* * Function getsam | *-----------------* | Generates a gene genealogy for a locus. */ int gensam(struct params *pparam, char **list, int **pnbvariant, int *pS) { int nsegs=0, k=0, seg=0, ns=0, start=0, end=0, len=0, segsit=0, nsites=0, nsam=0; /* The function returns ns, the number of sgregating sites. * nsegs is the gametes were broken into in tracing back the history of the gametes. * The histories of these segments are passed back to the calling function in the array of structures seglst[] */ struct segl *seglst=NULL; double nsinv=0.0, tseg=0.0, tt=0.0, theta=0.0; void make_gametes(int, struct node*, double, int, int, char**, int, int*, int**, int*, int*); void inititable(int, int, int*); void initimatrix(int, int, int, int**); void biggerimatrix(int, int**); void biggerlist(int, char**); void locate(int, double, double, double*); //// From make_gametes //// void prtree(struct node*, int); double ttime(struct node*, int); int poisso(double); //// From streec.c //// struct segl*segtre_mig(struct c_params*, int*); nsites=pparam->cp.nsites; // Locus lenght available for recombination nsinv=1./nsites; seglst=segtre_mig(&(pparam->cp), &nsegs); // Generate Xove and ARGr, record # segments nsam=pparam->cp.nsam; // # chromo in the sample theta=pparam->mp.theta; // mutation rate given by user ns=0; // # seg sites if(pparam->mp.treeflag) // Case output tree. { theta=pparam->mp.theta; ns=0; for(seg=0, k=0;k<nsegs;seg=seglst[seg].next, k++) { if((pparam->cp.r>0.0)||(pparam->cp.f>0.0)) { end=(k<nsegs-1 ? seglst[seglst[seg].next].beg-1:nsites-1); start=seglst[seg].beg; len=end-start+1; fprintf(stdout, "[%d]", len); } prtree(seglst[seg].ptree, nsam); if((theta==0.0)) free(seglst[seg].ptree); } } //--- Loop along all segments ---// for(seg=0, k=0;k<nsegs; seg=seglst[seg].next, k++) { end=(k<nsegs-1 ? seglst[seglst[seg].next].beg-1:nsites-1); // End of segment start=seglst[seg].beg; // beginning of segment len=end-start+1; // Lengh of segment tseg=len*(theta/nsites); // Mutation rate along the segment tt=ttime(seglst[seg].ptree, nsam); // Total time in the tree for this segment segsit=poisso(tseg*tt); // get # segsites along genealogy for the segment //--- Realloc memory if # segsite bigger than max previously define ---// if((segsit+ns)>=maxsites) { maxsites=segsit+ns+SITESINC; // Bigger Max sites biggerlist(nsam, list); // Increase list of haplotype typeseg=(int*)realloc(typeseg, maxsites*sizeof(int)); // Increase # seg sites in typeseg biggerimatrix(pparam->cp.npop+1, pnbvariant); // Increase matrix of variant } //--- Initialize table of variant and segType ---// initimatrix(ns, ns+segsit, pparam->cp.npop+1, pnbvariant); inititable(ns, segsit+ns, typeseg); make_gametes(nsam, seglst[seg].ptree, tt, segsit, ns, list, pparam->cp.npop, pparam->cp.config, pnbvariant, typeseg, pS); // Make gametes (Put segsites on gene genealogy) free(seglst[seg].ptree); // Free memory ns+=segsit; // Total # seg sites } for(k=0;k<nsam;k++) list[k][ns]='\0'; // End of haplotype strings return(ns); // Total # segsites }// End Gensam
int gensam( char **list, double *pprobss, double *ptmrca, double *pttot ) { int nsegs, h, i, k, j, seg, ns, start, end, len, segsit ; struct segl *seglst, *segtre_mig(struct c_params *p, int *nsegs ) ; /* used to be: [MAXSEG]; */ double nsinv, tseg, tt, ttime(struct node *, int nsam), ttimemf(struct node *, int nsam, int mfreq) ; double *pk; int *ss; int segsitesin,nsites; double theta, es ; int nsam, mfreq ; void prtree( struct node *ptree, int nsam); void make_gametes(int nsam, int mfreq, struct node *ptree, double tt, int newsites, int ns, char **list ); void ndes_setup( struct node *, int nsam ); nsites = pars.cp.nsites ; nsinv = 1./nsites; seglst = segtre_mig(&(pars.cp), &nsegs ) ; nsam = pars.cp.nsam; segsitesin = pars.mp.segsitesin ; theta = pars.mp.theta ; mfreq = pars.mp.mfreq ; if( pars.mp.treeflag ) { ns = 0 ; for( seg=0, k=0; k<nsegs; seg=seglst[seg].next, k++) { if( (pars.cp.r > 0.0 ) || (pars.cp.f > 0.0) ) { end = ( k<nsegs-1 ? seglst[seglst[seg].next].beg -1 : nsites-1 ); start = seglst[seg].beg ; len = end - start + 1 ; fprintf(stdout,"[%d]", len); } prtree( seglst[seg].ptree, nsam ) ; if( (segsitesin == 0) && ( theta == 0.0 ) && ( pars.mp.timeflag == 0 ) ) free(seglst[seg].ptree) ; } } if( pars.mp.timeflag ) { tt = 0.0 ; for( seg=0, k=0; k<nsegs; seg=seglst[seg].next, k++) { if( mfreq > 1 ) ndes_setup( seglst[seg].ptree, nsam ); end = ( k<nsegs-1 ? seglst[seglst[seg].next].beg -1 : nsites-1 ); start = seglst[seg].beg ; if( (nsegs==1) || ( ( start <= nsites/2) && ( end >= nsites/2 ) ) ) *ptmrca = (seglst[seg].ptree + 2*nsam-2) -> time ; len = end - start + 1 ; tseg = len/(double)nsites ; if( mfreq == 1 ) tt += ttime(seglst[seg].ptree,nsam)*tseg ; else tt += ttimemf(seglst[seg].ptree,nsam, mfreq)*tseg ; if( (segsitesin == 0) && ( theta == 0.0 ) ) free(seglst[seg].ptree) ; } *pttot = tt ; } if( (segsitesin == 0) && ( theta > 0.0) ) { ns = 0 ; for( seg=0, k=0; k<nsegs; seg=seglst[seg].next, k++) { if( mfreq > 1 ) ndes_setup( seglst[seg].ptree, nsam ); end = ( k<nsegs-1 ? seglst[seglst[seg].next].beg -1 : nsites-1 ); start = seglst[seg].beg ; len = end - start + 1 ; tseg = len*(theta/nsites) ; if( mfreq == 1) tt = ttime(seglst[seg].ptree, nsam); else tt = ttimemf(seglst[seg].ptree, nsam, mfreq ); segsit = poisso( tseg*tt ); if( (segsit + ns) >= maxsites ) { maxsites = segsit + ns + SITESINC ; posit = (double *)realloc(posit, maxsites*sizeof(double) ) ; biggerlist(nsam, list) ; } make_gametes(nsam,mfreq,seglst[seg].ptree,tt, segsit, ns, list ); free(seglst[seg].ptree) ; locate(segsit,start*nsinv, len*nsinv,posit+ns); ns += segsit; } } else if( segsitesin > 0 ) { pk = (double *)malloc((unsigned)(nsegs*sizeof(double))); ss = (int *)malloc((unsigned)(nsegs*sizeof(int))); if( (pk==NULL) || (ss==NULL) ) perror("malloc error. gensam.2"); tt = 0.0 ; for( seg=0, k=0; k<nsegs; seg=seglst[seg].next, k++) { if( mfreq > 1 ) ndes_setup( seglst[seg].ptree, nsam ); end = ( k<nsegs-1 ? seglst[seglst[seg].next].beg -1 : nsites-1 ); start = seglst[seg].beg ; len = end - start + 1 ; tseg = len/(double)nsites ; if( mfreq == 1 ) pk[k] = ttime(seglst[seg].ptree,nsam)*tseg ; else pk[k] = ttimemf(seglst[seg].ptree,nsam, mfreq)*tseg ; tt += pk[k] ; } if( theta > 0.0 ) { es = theta * tt ; *pprobss = exp( -es )*pow( es, (double) segsitesin) / segfac ; } if( tt > 0.0 ) { for (k=0; k<nsegs; k++) pk[k] /= tt ; mnmial(segsitesin,nsegs,pk,ss); } else for( k=0; k<nsegs; k++) ss[k] = 0 ; ns = 0 ; for( seg=0, k=0; k<nsegs; seg=seglst[seg].next, k++) { end = ( k<nsegs-1 ? seglst[seglst[seg].next].beg -1 : nsites-1 ); start = seglst[seg].beg ; len = end - start + 1 ; tseg = len/(double)nsites; make_gametes(nsam,mfreq,seglst[seg].ptree,tt*pk[k]/tseg, ss[k], ns, list); free(seglst[seg].ptree) ; locate(ss[k],start*nsinv, len*nsinv,posit+ns); ns += ss[k] ; } free(pk); free(ss); } for(i=0; i<nsam; i++) list[i][ns] = '\0' ; return( ns ) ; }
void cgenrel(Node *n, Node *nn, int inrel) { Node *l, *r; Prog *p1; Node nod, nod1, nod2, nod3, nod4; int o, t; long v, curs; if(debug['g']) { prtree(nn, "cgen lhs"); prtree(n, "cgen"); } if(n == Z || n->type == T) return; if(typesu[n->type->etype]) { sugen(n, nn, n->type->width); return; } l = n->left; r = n->right; o = n->op; if(n->addable >= INDEXED) { if(nn == Z) { switch(o) { default: nullwarn(Z, Z); break; case OINDEX: nullwarn(l, r); break; } return; } gmove(n, nn); return; } curs = cursafe; if(n->complex >= FNX) if(l->complex >= FNX) if(r != Z && r->complex >= FNX) switch(o) { default: if(cond(o) && typesu[l->type->etype]) break; regret(&nod, r); cgen(r, &nod); regsalloc(&nod1, r); gopcode(OAS, &nod, Z, &nod1); regfree(&nod); nod = *n; nod.right = &nod1; cgen(&nod, nn); return; case OFUNC: case OCOMMA: case OANDAND: case OOROR: case OCOND: case ODOT: break; } switch(o) { default: diag(n, "unknown op in cgen: %O", o); break; case ONEG: case OCOM: if(nn == Z) { nullwarn(l, Z); break; } regalloc(&nod, l, nn); cgen(l, &nod); gopcode(o, &nod, Z, &nod); gmove(&nod, nn); regfree(&nod); break; case OAS: if(l->op == OBIT) goto bitas; if(l->addable >= INDEXED && l->complex < FNX) { if(nn != Z || r->addable < INDEXED) { /* || hardconst(r) */ if(r->complex >= FNX && nn == Z) regret(&nod, r); else regalloc(&nod, r, nn); cgen(r, &nod); gmove(&nod, l); if(nn != Z) gmove(&nod, nn); regfree(&nod); } else gmove(r, l); break; } if(l->complex >= r->complex) { /* TO DO: see 6c for OINDEX && immconst(r) */ reglcgen(&nod1, l, Z); if(r->addable >= INDEXED) { /* && !hardconst(r) */ gmove(r, &nod1); if(nn != Z) gmove(r, nn); regfree(&nod1); break; } regalloc(&nod, r, nn); cgen(r, &nod); } else { regalloc(&nod, r, nn); cgen(r, &nod); reglcgen(&nod1, l, Z); } gmove(&nod, &nod1); regfree(&nod); regfree(&nod1); break; bitas: n = l->left; regalloc(&nod, r, nn); if(l->complex >= r->complex) { reglcgen(&nod1, n, Z); cgen(r, &nod); } else { cgen(r, &nod); reglcgen(&nod1, n, Z); } regalloc(&nod2, n, Z); gopcode(OAS, &nod1, Z, &nod2); bitstore(l, &nod, &nod1, &nod2, nn); break; case OBIT: if(nn == Z) { nullwarn(l, Z); break; } bitload(n, &nod, Z, Z, nn); gopcode(OAS, &nod, Z, nn); regfree(&nod); break; case ODIV: case OMOD: if(nn != Z) if((t = vlog(r)) >= 0) { /* signed div/mod by constant power of 2 */ cgen(l, nn); gopcode(OGE, nodconst(0), nn, Z); p1 = p; if(o == ODIV) { gopcode(OADD, nodconst((1<<t)-1), Z, nn); patch(p1, pc); gopcode(OASHR, nodconst(t), Z, nn); } else { gopcode(ONEG, nn, Z, nn); gopcode(OAND, nodconst((1<<t)-1), Z, nn); gopcode(ONEG, nn, Z, nn); gbranch(OGOTO); patch(p1, pc); p1 = p; gopcode(OAND, nodconst((1<<t)-1), Z, nn); patch(p1, pc); } break; } goto muldiv; case OXOR: #ifdef NOTYET if(nn != Z) if(r->op == OCONST && r->vconst == -1){ cgen(l, nn); gopcode(OCOM, nn, Z, nn); break; } #endif case OSUB: case OADD: case OAND: case OOR: case OLSHR: case OASHL: case OASHR: /* * immediate operands */ if(nn != Z) if(r->op == OCONST) if(!typefd[n->type->etype]) { cgen(l, nn); if(r->vconst == 0) if(o != OAND) break; if(nn != Z) gopcode(o, r, Z, nn); break; } case OLMUL: case OLDIV: case OLMOD: case OMUL: muldiv: if(nn == Z) { nullwarn(l, r); break; } if(o == OMUL || o == OLMUL) { if(mulcon(n, nn)) break; } if(l->complex >= r->complex) { regalloc(&nod, l, nn); cgen(l, &nod); regalloc(&nod1, l, Z); /* note: l used for type, so shifts work! */ cgen(r, &nod1); gopcode(o, &nod1, Z, &nod); } else { regalloc(&nod, l, nn); /* note: l used for type, so shifts work! */ cgen(r, &nod); regalloc(&nod1, l, Z); cgen(l, &nod1); gopcode(o, &nod, &nod1, &nod); } gopcode(OAS, &nod, Z, nn); regfree(&nod); regfree(&nod1); break; case OASLSHR: case OASASHL: case OASASHR: case OASAND: case OASADD: case OASSUB: case OASXOR: case OASOR: if(l->op == OBIT) goto asbitop; if(r->op == OCONST) if(!typefd[r->type->etype]) if(!typefd[n->type->etype]) { if(l->addable < INDEXED) reglcgen(&nod2, l, Z); else nod2 = *l; regalloc(&nod, l, nn); /* note: l used for type, so shifts work! */ gopcode(OAS, &nod2, Z, &nod); gopcode(o, r, Z, &nod); gopcode(OAS, &nod, Z, &nod2); regfree(&nod); if(l->addable < INDEXED) regfree(&nod2); break; } case OASLMUL: case OASLDIV: case OASLMOD: case OASMUL: case OASDIV: case OASMOD: if(l->op == OBIT) goto asbitop; if(l->complex >= r->complex) { if(l->addable < INDEXED) reglcgen(&nod2, l, Z); else nod2 = *l; regalloc(&nod, n, nn); cgen(r, &nod); } else { regalloc(&nod, n, nn); cgen(r, &nod); if(l->addable < INDEXED) reglcgen(&nod2, l, Z); else nod2 = *l; } regalloc(&nod1, n, Z); gopcode(OAS, &nod2, Z, &nod1); if(nod1.type->etype != nod.type->etype){ regalloc(&nod3, &nod, Z); gmove(&nod1, &nod3); regfree(&nod1); nod1 = nod3; } gopcode(o, &nod, &nod1, &nod); gmove(&nod, &nod2); if(nn != Z) gmove(&nod, nn); regfree(&nod); regfree(&nod1); if(l->addable < INDEXED) regfree(&nod2); break; asbitop: regalloc(&nod4, n, nn); regalloc(&nod3, r, Z); if(l->complex >= r->complex) { bitload(l, &nod, &nod1, &nod2, &nod4); cgen(r, &nod3); } else { cgen(r, &nod3); bitload(l, &nod, &nod1, &nod2, &nod4); } gmove(&nod, &nod4); gopcode(o, &nod3, Z, &nod4); regfree(&nod3); gmove(&nod4, &nod); regfree(&nod4); bitstore(l, &nod, &nod1, &nod2, nn); break; case OADDR: if(nn == Z) { nullwarn(l, Z); break; } lcgen(l, nn); break; case OFUNC: l = uncomma(l); if(l->complex >= FNX) { if(l->op != OIND) diag(n, "bad function call"); regret(&nod, l->left); cgen(l->left, &nod); regsalloc(&nod1, l->left); gopcode(OAS, &nod, Z, &nod1); regfree(&nod); nod = *n; nod.left = &nod2; nod2 = *l; nod2.left = &nod1; nod2.complex = 1; cgen(&nod, nn); return; } if(REGARG >= 0) o = reg[REGARG]; gargs(r, &nod, &nod1); if(l->addable < INDEXED) { reglcgen(&nod, l, Z); gopcode(OFUNC, Z, Z, &nod); regfree(&nod); } else gopcode(OFUNC, Z, Z, l); if(REGARG >= 0) if(o != reg[REGARG]) reg[REGARG]--; if(nn != Z) { regret(&nod, n); gopcode(OAS, &nod, Z, nn); regfree(&nod); } break; case OIND: if(nn == Z) { nullwarn(l, Z); break; } regialloc(&nod, n, nn); r = l; while(r->op == OADD) r = r->right; if(sconst(r) && (v = r->vconst+nod.xoffset) >= -4096 && v < 4096) { v = r->vconst; r->vconst = 0; cgen(l, &nod); nod.xoffset += v; r->vconst = v; } else cgen(l, &nod); regind(&nod, n); gopcode(OAS, &nod, Z, nn); regfree(&nod); break; case OEQ: case ONE: case OLE: case OLT: case OGE: case OGT: case OLO: case OLS: case OHI: case OHS: if(nn == Z) { nullwarn(l, r); break; } boolgen(n, 1, nn); break; case OANDAND: case OOROR: boolgen(n, 1, nn); if(nn == Z) patch(p, pc); break; case ONOT: if(nn == Z) { nullwarn(l, Z); break; } boolgen(n, 1, nn); break; case OCOMMA: cgen(l, Z); cgen(r, nn); break; case OCAST: if(nn == Z) { nullwarn(l, Z); break; } /* * convert from types l->n->nn */ if(nocast(l->type, n->type) && nocast(n->type, nn->type)) { /* both null, gen l->nn */ cgen(l, nn); break; } if(ewidth[n->type->etype] < ewidth[l->type->etype]){ if(l->type->etype == TIND && typechlp[n->type->etype]) warn(n, "conversion of pointer to shorter integer"); }else if(0){ if(nocast(n->type, nn->type) || castup(n->type, nn->type)){ if(typefd[l->type->etype] != typefd[nn->type->etype]) regalloc(&nod, l, nn); else regalloc(&nod, nn, nn); cgen(l, &nod); gmove(&nod, nn); regfree(&nod); break; } } regalloc(&nod, l, nn); cgen(l, &nod); regalloc(&nod1, n, &nod); if(inrel) gmover(&nod, &nod1); else gopcode(OAS, &nod, Z, &nod1); gopcode(OAS, &nod1, Z, nn); regfree(&nod1); regfree(&nod); break; case ODOT: sugen(l, nodrat, l->type->width); if(nn != Z) { warn(n, "non-interruptable temporary"); nod = *nodrat; if(!r || r->op != OCONST) { diag(n, "DOT and no offset"); break; } nod.xoffset += (long)r->vconst; nod.type = n->type; cgen(&nod, nn); } break; case OCOND: bcgen(l, 1); p1 = p; cgen(r->left, nn); gbranch(OGOTO); patch(p1, pc); p1 = p; cgen(r->right, nn); patch(p1, pc); break; case OPOSTINC: case OPOSTDEC: v = 1; if(l->type->etype == TIND) v = l->type->link->width; if(o == OPOSTDEC) v = -v; if(l->op == OBIT) goto bitinc; if(nn == Z) goto pre; if(l->addable < INDEXED) reglcgen(&nod2, l, Z); else nod2 = *l; regalloc(&nod, l, nn); gopcode(OAS, &nod2, Z, &nod); regalloc(&nod1, l, Z); if(typefd[l->type->etype]) { regalloc(&nod3, l, Z); if(v < 0) { gopcode(OAS, nodfconst(-v), Z, &nod3); gopcode(OSUB, &nod3, &nod, &nod1); } else { gopcode(OAS, nodfconst(v), Z, &nod3); gopcode(OADD, &nod3, &nod, &nod1); } regfree(&nod3); } else gopcode(OADD, nodconst(v), &nod, &nod1); gopcode(OAS, &nod1, Z, &nod2); regfree(&nod); regfree(&nod1); if(l->addable < INDEXED) regfree(&nod2); break; case OPREINC: case OPREDEC: v = 1; if(l->type->etype == TIND) v = l->type->link->width; if(o == OPREDEC) v = -v; if(l->op == OBIT) goto bitinc; pre: if(l->addable < INDEXED) reglcgen(&nod2, l, Z); else nod2 = *l; regalloc(&nod, l, nn); gopcode(OAS, &nod2, Z, &nod); if(typefd[l->type->etype]) { regalloc(&nod3, l, Z); if(v < 0) { gopcode(OAS, nodfconst(-v), Z, &nod3); gopcode(OSUB, &nod3, Z, &nod); } else { gopcode(OAS, nodfconst(v), Z, &nod3); gopcode(OADD, &nod3, Z, &nod); } regfree(&nod3); } else gopcode(OADD, nodconst(v), Z, &nod); gopcode(OAS, &nod, Z, &nod2); if(nn && l->op == ONAME) /* in x=++i, emit USED(i) */ gins(ANOP, l, Z); regfree(&nod); if(l->addable < INDEXED) regfree(&nod2); break; bitinc: if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) { bitload(l, &nod, &nod1, &nod2, Z); gopcode(OAS, &nod, Z, nn); gopcode(OADD, nodconst(v), Z, &nod); bitstore(l, &nod, &nod1, &nod2, Z); break; } bitload(l, &nod, &nod1, &nod2, nn); gopcode(OADD, nodconst(v), Z, &nod); bitstore(l, &nod, &nod1, &nod2, nn); break; } cursafe = curs; return; }
void lcgen(Node *n, int result, Node *nn) { Node rn; Prog *p1; int lg; if(n == Z || n->type == T) return; if(debug['g']) { if(result == D_TREE) prtree(nn, "result"); else print("result = %R\n", result); prtree(n, "lcgen"); } if(nn == Z) { nn = &rn; nn->type = types[TIND]; } switch(n->op) { case OCOMMA: cgen(n->left, D_NONE, n->left); doinc(n->left, POST); doinc(n->right, PRE); lcgen(n->right, result, nn); break; case OCOND: doinc(n->left, PRE); boolgen(n->left, 1, D_NONE, Z, n->left); p1 = p; inargs++; doinc(n->right->left, PRE); lcgen(n->right->left, result, nn); doinc(n->right->left, POST); gbranch(OGOTO); patch(p1, pc); p1 = p; doinc(n->right->right, PRE); lcgen(n->right->right, result, nn); doinc(n->right->right, POST); patch(p1, pc); inargs--; break; case OIND: if(n->addable >= INDEXED) { if(result >= D_A0 && result < D_A0+NREG) { gopcode(OADDR, types[TLONG], D_TREE, n, result, nn); break; } if(result == D_TOS) { gopcode(OADDR, types[TSHORT], D_NONE, nn, D_TREE, n); break; } } cgen(n->left, result, nn); break; default: if(n->addable < INDEXED) { diag(n, "unknown op in lcgen: %O", n->op); break; } if(result >= D_A0 && result < D_A0+NREG) { gopcode(OADDR, types[TLONG], D_TREE, n, result, nn); break; } if(result == D_TOS) { gopcode(OADDR, types[TSHORT], D_NONE, nn, D_TREE, n); break; } lg = regaddr(result); gopcode(OADDR, types[TLONG], D_TREE, n, lg, nn); gopcode(OAS, nn->type, lg, nn, result, nn); regfree(lg); break; } }
void cgen(Node *n, int result, Node *nn) { Node *l, *r, nod; int lg, rg, xg, yg, g, o; long v; Prog *p1; if(n == Z || n->type == T) return; if(typesuv[n->type->etype]) { sugen(n, result, nn, n->type->width); return; } if(debug['g']) { if(result == D_TREE) prtree(nn, "result"); else print("result = %R\n", result); prtree(n, "cgen"); } l = n->left; r = n->right; o = n->op; if(n->addable >= INDEXED) { if(result == D_NONE) { if(nn == Z) switch(o) { default: nullwarn(Z, Z); break; case OINDEX: nullwarn(l, r); break; } return; } gmove(n->type, nn->type, D_TREE, n, result, nn); return; } v = 0; /* set */ switch(o) { default: diag(n, "unknown op in cgen: %O", o); break; case OAS: if(l->op == OBIT) goto bitas; /* * recursive use of result */ if(result == D_NONE) if(l->addable > INDEXED) if(l->complex < FNX) { cgen(r, D_TREE, l); break; } /* * function calls on both sides */ if(l->complex >= FNX && r->complex >= FNX) { cgen(r, D_TOS, r); v = argoff; lg = regaddr(result); lcgen(l, lg, Z); lg |= I_INDIR; adjsp(v - argoff); gmove(r->type, l->type, D_TOS, r, lg, l); if(result != D_NONE) gmove(l->type, nn->type, lg, l, result, nn); regfree(lg); break; } rg = D_TREE; lg = D_TREE; if(r->complex >= l->complex) { /* * right side before left */ if(result != D_NONE) { rg = regalloc(n->type, result); cgen(r, rg, n); } else if(r->complex >= FNX || r->addable < INDEXED) { rg = regalloc(r->type, result); cgen(r, rg, r); } if(l->addable < INDEXED) { lg = regaddr(lg); lcgen(l, lg, Z); lg |= I_INDIR; } } else { /* * left before right */ if(l->complex >= FNX || l->addable < INDEXED) { lg = regaddr(lg); lcgen(l, lg, Z); lg |= I_INDIR; } if(result != D_NONE) { rg = regalloc(n->type, result); cgen(r, rg, n); } else if(r->addable < INDEXED) { rg = regalloc(r->type, result); cgen(r, rg, r); } } if(result != D_NONE) { gmove(n->type, l->type, rg, r, lg, l); gmove(n->type, nn->type, rg, r, result, nn); } else gmove(r->type, l->type, rg, r, lg, l); regfree(lg); regfree(rg); break; bitas: n = l->left; rg = regalloc(tfield, result); if(l->complex >= r->complex) { lg = regaddr(D_NONE); lcgen(n, lg, Z); lg |= I_INDIR; cgen(r, rg, r); } else { cgen(r, rg, r); lg = regaddr(D_NONE); lcgen(n, lg, Z); lg |= I_INDIR; } g = regalloc(n->type, D_NONE); gmove(l->type, l->type, lg, l, g, l); bitstore(l, rg, lg, g, result, nn); break; case OBIT: if(result == D_NONE) { nullwarn(l, Z); break; } g = bitload(n, D_NONE, D_NONE, result, nn); gopcode(OAS, nn->type, g, n, result, nn); regfree(g); break; case ODOT: sugen(l, D_TREE, nodrat, l->type->width); if(result != D_NONE) { warn(n, "non-interruptable temporary"); nod = *nodrat; if(!r || r->op != OCONST) { diag(n, "DOT and no offset"); break; } nod.xoffset += r->vconst; nod.type = n->type; cgen(&nod, result, nn); } break; case OASLDIV: case OASLMOD: case OASDIV: case OASMOD: if(l->op == OBIT) goto asbitop; if(typefd[n->type->etype]) goto asbinop; rg = D_TREE; if(l->complex >= FNX || r->complex >= FNX) { rg = D_TOS; cgen(r, rg, r); v = argoff; } else if(r->addable < INDEXED) { rg = regalloc(n->type, D_NONE); cgen(r, rg, r); } lg = D_TREE; if(!simplv(l)) { lg = regaddr(D_NONE); lcgen(l, lg, Z); /* destroys register optimization */ lg |= I_INDIR; } g = regpair(result); gmove(l->type, n->type, lg, l, g, n); if(rg == D_TOS) adjsp(v - argoff); gopcode(o, n->type, rg, r, g, n); if(o == OASLMOD || o == OASMOD) gmove(n->type, l->type, g+1, n, lg, l); else gmove(n->type, l->type, g, n, lg, l); if(result != D_NONE) if(o == OASLMOD || o == OASMOD) gmove(n->type, nn->type, g+1, n, result, nn); else gmove(n->type, nn->type, g, n, result, nn); regfree(g); regfree(g+1); regfree(lg); regfree(rg); break; case OASXOR: case OASAND: case OASOR: if(l->op == OBIT) goto asbitop; if(l->complex >= FNX || l->addable < INDEXED || result != D_NONE || typefd[n->type->etype]) goto asbinop; rg = D_TREE; if(r->op != OCONST) { rg = regalloc(n->type, D_NONE); cgen(r, rg, r); } gopcode(o, l->type, rg, r, D_TREE, l); regfree(rg); break; case OASADD: case OASSUB: if(l->op == OBIT || l->complex >= FNX || l->addable < INDEXED || result != D_NONE || typefd[n->type->etype]) goto asbinop; v = vconst(r); if(v > 0 && v <= 8) { gopcode(o, n->type, D_TREE, r, D_TREE, l); break; } rg = regalloc(n->type, D_NONE); cgen(r, rg, r); gopcode(o, n->type, rg, r, D_TREE, l); regfree(rg); break; case OASLSHR: case OASASHR: case OASASHL: if(l->op == OBIT || l->complex >= FNX || l->addable < INDEXED || result != D_NONE || typefd[n->type->etype]) goto asbinop; rg = D_TREE; v = vconst(r); if(v <= 0 || v > 8) { rg = regalloc(n->type, D_NONE); cgen(r, rg, r); } lg = regalloc(n->type, D_NONE); cgen(l, lg, l); gopcode(o, n->type, rg, r, lg, l); gmove(n->type, n->type, lg, l, D_TREE, l); regfree(lg); regfree(rg); break; case OASLMUL: case OASMUL: asbinop: if(l->op == OBIT) goto asbitop; rg = D_TREE; if(l->complex >= FNX || r->complex >= FNX) { rg = D_TOS; cgen(r, rg, r); v = argoff; } else if(r->addable < INDEXED) { rg = regalloc(n->type, D_NONE); cgen(r, rg, r); } else { if(o == OASLSHR || o == OASASHR || o == OASASHL) { v = vconst(r); if(v <= 0 || v > 8) { rg = regalloc(n->type, D_NONE); cgen(r, rg, r); } } } lg = D_TREE; if(!simplv(l)) { lg = regaddr(D_NONE); lcgen(l, lg, Z); /* destroys register optimization */ lg |= I_INDIR; } g = regalloc(n->type, result); gmove(l->type, n->type, lg, l, g, n); if(rg == D_TOS) adjsp(v - argoff); if(o == OASXOR) if(rg == D_TREE) { rg = regalloc(n->type, D_NONE); cgen(r, rg, r); } if(o == OASXOR || o == OASLSHR || o == OASASHR || o == OASASHL) if(rg == D_TOS) { rg = regalloc(n->type, D_NONE); gmove(n->type, n->type, D_TOS, n, rg, n); } gopcode(o, n->type, rg, r, g, n); gmove(n->type, l->type, g, n, lg, l); if(result != D_NONE) gmove(n->type, nn->type, g, n, result, nn); regfree(g); regfree(lg); regfree(rg); break; asbitop: rg = regaddr(D_NONE); lg = regalloc(tfield, D_NONE); if(l->complex >= r->complex) { g = bitload(l, lg, rg, result, nn); xg = regalloc(r->type, D_NONE); cgen(r, xg, nn); } else { xg = regalloc(r->type, D_NONE); cgen(r, xg, nn); g = bitload(l, lg, rg, result, nn); } if(!typefd[n->type->etype]) { if(o == OASLDIV || o == OASDIV) { yg = regpair(result); gmove(tfield, n->type, g, l, yg, n); gopcode(o, n->type, xg, r, yg, n); gmove(n->type, tfield, yg, n, g, l); regfree(yg); regfree(yg+1); regfree(xg); bitstore(l, g, rg, lg, D_NONE, nn); break; } if(o == OASLMOD || o == OASMOD) { yg = regpair(result); gmove(tfield, n->type, g, l, yg, n); gopcode(o, n->type, xg, r, yg, n); gmove(n->type, tfield, yg+1, n, g, l); regfree(yg); regfree(yg+1); regfree(xg); bitstore(l, g, rg, lg, D_NONE, nn); break; } } yg = regalloc(n->type, result); gmove(tfield, n->type, g, l, yg, n); gopcode(o, n->type, xg, r, yg, n); gmove(n->type, tfield, yg, n, g, l); regfree(yg); regfree(xg); bitstore(l, g, rg, lg, D_NONE, nn); break; case OCAST: if(result == D_NONE) { nullwarn(l, Z); break; } lg = result; if(l->complex >= FNX) lg = regret(l->type); lg = eval(l, lg); if(nocast(l->type, n->type)) { gmove(n->type, nn->type, lg, l, result, nn); regfree(lg); break; } if(nocast(n->type, nn->type)) { gmove(l->type, n->type, lg, l, result, nn); regfree(lg); break; } rg = regalloc(n->type, result); gmove(l->type, n->type, lg, l, rg, n); gmove(n->type, nn->type, rg, n, result, nn); regfree(rg); regfree(lg); break; case OCOND: doinc(l, PRE); boolgen(l, 1, D_NONE, Z, l); p1 = p; inargs++; doinc(r->left, PRE); cgen(r->left, result, nn); doinc(r->left, POST); gbranch(OGOTO); patch(p1, pc); p1 = p; doinc(r->right, PRE); cgen(r->right, result, nn); doinc(r->right, POST); patch(p1, pc); inargs--; break; case OIND: if(result == D_NONE) { nullwarn(l, Z); break; } lg = nodalloc(types[TIND], result, &nod); nod.lineno = n->lineno; if(l->op == OADD) { if(l->left->op == OCONST) { nod.xoffset += l->left->vconst; l = l->right; } else if(l->right->op == OCONST) { nod.xoffset += l->right->vconst; l = l->left; } } cgen(l, lg, l); gmove(n->type, nn->type, D_TREE, &nod, result, nn); regfree(lg); break; case OFUNC: v = argoff; inargs++; gargs(r); lg = D_TREE; if(l->addable < INDEXED) { lg = regaddr(result); lcgen(l, lg, Z); lg |= I_INDIR; } inargs--; doinc(r, POST); doinc(l, POST); gopcode(OFUNC, types[TCHAR], D_NONE, Z, lg, l); regfree(lg); if(inargs) adjsp(v - argoff); if(result != D_NONE) { lg = regret(n->type); gmove(n->type, nn->type, lg, n, result, nn); } break; case OLDIV: case OLMOD: case ODIV: case OMOD: if(result == D_NONE) { nullwarn(l, r); break; } if(typefd[n->type->etype]) goto binop; if(r->addable >= INDEXED && r->complex < FNX) { lg = regpair(result); cgen(l, lg, l); rg = D_TREE; } else { cgen(r, D_TOS, r); v = argoff; lg = regpair(result); cgen(l, lg, l); adjsp(v - argoff); rg = D_TOS; } gopcode(o, n->type, rg, r, lg, l); if(o == OMOD || o == OLMOD) gmove(l->type, nn->type, lg+1, l, result, nn); else gmove(l->type, nn->type, lg, l, result, nn); regfree(lg); regfree(lg+1); break; case OMUL: case OLMUL: if(l->op == OCONST) if(mulcon(r, l, result, nn)) break; if(r->op == OCONST) if(mulcon(l, r, result, nn)) break; if(debug['M']) print("%L multiply\n", n->lineno); goto binop; case OAND: if(r->op == OCONST) if(typeil[n->type->etype]) if(l->op == OCAST) { if(typec[l->left->type->etype]) if(!(r->vconst & ~0xff)) { l = l->left; goto binop; } if(typeh[l->left->type->etype]) if(!(r->vconst & ~0xffff)) { l = l->left; goto binop; } } goto binop; case OADD: if(result == D_TOS) if(r->addable >= INDEXED) if(l->op == OCONST) if(typeil[l->type->etype]) { v = l->vconst; if(v > -32768 && v < 32768) { rg = regaddr(D_NONE); gmove(r->type, r->type, D_TREE, r, rg, r); gopcode(OADDR, types[TSHORT], D_NONE, Z, rg, r); p->to.offset = v; p->to.type |= I_INDIR; regfree(rg); break; } } case OSUB: if(result == D_TOS) if(l->addable >= INDEXED) if(r->op == OCONST) if(typeil[r->type->etype]) { v = r->vconst; if(v > -32768 && v < 32768) { if(n->op == OSUB) v = -v; lg = regaddr(D_NONE); gmove(l->type, l->type, D_TREE, l, lg, l); gopcode(OADDR, types[TSHORT], D_NONE, Z, lg, l); p->to.offset = v; p->to.type |= I_INDIR; regfree(lg); break; } } goto binop; case OOR: case OXOR: binop: if(result == D_NONE) { nullwarn(l, r); break; } if(l->complex >= FNX && r->complex >= FNX) { cgen(r, D_TOS, r); v = argoff; lg = regalloc(l->type, result); cgen(l, lg, l); adjsp(v - argoff); if(o == OXOR) { rg = regalloc(r->type, D_NONE); gmove(r->type, r->type, D_TOS, r, rg, r); gopcode(o, n->type, rg, r, lg, l); regfree(rg); } else gopcode(o, n->type, D_TOS, r, lg, l); gmove(n->type, nn->type, lg, l, result, nn); regfree(lg); break; } if(l->complex >= r->complex) { if(l->op == OADDR && (o == OADD || o == OSUB)) lg = regaddr(result); else lg = regalloc(l->type, result); cgen(l, lg, l); rg = eval(r, D_NONE); } else { rg = regalloc(r->type, D_NONE); cgen(r, rg, r); lg = regalloc(l->type, result); cgen(l, lg, l); } if(o == OXOR) { if(rg == D_TREE) { rg = regalloc(r->type, D_NONE); cgen(r, rg, r); } if(rg == D_TOS) { rg = regalloc(r->type, D_NONE); gmove(r->type, r->type, D_TOS, r, rg, r); } } gopcode(o, n->type, rg, r, lg, l); gmove(n->type, nn->type, lg, l, result, nn); regfree(lg); regfree(rg); break; case OASHL: if(r->op == OCONST) if(shlcon(l, r, result, nn)) break; case OLSHR: case OASHR: if(result == D_NONE) { nullwarn(l, r); break; } if(l->complex >= FNX && r->complex >= FNX) { cgen(r, D_TOS, r); v = argoff; lg = regalloc(l->type, result); cgen(l, lg, l); adjsp(v - argoff); rg = regalloc(r->type, D_NONE); gopcode(OAS, r->type, D_TOS, r, rg, r); gopcode(n->op, n->type, rg, r, lg, l); gmove(n->type, nn->type, lg, l, result, nn); regfree(lg); regfree(rg); break; } if(l->complex >= r->complex) { lg = regalloc(l->type, result); cgen(l, lg, l); v = vconst(r); if(v <= 0 || v > 8) { rg = regalloc(r->type, D_NONE); cgen(r, rg, r); } else rg = eval(r, D_NONE); } else { rg = regalloc(r->type, D_NONE); cgen(r, rg, r); lg = regalloc(l->type, result); cgen(l, lg, l); } gopcode(o, n->type, rg, r, lg, l); gmove(n->type, nn->type, lg, l, result, nn); regfree(lg); regfree(rg); break; case ONEG: case OCOM: if(result == D_NONE) { nullwarn(l, Z); break; } lg = regalloc(l->type, result); cgen(l, lg, l); gopcode(o, l->type, D_NONE, Z, lg, l); gmove(n->type, nn->type, lg, l, result, nn); regfree(lg); break; case OADDR: if(result == D_NONE) { nullwarn(l, Z); break; } lcgen(l, result, nn); break; case OEQ: case ONE: case OLE: case OLT: case OGE: case OGT: case OLO: case OLS: case OHI: case OHS: if(result == D_NONE) { nullwarn(l, r); break; } boolgen(n, 1, result, nn, Z); break; case OANDAND: case OOROR: boolgen(n, 1, result, nn, Z); if(result == D_NONE) patch(p, pc); break; case OCOMMA: cgen(l, D_NONE, l); doinc(l, POST); doinc(r, PRE); cgen(r, result, nn); break; case ONOT: if(result == D_NONE) { nullwarn(l, Z); break; } boolgen(n, 1, result, nn, Z); break; case OPOSTINC: case OPOSTDEC: v = 1; if(l->type->etype == TIND) v = l->type->link->width; if(o == OPOSTDEC) v = -v; if(l->op == OBIT) goto bitinc; if(nn == Z) goto pre; lg = D_TREE; if(l->addable < INDEXED) { lg = regaddr(D_NONE); lcgen(l, lg, Z); lg |= I_INDIR; } if(result != D_NONE) gmove(l->type, nn->type, lg, l, result, nn); if(typefd[n->type->etype]) { rg = regalloc(n->type, D_NONE); gmove(l->type, l->type, lg, l, rg, l); gopcode(o, n->type, D_CONST, nodconst(1), rg, l); gmove(l->type, l->type, rg, l, lg, l); regfree(rg); } else { if(v < 0) gopcode(o, n->type, D_CONST, nodconst(-v), lg, l); else gopcode(o, n->type, D_CONST, nodconst(v), lg, l); } regfree(lg); break; case OPREINC: case OPREDEC: v = 1; if(l->type->etype == TIND) v = l->type->link->width; if(o == OPREDEC) v = -v; if(l->op == OBIT) goto bitinc; pre: lg = D_TREE; if(l->addable < INDEXED) { lg = regaddr(D_NONE); lcgen(l, lg, Z); lg |= I_INDIR; } if(typefd[n->type->etype]) { rg = regalloc(n->type, D_NONE); gmove(l->type, l->type, lg, l, rg, l); gopcode(o, n->type, D_CONST, nodconst(1), rg, l); gmove(l->type, l->type, rg, l, lg, l); regfree(rg); } else { if(v < 0) gopcode(o, n->type, D_CONST, nodconst(-v), lg, l); else gopcode(o, n->type, D_CONST, nodconst(v), lg, l); } if(result != D_NONE) gmove(l->type, nn->type, lg, l, result, nn); regfree(lg); break; bitinc: rg = regaddr(D_NONE); lg = regalloc(tfield, D_NONE); if(result != D_NONE && (o == OPOSTINC || o == OPOSTDEC)) { g = bitload(l, lg, rg, D_NONE, nn); if(nn != Z) gmove(l->type, nn->type, g, l, result, nn); if(v < 0) gopcode(o, n->type, D_CONST, nodconst(-v), g, n); else gopcode(o, n->type, D_CONST, nodconst(v), g, n); bitstore(l, g, rg, lg, D_NONE, nn); break; } g = bitload(l, lg, rg, result, nn); if(v < 0) gopcode(o, n->type, D_CONST, nodconst(-v), g, n); else gopcode(o, n->type, D_CONST, nodconst(v), g, n); if(result != D_NONE) gmove(l->type, nn->type, g, l, result, nn); bitstore(l, g, rg, lg, D_NONE, nn); break; } }