mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
Implement invoke statepoint verification.
Differential Revision: http://reviews.llvm.org/D7366 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@229840 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
589d13e8f5
commit
05be69f1e3
@ -1987,6 +1987,13 @@ void Verifier::visitInvokeInst(InvokeInst &II) {
|
||||
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(Instruction &I) {
|
||||
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::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
|
||||
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);
|
||||
|
@ -7,7 +7,7 @@ declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()*, i32, i32, ...
|
||||
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
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user