From 7d4fb4b4448c47fdf721815f7b4234ce978bdff3 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Sat, 10 Sep 2016 19:42:53 +0000 Subject: [PATCH] It should also be legal to pass a swifterror parameter to a call as a swifterror argument. rdar://28233388 llvm-svn: 281147 --- docs/LangRef.rst | 9 +++-- lib/IR/Verifier.cpp | 13 +++++-- test/CodeGen/X86/swifterror.ll | 68 ++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 8 deletions(-) diff --git a/docs/LangRef.rst b/docs/LangRef.rst index b2ac11b5ee1..917a54622a8 100644 --- a/docs/LangRef.rst +++ b/docs/LangRef.rst @@ -1126,10 +1126,11 @@ Currently, only the following parameter attributes are defined: This attribute is motivated to model and optimize Swift error handling. It can be applied to a parameter with pointer to pointer type or a pointer-sized alloca. At the call site, the actual argument that corresponds - to a ``swifterror`` parameter has to come from a ``swifterror`` alloca. A - ``swifterror`` value (either the parameter or the alloca) can only be loaded - and stored from, or used as a ``swifterror`` argument. This is not a valid - attribute for return values and can only be applied to one parameter. + to a ``swifterror`` parameter has to come from a ``swifterror`` alloca or + the ``swifterror`` parameter of the caller. A ``swifterror`` value (either + the parameter or the alloca) can only be loaded and stored from, or used as + a ``swifterror`` argument. This is not a valid attribute for return values + and can only be applied to one parameter. These constraints allow the calling convention to optimize access to ``swifterror`` variables by associating them with a specific register at diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index 6e9eb7476a1..ba7db85094e 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -2586,15 +2586,20 @@ void Verifier::verifyCallSite(CallSite CS) { } // For each argument of the callsite, if it has the swifterror argument, - // make sure the underlying alloca has swifterror as well. + // make sure the underlying alloca/parameter it comes from has a swifterror as + // well. for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) if (CS.paramHasAttr(i+1, Attribute::SwiftError)) { Value *SwiftErrorArg = CS.getArgument(i); - auto AI = dyn_cast(SwiftErrorArg->stripInBoundsOffsets()); - Assert(AI, "swifterror argument should come from alloca", AI, I); - if (AI) + if (auto AI = dyn_cast(SwiftErrorArg->stripInBoundsOffsets())) { Assert(AI->isSwiftError(), "swifterror argument for call has mismatched alloca", AI, I); + continue; + } + auto ArgI = dyn_cast(SwiftErrorArg); + Assert(ArgI, "swifterror argument should come from an alloca or parameter", SwiftErrorArg, I); + Assert(ArgI->hasSwiftErrorAttr(), + "swifterror argument for call has mismatched parameter", ArgI, I); } if (FTy->isVarArg()) { diff --git a/test/CodeGen/X86/swifterror.ll b/test/CodeGen/X86/swifterror.ll index 21695cbc003..b1e82e54328 100644 --- a/test/CodeGen/X86/swifterror.ll +++ b/test/CodeGen/X86/swifterror.ll @@ -398,3 +398,71 @@ entry: store i8 1, i8* %tmp ret float 1.0 } + +declare swiftcc float @moo(%swift_error** swifterror) + +; Test parameter forwarding. +define swiftcc float @forward_swifterror(%swift_error** swifterror %error_ptr_ref) { +; CHECK-APPLE-LABEL: forward_swifterror: +; CHECK-APPLE: pushq %rax +; CHECK-APPLE: callq _moo +; CHECK-APPLE: popq %rax +; CHECK-APPLE: retq + +; CHECK-O0-LABEL: forward_swifterror: +; CHECK-O0: subq $24, %rsp +; CHECK-O0: movq %r12, %rcx +; CHECK-O0: movq %rcx, 16(%rsp) +; CHECK-O0: movq %rax, 8(%rsp) +; CHECK-O0: callq _moo +; CHECK-O0: addq $24, %rsp +; CHECK-O0: retq + +entry: + %call = call swiftcc float @moo(%swift_error** swifterror %error_ptr_ref) + ret float %call +} + +define swiftcc float @conditionally_forward_swifterror(%swift_error** swifterror %error_ptr_ref, i32 %cc) { +; CHECK-APPLE-LABEL: conditionally_forward_swifterror: +; CHECK-APPLE: pushq %rax +; CHECK-APPLE: testl %edi, %edi +; CHECK-APPLE: je + +; CHECK-APPLE: callq _moo +; CHECK-APPLE: popq %rax +; CHECK-APPLE: retq + +; CHECK-APPLE: xorps %xmm0, %xmm0 +; CHECK-APPLE: popq %rax +; CHECK-APPLE: retq + +; CHECK-O0-LABEL: conditionally_forward_swifterror: +; CHECK-O0: subq $24, %rsp +; CHECK-O0: movq %r12, %rcx +; CHECK-O0: cmpl $0, %edi +; CHECK-O0: movq %rax, 16(%rsp) +; CHECK-O0: movq %r12, 8(%rsp) +; CHECK-O0: movq %rcx, (%rsp) +; CHECK-O0: je + +; CHECK-O0: movq 8(%rsp), %r12 +; CHECK-O0: callq _moo +; CHECK-O0: addq $24, %rsp +; CHECK-O0: retq + +; CHECK-O0: xorps %xmm0, %xmm0 +; CHECK-O0: movq 8(%rsp), %r12 +; CHECK-O0: addq $24, %rsp +; CHECK-O0: retq +entry: + %cond = icmp ne i32 %cc, 0 + br i1 %cond, label %gen_error, label %normal + +gen_error: + %call = call swiftcc float @moo(%swift_error** swifterror %error_ptr_ref) + ret float %call + +normal: + ret float 0.0 +}