From 1edbd6f3f07176851cb03f7932ff50b9e9619dfb Mon Sep 17 00:00:00 2001 From: John McCall Date: Wed, 1 Jun 2011 02:17:11 +0000 Subject: [PATCH] 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 --- lib/Transforms/Utils/InlineFunction.cpp | 22 ++++++++++++++---- test/Transforms/Inline/inline_invoke.ll | 31 +++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp index d2fd07aed10..4a829874832 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(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 110a82823e1..5f657387c21 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]]