summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-06-01 02:17:11 +0000
committerJohn McCall <rjmccall@apple.com>2011-06-01 02:17:11 +0000
commit1edbd6f3f07176851cb03f7932ff50b9e9619dfb (patch)
tree148a40729298608a35dfc17fea9f40ef397e3c9e
parentedac4923dc2e1694f7004123ccd7c1af952d0d68 (diff)
downloadllvm-1edbd6f3f07176851cb03f7932ff50b9e9619dfb.tar.gz
llvm-1edbd6f3f07176851cb03f7932ff50b9e9619dfb.tar.bz2
llvm-1edbd6f3f07176851cb03f7932ff50b9e9619dfb.tar.xz
First, do no harm -- even if we can't find a selector for an enclosing
landing pad, forward llvm.eh.resume calls to it instead of turning them invalidly into invokes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@132382 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/Utils/InlineFunction.cpp22
-rw-r--r--test/Transforms/Inline/inline_invoke.ll31
2 files changed, 47 insertions, 6 deletions
diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp
index d2fd07aed1..4a82987483 100644
--- a/lib/Transforms/Utils/InlineFunction.cpp
+++ b/lib/Transforms/Utils/InlineFunction.cpp
@@ -214,13 +214,24 @@ BasicBlock *InvokeInliningInfo::getInnerUnwindDest() {
/// at the end of the given block, as a branch to the inner unwind
/// block. Returns true if the call was forwarded.
bool InvokeInliningInfo::forwardEHResume(CallInst *call, BasicBlock *src) {
+ // First, check whether this is a call to the intrinsic.
Function *fn = dyn_cast<Function>(call->getCalledValue());
if (!fn || fn->getName() != "llvm.eh.resume")
return false;
+
+ // At this point, we need to return true on all paths, because
+ // otherwise we'll construct an invoke of the intrinsic, which is
+ // not well-formed.
- // If this fails, maybe it should be a fatal error.
+ // Try to find or make an inner unwind dest, which will fail if we
+ // can't find a selector call for the outer unwind dest.
BasicBlock *dest = getInnerUnwindDest();
- if (!dest) return false;
+ bool hasSelector = (dest != 0);
+
+ // If we failed, just use the outer unwind dest, dropping the
+ // exception and selector on the floor.
+ if (!hasSelector)
+ dest = OuterUnwindDest;
// Make a branch.
BranchInst::Create(dest, src);
@@ -228,8 +239,11 @@ bool InvokeInliningInfo::forwardEHResume(CallInst *call, BasicBlock *src) {
// Update the phis in the destination. They were inserted in an
// order which makes this work.
addIncomingPHIValuesForInto(src, dest);
- InnerExceptionPHI->addIncoming(call->getArgOperand(0), src);
- InnerSelectorPHI->addIncoming(call->getArgOperand(1), src);
+
+ if (hasSelector) {
+ InnerExceptionPHI->addIncoming(call->getArgOperand(0), src);
+ InnerSelectorPHI->addIncoming(call->getArgOperand(1), src);
+ }
return true;
}
diff --git a/test/Transforms/Inline/inline_invoke.ll b/test/Transforms/Inline/inline_invoke.ll
index 110a82823e..5f657387c2 100644
--- a/test/Transforms/Inline/inline_invoke.ll
+++ b/test/Transforms/Inline/inline_invoke.ll
@@ -4,7 +4,7 @@
; by appending selectors and forwarding _Unwind_Resume directly to the
; enclosing landing pad.
-;; Test 1 - basic functionality.
+;; Test 0 - basic functionality.
%struct.A = type { i8 }
@@ -112,7 +112,7 @@ eh.resume:
; CHECK-NEXT: call i32 @llvm.eh.typeid.for(
-;; Test 2 - Correctly handle phis in outer landing pads.
+;; Test 1 - Correctly handle phis in outer landing pads.
define void @test1_out() uwtable ssp {
entry:
@@ -216,3 +216,30 @@ eh.resume:
; CHECK: call void @use(i32 [[YJ1]])
; CHECK: call void @llvm.eh.resume(i8* [[EXNJ1]], i32 [[SELJ1]])
+
+;; Test 2 - Don't make invalid IR for inlines into landing pads without eh.exception calls
+
+define void @test2_out() uwtable ssp {
+entry:
+ invoke void @test0_in()
+ to label %ret unwind label %lpad
+
+ret:
+ ret void
+
+lpad:
+ call void @_ZSt9terminatev()
+ unreachable
+}
+
+; CHECK: define void @test2_out()
+; CHECK: [[A:%.*]] = alloca %struct.A,
+; CHECK: [[B:%.*]] = alloca %struct.A,
+; CHECK: invoke void @_ZN1AC1Ev(%struct.A* [[A]])
+; CHECK-NEXT: unwind label %[[LPAD:[^\s]+]]
+; CHECK: invoke void @_ZN1AC1Ev(%struct.A* [[B]])
+; CHECK-NEXT: unwind label %[[LPAD2:[^\s]+]]
+; CHECK: invoke void @_ZN1AD1Ev(%struct.A* [[B]])
+; CHECK-NEXT: unwind label %[[LPAD2]]
+; CHECK: invoke void @_ZN1AD1Ev(%struct.A* [[A]])
+; CHECK-NEXT: unwind label %[[LPAD]]