[llvm] r229840 - Implement invoke statepoint verification.
Igor Laevsky
igmyrj at gmail.com
Thu Feb 19 03:28:47 PST 2015
Author: igor.laevsky
Date: Thu Feb 19 05:28:47 2015
New Revision: 229840
URL: http://llvm.org/viewvc/llvm-project?rev=229840&view=rev
Log:
Implement invoke statepoint verification.
Differential Revision: http://reviews.llvm.org/D7366
Modified:
llvm/trunk/lib/IR/Verifier.cpp
llvm/trunk/test/Verifier/statepoint.ll
Modified: llvm/trunk/lib/IR/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=229840&r1=229839&r2=229840&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Verifier.cpp (original)
+++ llvm/trunk/lib/IR/Verifier.cpp Thu Feb 19 05:28:47 2015
@@ -1987,6 +1987,13 @@ void Verifier::visitInvokeInst(InvokeIns
Assert1(II.getUnwindDest()->isLandingPad(),
"The unwind destination does not have a landingpad instruction!",&II);
+ if (Function *F = II.getCalledFunction())
+ // TODO: Ideally we should use visitIntrinsicFunction here. But it uses
+ // CallInst as an input parameter. It not woth updating this whole
+ // function only to support statepoint verification.
+ if (F->getIntrinsicID() == Intrinsic::experimental_gc_statepoint)
+ VerifyStatepoint(ImmutableCallSite(&II));
+
visitTerminatorInst(II);
}
@@ -2486,7 +2493,8 @@ void Verifier::visitInstruction(Instruct
Assert1(!F->isIntrinsic() || isa<CallInst>(I) ||
F->getIntrinsicID() == Intrinsic::donothing ||
F->getIntrinsicID() == Intrinsic::experimental_patchpoint_void ||
- F->getIntrinsicID() == Intrinsic::experimental_patchpoint_i64,
+ F->getIntrinsicID() == Intrinsic::experimental_patchpoint_i64 ||
+ F->getIntrinsicID() == Intrinsic::experimental_gc_statepoint,
"Cannot invoke an intrinsinc other than"
" donothing or patchpoint", &I);
Assert1(F->getParent() == M, "Referencing function in another module!",
@@ -2901,14 +2909,46 @@ void Verifier::visitIntrinsicFunctionCal
break;
}
case Intrinsic::experimental_gc_relocate: {
- // Are we tied to a statepoint properly?
- CallSite StatepointCS(CI.getArgOperand(0));
- const Function *StatepointFn =
- StatepointCS.getInstruction() ? StatepointCS.getCalledFunction() : nullptr;
- Assert2(StatepointFn && StatepointFn->isDeclaration() &&
- StatepointFn->getIntrinsicID() == Intrinsic::experimental_gc_statepoint,
- "gc.relocate operand #1 must be from a statepoint",
- &CI, CI.getArgOperand(0));
+ Assert1(CI.getNumArgOperands() == 3, "wrong number of arguments", &CI);
+
+ // Check that this relocate is correctly tied to the statepoint
+
+ // This is case for relocate on the unwinding path of an invoke statepoint
+ if (ExtractValueInst *ExtractValue =
+ dyn_cast<ExtractValueInst>(CI.getArgOperand(0))) {
+ Assert1(isa<LandingPadInst>(ExtractValue->getAggregateOperand()),
+ "gc relocate on unwind path incorrectly linked to the statepoint",
+ &CI);
+
+ const BasicBlock *invokeBB =
+ ExtractValue->getParent()->getUniquePredecessor();
+
+ // Landingpad relocates should have only one predecessor with invoke
+ // statepoint terminator
+ Assert1(invokeBB,
+ "safepoints should have unique landingpads",
+ ExtractValue->getParent());
+ Assert1(invokeBB->getTerminator(),
+ "safepoint block should be well formed",
+ invokeBB);
+ Assert1(isStatepoint(invokeBB->getTerminator()),
+ "gc relocate should be linked to a statepoint",
+ invokeBB);
+ }
+ else {
+ // In all other cases relocate should be tied to the statepoint directly.
+ // This covers relocates on a normal return path of invoke statepoint and
+ // relocates of a call statepoint
+ auto Token = CI.getArgOperand(0);
+ Assert2(isa<Instruction>(Token) && isStatepoint(cast<Instruction>(Token)),
+ "gc relocate is incorrectly tied to the statepoint",
+ &CI, Token);
+ }
+
+ // Verify rest of the relocate arguments
+
+ GCRelocateOperands ops(&CI);
+ ImmutableCallSite StatepointCS(ops.statepoint());
// Both the base and derived must be piped through the safepoint
Value* Base = CI.getArgOperand(1);
Modified: llvm/trunk/test/Verifier/statepoint.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/statepoint.ll?rev=229840&r1=229839&r2=229840&view=diff
==============================================================================
--- llvm/trunk/test/Verifier/statepoint.ll (original)
+++ llvm/trunk/test/Verifier/statepoint.ll Thu Feb 19 05:28:47 2015
@@ -7,7 +7,7 @@ declare i32 @llvm.experimental.gc.statep
declare i32 @"personality_function"()
;; Basic usage
-define i64 addrspace(1)* @test1(i8 addrspace(1)* %arg) {
+define i64 addrspace(1)* @test1(i8 addrspace(1)* %arg) gc "statepoint-example" {
entry:
%cast = bitcast i8 addrspace(1)* %arg to i64 addrspace(1)*
%safepoint_token = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 5, i32 0, i32 0, i32 0, i32 10, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg)
@@ -29,7 +29,7 @@ entry:
; 2) A value can be replaced by one which is known equal. This
; means a potentially derived pointer can be known base and that
; we can't check that derived pointer are never bases.
-define void @test2(i8 addrspace(1)* %arg, i64 addrspace(1)* %arg2) {
+define void @test2(i8 addrspace(1)* %arg, i64 addrspace(1)* %arg2) gc "statepoint-example" {
entry:
%cast = bitcast i8 addrspace(1)* %arg to i64 addrspace(1)*
%c = icmp eq i64 addrspace(1)* %cast, %arg2
@@ -51,3 +51,33 @@ equal:
; CHECK-NEXT: ret voi
}
+; Basic test for invoke statepoints
+define i8 addrspace(1)* @test3(i8 addrspace(1)* %obj, i8 addrspace(1)* %obj1) gc "statepoint-example" {
+; CHECK-LABEL: test3
+entry:
+ ; CHECK-LABEL: entry
+ ; CHECK: statepoint
+ %0 = invoke i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj, i8 addrspace(1)* %obj1)
+ to label %normal_dest unwind label %exceptional_return
+
+normal_dest:
+ ; CHECK-LABEL: normal_dest:
+ ; CHECK: gc.relocate
+ ; CHECK: gc.relocate
+ ; CHECK: ret
+ %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 9, i32 9)
+ %obj1.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 10, i32 10)
+ ret i8 addrspace(1)* %obj.relocated
+
+exceptional_return:
+ ; CHECK-LABEL: exceptional_return
+ ; CHECK: gc.relocate
+ ; CHECK: gc.relocate
+ %landing_pad = landingpad { i8*, i32 } personality i32 ()* @"personality_function"
+ cleanup
+ %relocate_token = extractvalue { i8*, i32 } %landing_pad, 1
+ %obj.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %relocate_token, i32 9, i32 9)
+ %obj1.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %relocate_token, i32 10, i32 10)
+ ret i8 addrspace(1)* %obj1.relocated1
+}
+
More information about the llvm-commits
mailing list