Skip to content

Commit

Permalink
[GC] Verify-pass void vararg functions in gc.statepoint
Browse files Browse the repository at this point in the history
With the appropriate Verifier changes, exactracting the result out of a
statepoint wrapping a vararg function crashes. However, a void vararg
function works fine: commit this first step.

Differential Revision: http://reviews.llvm.org/D7071

llvm-svn: 226599
  • Loading branch information
artagnon committed Jan 20, 2015
1 parent 565cc18 commit be10ece
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 5 deletions.
18 changes: 13 additions & 5 deletions llvm/lib/IR/Verifier.cpp
Expand Up @@ -2639,8 +2639,6 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
"gc.statepoint callee must be of function pointer type",
&CI, Target);
FunctionType *TargetFuncType = cast<FunctionType>(PT->getElementType());
Assert1(!TargetFuncType->isVarArg(),
"gc.statepoint support for var arg functions not implemented", &CI);

const Value *NumCallArgsV = CI.getArgOperand(1);
Assert1(isa<ConstantInt>(NumCallArgsV),
Expand All @@ -2650,8 +2648,18 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
Assert1(NumCallArgs >= 0,
"gc.statepoint number of arguments to underlying call "
"must be positive", &CI);
Assert1(NumCallArgs == (int)TargetFuncType->getNumParams(),
"gc.statepoint mismatch in number of call args", &CI);
const int NumParams = (int)TargetFuncType->getNumParams();
if (TargetFuncType->isVarArg()) {
Assert1(NumCallArgs >= NumParams,
"gc.statepoint mismatch in number of vararg call args", &CI);

// TODO: Remove this limitation
Assert1(TargetFuncType->getReturnType()->isVoidTy(),
"gc.statepoint doesn't support wrapping non-void "
"vararg functions yet", &CI);
} else
Assert1(NumCallArgs == NumParams,
"gc.statepoint mismatch in number of call args", &CI);

const Value *Unused = CI.getArgOperand(2);
Assert1(isa<ConstantInt>(Unused) &&
Expand All @@ -2660,7 +2668,7 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {

// Verify that the types of the call parameter arguments match
// the type of the wrapped callee.
for (int i = 0; i < NumCallArgs; i++) {
for (int i = 0; i < NumParams; i++) {
Type *ParamType = TargetFuncType->getParamType(i);
Type *ArgType = CI.getArgOperand(3+i)->getType();
Assert1(ArgType == ParamType,
Expand Down
14 changes: 14 additions & 0 deletions llvm/test/CodeGen/X86/statepoint-call-lowering.ll
Expand Up @@ -9,6 +9,7 @@ declare zeroext i1 @return_i1()
declare zeroext i32 @return_i32()
declare i32* @return_i32ptr()
declare float @return_float()
declare void @varargf(i32, ...)

define i1 @test_i1_return() gc "statepoint-example" {
; CHECK-LABEL: test_i1_return
Expand Down Expand Up @@ -75,6 +76,17 @@ entry:
ret i1 %call2
}

define void @test_void_vararg() gc "statepoint-example" {
; CHECK-LABEL: test_void_vararg
; Check a statepoint wrapping a *void* returning vararg function works
; CHECK: callq varargf
entry:
%safepoint_token = tail call i32 (void (i32, ...)*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidi32varargf(void (i32, ...)* @varargf, i32 2, i32 0, i32 42, i32 43, i32 0)
;; if we try to use the result from a statepoint wrapping a
;; non-void-returning varargf, we will experience a crash.
ret void
}

declare i32 @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()*, i32, i32, ...)
declare i1 @llvm.experimental.gc.result.int.i1(i32)

Expand All @@ -87,4 +99,6 @@ declare i32* @llvm.experimental.gc.result.ptr.p0i32(i32)
declare i32 @llvm.experimental.gc.statepoint.p0f_f32f(float ()*, i32, i32, ...)
declare float @llvm.experimental.gc.result.float.f32(i32)

declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidi32varargf(void (i32, ...)*, i32, i32, ...)

declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32, i32, i32)

0 comments on commit be10ece

Please sign in to comment.