forked from OSchip/llvm-project
[GC] improve testing around gc.relocate and fix a test
Patch by: Ramkumar Ramachandra <artagnon@gmail.com> "This patch started out as an exploration of gc.relocate, and an attempt to write a simple test in call-lowering. I then noticed that the arguments of gc.relocate were not checked fully, so I went in and fixed a few things. Finally, the most important outcome of this patch is that my new error handling code caught a bug in a callsite in stackmap-format." Differential Revision: http://reviews.llvm.org/D6824 llvm-svn: 225412
This commit is contained in:
parent
97fea8bb95
commit
76ebd15437
|
@ -2691,10 +2691,12 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
|
|||
case Intrinsic::experimental_gc_result_ptr: {
|
||||
// Are we tied to a statepoint properly?
|
||||
CallSite StatepointCS(CI.getArgOperand(0));
|
||||
const Function *StatepointFn = StatepointCS.getCalledFunction();
|
||||
const Function *StatepointFn =
|
||||
StatepointCS.getInstruction() ? StatepointCS.getCalledFunction() : nullptr;
|
||||
Assert2(StatepointFn && StatepointFn->isDeclaration() &&
|
||||
StatepointFn->getIntrinsicID() == Intrinsic::experimental_gc_statepoint,
|
||||
"token must be from a statepoint", &CI, CI.getArgOperand(0));
|
||||
"gc.result operand #1 must be from a statepoint",
|
||||
&CI, CI.getArgOperand(0));
|
||||
|
||||
// Assert that result type matches wrapped callee.
|
||||
const Value *Target = StatepointCS.getArgument(0);
|
||||
|
@ -2710,32 +2712,53 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
|
|||
// Are we tied to a statepoint properly?
|
||||
CallSite StatepointCS(CI.getArgOperand(0));
|
||||
const Function *StatepointFn =
|
||||
StatepointCS.getInstruction() ? StatepointCS.getCalledFunction() : NULL;
|
||||
StatepointCS.getInstruction() ? StatepointCS.getCalledFunction() : nullptr;
|
||||
Assert2(StatepointFn && StatepointFn->isDeclaration() &&
|
||||
StatepointFn->getIntrinsicID() == Intrinsic::experimental_gc_statepoint,
|
||||
"token must be from a statepoint", &CI, CI.getArgOperand(0));
|
||||
"gc.relocate operand #1 must be from a statepoint",
|
||||
&CI, CI.getArgOperand(0));
|
||||
|
||||
// Both the base and derived must be piped through the safepoint
|
||||
Value* Base = CI.getArgOperand(1);
|
||||
Assert1( isa<ConstantInt>(Base), "must be integer offset", &CI);
|
||||
Assert1(isa<ConstantInt>(Base),
|
||||
"gc.relocate operand #2 must be integer offset", &CI);
|
||||
|
||||
Value* Derived = CI.getArgOperand(2);
|
||||
Assert1( isa<ConstantInt>(Derived), "must be integer offset", &CI);
|
||||
Assert1(isa<ConstantInt>(Derived),
|
||||
"gc.relocate operand #3 must be integer offset", &CI);
|
||||
|
||||
const int BaseIndex = cast<ConstantInt>(Base)->getZExtValue();
|
||||
const int DerivedIndex = cast<ConstantInt>(Derived)->getZExtValue();
|
||||
// Check the bounds
|
||||
Assert1(0 <= BaseIndex &&
|
||||
BaseIndex < (int)StatepointCS.arg_size(),
|
||||
"index out of bounds", &CI);
|
||||
"gc.relocate: statepoint base index out of bounds", &CI);
|
||||
Assert1(0 <= DerivedIndex &&
|
||||
DerivedIndex < (int)StatepointCS.arg_size(),
|
||||
"index out of bounds", &CI);
|
||||
"gc.relocate: statepoint derived index out of bounds", &CI);
|
||||
|
||||
// Check that BaseIndex and DerivedIndex fall within the 'gc parameters'
|
||||
// section of the statepoint's argument
|
||||
const int NumCallArgs =
|
||||
cast<ConstantInt>(StatepointCS.getArgument(1))->getZExtValue();
|
||||
const int NumDeoptArgs =
|
||||
cast<ConstantInt>(StatepointCS.getArgument(NumCallArgs + 3))->getZExtValue();
|
||||
const int GCParamArgsStart = NumCallArgs + NumDeoptArgs + 4;
|
||||
const int GCParamArgsEnd = StatepointCS.arg_size();
|
||||
Assert1(GCParamArgsStart <= BaseIndex &&
|
||||
BaseIndex < GCParamArgsEnd,
|
||||
"gc.relocate: statepoint base index doesn't fall within the "
|
||||
"'gc parameters' section of the statepoint call", &CI);
|
||||
Assert1(GCParamArgsStart <= DerivedIndex &&
|
||||
DerivedIndex < GCParamArgsEnd,
|
||||
"gc.relocate: statepoint derived index doesn't fall within the "
|
||||
"'gc parameters' section of the statepoint call", &CI);
|
||||
|
||||
|
||||
// Assert that the result type matches the type of the relocated pointer
|
||||
GCRelocateOperands Operands(&CI);
|
||||
Assert1(Operands.derivedPtr()->getType() == CI.getType(),
|
||||
"gc.relocate: relocating a pointer shouldn't change it's type",
|
||||
"gc.relocate: relocating a pointer shouldn't change its type",
|
||||
&CI);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -60,6 +60,21 @@ entry:
|
|||
ret float %call1
|
||||
}
|
||||
|
||||
define i1 @test_relocate(i32* %a) {
|
||||
; CHECK-LABEL: test_relocate
|
||||
; Check that an ununsed relocate has no code-generation impact
|
||||
; CHECK: pushq %rax
|
||||
; CHECK: callq return_i1
|
||||
; CHECK-NEXT: .Ltmp13:
|
||||
; CHECK-NEXT: popq %rdx
|
||||
; CHECK-NEXT: retq
|
||||
entry:
|
||||
%safepoint_token = tail call i32 (i1 ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32* %a)
|
||||
%call1 = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %safepoint_token, i32 4, i32 4)
|
||||
%call2 = call zeroext i1 @llvm.experimental.gc.result.int.i1(i32 %safepoint_token)
|
||||
ret i1 %call2
|
||||
}
|
||||
|
||||
declare i32 @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()*, i32, i32, ...)
|
||||
declare i1 @llvm.experimental.gc.result.int.i1(i32)
|
||||
|
||||
|
@ -72,3 +87,4 @@ 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.relocate.p0i32(i32, i32, i32)
|
||||
|
|
|
@ -21,12 +21,10 @@ define i1 @test(i32 addrspace(1)* %ptr) {
|
|||
entry:
|
||||
%metadata1 = alloca i32 addrspace(1)*, i32 2, align 8
|
||||
store i32 addrspace(1)* null, i32 addrspace(1)** %metadata1
|
||||
; NOTE: Currently NOT testing alloca lowering in the StackMap format. Its
|
||||
; known to be broken.
|
||||
%safepoint_token = tail call i32 (i1 ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 2, i32 addrspace(1)* %ptr, i32 addrspace(1)* null)
|
||||
%safepoint_token = tail call i32 (i1 ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 2, i32 addrspace(1)* %ptr, i32 addrspace(1)* null, i32 addrspace(1)* %ptr, i32 addrspace(1)* null)
|
||||
%call1 = call zeroext i1 @llvm.experimental.gc.result.int.i1(i32 %safepoint_token)
|
||||
%a = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4)
|
||||
%b = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 5, i32 5)
|
||||
%a = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 6, i32 6)
|
||||
%b = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 7, i32 7)
|
||||
;
|
||||
ret i1 %call1
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue