static int typeuid(Type ty) { rcc_type_ty type; assert(ty); if (ty->x.typeno != 0) return ty->x.typeno; ty->x.typeno = pickle->nuids++; switch (ty->op) { #define xx(op) case op: type = rcc_##op(ty->size, ty->align); break xx(INT); xx(UNSIGNED); xx(FLOAT); xx(VOID); #undef xx #define xx(op) case op: type = rcc_##op(ty->size, ty->align, typeuid(ty->type)); break xx(POINTER); xx(ARRAY); xx(CONST); xx(VOLATILE); #undef xx case CONST+VOLATILE: type = rcc_CONST(ty->size, ty->align, typeuid(ty->type)); break; case ENUM: { list_ty ids = Seq_new(0); int i; for (i = 0; ty->u.sym->u.idlist[i] != NULL; i++) Seq_addhi(ids, rcc_enum_(ty->u.sym->u.idlist[i]->name, ty->u.sym->u.idlist[i]->u.value)); assert(i > 0); type = rcc_ENUM(ty->size, ty->align, ty->u.sym->name, ids); break; } case STRUCT: case UNION: { list_ty fields = Seq_new(0); Field p = fieldlist(ty); for ( ; p != NULL; p = p->link) Seq_addhi(fields, rcc_field(p->name, typeuid(p->type), p->offset, p->bitsize, p->lsb)); if (ty->op == STRUCT) type = rcc_STRUCT(ty->size, ty->align, ty->u.sym->name, fields); else type = rcc_UNION (ty->size, ty->align, ty->u.sym->name, fields); break; } case FUNCTION: { list_ty formals = Seq_new(0); if (ty->u.f.proto != NULL && ty->u.f.proto[0] != NULL) { int i; for (i = 0; ty->u.f.proto[i] != NULL; i++) Seq_addhi(formals, to_generic_int(typeuid(ty->u.f.proto[i]))); } else if (ty->u.f.proto != NULL && ty->u.f.proto[0] == NULL) Seq_addhi(formals, to_generic_int(typeuid(voidtype))); type = rcc_FUNCTION(ty->size, ty->align, typeuid(ty->type), formals); break; } default: assert(0); } Seq_addhi(pickle->items, rcc_Type(ty->x.typeno, type)); return ty->x.typeno; }
/* symboluid - returns sym's uid, adding the symbol, if necessary */ static int symboluid(const Symbol p) { int uid; sym_symbol_ty sym; if (p == NULL) return 0; sym = Table_get(uidTable, p); if (sym != NULL) return sym->uid; uid = pickle->nuids++; switch (p->sclass) { case ENUM: sym = sym_ENUMCONST(p->name, uid, uname, NULL, 0, 0, p->u.value); sym->type = typeuid(inttype); break; case TYPEDEF: sym = sym_TYPEDEF(p->name, uid, uname, NULL, 0, 0); sym->type = typeuid(p->type); break; default: if (p->sclass == STATIC) { sym = sym_STATIC(p->name, uid, uname, NULL, 0, 0, Seq_length(statics)); Seq_addhi(statics, p); } else if (p->scope == GLOBAL || p->sclass == EXTERN) { sym = sym_GLOBAL(p->name, uid, uname, NULL, 0, 0, Seq_length(statics)); Seq_addhi(statics, p); } else if (p->scope == PARAM) sym = sym_PARAM(p->name, uid, uname, NULL, 0, 0, p->x.offset); else { assert(p->scope >= LOCAL); sym = sym_LOCAL(p->name, uid, uname, NULL, 0, 0, p->x.offset); } sym->type = typeuid(p->type); } Table_put(uidTable, p, sym); Seq_addhi(pickle->items, sym_Symbol(uid, sym)); sym->src = sym_coordinate(p->src.file ? p->src.file : string(""), p->src.x, p->src.y); sym->uplink = symboluid(up(p->up)); return sym->uid; }
static rcc_symbol_ty mk_symbol(Symbol p) { int flags = 0, ref = 10000*p->ref; if (p->ref > 0 && ref == 0) ref++; #define xx(f,n) flags |= p->f<<n; xx(structarg,0) xx(addressed,1) xx(computed,2) xx(temporary,3) xx(generated,4) #undef xx return rcc_symbol(p->name, typeuid(p->type), p->scope, p->sclass, ref, flags); }
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; }