]> granicus.if.org Git - llvm/commitdiff
SjLjEHPrepare: Fix the pass for swifterror arguments
authorArnold Schwaighofer <aschwaighofer@apple.com>
Tue, 7 Mar 2017 20:29:02 +0000 (20:29 +0000)
committerArnold Schwaighofer <aschwaighofer@apple.com>
Tue, 7 Mar 2017 20:29:02 +0000 (20:29 +0000)
We cannot leave the identity copies 'select true, arg, undef' that this pass
inserts for arguments to simplify handling of values on swifterror arguments.

swifterror arguments have restrictions on their uses.

rdar://30839288

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@297197 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/SjLjEHPrepare.cpp
test/CodeGen/ARM/sjljeh-swifterror.ll [new file with mode: 0644]

index 209bbe54ea2362092c95409795abdb850ea088eb..76e4dc5457ae3ea9be731fb6f4a2706a52a95f1d 100644 (file)
@@ -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/test/CodeGen/ARM/sjljeh-swifterror.ll b/test/CodeGen/ARM/sjljeh-swifterror.ll
new file mode 100644 (file)
index 0000000..aae0e75
--- /dev/null
@@ -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
+}
+