/* stabend - emits the symbol table */ static void stabend(Coordinate *cp, Symbol symroot, Coordinate *cpp[], Symbol sp[], Symbol *ignore) { Symbol addresses; int naddresses, nmodule; { /* annotate top-level symbols */ Symbol p; for (p = symroot; p != NULL; p = up(p->up)) symboluid(p); pickle->globals = symboluid(symroot); } { /* emit addresses of top-level and static symbols */ int i, lc = 0, count = Seq_length(statics); addresses = genident(STATIC, array(voidptype, 1, 0), GLOBAL); comment("addresses:\n"); defglobal(addresses, LIT); for (i = 0; i < count; i++) { Symbol p = Seq_get(statics, i); lc = emit_value(lc, voidptype, p); } lc = pad(maxalign, lc); naddresses = lc; Seq_free(&statics); } { /* emit bp count as an alias for the module */ Symbol spoints = mksymbol(AUTO, stringf("_spoints_V%x_%d", uname, Seq_length(pickle->spoints)), array(unsignedtype, 0, 0)); spoints->generated = 1; defglobal(spoints, LIT); } { /* emit module */ int lc; comment("module:\n"); defglobal(module, LIT); lc = emit_value( 0, unsignedtype, (unsigned long)uname); lc = emit_value(lc, voidptype, addresses); lc = pad(maxalign, lc); nmodule = lc; } Seq_free(&locals); #define printit(x) fprintf(stderr, "%7d " #x "\n", n##x); total += n##x { int total = 0; printit(addresses); printit(module); fprintf(stderr, "%7d bytes total\n", total); } #undef printit { /* complete and write symbol-table pickle */ FILE *f = fopen(stringf("%d.pickle", uname), "wb"); sym_write_module(pickle, f); fclose(f); } }
static void dopending(Symbol p) { if (pending != NULL) { int uid = symboluid(pending); rcc_symbol_ty symbol = mk_symbol(pending); Seq_addhi(pickle->items, rcc_Symbol(uid, symbol)); } pending = p; }
static void asdl_local(Symbol p) { assert(p->x.offset == 0); put(rcc_Local(symboluid(p), mk_symbol(p))); if (p->temporary && p->u.t.cse) { p->u.t.next = temps; temps = p; } }
/* tail - returns the current tail of the symbol table */ static int tail(void) { Symbol p = allsymbols(identifiers); p = up(p); if (p) return symboluid(p); else return 0; }
static void asdl_function(Symbol f, Symbol caller[], Symbol callee[], int ncalls) { list_ty codelist = Seq_new(0), save, calleelist = Seq_new(0), callerlist = Seq_new(0); int i; dopending(f); for (i = 0; caller[i] != NULL; i++) { asdl_local(caller[i]); Seq_addhi(callerlist, to_generic_int(symboluid(caller[i]))); } for (i = 0; callee[i] != NULL; i++) { asdl_local(callee[i]); Seq_addhi(calleelist, to_generic_int(symboluid(callee[i]))); } save = interfaces; interfaces = codelist; gencode(caller, callee); asdl_segment(CODE); emitcode(); interfaces = save; put(rcc_Function(symboluid(f), callerlist, calleelist, ncalls, codelist)); }
/* 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; }
/* entry_hook - called an function entry */ static void entry_hook(void *cl, Symbol cfunc) { static int nfuncs; Type ty; /* Simulate the declaration of an sframe structure, but without the tag. */ ty = newstruct(STRUCT, ""); #define addfield(name,t) \ ty->size = roundup(ty->size, t->align);\ if (ty->align < t->align) ty->align = t->align; \ newfield(string(name), ty, t)->offset = ty->size; \ ty->size += t->size addfield("up", voidptype); addfield("down", voidptype); addfield("func", inttype); addfield("module",inttype); addfield("ip", inttype); #undef addfield ty->size = roundup(ty->size, ty->align); ty->u.sym->defined = 1; ty->u.sym->generated = 1; tos = genident(AUTO, ty, LOCAL); addlocal(tos); tos->defined = 1; /* Generated the assignments to the shadow frame fields. */ #define set(name,e) walk(asgntree(ASGN,field(lvalue(idtree(tos)),string(#name)),(e)),0,0) set(down, idtree(nub_tos)); set(func, cnsttree(inttype, symboluid(cfunc))); set(module, cnsttree(inttype, uname)); #undef set walk(asgn(nub_tos, lvalue(idtree(tos))), 0, 0); foreach(identifiers, PARAM, setoffset, tos); }
static void asdl_import(Symbol p) { dopending(p); put(rcc_Import(symboluid(p))); }
static void asdl_global(Symbol p) { dopending(p); put(rcc_Global(symboluid(p), p->u.seg)); }
static void asdl_export(Symbol p) { put(rcc_Export(symboluid(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; }
static void asdl_defsymbol(Symbol p) { if (p->scope >= GLOBAL) symboluid(p); }
static void asdl_defaddress(Symbol p) { if (p->scope == LABELS) put(rcc_Deflabel(p->u.l.label)); else put(rcc_Defaddress(symboluid(p))); }
static void asdl_address(Symbol q, Symbol p, long n) { assert(q->x.offset == 0); put(rcc_Address(symboluid(q), mk_symbol(q), symboluid(p), n)); }