NODE * getlr(NODE *p, int c) { /* return the pointer to the left or right side of p, or p itself, depending on the optype of p */ switch (c) { case '1': case '2': case '3': case 'D': if (c == 'D') c = 0; else c -= '0'; if (resc[c].n_op == FREE) comperr("getlr: free node"); return &resc[c]; case 'L': return( optype( p->n_op ) == LTYPE ? p : p->n_left ); case 'R': return( optype( p->n_op ) != BITYPE ? p : p->n_right ); } cerror( "bad getlr: %c", c ); /* NOTREACHED */ return NULL; }
/* * Convert a node to REG or OREG. * Shape is register class where we want the result. * Returns register class if register nodes. * If w is: (should be shapes) * - SRREG - result in register, call geninsn(). * - SROREG - create OREG; call offstar(). * - 0 - clear su, walk down. */ static int swmatch(NODE *p, int shape, int w) { int rv = 0; F2DEBUG(("swmatch: p=%p, shape=%s, w=%s\n", p, prcook(shape), srtyp[w])); switch (w) { case SRREG: rv = geninsn(p, shape); break; case SROREG: /* should be here only if op == UMUL */ if (p->n_op != UMUL && p->n_op != FLD) comperr("swmatch %p", p); if (p->n_op == FLD) { offstar(p->n_left->n_left, shape); p->n_left->n_su = 0; } else offstar(p->n_left, shape); p->n_su = 0; rv = ffs(shape)-1; break; case 0: if (optype(p->n_op) == BITYPE) swmatch(p->n_right, 0, 0); if (optype(p->n_op) != LTYPE) swmatch(p->n_left, 0, 0); p->n_su = 0; } return rv; }
static void tmpalloc(sNode_t p) { p->x.optimized=0; p->x.name="*******"; p->x.adrmode='*'; releasetmp(p->kids[0]); releasetmp(p->kids[1]); switch (generic(p->op)) { case ARG: p->x.argoffset = argoffset; argoffset += p->syms[0]->u.c.v.i; /* if (0) { Node k=p->kids[0]; if (k->count==0 && generic(k->op)!=INDIR && generic(k->op)!=ADDRF && generic(k->op)!=ADDRG && generic(k->op)!=ADDRL && generic(k->op)!=CNST ) { p->x.optimized=1; k->x.optimized=1; k->x.name=stringf("(sp),%d",p->x.argoffset); k->x.adrmode='I'; } } */ break; case CALL: p->x.argoffset = argoffset; argoffset = 0; break; case ASGN: if (optimizelevel>=3) { /* kids[1] : expression droite */ if (optype(p->op)!=B && p==p->kids[1]->x.next && ( generic(p->kids[0]->op)==ADDRF || generic(p->kids[0]->op)==ADDRG || generic(p->kids[0]->op)==ADDRL) && generic(p->kids[1]->op)!=INDIR && generic(p->kids[1]->op)!=ADDRF && generic(p->kids[1]->op)!=ADDRG && generic(p->kids[1]->op)!=ADDRL && generic(p->kids[1]->op)!=CNST ) { sNode_t k=p->kids[1]; p->x.optimized=1; k->x.optimized=1; k->x.result=p->kids[0]->x.result; k->x.name=k->x.result->x.name; k->x.adrmode=k->x.result->x.adrmode; if (k->x.adrmode=='C') k->x.adrmode='D'; else k->x.adrmode='I'; } } break; } if (needtmp(p)) gettmp(p); }
static void prelabel(Node p) { if (p == NULL) return; prelabel(p->kids[0]); prelabel(p->kids[1]); if (NeedsReg[opindex(p->op)]) setreg(p, (*IR->x.rmap)(opkind(p->op))); switch (generic(p->op)) { case ADDRF: case ADDRL: if (p->syms[0]->sclass == REGISTER) p->op = VREG+P; break; case INDIR: if (p->kids[0]->op == VREG+P) setreg(p, p->kids[0]->syms[0]); break; case ASGN: if (p->kids[0]->op == VREG+P) rtarget(p, 1, p->kids[0]->syms[0]); break; case CVI: case CVU: case CVP: if (optype(p->op) != F && opsize(p->op) <= p->syms[0]->u.c.v.i) p->op = LOAD + opkind(p->op); break; } (IR->x.target)(p); }
/* XXX should this go away now? */ int shtemp(NODE *p) { return 0; #if 0 int r; if (p->n_op == STARG ) p = p->n_left; switch (p->n_op) { case REG: return (!istreg(p->n_rval)); case OREG: r = p->n_rval; if (R2TEST(r)) { if (istreg(R2UPK1(r))) return(0); r = R2UPK2(r); } return (!istreg(r)); case UMUL: p = p->n_left; return (p->n_op != UMUL && shtemp(p)); } if (optype(p->n_op) != LTYPE) return(0); return(1); #endif }
char *opname(int op) { static char *opnames[] = { "", "CNST", "ARG", "ASGN", "INDIR", "CVC", "CVD", "CVF", "CVI", "CVP", "CVS", "CVU", "NEG", "CALL", "*LOAD*", "RET", "ADDRG", "ADDRF", "ADDRL", "ADD", "SUB", "LSH", "MOD", "RSH", "BAND", "BCOM", "BOR", "BXOR", "DIV", "MUL", "EQ", "GE", "GT", "LE", "LT", "NE", "JUMP", "LABEL", "AND", "NOT", "OR", "COND", "RIGHT", "FIELD" }, *suffixes[] = { "0", "F", "D", "C", "S", "I", "U", "P", "V", "B", "10","11","12","13","14","15" }; if (generic(op) >= AND && generic(op) <= FIELD && opsize(op) == 0) return opnames[opindex(op)]; return stringf("%s%s%s", opindex(op) > 0 && opindex(op) < NELEMS(opnames) ? opnames[opindex(op)] : stringd(opindex(op)), suffixes[optype(op)], opsize(op) > 0 ? stringd(opsize(op)) : ""); }
static void gettmp(sNode_t p) { int t; /* Node q; int call_found=0, use_zpage=1; for (q=p->x.next; q; q=q->x.next) { if (generic(q->op)==CALL) call_found=1; if ((q->kids[0]==p || q->kids[1]==p) && call_found) use_zpage=0; } */ if ( optype(p->op)!=F && optype(p->op)!=D ) { for (t=0;t<24;t++) if ((busy&(1<<t))==0) { busy|=1<<t; p->x.result=temp[t]; p->x.adrmode='D'; if (t>=8) { temp[t]->type->size=2; local(temp[t]); p->x.adrmode='I'; } p->x.name=temp[t]->x.name; return; } } else for (t=24;t<32;t++) if ((busy&(1<<t))==0) { busy|=1<<t; p->x.result=temp[t]; p->x.adrmode='I'; temp[t]->type->size=5; local(temp[t]); p->x.name=temp[t]->x.name; return; } perror("Too complex expression"); exit(1); }
static Symbol rmap(int opk) { switch (optype(opk)) { case B: case P: case I: case U: case F: return regw; default: return 0; } }
static void I(defsymbol)(Symbol p) { if (p->scope == CONSTANTS) switch (optype(ttob(p->type))) { case I: p->x.name = stringf("%D", p->u.c.v.i); break; case U: p->x.name = stringf("%U", p->u.c.v.u); break; case P: p->x.name = stringf("%U", p->u.c.v.p); break; default: assert(0); } else if (p->scope >= LOCAL && p->sclass == STATIC) p->x.name = stringf("$%d", genlabel(1)); else if (p->scope == LABELS || p->generated) p->x.name = stringf("$%s", p->name); else p->x.name = p->name; }
char* getNodeText(Node p) { switch (generic(p->op)) { case LABEL: return stringf("LABEL %s", p->syms[0]->x.name); case ADDRL: if (isdigit(p->syms[0]->name[0])) return stringf("ADDRL t%s", p->syms[0]->name); else return stringf("ADDRL %s", p->syms[0]->name); case ADDRG: return stringf("ADDRG %s", p->syms[0]->x.name); case ADDRF: return stringf("ADDRF %s", p->syms[0]->name); case EQ: return stringf("BREQ %s", p->syms[0]->x.name); case NE: return stringf("BRNE %s", p->syms[0]->x.name); case LT: return stringf("BRLT %s", p->syms[0]->x.name); case GT: return stringf("BRGT %s", p->syms[0]->x.name); case LE: return stringf("BRLE %s", p->syms[0]->x.name); case GE: return stringf("BRGE %s", p->syms[0]->x.name); case CNST: if (optype(p->op) == I) return stringf("CNST %d", p->syms[0]->u.c.v.i); else if (optype(p->op) == U) return stringf("CNST %u", p->syms[0]->u.c.v.u); else return opname(p->op); default: return opname(p->op); } }
/* * make a fresh copy of p */ NODE * tcopy(NODE *p) { NODE *q; q = talloc(); *q = *p; switch (optype(q->n_op)) { case BITYPE: q->n_right = tcopy(p->n_right); case UTYPE: q->n_left = tcopy(p->n_left); } return(q); }
static void spillr(Symbol r, Node here) { int i; Symbol tmp; Node p = r->x.lastuse; assert(p); while (p->x.prevuse) assert(r == p->syms[RX]), p = p->x.prevuse; assert(p->x.registered && !readsreg(p)); tmp = newtemp(AUTO, optype(p->op), opsize(p->op)); genspill(r, p, tmp); for (p = here->x.next; p; p = p->x.next) for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) { Node k = p->x.kids[i]; if (k->x.registered && k->syms[RX] == r) genreload(p, tmp, i); } putreg(r); }
static void dumptree(Node p) { if (p->op == VREG+P && p->syms[0]) { fprint(stderr, "VREGP(%s)", p->syms[0]->name); return; } else if (generic(p->op) == LOAD) { fprint(stderr, "LOAD("); dumptree(p->kids[0]); fprint(stderr, ")"); return; } fprint(stderr, "%s(", opname(p->op)); switch (generic(p->op)) { case CNST: case LABEL: case ADDRG: case ADDRF: case ADDRL: if (p->syms[0]) fprint(stderr, "%s", p->syms[0]->name); break; case RET: if (p->kids[0]) dumptree(p->kids[0]); break; case CVF: case CVI: case CVP: case CVU: case JUMP: case ARG: case BCOM: case NEG: case INDIR: dumptree(p->kids[0]); break; case CALL: if (optype(p->op) != B) { dumptree(p->kids[0]); break; } /* else fall thru */ case EQ: case NE: case GT: case GE: case LE: case LT: case ASGN: case BOR: case BAND: case BXOR: case RSH: case LSH: case ADD: case SUB: case DIV: case MUL: case MOD: dumptree(p->kids[0]); fprint(stderr, ", "); dumptree(p->kids[1]); break; default: assert(0); } fprint(stderr, ")"); }
/* * set registers in calling conventions live. */ int * livecall(NODE *p) { static int r[NTEMPREG+1]; NODE *q; int cr = 0; if (optype(p->n_op) != BITYPE) return r[0] = -1, r; for (q = p->n_right; q->n_op == CM; q = q->n_left) { if (q->n_right->n_op == ASSIGN && q->n_right->n_left->n_op == REG) r[cr++] = regno(q->n_right->n_left); } if (q->n_op == ASSIGN && q->n_left->n_op == REG) r[cr++] = regno(q->n_left); r[cr++] = -1; return r; }
static void I(defsymbol)(Symbol p) { if (p->scope == CONSTANTS) switch (optype(ttob(p->type))) { case I: p->x.name = stringf("%D", p->u.c.v.i); break; case U: p->x.name = stringf("%U", p->u.c.v.u); break; case P: p->x.name = stringf("%U", p->u.c.v.p); break; case F: { // JDC: added this to get inline floats floatint_t temp; temp.f = p->u.c.v.d; p->x.name = stringf("%U", temp.ui ); } break;// JDC: added this default: assert(0); } else if (p->scope >= LOCAL && p->sclass == STATIC) p->x.name = stringf("$%d", genlabel(1)); else if (p->scope == LABELS || p->generated) p->x.name = stringf("$%s", p->name); else p->x.name = p->name; }
/* getop: get next operator or numeric operand, return type */ int getop(char s[]) { int i, c, type; i = 0; while ( (s[i] = c = getch()) == ' ' || c == '\t') ; /* skip white space */ if (c == '-') { /* '-' could be operator or negative indicator */ s[++i] = c = getch(); if (!isdigit(c)) { ungetch(c); s[i] = '\0'; return s[0]; } } if (isop(c) || c == '\n') { s[i] = '\0'; return c; } else if (isdigit(c) || c == '.') { /* digit */ type = NUMBER; if (isdigit(c)) /* collect integer part */ while (isdigit(s[++i] = c = getch())) ; if (c == '.') /* collect fraction part */ while (isdigit(s[++i] = c = getch())) ; } else { /* handles any other input */ while ( (s[++i] = c = getch()) != ' ' && c != '\t' && c != '\n') ; type = optype(s, i-1); } s[i] = '\0'; if (c != EOF) ungetch(c); return type; }
static void dumptree(Node p) { switch (specific(p->op)) { case ASGN+B: assert(p->kids[0]); assert(p->kids[1]); assert(p->syms[0]); dumptree(p->kids[0]); dumptree(p->kids[1]); print("%s %d\n", opname(p->op), p->syms[0]->u.c.v.u); return; case RET+V: assert(!p->kids[0]); assert(!p->kids[1]); print("%s\n", opname(p->op)); return; } switch (generic(p->op)) { case CNST: case ADDRG: case ADDRF: case ADDRL: case LABEL: assert(!p->kids[0]); assert(!p->kids[1]); assert(p->syms[0] && p->syms[0]->x.name); print("%s %s\n", opname(p->op), p->syms[0]->x.name); return; case CVF: case CVI: case CVP: case CVU: assert(p->kids[0]); assert(!p->kids[1]); assert(p->syms[0]); dumptree(p->kids[0]); print("%s %d\n", opname(p->op), p->syms[0]->u.c.v.i); return; case ARG: case BCOM: case NEG: case INDIR: case JUMP: case RET: assert(p->kids[0]); assert(!p->kids[1]); dumptree(p->kids[0]); print("%s\n", opname(p->op)); return; case CALL: assert(p->kids[0]); assert(!p->kids[1]); assert(optype(p->op) != B); dumptree(p->kids[0]); print("%s\n", opname(p->op)); return; case ASGN: case BOR: case BAND: case BXOR: case RSH: case LSH: case ADD: case SUB: case DIV: case MUL: case MOD: assert(p->kids[0]); assert(p->kids[1]); dumptree(p->kids[0]); dumptree(p->kids[1]); print("%s\n", opname(p->op)); return; case EQ: case NE: case GT: case GE: case LE: case LT: assert(p->kids[0]); assert(p->kids[1]); assert(p->syms[0]); assert(p->syms[0]->x.name); dumptree(p->kids[0]); dumptree(p->kids[1]); print("%s %s\n", opname(p->op), p->syms[0]->x.name); return; } assert(0); }
static Tree root1(Tree p) { if (p == NULL) return p; if (p->type == voidtype) warn++; switch (generic(p->op)) { case COND: { Tree q = p->kids[1]; assert(q && q->op == RIGHT); if (p->u.sym && q->kids[0] && generic(q->kids[0]->op) == ASGN) q->kids[0] = root1(q->kids[0]->kids[1]); else q->kids[0] = root1(q->kids[0]); if (p->u.sym && q->kids[1] && generic(q->kids[1]->op) == ASGN) q->kids[1] = root1(q->kids[1]->kids[1]); else q->kids[1] = root1(q->kids[1]); p->u.sym = 0; if (q->kids[0] == 0 && q->kids[1] == 0) p = root1(p->kids[0]); } break; case AND: case OR: if ((p->kids[1] = root1(p->kids[1])) == 0) p = root1(p->kids[0]); break; case NOT: if (warn++ == 0) warning("expression with no effect elided\n"); return root1(p->kids[0]); case RIGHT: if (p->kids[1] == 0) return root1(p->kids[0]); if (p->kids[0] && p->kids[0]->op == CALL+B && p->kids[1] && p->kids[1]->op == INDIR+B) /* avoid premature release of the CALL+B temporary */ return p->kids[0]; if (p->kids[0] && p->kids[0]->op == RIGHT && p->kids[1] == p->kids[0]->kids[0]) /* de-construct e++ construction */ return p->kids[0]->kids[1]; p = tree(RIGHT, p->type, root1(p->kids[0]), root1(p->kids[1])); return p->kids[0] || p->kids[1] ? p : (Tree)0; case EQ: case NE: case GT: case GE: case LE: case LT: case ADD: case SUB: case MUL: case DIV: case MOD: case LSH: case RSH: case BAND: case BOR: case BXOR: if (warn++ == 0) warning("expression with no effect elided\n"); p = tree(RIGHT, p->type, root1(p->kids[0]), root1(p->kids[1])); return p->kids[0] || p->kids[1] ? p : (Tree)0; case INDIR: if (p->type->size == 0 && unqual(p->type) != voidtype) warning("reference to `%t' elided\n", p->type); if (isptr(p->kids[0]->type) && isvolatile(p->kids[0]->type->type)) warning("reference to `volatile %t' elided\n", p->type); /* fall thru */ case NEG: case BCOM: case FIELD: if (warn++ == 0) warning("expression with no effect elided\n"); return root1(p->kids[0]); case ADDRL: case ADDRG: case ADDRF: case CNST: if (needconst) return p; if (warn++ == 0) warning("expression with no effect elided\n"); return NULL; case CVF: if (optype(p->op) == I || p->type->size < p->kids[0]->type->size) if (warn++ == 0) warning("expression with no effect elided\n"); return root1(p->kids[0]); case CVI: if ((optype(p->op) == U || optype(p->op) == I) && p->type->size < p->kids[0]->type->size && specific(p->kids[0]->op) != CALL+I) if (warn++ == 0) warning("expression with no effect elided\n"); return root1(p->kids[0]); case CVU: case CVP: if ((optype(p->op) == U && p->type->size < p->kids[0]->type->size) || (optype(p->op) == I && p->type->size <= p->kids[0]->type->size)) if (warn++ == 0) warning("expression with no effect elided\n"); return root1(p->kids[0]); case ARG: case ASGN: case CALL: case JUMP: case LABEL: break; default: assert(0); } return p; }
static rcc_node_ty visit(Node p) { Symbol q; rcc_node_ty left = NULL, right = NULL; int suffix = optype(p->op), size = opsize(p->op); assert(p); for (q = temps; q; q = q->u.t.next) if (q->u.t.cse == p) { q->u.t.cse = NULL; return rcc_CSE(0, 0, symboluid(q), visit(p)); } if (p->kids[0] != NULL) left = visit(p->kids[0]); if (p->kids[1] != NULL) right = visit(p->kids[1]); switch (specific(p->op)) { case CNST+F: assert(p->syms[0]); return rcc_CNSTF(suffix, size, mk_real(size, p->syms[0]->u.c.v)); case CALL+B: assert(p->syms[0]); assert(p->syms[0]->type); return rcc_CALLB(suffix, size, left, right, typeuid(p->syms[0]->type)); case RET+V: return rcc_RET(suffix, size); case LABEL+V: assert(p->syms[0]); return rcc_LABEL(suffix, size, p->syms[0]->u.l.label); } switch (generic(p->op)) { case CNST: assert(p->syms[0]); return rcc_CNST(suffix, size, p->syms[0]->u.c.v.i); /* FIXME */ case ARG: assert(p->syms[0]); return rcc_ARG(suffix, size, left, p->syms[0]->u.c.v.i, p->syms[1]->u.c.v.i); case ASGN: assert(p->syms[0]); assert(p->syms[1]); return rcc_ASGN(suffix, size, left, right, p->syms[0]->u.c.v.i, p->syms[1]->u.c.v.i); case CVF: case CVI: case CVP: case CVU: assert(p->syms[0]); return rcc_CVT(suffix, size, generic(p->op), left, p->syms[0]->u.c.v.i); case CALL: assert(p->syms[0]); assert(p->syms[0]->type); return rcc_CALL(suffix, size, left, typeuid(p->syms[0]->type)); #define xx(op) case op: return rcc_##op(suffix, size, symboluid(p->syms[0])) xx(ADDRG); xx(ADDRF); #undef xx case ADDRL: if (!p->syms[0]->defined) (*IR->local)(p->syms[0]); p->syms[0]->defined = 1; return rcc_ADDRL(suffix, size, symboluid(p->syms[0])); case JUMP: if (p->syms[0] != NULL) return rcc_BRANCH(suffix, size, p->syms[0]->u.l.label); return rcc_Unary(suffix, size, generic(p->op), left); case INDIR: case RET: case NEG: case BCOM: return rcc_Unary(suffix, size, generic(p->op), left); case BOR: case BAND: case BXOR: case RSH: case LSH: case ADD: case SUB: case DIV: case MUL: case MOD: return rcc_Binary(suffix, size, generic(p->op), left, right); case EQ: case NE: case GT: case GE: case LE: case LT: assert(p->syms[0]); return rcc_Compare(suffix, size, generic(p->op), left, right, p->syms[0]->u.l.label); } assert(0); return NULL; }
/* * Try to find constructs like "a = a + 1;" and match them together * with instructions like "incl a" or "addl $1,a". * * Level assignment for priority: * left right prio * - - - * direct direct 1 * direct REG 2 * direct OREG 3 * OREG direct 4 * OREG REG 5 * OREG OREG 6 */ int findmops(NODE *p, int cookie) { extern int *qtable[]; struct optab *q; int i, sh, shl, shr, lvl = 10; NODE *l, *r; int *ixp; struct optab *qq = NULL; /* XXX gcc */ int idx = 0, gol = 0, gor = 0; shl = shr = 0; F2DEBUG(("findmops tree: %s\n", prcook(cookie))); F2WALK(p); l = getlr(p, 'L'); r = getlr(p, 'R'); /* See if this is a usable tree to work with */ /* Currently only check for leaves */ if (optype(r->n_op) != BITYPE || treecmp(l, r->n_left) == 0) return FFAIL; F2DEBUG(("findmops is useable\n")); /* We can try to find a match. Use right op */ ixp = qtable[r->n_op]; l = getlr(r, 'L'); r = getlr(r, 'R'); for (i = 0; ixp[i] >= 0; i++) { q = &table[ixp[i]]; F2DEBUG(("findmops: ixp %d\n", ixp[i])); if (!acceptable(q)) /* target-dependent filter */ continue; if (ttype(l->n_type, q->ltype) == 0 || ttype(r->n_type, q->rtype) == 0) continue; /* Types must be correct */ F2DEBUG(("findmops got types\n")); switch (cookie) { case FOREFF: if ((q->visit & FOREFF) == 0) continue; /* Not only for side effects */ break; case FORCC: if ((q->visit & FORCC) == 0) continue; /* Not only for side effects */ break; default: if ((cookie & q->visit) == 0) continue; /* Won't match requested shape */ if (((cookie & INREGS & q->lshape) == 0) || !isreg(l)) continue; /* Bad return register */ break; } F2DEBUG(("findmops cookie\n")); /* * left shape must match left node. */ if ((shl = tshape(l, q->lshape)) != SRDIR && (shl != SROREG)) continue; F2DEBUG(("findmops lshape %s\n", srtyp[shl])); F2WALK(l); if ((shr = chcheck(r, q->rshape, 0)) == SRNOPE) continue; F2DEBUG(("findmops rshape %s\n", srtyp[shr])); /* * Only allow RLEFT. XXX */ if ((q->rewrite & (RLEFT|RRIGHT)) != RLEFT) continue; F2DEBUG(("rewrite OK\n")); F2WALK(r); if (q->needs & REWRITE) break; /* Done here */ if (lvl <= (shl + shr)) continue; lvl = shl + shr; qq = q; idx = ixp[i]; gol = shl; gor = shr; } if (lvl == 10) return FFAIL; F2DEBUG(("findmops entry %d(%s,%s)\n", idx, srtyp[gol], srtyp[gor])); /* * Now we're here and have a match. left is semi-direct and * right may be anything. */ sh = -1; sh = shswitch(sh, p->n_left, qq->lshape, cookie, qq->rewrite & RLEFT, gol); sh = shswitch(sh, r, qq->rshape, cookie, 0, gor); if (sh == -1) { if (cookie & (FOREFF|FORCC)) sh = 0; else sh = ffs(cookie & qq->visit & INREGS)-1; } F2DEBUG(("findmops done: node %p class %d\n", p, sh)); /* Trickery: Set table index on assign to op instead */ /* gencode() will remove useless nodes */ p->n_su = MKIDX(idx, 0); p->n_su |= ISMOPS; /* XXX tell gencode to reduce the right tree */ SCLASS(p->n_su, sh); return sh; }
//function(..) module saved jan 1 2013 as part of prep for scrt integration static void function(Symbol f, Symbol caller[], Symbol callee[], int ncalls) { int i, saved, sizefsave, sizeisave, varargs; Symbol r, argregs[NUM_ARG_REGS]; usedmask[0] = usedmask[1] = 0; freemask[0] = freemask[1] = ~(unsigned)0; offset = maxoffset = maxargoffset = 0; for (i = 0; callee[i]; i++) //find last argument ; varargs = variadic(f->type) //see if variable arguments by type or by name of final argument || i > 0 && strcmp(callee[i-1]->name, "va_alist") == 0; for (i = 0; callee[i]; i++) { //for each argument Symbol p = callee[i]; Symbol q = caller[i]; assert(q); offset = roundup(offset, q->type->align); //calculate the offset from the caller's sp p->x.offset = q->x.offset = offset; p->x.name = q->x.name = stringd(offset); r = argreg(i, offset, optype(ttob(q->type)), q->type->size, optype(ttob(caller[0]->type))); if (i < NUM_ARG_REGS) argregs[i] = r; offset = roundup(offset + q->type->size, 2); //i dunno if (varargs) p->sclass = AUTO; //variable args are always auto? else if (r && ncalls == 0 && //I dunno !isstruct(q->type) && !p->addressed && !(isfloat(q->type) && r->x.regnode->set == IREG)) { p->sclass = q->sclass = REGISTER; askregvar(p, r); assert(p->x.regnode && p->x.regnode->vbl == p); q->x = p->x; q->type = p->type; } else if (askregvar(p, rmap(ttob(p->type))) && r != NULL && (isint(p->type) || p->type == q->type)) { assert(q->sclass != REGISTER); p->sclass = q->sclass = REGISTER; q->type = p->type; } } assert(!caller[i]); //done with arguments, their individual offsets and maxargoffset have been set offset = 0; gencode(caller, callee); if (ncalls) //prepare to save return address if necessary(i.e. we do calls of our own) usedmask[IREG] |= ((unsigned)1)<<REG_RETADDR; usedmask[IREG] &= INT_CALLEE_SAVE; //limit saving to those we're responsible for usedmask[FREG] &= 0xfff00000; maxargoffset = roundup(maxargoffset, usedmask[FREG] ? 8 : 2); if (ncalls && maxargoffset < NUM_ARG_REGS*2) maxargoffset = NUM_ARG_REGS*2; sizefsave = 4*bitcount(usedmask[FREG]); //space needed to save the float regs sizeisave = 2*bitcount(usedmask[IREG]); //space needed to save the int regs framesize = roundup(maxargoffset + sizefsave //space for outgoing arguments, space for saving floats, + sizeisave + maxoffset, 2); //space for saving ints, space for locals //segment(CODE); //printf("\talign 16\n"); printf("%s:\n", f->x.name); i = maxargoffset + sizefsave - framesize; //I dunno but it's -v and it's never used! if (framesize > 0) print("\talu2I sp,sp,%d,smi,smbi\n", framesize); saved = maxargoffset; /space needed for outgoing arguments
static int needtmp(sNode_t p) { switch (generic(p->op)) { case ADDRF: case ADDRG: case ADDRL: case CNST: assert(optimizelevel==0); return 1; case INDIR: if (optimizelevel>=3) { if (optype(p->op)==B) { /* fix frontend bug: remove all INDIRB nodes */ p->x.optimized=1; p->x.result=p->kids[0]->x.result; p->x.name=p->x.result->x.name; p->x.adrmode=p->kids[0]->x.adrmode; return 0; } else if (p->x.next && ( p->kids[0]->count==0 || p->count==1 && ( p->x.next->kids[0]==p || p->x.next->kids[1]==p) ) && ( generic(p->kids[0]->op)==ADDRF || generic(p->kids[0]->op)==ADDRG || generic(p->kids[0]->op)==ADDRL || generic(p->kids[0]->op)==CNST )) { p->x.optimized=1; p->x.result=p->kids[0]->x.result; p->x.name=p->x.result->x.name; if (p->x.result->x.adrmode=='C') p->x.adrmode='D'; else p->x.adrmode='I'; return 0; } } return 1; case ASGN: case ARG: case EQ: case GE: case GT: case LE: case LT: case NE: case RET: case JUMP: case LABEL: return 0; case CALL: if (optype(p->op)==B) return 0; if (p->count==0) p->op=CALLV; if (optype(p->op)==V) return 0; else return 1; default: return 1; } }