From db4a46b079d203a832a5229f073d5ffe124b5311 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Mon, 13 Feb 2017 19:58:28 +0000 Subject: [PATCH] swiftcc: Don't emit tail calls from callers with swifterror parameters Backends don't support this yet. They would have to move to the swifterror register before the tail call to make sure it is live-in to the call. rdar://30495920 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@294982 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 9 +++++++++ test/CodeGen/AArch64/swifterror.ll | 14 ++++++++++++++ test/CodeGen/ARM/swifterror.ll | 15 +++++++++++++++ test/CodeGen/X86/swifterror.ll | 15 +++++++++++++++ 4 files changed, 53 insertions(+) diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 5966069d31b..d59419ec09f 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -5916,6 +5916,15 @@ void SelectionDAGBuilder::LowerCallTo(ImmutableCallSite CS, SDValue Callee, const Value *SwiftErrorVal = nullptr; const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + + // We can't tail call inside a function with a swifterror argument. Lowering + // does not support this yet. It would have to move into the swifterror + // register before the call. + auto *Caller = CS.getInstruction()->getParent()->getParent(); + if (TLI.supportSwiftError() && + Caller->getAttributes().hasAttrSomewhere(Attribute::SwiftError)) + isTailCall = false; + for (ImmutableCallSite::arg_iterator i = CS.arg_begin(), e = CS.arg_end(); i != e; ++i) { const Value *V = *i; diff --git a/test/CodeGen/AArch64/swifterror.ll b/test/CodeGen/AArch64/swifterror.ll index 016af2a1069..69bf3510cc5 100644 --- a/test/CodeGen/AArch64/swifterror.ll +++ b/test/CodeGen/AArch64/swifterror.ll @@ -583,3 +583,17 @@ define swiftcc { i64, i64, i64, i64, i64, i64, i64, i64 } @params_and_return_in_ } declare swiftcc { i64, i64, i64, i64, i64, i64, i64, i64 } @params_and_return_in_reg2(i64, i64, i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err) + +declare void @acallee(i8*) + +; Make sure we don't tail call if the caller returns a swifterror value. We +; would have to move into the swifterror register before the tail call. +; CHECK-APPLE: tailcall_from_swifterror: +; CHECK-APPLE-NOT: b _acallee +; CHECK-APPLE: bl _acallee + +define swiftcc void @tailcall_from_swifterror(%swift_error** swifterror %error_ptr_ref) { +entry: + tail call void @acallee(i8* null) + ret void +} diff --git a/test/CodeGen/ARM/swifterror.ll b/test/CodeGen/ARM/swifterror.ll index 45a864d1af1..78764202f62 100644 --- a/test/CodeGen/ARM/swifterror.ll +++ b/test/CodeGen/ARM/swifterror.ll @@ -513,3 +513,18 @@ define swiftcc { i32, i32, i32, i32} @params_and_return_in_reg(i32, i32, i32, i3 } declare swiftcc { i32, i32, i32, i32 } @params_and_return_in_reg2(i32, i32, i32, i32, i8* swiftself, %swift_error** nocapture swifterror %err) + + +declare void @acallee(i8*) + +; Make sure we don't tail call if the caller returns a swifterror value. We +; would have to move into the swifterror register before the tail call. +; CHECK-APPLE: tailcall_from_swifterror: +; CHECK-APPLE-NOT: b _acallee +; CHECK-APPLE: bl _acallee + +define swiftcc void @tailcall_from_swifterror(%swift_error** swifterror %error_ptr_ref) { +entry: + tail call void @acallee(i8* null) + ret void +} diff --git a/test/CodeGen/X86/swifterror.ll b/test/CodeGen/X86/swifterror.ll index cd415059722..86e0221c201 100644 --- a/test/CodeGen/X86/swifterror.ll +++ b/test/CodeGen/X86/swifterror.ll @@ -670,3 +670,18 @@ define swiftcc { i64, i64, i64, i64} @params_and_return_in_reg(i64, i64, i64, i6 } declare swiftcc { i64, i64, i64, i64 } @params_and_return_in_reg2(i64, i64, i64, i64, i64, i64, i8* swiftself, %swift_error** nocapture swifterror %err) + + +declare void @acallee(i8*) + +; Make sure we don't tail call if the caller returns a swifterror value. We +; would have to move into the swifterror register before the tail call. +; CHECK-APPLE: tailcall_from_swifterror: +; CHECK-APPLE-NOT: jmp _acallee +; CHECK-APPLE: callq _acallee + +define swiftcc void @tailcall_from_swifterror(%swift_error** swifterror %error_ptr_ref) { +entry: + tail call void @acallee(i8* null) + ret void +} -- 2.50.1