@@ -7304,6 +7304,61 @@ void CodeGen::genReturnSuspend(GenTreeUnOp* treeNode)
73047304 genMarkReturnGCInfo ();
73057305}
73067306
7307+ // ------------------------------------------------------------------------
7308+ // genPatchpoint:
7309+ // Generate code for GT_PATCHPOINT / GT_PATCHPOINT_FORCED nodes.
7310+ // Emits a call to the patchpoint helper followed by an unconditional jump
7311+ // to the returned address.
7312+ //
7313+ // Arguments:
7314+ // treeNode - The patchpoint node (GT_PATCHPOINT or GT_PATCHPOINT_FORCED)
7315+ //
7316+ void CodeGen::genPatchpoint (GenTreeOp* treeNode)
7317+ {
7318+ assert (treeNode->OperIs (GT_PATCHPOINT , GT_PATCHPOINT_FORCED ));
7319+
7320+ genConsumeOperands (treeNode);
7321+
7322+ // Move operands into the expected argument registers if needed.
7323+ genCopyRegIfNeeded (treeNode->gtGetOp1 (), REG_ARG_0 );
7324+ if (treeNode->OperIs (GT_PATCHPOINT ))
7325+ {
7326+ genCopyRegIfNeeded (treeNode->gtGetOp2 (), REG_ARG_1 );
7327+ }
7328+
7329+ CorInfoHelpFunc helper = treeNode->OperIs (GT_PATCHPOINT ) ? CORINFO_HELP_PATCHPOINT : CORINFO_HELP_PATCHPOINT_FORCED ;
7330+
7331+ genEmitHelperCall (helper, 0 , EA_UNKNOWN );
7332+
7333+ // On non-x64 targets, mark the method as having tail calls so that
7334+ // return-address hijacking is disabled — after the jump the return
7335+ // address may have moved in the frame and unhijacking will write
7336+ // to the wrong slot.
7337+ // On x64 this is unnecessary because the return address is always at
7338+ // the same stack slot regardless of tail calls.
7339+ #ifndef TARGET_XARCH
7340+ SetHasTailCalls (true );
7341+ #endif
7342+
7343+ // Jump to the address returned by the patchpoint helper.
7344+ // Must not use INS_tail_i_jmp: it is a REX-prefixed jump that the
7345+ // win-x64 unwinder detects as an epilog instruction, which would
7346+ // incorrectly signal that callee saves / RSP have been restored.
7347+ #ifdef TARGET_XARCH
7348+ GetEmitter ()->emitIns_R (INS_i_jmp, EA_PTRSIZE , REG_INTRET );
7349+ #elif defined(TARGET_ARM64)
7350+ GetEmitter ()->emitIns_R (INS_br, EA_PTRSIZE , REG_INTRET );
7351+ #elif defined(TARGET_ARM)
7352+ GetEmitter ()->emitIns_R (INS_bx, EA_PTRSIZE , REG_INTRET );
7353+ #elif defined(TARGET_LOONGARCH64)
7354+ GetEmitter ()->emitIns_R_R_I (INS_jirl, EA_PTRSIZE , REG_R0 , REG_INTRET , 0 );
7355+ #elif defined(TARGET_RISCV64)
7356+ GetEmitter ()->emitIns_R_R_I (INS_jalr, EA_PTRSIZE , REG_R0 , REG_INTRET , 0 );
7357+ #else
7358+ #error "Unsupported target architecture for GT_PATCHPOINT"
7359+ #endif
7360+ }
7361+
73077362// ------------------------------------------------------------------------
73087363// genMarkReturnGCInfo:
73097364// Mark GC and non-GC pointers of return registers going into the epilog..
0 commit comments