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; }
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; }