From 4a1c5da7ac063a6a73da973871fb9584fce19104 Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Fri, 16 Nov 2018 14:28:05 +0000 Subject: [PATCH] [IRVerifier] Allow StructRet in statepoint Summary: StructRet attribute is not allowed in vararg calls. The statepoint intrinsic is vararg, but the wrapped function may be not. Allow calls of statepoint with StructRet arg, as long as the wrapped function is not vararg. Reviewers: thanm, anna Reviewed By: anna Subscribers: anna, llvm-commits Differential Revision: https://reviews.llvm.org/D53602 llvm-svn: 347050 --- llvm/lib/IR/Verifier.cpp | 16 ++++++++++++++-- llvm/test/Verifier/statepoint.ll | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 899534dd10fa..bc2e10c049aa 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 c07a85b9bd36..8dba5c4d02af 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 +}