From a7f8f932a67badb25ac005186e39ed419ea15681 Mon Sep 17 00:00:00 2001 From: Philip Reames Date: Wed, 7 Jan 2015 22:48:01 +0000 Subject: [PATCH] [GC] improve testing around gc.relocate and fix a test Patch by: Ramkumar Ramachandra "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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225412 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/IR/Verifier.cpp | 41 +++++++++++++++---- test/CodeGen/X86/statepoint-call-lowering.ll | 16 ++++++++ .../CodeGen/X86/statepoint-stackmap-format.ll | 8 ++-- 3 files changed, 51 insertions(+), 14 deletions(-) diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index bc721145d2a..ad7473b6611 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -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(Base), "must be integer offset", &CI); + Assert1(isa(Base), + "gc.relocate operand #2 must be integer offset", &CI); Value* Derived = CI.getArgOperand(2); - Assert1( isa(Derived), "must be integer offset", &CI); + Assert1(isa(Derived), + "gc.relocate operand #3 must be integer offset", &CI); const int BaseIndex = cast(Base)->getZExtValue(); const int DerivedIndex = cast(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(StatepointCS.getArgument(1))->getZExtValue(); + const int NumDeoptArgs = + cast(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; } diff --git a/test/CodeGen/X86/statepoint-call-lowering.ll b/test/CodeGen/X86/statepoint-call-lowering.ll index aacdc8a0377..e7a0dcab9ab 100644 --- a/test/CodeGen/X86/statepoint-call-lowering.ll +++ b/test/CodeGen/X86/statepoint-call-lowering.ll @@ -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) diff --git a/test/CodeGen/X86/statepoint-stackmap-format.ll b/test/CodeGen/X86/statepoint-stackmap-format.ll index f78ca55e6a2..416674839ea 100644 --- a/test/CodeGen/X86/statepoint-stackmap-format.ll +++ b/test/CodeGen/X86/statepoint-stackmap-format.ll @@ -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 } -- 2.34.1