summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2012-01-28 01:17:56 +0000
committerBill Wendling <isanbard@gmail.com>2012-01-28 01:17:56 +0000
commit0ae06de09417ea8119ef26c57d60877ad4ce9fa2 (patch)
tree0a21ae7eaafa63e46955a30a72ba389005810776
parent1c1c5bba577c710bdea01d084418d62281481cad (diff)
downloadllvm-0ae06de09417ea8119ef26c57d60877ad4ce9fa2.tar.gz
llvm-0ae06de09417ea8119ef26c57d60877ad4ce9fa2.tar.bz2
llvm-0ae06de09417ea8119ef26c57d60877ad4ce9fa2.tar.xz
Reapply r149159 with a fix to add to a PHI node with a non-null parent.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@149164 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/DwarfEHPrepare.cpp98
1 files changed, 64 insertions, 34 deletions
diff --git a/lib/CodeGen/DwarfEHPrepare.cpp b/lib/CodeGen/DwarfEHPrepare.cpp
index f2b2977275..944dd4fb41 100644
--- a/lib/CodeGen/DwarfEHPrepare.cpp
+++ b/lib/CodeGen/DwarfEHPrepare.cpp
@@ -39,6 +39,7 @@ namespace {
Constant *RewindFunction;
bool InsertUnwindResumeCalls(Function &Fn);
+ Instruction *GetExceptionObject(ResumeInst *RI);
public:
static char ID; // Pass identification, replacement for typeid.
@@ -64,6 +65,46 @@ FunctionPass *llvm::createDwarfEHPass(const TargetMachine *tm) {
return new DwarfEHPrepare(tm);
}
+/// GetExceptionObject - Return the exception object from the value passed into
+/// the 'resume' instruction (typically an aggregate). Clean up any dead
+/// instructions, including the 'resume' instruction.
+Instruction *DwarfEHPrepare::GetExceptionObject(ResumeInst *RI) {
+ Value *V = RI->getOperand(0);
+ Instruction *ExnObj = 0;
+ InsertValueInst *SelIVI = dyn_cast<InsertValueInst>(V);
+ LoadInst *SelLoad = 0;
+ InsertValueInst *ExcIVI = 0;
+ bool EraseIVIs = false;
+
+ if (SelIVI) {
+ if (SelIVI->getNumIndices() == 1 && *SelIVI->idx_begin() == 1) {
+ ExcIVI = dyn_cast<InsertValueInst>(SelIVI->getOperand(0));
+ if (ExcIVI && isa<UndefValue>(ExcIVI->getOperand(0)) &&
+ ExcIVI->getNumIndices() == 1 && *ExcIVI->idx_begin() == 0) {
+ ExnObj = cast<Instruction>(ExcIVI->getOperand(1));
+ SelLoad = dyn_cast<LoadInst>(SelIVI->getOperand(1));
+ EraseIVIs = true;
+ }
+ }
+ }
+
+ if (!ExnObj)
+ ExnObj = ExtractValueInst::Create(RI->getOperand(0), 0, "exn.obj", RI);
+
+ RI->eraseFromParent();
+
+ if (EraseIVIs) {
+ if (SelIVI->getNumUses() == 0)
+ SelIVI->eraseFromParent();
+ if (ExcIVI->getNumUses() == 0)
+ ExcIVI->eraseFromParent();
+ if (SelLoad && SelLoad->getNumUses() == 0)
+ SelLoad->eraseFromParent();
+ }
+
+ return ExnObj;
+}
+
/// InsertUnwindResumeCalls - Convert the ResumeInsts that are still present
/// into calls to the appropriate _Unwind_Resume function.
bool DwarfEHPrepare::InsertUnwindResumeCalls(Function &Fn) {
@@ -91,8 +132,26 @@ bool DwarfEHPrepare::InsertUnwindResumeCalls(Function &Fn) {
// Create the basic block where the _Unwind_Resume call will live.
LLVMContext &Ctx = Fn.getContext();
+ unsigned ResumesSize = Resumes.size();
+
+ if (ResumesSize == 1) {
+ // Instead of creating a new BB and PHI node, just append the call to
+ // _Unwind_Resume to the end of the single resume block.
+ ResumeInst *RI = Resumes.front();
+ BasicBlock *UnwindBB = RI->getParent();
+ Instruction *ExnObj = GetExceptionObject(RI);
+
+ // Call the _Unwind_Resume function.
+ CallInst *CI = CallInst::Create(RewindFunction, ExnObj, "", UnwindBB);
+ CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME));
+
+ // We never expect _Unwind_Resume to return.
+ new UnreachableInst(Ctx, UnwindBB);
+ return true;
+ }
+
BasicBlock *UnwindBB = BasicBlock::Create(Ctx, "unwind_resume", &Fn);
- PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), Resumes.size(),
+ PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), ResumesSize,
"exn.obj", UnwindBB);
// Extract the exception object from the ResumeInst and add it to the PHI node
@@ -100,40 +159,11 @@ bool DwarfEHPrepare::InsertUnwindResumeCalls(Function &Fn) {
for (SmallVectorImpl<ResumeInst*>::iterator
I = Resumes.begin(), E = Resumes.end(); I != E; ++I) {
ResumeInst *RI = *I;
- BranchInst::Create(UnwindBB, RI->getParent());
-
- Value *V = RI->getOperand(0);
- Instruction *ExnObj = 0;
- InsertValueInst *SelIVI = dyn_cast<InsertValueInst>(V);
- LoadInst *SelLoad = 0;
- InsertValueInst *ExcIVI = 0;
- bool EraseIVIs = false;
- if (SelIVI) {
- if (SelIVI->getNumIndices() == 1 && *SelIVI->idx_begin() == 1) {
- ExcIVI = dyn_cast<InsertValueInst>(SelIVI->getOperand(0));
- if (ExcIVI && isa<UndefValue>(ExcIVI->getOperand(0)) &&
- ExcIVI->getNumIndices() == 1 && *ExcIVI->idx_begin() == 0) {
- ExnObj = cast<Instruction>(ExcIVI->getOperand(1));
- SelLoad = dyn_cast<LoadInst>(SelIVI->getOperand(1));
- EraseIVIs = true;
- }
- }
- }
-
- if (!ExnObj)
- ExnObj = ExtractValueInst::Create(RI->getOperand(0), 0, "exn.obj", RI);
+ BasicBlock *Parent = RI->getParent();
+ BranchInst::Create(UnwindBB, Parent);
- PN->addIncoming(ExnObj, RI->getParent());
- RI->eraseFromParent();
-
- if (EraseIVIs) {
- if (SelIVI->getNumUses() == 0)
- SelIVI->eraseFromParent();
- if (ExcIVI->getNumUses() == 0)
- ExcIVI->eraseFromParent();
- if (SelLoad && SelLoad->getNumUses() == 0)
- SelLoad->eraseFromParent();
- }
+ Instruction *ExnObj = GetExceptionObject(RI);
+ PN->addIncoming(ExnObj, Parent);
++NumResumesLowered;
}