- // 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());