bool CodePreparation::eliminatePHINodes(Function &F) { // The PHINodes that will be deleted. std::vector<PHINode*> PNtoDel; // The PHINodes that will be preserved. std::vector<PHINode*> PreservedPNs; // Scan the PHINodes in this function. for (Function::iterator ibb = F.begin(), ibe = F.end(); ibb != ibe; ++ibb) for (BasicBlock::iterator iib = ibb->begin(), iie = ibb->getFirstNonPHI(); iib != iie; ++iib) if (PHINode *PN = cast<PHINode>(iib)) { if (Loop *L = LI->getLoopFor(ibb)) { // Induction variable will be preserved. if (L->getCanonicalInductionVariable() == PN) { PreservedPNs.push_back(PN); continue; } } // As DemotePHIToStack does not support invoke edges, we preserve // PHINodes that have invoke edges. if (hasInvokeEdge(PN)) PreservedPNs.push_back(PN); else PNtoDel.push_back(PN); } if (PNtoDel.empty()) return false; // Eliminate the PHINodes that not an Induction variable. while (!PNtoDel.empty()) { PHINode *PN = PNtoDel.back(); PNtoDel.pop_back(); DemotePHIToStack(PN); } // Move all preserved PHINodes to the beginning of the BasicBlock. while (!PreservedPNs.empty()) { PHINode *PN = PreservedPNs.back(); PreservedPNs.pop_back(); BasicBlock *BB = PN->getParent(); if (PN == BB->begin()) continue; PN->moveBefore(BB->begin()); } return true; }
void insert_function_limits(Function &F){ //Functions to be inserted as pragmas FunctionType* funvoid = FunctionType::get(Type::getVoidTy( F.getParent()->getContext() ), false); InlineAsm* fun_begin; InlineAsm* fun_end; if (sizeof(void*)==sizeof(long long)){ fun_begin = InlineAsm::get(funvoid, "callq\tpragma_function_begin", "", false); fun_end = InlineAsm::get(funvoid, "callq\tpragma_function_end", "", false); } else { fun_begin = InlineAsm::get(funvoid, "call\tpragma_function_begin", "", false); fun_end = InlineAsm::get(funvoid, "call\tpragma_function_end", "", false); } //In the beginning { BasicBlock& first = F.getEntryBlock(); int preds = 0; for (pred_iterator pi = pred_begin(&first), pe = pred_end(&first); pi != pe; pi++){ preds++; } if (preds > 0){ report_fatal_error("Error: The first basic block has predecessor.\n"); //TODO: insert a new basic block in the beginning } CallInst* before = CallInst::Create(fun_begin); before->setDoesNotThrow(); before->insertBefore( first.getFirstNonPHI() ); } //In the end for (Function::iterator bb = F.begin(), en = F.end(); bb != en; bb++){ TerminatorInst* inst = bb->getTerminator(); if ( isa<ReturnInst>(inst) ){ CallInst* after = CallInst::Create(fun_end); after->setDoesNotThrow(); //after->insertBefore( inst ); after->insertBefore( bb->getFirstNonPHI() ); } } }
bool LowerEmExceptions::runOnModule(Module &M) { TheModule = &M; // Add functions Type *i32 = Type::getInt32Ty(M.getContext()); Type *i8 = Type::getInt8Ty(M.getContext()); Type *i1 = Type::getInt1Ty(M.getContext()); Type *i8P = i8->getPointerTo(); Type *Void = Type::getVoidTy(M.getContext()); if (!(GetHigh = TheModule->getFunction("getHigh32"))) { FunctionType *GetHighFunc = FunctionType::get(i32, false); GetHigh = Function::Create(GetHighFunc, GlobalValue::ExternalLinkage, "getHigh32", TheModule); } if (!(PreInvoke = TheModule->getFunction("emscripten_preinvoke"))) { FunctionType *VoidFunc = FunctionType::get(Void, false); PreInvoke = Function::Create(VoidFunc, GlobalValue::ExternalLinkage, "emscripten_preinvoke", TheModule); } if (!(PostInvoke = TheModule->getFunction("emscripten_postinvoke"))) { FunctionType *IntFunc = FunctionType::get(i32, false); PostInvoke = Function::Create(IntFunc, GlobalValue::ExternalLinkage, "emscripten_postinvoke", TheModule); } FunctionType *LandingPadFunc = FunctionType::get(i8P, true); LandingPad = Function::Create(LandingPadFunc, GlobalValue::ExternalLinkage, "emscripten_landingpad", TheModule); FunctionType *ResumeFunc = FunctionType::get(Void, true); Resume = Function::Create(ResumeFunc, GlobalValue::ExternalLinkage, "emscripten_resume", TheModule); // Process bool HasWhitelist = Whitelist.size() > 0; std::string WhitelistChecker; if (HasWhitelist) WhitelistChecker = "," + Whitelist + ","; bool Changed = false; for (Module::iterator Iter = M.begin(), E = M.end(); Iter != E; ) { Function *F = Iter++; std::vector<Instruction*> ToErase; std::set<LandingPadInst*> LandingPads; bool AllowExceptionsInFunc = !HasWhitelist || int(WhitelistChecker.find(F->getName())) > 0; for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { // check terminator for invokes if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator())) { LandingPads.insert(II->getLandingPadInst()); bool NeedInvoke = AllowExceptionsInFunc && canThrow(II->getCalledValue()); if (NeedInvoke) { // Insert a normal call instruction folded in between pre- and post-invoke CallInst::Create(PreInvoke, "", II); SmallVector<Value*,16> CallArgs(II->op_begin(), II->op_end() - 3); CallInst *NewCall = CallInst::Create(II->getCalledValue(), CallArgs, "", II); NewCall->takeName(II); NewCall->setCallingConv(II->getCallingConv()); NewCall->setAttributes(II->getAttributes()); NewCall->setDebugLoc(II->getDebugLoc()); II->replaceAllUsesWith(NewCall); ToErase.push_back(II); CallInst *Post = CallInst::Create(PostInvoke, "", II); Instruction *Post1 = new TruncInst(Post, i1, "", II); // Insert a branch based on the postInvoke BranchInst::Create(II->getUnwindDest(), II->getNormalDest(), Post1, II); } else { // This can't throw, and we don't need this invoke, just replace it with a call+branch SmallVector<Value*,16> CallArgs(II->op_begin(), II->op_end() - 3); CallInst *NewCall = CallInst::Create(II->getCalledValue(), CallArgs, "", II); NewCall->takeName(II); NewCall->setCallingConv(II->getCallingConv()); NewCall->setAttributes(II->getAttributes()); NewCall->setDebugLoc(II->getDebugLoc()); II->replaceAllUsesWith(NewCall); ToErase.push_back(II); BranchInst::Create(II->getNormalDest(), II); // Remove any PHI node entries from the exception destination. II->getUnwindDest()->removePredecessor(BB); } Changed = true; } // scan the body of the basic block for resumes for (BasicBlock::iterator Iter = BB->begin(), E = BB->end(); Iter != E; ) { Instruction *I = Iter++; if (ResumeInst *R = dyn_cast<ResumeInst>(I)) { // split the input into legal values Value *Input = R->getValue(); ExtractValueInst *Low = ExtractValueInst::Create(Input, 0, "", R); ExtractValueInst *High = ExtractValueInst::Create(Input, 1, "", R); // create a resume call SmallVector<Value*,2> CallArgs; CallArgs.push_back(Low); CallArgs.push_back(High); CallInst::Create(Resume, CallArgs, "", R); new UnreachableInst(TheModule->getContext(), R); // add a terminator to the block ToErase.push_back(R); } } } // Look for orphan landingpads, can occur in blocks with no predecesors for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { Instruction *I = BB->getFirstNonPHI(); if (LandingPadInst *LP = dyn_cast<LandingPadInst>(I)) { LandingPads.insert(LP); } } // Handle all the landingpad for this function together, as multiple invokes may share a single lp for (std::set<LandingPadInst*>::iterator I = LandingPads.begin(); I != LandingPads.end(); I++) { // Replace the landingpad with a landingpad call to get the low part, and a getHigh for the high LandingPadInst *LP = *I; unsigned Num = LP->getNumClauses(); SmallVector<Value*,16> NewLPArgs; NewLPArgs.push_back(LP->getPersonalityFn()); for (unsigned i = 0; i < Num; i++) { Value *Arg = LP->getClause(i); // As a temporary workaround for the lack of aggregate varargs support // in the varargs lowering code, break out filter operands into their // component elements. if (LP->isFilter(i)) { ArrayType *ATy = cast<ArrayType>(Arg->getType()); for (unsigned elem = 0, elemEnd = ATy->getNumElements(); elem != elemEnd; ++elem) { Instruction *EE = ExtractValueInst::Create(Arg, makeArrayRef(elem), "", LP); NewLPArgs.push_back(EE); } } else { NewLPArgs.push_back(Arg); } } NewLPArgs.push_back(LP->isCleanup() ? ConstantInt::getTrue(i1) : ConstantInt::getFalse(i1)); CallInst *NewLP = CallInst::Create(LandingPad, NewLPArgs, "", LP); Instruction *High = CallInst::Create(GetHigh, "", LP); // New recreate an aggregate for them, which will be all simplified later (simplification cannot handle landingpad, hence all this) InsertValueInst *IVA = InsertValueInst::Create(UndefValue::get(LP->getType()), NewLP, 0, "", LP); InsertValueInst *IVB = InsertValueInst::Create(IVA, High, 1, "", LP); LP->replaceAllUsesWith(IVB); ToErase.push_back(LP); } // erase everything we no longer need in this function for (unsigned i = 0; i < ToErase.size(); i++) ToErase[i]->eraseFromParent(); } return Changed; }