It should also be legal to pass a swifterror parameter to a call as a swifterror

argument.

rdar://28233388

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@281147 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Arnold Schwaighofer 2016-09-10 19:42:53 +00:00
parent a8edd76b0e
commit 10c97f029a
3 changed files with 82 additions and 8 deletions

View File

@ -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

View File

@ -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<AllocaInst>(SwiftErrorArg->stripInBoundsOffsets());
Assert(AI, "swifterror argument should come from alloca", AI, I);
if (AI)
if (auto AI = dyn_cast<AllocaInst>(SwiftErrorArg->stripInBoundsOffsets())) {
Assert(AI->isSwiftError(),
"swifterror argument for call has mismatched alloca", AI, I);
continue;
}
auto ArgI = dyn_cast<Argument>(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()) {

View File

@ -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
}