summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/IR/Verifier.cpp16
-rw-r--r--llvm/test/Verifier/statepoint.ll18
2 files changed, 32 insertions, 2 deletions
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 899534dd10f..bc2e10c049a 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -1930,6 +1930,7 @@ void Verifier::verifyStatepoint(ImmutableCallSite CS) {
// Verify that the types of the call parameter arguments match
// the type of the wrapped callee.
+ AttributeList Attrs = CS.getAttributes();
for (int i = 0; i < NumParams; i++) {
Type *ParamType = TargetFuncType->getParamType(i);
Type *ArgType = CS.getArgument(5 + i)->getType();
@@ -1937,6 +1938,12 @@ void Verifier::verifyStatepoint(ImmutableCallSite CS) {
"gc.statepoint call argument does not match wrapped "
"function type",
&CI);
+
+ if (TargetFuncType->isVarArg()) {
+ AttributeSet ArgAttrs = Attrs.getParamAttributes(5 + i);
+ Assert(!ArgAttrs.hasAttribute(Attribute::StructRet),
+ "Attribute 'sret' cannot be used for vararg call arguments!", &CI);
+ }
}
const int EndCallArgsInx = 4 + NumCallArgs;
@@ -2814,8 +2821,13 @@ void Verifier::verifyCallSite(CallSite CS) {
SawReturned = true;
}
- Assert(!ArgAttrs.hasAttribute(Attribute::StructRet),
- "Attribute 'sret' cannot be used for vararg call arguments!", I);
+ // Statepoint intrinsic is vararg but the wrapped function may be not.
+ // Allow sret here and check the wrapped function in verifyStatepoint.
+ if (CS.getCalledFunction() == nullptr ||
+ CS.getCalledFunction()->getIntrinsicID() !=
+ Intrinsic::experimental_gc_statepoint)
+ Assert(!ArgAttrs.hasAttribute(Attribute::StructRet),
+ "Attribute 'sret' cannot be used for vararg call arguments!", I);
if (ArgAttrs.hasAttribute(Attribute::InAlloca))
Assert(Idx == CS.arg_size() - 1, "inalloca isn't on the last argument!",
diff --git a/llvm/test/Verifier/statepoint.ll b/llvm/test/Verifier/statepoint.ll
index c07a85b9bd3..8dba5c4d02a 100644
--- a/llvm/test/Verifier/statepoint.ll
+++ b/llvm/test/Verifier/statepoint.ll
@@ -4,6 +4,7 @@ declare void @use(...)
declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token, i32, i32)
declare i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(token, i32, i32)
declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...)
+declare token @llvm.experimental.gc.statepoint.p0f_isVoidp0s_structsf(i64, i32, void (%struct*)*, i32, i32, ...)
declare i32 @"personality_function"()
;; Basic usage
@@ -79,3 +80,20 @@ exceptional_return:
%obj1.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %landing_pad, i32 12, i32 12)
ret i8 addrspace(1)* %obj1.relocated1
}
+
+; Test for statepoint with sret attribute.
+; This should be allowed as long as the wrapped function is not vararg.
+%struct = type { i64, i64, i64 }
+
+declare void @fn_sret(%struct* sret)
+
+define void @test_sret() gc "statepoint-example" {
+ %x = alloca %struct
+ %statepoint_token = call token (i64, i32, void (%struct*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidp0s_structsf(i64 0, i32 0, void (%struct*)* @fn_sret, i32 1, i32 0, %struct* sret %x, i32 0, i32 0)
+ ret void
+ ; CHECK-LABEL: test_sret
+ ; CHECK: alloca
+ ; CHECK: statepoint
+ ; CHECK-SAME: sret
+ ; CHECK: ret
+}
OpenPOWER on IntegriCloud