summaryrefslogtreecommitdiff
path: root/lib/CodeGen/DwarfEHPrepare.cpp
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2011-07-28 20:48:05 +0000
committerBill Wendling <isanbard@gmail.com>2011-07-28 20:48:05 +0000
commitb4904503de3195fb611a0aca2e58f4b770ccff51 (patch)
tree8dc15788afef486bc1814043d6bb3fab60ade894 /lib/CodeGen/DwarfEHPrepare.cpp
parentaf7a46d5a6fa1e6dac1d83f38ba9823bea3870b6 (diff)
downloadllvm-b4904503de3195fb611a0aca2e58f4b770ccff51.tar.gz
llvm-b4904503de3195fb611a0aca2e58f4b770ccff51.tar.bz2
llvm-b4904503de3195fb611a0aca2e58f4b770ccff51.tar.xz
Initial code to convert ResumeInsts into calls to _Unwind_Resume.
This should be the only code necessary for DWARF EH prepare. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@136387 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/DwarfEHPrepare.cpp')
-rw-r--r--lib/CodeGen/DwarfEHPrepare.cpp58
1 files changed, 57 insertions, 1 deletions
diff --git a/lib/CodeGen/DwarfEHPrepare.cpp b/lib/CodeGen/DwarfEHPrepare.cpp
index 03604b0a17..3aa72ee196 100644
--- a/lib/CodeGen/DwarfEHPrepare.cpp
+++ b/lib/CodeGen/DwarfEHPrepare.cpp
@@ -63,6 +63,8 @@ namespace {
typedef SmallPtrSet<BasicBlock*, 8> BBSet;
BBSet LandingPads;
+ bool InsertUnwindResumeCalls();
+
bool NormalizeLandingPads();
bool LowerUnwindsAndResumes();
bool MoveExceptionValueCalls();
@@ -658,13 +660,67 @@ Instruction *DwarfEHPrepare::CreateExceptionValueCall(BasicBlock *BB) {
return CallInst::Create(ExceptionValueIntrinsic, "eh.value.call", Start);
}
+/// InsertUnwindResumeCalls - Convert the ResumeInsts that are still present
+/// into calls to the appropriate _Unwind_Resume function.
+bool DwarfEHPrepare::InsertUnwindResumeCalls() {
+ SmallVector<ResumeInst*, 16> Resumes;
+ for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I)
+ for (BasicBlock::iterator II = I->begin(), IE = I->end(); II != IE; ++II)
+ if (ResumeInst *RI = dyn_cast<ResumeInst>(II))
+ Resumes.push_back(RI);
+
+ if (Resumes.empty())
+ return false;
+
+ // Find the rewind function if we didn't already.
+ if (!RewindFunction) {
+ LLVMContext &Ctx = Resumes[0]->getContext();
+ FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx),
+ Type::getInt8PtrTy(Ctx), false);
+ const char *RewindName = TLI->getLibcallName(RTLIB::UNWIND_RESUME);
+ RewindFunction = F->getParent()->getOrInsertFunction(RewindName, FTy);
+ }
+
+ // Create the basic block where the _Unwind_Resume call will live.
+ LLVMContext &Ctx = F->getContext();
+ BasicBlock *UnwindBB = BasicBlock::Create(Ctx, "unwind_resume", F);
+ PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), Resumes.size(),
+ "exn.obj", UnwindBB);
+
+ // Extract the exception object from the ResumeInst and add it to the PHI node
+ // that feeds the _Unwind_Resume call.
+ for (SmallVectorImpl<ResumeInst*>::iterator
+ I = Resumes.begin(), E = Resumes.end(); I != E; ++I) {
+ ResumeInst *RI = *I;
+ BranchInst::Create(UnwindBB, RI->getParent());
+ ExtractValueInst *ExnObj = ExtractValueInst::Create(RI->getOperand(0),
+ 0, "exn.obj", RI);
+ PN->addIncoming(ExnObj, RI->getParent());
+ RI->eraseFromParent();
+ }
+
+ // Call the function.
+ CallInst *CI = CallInst::Create(RewindFunction, PN, "", UnwindBB);
+ CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME));
+
+ // We never expect _Unwind_Resume to return.
+ new UnreachableInst(Ctx, UnwindBB);
+ return true;
+}
+
bool DwarfEHPrepare::runOnFunction(Function &Fn) {
bool Changed = false;
// Initialize internal state.
- DT = &getAnalysis<DominatorTree>();
+ DT = &getAnalysis<DominatorTree>(); // FIXME: We won't need this with the new EH.
F = &Fn;
+ if (InsertUnwindResumeCalls()) {
+ // FIXME: The reset of this function can go once the new EH is done.
+ LandingPads.clear();
+ return true;
+ }
+
// Ensure that only unwind edges end at landing pads (a landing pad is a
// basic block where an invoke unwind edge ends).
Changed |= NormalizeLandingPads();