Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -1859,6 +1859,10 @@ Assert1(II.getUnwindDest()->isLandingPad(), "The unwind destination does not have a landingpad instruction!",&II); + if (Function *F = II.getCalledFunction()) + if (F->getIntrinsicID() == Intrinsic::experimental_gc_statepoint) + VerifyStatepoint(ImmutableCallSite(&II)); + visitTerminatorInst(II); } @@ -2358,7 +2362,8 @@ Assert1(!F->isIntrinsic() || isa(I) || F->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID() == Intrinsic::experimental_patchpoint_void || - F->getIntrinsicID() == Intrinsic::experimental_patchpoint_i64, + F->getIntrinsicID() == Intrinsic::experimental_patchpoint_i64 || + isStatepoint(&I), "Cannot invoke an intrinsinc other than" " donothing or patchpoint", &I); Assert1(F->getParent() == M, "Referencing function in another module!", @@ -2756,8 +2761,43 @@ break; } case Intrinsic::experimental_gc_relocate: { + Assert1(CI.getNumArgOperands() == 3, "wrong number of arguments", &CI); + + // We should be tied to either extractvalue from landingpad or statepoint + bool isLandingpad = isa(CI.getArgOperand(0)); + Assert2(isStatepoint(cast(CI.getArgOperand(0))) || isLandingpad, + "token must be from a statepoint or landingpad", &CI, CI.getArgOperand(0)); + + if (isLandingpad) { + Assert1(isa( + cast( + CI.getArgOperand(0))->getAggregateOperand()), + "gc relocate on unwind path incorrectly linked to the statepoint", + &CI); + + const BasicBlock *invokeBB = + cast(CI.getArgOperand(0))->getParent()->getUniquePredecessor(); + + // Landingpad relocates should have only one predecessor with terminator invoke statepoint + Assert1(invokeBB, + "safepoints should have unique landingpads", + cast(CI.getArgOperand(0))->getParent()); + Assert1(invokeBB->getTerminator(), + "safepoint block should be well formed", + invokeBB); + Assert1(isStatepoint(invokeBB->getTerminator()), + "gc relocate should be linked to a statepoint", + invokeBB); + } + // Are we tied to a statepoint properly? - CallSite StatepointCS(CI.getArgOperand(0)); + GCRelocateOperands ops(&CI); + ImmutableCallSite StatepointCS = [&]() { + if (isLandingpad) + return ImmutableCallSite(ops.statepoint()); + return ImmutableCallSite(CI.getArgOperand(0)); + }(); + const Function *StatepointFn = StatepointCS.getInstruction() ? StatepointCS.getCalledFunction() : nullptr; Assert2(StatepointFn && StatepointFn->isDeclaration() && Index: test/Verifier/statepoint.ll =================================================================== --- test/Verifier/statepoint.ll +++ test/Verifier/statepoint.ll @@ -50,3 +50,37 @@ ; CHECK-NEXT: call ; CHECK-NEXT: ret voi } + +; Basic test for invoke statepoints +define i8 addrspace(1)* @test3(i8 addrspace(1)* %obj, i8 addrspace(1)* %obj1) { +; 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 %invoke_safepoint_normal_dest unwind label %exceptional_return + +invoke_safepoint_normal_dest: + ; CHECK-LABEL: invoke_safepoint_normal_dest + ; CHECK: gc.relocate + ; CHECK: gc.relocate + %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) + br label %normal_return + +normal_return: + ; CHECK-LABEL: normal_return + ; CHECK: ret + 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 +}