bool Builder::HasNamedMetaDataOnCallInstr(Instruction* inst, StringRef mdName) { CallInst* pCallInstr = dyn_cast<CallInst>(inst); if (!pCallInstr) { return false; } return (pCallInstr->getMetadata(mdName) != nullptr); }
bool LowerExcHandlers::runOnFunction(Function &F) { if (!except_enter_func) return false; // No EH frames in this module /* Step 1: EH Depth Numbering */ std::map<llvm::CallInst *, int> EnterDepth; std::map<llvm::CallInst *, int> LeaveDepth; std::map<BasicBlock *, int> ExitDepth; int MaxDepth = 0; // Compute EH Depth at each basic block using a DFS traversal. for (df_iterator<BasicBlock *> I = df_begin(&F.getEntryBlock()), E = df_end(&F.getEntryBlock()); I != E; ++I) { auto *BB = *I; int Depth = 0; /* Here we use the assumption that all incoming edges have the same * EH depth. */ for (auto *Pred : predecessors(BB)) { auto it = ExitDepth.find(Pred); if (it != ExitDepth.end()) { Depth = it->second; break; } } /* Compute the depth within the basic block */ for (auto &I : *BB) { auto *CI = dyn_cast<CallInst>(&I); if (!CI) continue; Function *Callee = CI->getCalledFunction(); if (!Callee) continue; if (Callee == except_enter_func) EnterDepth[CI] = Depth++; else if (Callee == leave_func) { LeaveDepth[CI] = Depth; Depth -= cast<ConstantInt>(CI->getArgOperand(0))->getLimitedValue(); } assert(Depth >= 0); if (Depth > MaxDepth) MaxDepth = Depth; } /* Remember the depth at the BB boundary */ ExitDepth[BB] = Depth; } /* Step 2: EH Frame lowering */ // Allocate stack space for each handler. We allocate these as separate // allocas so the optimizer can later merge and reaarange them if it wants // to. Value *handler_sz = ConstantInt::get(Type::getInt32Ty(F.getContext()), sizeof(jl_handler_t)); Value *handler_sz64 = ConstantInt::get(Type::getInt64Ty(F.getContext()), sizeof(jl_handler_t)); Instruction *firstInst = &F.getEntryBlock().front(); std::vector<AllocaInst *> buffs; for (int i = 0; i < MaxDepth; ++i) { auto *buff = new AllocaInst(Type::getInt8Ty(F.getContext()), 0, handler_sz, "", firstInst); buff->setAlignment(16); buffs.push_back(buff); } // Lower enter funcs for (auto it : EnterDepth) { assert(it.second >= 0); AllocaInst *buff = buffs[it.second]; CallInst *enter = it.first; auto new_enter = CallInst::Create(jlenter_func, buff, "", enter); Value *lifetime_args[] = { handler_sz64, buff }; CallInst::Create(lifetime_start, lifetime_args, "", new_enter); #ifndef _OS_WINDOWS_ // For LLVM 3.3 compatibility Value *args[] = {buff, ConstantInt::get(Type::getInt32Ty(F.getContext()), 0)}; auto sj = CallInst::Create(setjmp_func, args, "", enter); #else auto sj = CallInst::Create(setjmp_func, buff, "", enter); #endif // We need to mark this on the call site as well. See issue #6757 sj->setCanReturnTwice(); if (auto dbg = enter->getMetadata(LLVMContext::MD_dbg)) { new_enter->setMetadata(LLVMContext::MD_dbg, dbg); sj->setMetadata(LLVMContext::MD_dbg, dbg); } enter->replaceAllUsesWith(sj); enter->eraseFromParent(); } // Insert lifetime end intrinsics after every leave. for (auto it : LeaveDepth) { int StartDepth = it.second - 1; int npops = cast<ConstantInt>(it.first->getArgOperand(0))->getLimitedValue(); for (int i = 0; i < npops; ++i) { assert(StartDepth-i >= 0); Value *lifetime_args[] = { handler_sz64, buffs[StartDepth-i] }; auto LifetimeEnd = CallInst::Create(lifetime_end, lifetime_args); LifetimeEnd->insertAfter(it.first); } } return true; }