diff options
-rw-r--r-- | llvm/lib/CodeGen/SjLjEHPrepare.cpp | 22 | ||||
-rw-r--r-- | llvm/test/CodeGen/ARM/sjljeh-swifterror.ll | 27 |
2 files changed, 49 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/SjLjEHPrepare.cpp b/llvm/lib/CodeGen/SjLjEHPrepare.cpp index 209bbe54ea2..76e4dc5457a 100644 --- a/llvm/lib/CodeGen/SjLjEHPrepare.cpp +++ b/llvm/lib/CodeGen/SjLjEHPrepare.cpp @@ -64,6 +64,7 @@ public: private: bool setupEntryBlockAndCallSites(Function &F); + bool undoSwiftErrorSelect(Function &F); void substituteLPadValues(LandingPadInst *LPI, Value *ExnVal, Value *SelVal); Value *setupFunctionContext(Function &F, ArrayRef<LandingPadInst *> LPads); void lowerIncomingArguments(Function &F); @@ -458,6 +459,25 @@ bool SjLjEHPrepare::setupEntryBlockAndCallSites(Function &F) { return true; } +bool SjLjEHPrepare::undoSwiftErrorSelect(Function &F) { + // We have inserted dummy copies 'select true, arg, undef' in the entry block + // for arguments to simplify this pass. + // swifterror arguments cannot be used in this way. Undo the select for the + // swifterror argument. + for (auto &AI : F.args()) { + if (AI.isSwiftError()) { + assert(AI.hasOneUse() && "Must have converted the argument to a select"); + auto *Select = dyn_cast<SelectInst>(AI.use_begin()->getUser()); + assert(Select && "There must be single select user"); + auto *OrigSwiftError = cast<Argument>(Select->getTrueValue()); + Select->replaceAllUsesWith(OrigSwiftError); + Select->eraseFromParent(); + return true; + } + } + return false; +} + bool SjLjEHPrepare::runOnFunction(Function &F) { Module &M = *F.getParent(); RegisterFn = M.getOrInsertFunction( @@ -476,5 +496,7 @@ bool SjLjEHPrepare::runOnFunction(Function &F) { FuncCtxFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_functioncontext); bool Res = setupEntryBlockAndCallSites(F); + if (Res) + Res |= undoSwiftErrorSelect(F); return Res; } diff --git a/llvm/test/CodeGen/ARM/sjljeh-swifterror.ll b/llvm/test/CodeGen/ARM/sjljeh-swifterror.ll new file mode 100644 index 00000000000..aae0e75c98a --- /dev/null +++ b/llvm/test/CodeGen/ARM/sjljeh-swifterror.ll @@ -0,0 +1,27 @@ +; RUN: opt -sjljehprepare -verify < %s | FileCheck %s +target datalayout = "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" +target triple = "armv7s-apple-ios7.0" + +%swift.error = type opaque + +declare void @objc_msgSend() local_unnamed_addr + +declare i32 @__objc_personality_v0(...) + +; Make sure we don't leave a select on a swifterror argument. +; CHECK-LABEL; @test +; CHECK-NOT: select true, %0 +define swiftcc void @test(%swift.error** swifterror) local_unnamed_addr personality i32 (...)* @__objc_personality_v0 { +entry: + %call28.i = invoke i32 bitcast (void ()* @objc_msgSend to i32 (i8*, i8*)*)(i8* undef, i8* undef) + to label %invoke.cont.i unwind label %lpad.i + +invoke.cont.i: + unreachable + +lpad.i: + %1 = landingpad { i8*, i32 } + cleanup + resume { i8*, i32 } undef +} + |