@@ -251,6 +251,11 @@ void CodeGen::genPopCalleeSavedRegistersAndFreeLclFrame(bool jmpEpilog)
251251 }
252252 }
253253
254+ if (JitConfig.JitPacEnabled () != 0 )
255+ {
256+ GetEmitter ()->emitPacInEpilog ();
257+ }
258+
254259 // For OSR, we must also adjust the SP to remove the Tier0 frame.
255260 //
256261 if (m_compiler->opts .IsOSR ())
@@ -487,9 +492,10 @@ void CodeGen::genPrologSaveRegPair(regNumber reg1,
487492
488493 if ((spOffset == 0 ) && (spDelta >= -512 ))
489494 {
490- // We can use pre-indexed addressing.
495+ // We can use pre-indexed addressing when the stack adjustment fits in the instruction .
491496 // stp REG, REG + 1, [SP, #spDelta]!
492497 // 64-bit STP offset range: -512 to 504, multiple of 8.
498+ assert (reg1 != REG_LR);
493499 GetEmitter ()->emitIns_R_R_R_I (INS_stp, EA_PTRSIZE, reg1, reg2, REG_SPBASE, spDelta, INS_OPTS_PRE_INDEX);
494500 m_compiler->unwindSaveRegPairPreindexed (reg1, reg2, spDelta);
495501
@@ -511,6 +517,8 @@ void CodeGen::genPrologSaveRegPair(regNumber reg1,
511517 // 64-bit STP offset range: -512 to 504, multiple of 8.
512518 assert (spOffset <= 504 );
513519 assert ((spOffset % 8 ) == 0 );
520+ assert (reg1 != REG_LR);
521+
514522 GetEmitter ()->emitIns_R_R_R_I (INS_stp, EA_PTRSIZE, reg1, reg2, REG_SPBASE, spOffset);
515523
516524 if (TargetOS::IsUnix && m_compiler->generateCFIUnwindCodes ())
@@ -622,6 +630,7 @@ void CodeGen::genRestoreRegPair(regNumber reg1,
622630 assert ((spDelta % 16 ) == 0 ); // SP changes must be 16-byte aligned
623631 assert (genIsValidFloatReg (reg1) == genIsValidFloatReg (reg2)); // registers must be both general-purpose, or both
624632 // FP/SIMD
633+ assert (reg1 != REG_LR);
625634
626635 if (spDelta != 0 )
627636 {
@@ -1384,6 +1393,11 @@ void CodeGen::genFuncletProlog(BasicBlock* block)
13841393
13851394 m_compiler->unwindBegProlog ();
13861395
1396+ if (JitConfig.JitPacEnabled () != 0 )
1397+ {
1398+ GetEmitter ()->emitPacInProlog ();
1399+ }
1400+
13871401 regMaskTP maskSaveRegsFloat = genFuncletInfo.fiSaveRegs & RBM_ALLFLOAT;
13881402 regMaskTP maskSaveRegsInt = genFuncletInfo.fiSaveRegs & ~maskSaveRegsFloat;
13891403
@@ -1669,6 +1683,11 @@ void CodeGen::genFuncletEpilog(BasicBlock* /* block */)
16691683 }
16701684 }
16711685
1686+ if (JitConfig.JitPacEnabled () != 0 )
1687+ {
1688+ GetEmitter ()->emitPacInEpilog ();
1689+ }
1690+
16721691 inst_RV (INS_ret, REG_LR, TYP_I_IMPL);
16731692 m_compiler->unwindReturn (REG_LR);
16741693
@@ -5675,6 +5694,20 @@ void CodeGen::genOSRHandleTier0CalleeSavedRegistersAndFrame()
56755694 genRestoreRegPair (REG_FP, REG_LR, REG_FP, 0 , 0 , false , REG_IP1, nullptr ,
56765695 /* reportUnwindData */ false );
56775696
5697+ if (JitConfig.JitPacEnabled () != 0 )
5698+ {
5699+ // Tier0 signed LR with the Tier0 caller SP before allocating its frame.
5700+ // Recreate that SP from the current Tier0 body SP so we can authenticate
5701+ // LR before the OSR prolog later re-signs it with the OSR SP.
5702+ // TODO-PAC: Avoid authenticating and re-signing so the signing SP will point to the start of the frame. It may
5703+ // require adding a phantom pac_sign_lr unwind code.
5704+ genInstrWithConstant (INS_add, EA_PTRSIZE, REG_IP0, REG_SPBASE, patchpointInfo->TotalFrameSize (), REG_IP0,
5705+ /* inUnwindRegion */ false );
5706+ GetEmitter ()->emitIns_Mov (INS_mov, EA_PTRSIZE, REG_IP1, REG_LR, /* canSkip */ false );
5707+ GetEmitter ()->emitIns (TargetOS::IsWindows ? INS_autib1716 : INS_autia1716);
5708+ GetEmitter ()->emitIns_Mov (INS_mov, EA_PTRSIZE, REG_LR, REG_IP1, /* canSkip */ false );
5709+ }
5710+
56785711 // Emit phantom unwind data for the tier0 frame.
56795712 m_compiler->unwindAllocStack (patchpointInfo->TotalFrameSize ());
56805713 // Emit nops to make the prolog 1:1 in unwind codes to instructions. This
0 commit comments