BB* BBTransform::clone(BB* src, Code* target, ClosureVersion* targetClosure) { std::vector<BB*> bbs; // Copy instructions and remember old -> new instruction map. std::unordered_map<Value*, Instruction*> relocation_table; Visitor::run(src, [&](BB* bb) { BB* theClone = BB::cloneInstrs(bb, target->nextBBId++, target); assert(bb->size() == theClone->size()); if (bb->id >= bbs.size()) bbs.resize(bb->id + 5); bbs[bb->id] = theClone; for (size_t i = 0; i < bb->size(); ++i) relocation_table[bb->at(i)] = theClone->at(i); }); // Fixup CFG: next pointers of copied BB's need to be filled in. Visitor::run(src, [&](BB* bb) { bbs[bb->id]->next0 = bbs[bb->id]->next1 = nullptr; if (bb->next0) bbs[bb->id]->next0 = bbs[bb->next0->id]; if (bb->next1) bbs[bb->id]->next1 = bbs[bb->next1->id]; }); std::unordered_map<Promise*, Promise*> promMap; // Relocate argument pointers using old -> new map BB* newEntry = bbs[src->id]; Visitor::run(newEntry, [&](Instruction* i) { auto phi = Phi::Cast(i); if (phi) { for (size_t j = 0; j < phi->nargs(); ++j) phi->updateInputAt(j, bbs[phi->inputAt(j)->id]); } i->eachArg([&](InstrArg& arg) { if (arg.val()->isInstruction()) { assert(relocation_table.count(arg.val())); arg.val() = relocation_table.at(arg.val()); } }); if (auto mk = MkArg::Cast(i)) { Promise* p = mk->prom(); if (p->owner != targetClosure) { if (promMap.count(p)) { mk->updatePromise(promMap.at(p)); } else { auto c = targetClosure->createProm(p->srcPoolIdx()); c->entry = clone(p->entry, c, targetClosure); mk->updatePromise(c); } } } }); return newEntry; }
/* Writes the procedure's declaration (including arguments), local variables, * and invokes the procedure that writes the code of the given record *hli */ void Function::codeGen (std::ostream &fs) { int numLoc; ostringstream ostr; //STKFRAME * args; /* Procedure arguments */ //char buf[200], /* Procedure's definition */ // arg[30]; /* One argument */ BB *pBB; /* Pointer to basic block */ /* Write procedure/function header */ cCode.init(); if (flg & PROC_IS_FUNC) /* Function */ ostr<< "\n"<<TypeContainer::typeName(retVal.type)<<" "<<name<<" ("; else /* Procedure */ ostr<< "\nvoid "<<name<<" ("; /* Write arguments */ for (size_t i = 0; i < args.size(); i++) { if ( args[i].invalid ) continue; ostr<<hlTypes[args[i].type]<<" "<<args[i].name; if (i < (args.size() - 1)) ostr<<", "; } ostr<<")\n"; /* Write comments */ writeProcComments( ostr ); /* Write local variables */ if (! (flg & PROC_ASM)) { numLoc = 0; for (ID &refId : localId ) { /* Output only non-invalidated entries */ if ( refId.illegal ) continue; if (refId.loc == REG_FRAME) { /* Register variables are assigned to a local variable */ if (((flg & SI_REGVAR) && (refId.id.regi == rSI)) || ((flg & DI_REGVAR) && (refId.id.regi == rDI))) { refId.setLocalName(++numLoc); ostr << "int "<<refId.name<<";\n"; } /* Other registers are named when they are first used in * the output C code, and appended to the proc decl. */ } else if (refId.loc == STK_FRAME) { /* Name local variables and output appropriate type */ refId.setLocalName(++numLoc); ostr << TypeContainer::typeName(refId.type)<<" "<<refId.name<<";\n"; } } } fs<<ostr.str(); /* Write procedure's code */ if (flg & PROC_ASM) /* generate assembler */ { Disassembler ds(3); ds.disassem(this); } else /* generate C */ { m_cfg.front()->writeCode (1, this, &numLoc, MAX, UN_INIT); } cCode.appendCode( "}\n\n"); writeBundle (fs, cCode); freeBundle (&cCode); /* Write Live register analysis information */ if (option.verbose) for (size_t i = 0; i < numBBs; i++) { pBB = m_dfsLast[i]; if (pBB->flg & INVALID_BB) continue; /* skip invalid BBs */ cout << "BB "<<i<<"\n"; cout << " Start = "<<pBB->begin()->loc_ip; cout << ", end = "<<pBB->begin()->loc_ip+pBB->size()<<"\n"; cout << " LiveUse = "; Machine_X86::writeRegVector(cout,pBB->liveUse); cout << "\n Def = "; Machine_X86::writeRegVector(cout,pBB->def); cout << "\n LiveOut = "; Machine_X86::writeRegVector(cout,pBB->liveOut); cout << "\n LiveIn = "; Machine_X86::writeRegVector(cout,pBB->liveIn); cout <<"\n\n"; } }