Skip to content
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
150 commits
Select commit Hold shift + click to select a range
7dfa35d
Arm64: [PAC-RET] Add Pointer Authentication support for Arm64
SwapnilGaikwad Dec 18, 2025
8551ad0
Merge main
SwapnilGaikwad Mar 11, 2026
584a268
Fix build failures
SwapnilGaikwad Mar 11, 2026
8216472
Merge main
SwapnilGaikwad Mar 12, 2026
74a5293
Fix build errors
SwapnilGaikwad Mar 12, 2026
c9c43c9
Limit thread context changes to Arm64
SwapnilGaikwad Mar 12, 2026
5d6058c
Merge main
SwapnilGaikwad Mar 12, 2026
ce5d79b
Fix build issues on x86
SwapnilGaikwad Mar 12, 2026
8db6f6d
Merge main
SwapnilGaikwad Mar 12, 2026
872443e
Merge branch 'main' into github-add-pac
SwapnilGaikwad Mar 12, 2026
3591b2a
Merge main
SwapnilGaikwad Mar 18, 2026
867e149
Limit framelayout changes to JIT
SwapnilGaikwad Mar 18, 2026
f00f789
Fix formatting
SwapnilGaikwad Mar 18, 2026
9616e73
Merge main
SwapnilGaikwad Mar 31, 2026
4582f73
Add MethodAssociatedData containing hijackinfo for NativeAOT
SwapnilGaikwad Mar 31, 2026
d1e65cb
Merge main
SwapnilGaikwad Apr 9, 2026
e1cfd90
Use unwind info to determine value of SP at the time of signing using…
SwapnilGaikwad Apr 9, 2026
cfe6ab8
Fix windows build
SwapnilGaikwad Apr 10, 2026
bed17cd
Merge main
SwapnilGaikwad Apr 10, 2026
cefcd3f
Fix register addressing in asmhelpers
SwapnilGaikwad Apr 10, 2026
f93804f
Merge main
SwapnilGaikwad Apr 10, 2026
280870c
Refactor out IsPacPresent to avoid parsing unwind info multiple times
SwapnilGaikwad Apr 10, 2026
5cc10be
Merge main
SwapnilGaikwad Apr 10, 2026
f186f19
Bail out of RAH instead of hijacking calling frame
SwapnilGaikwad Apr 10, 2026
941d9e2
Remove left-over changes from MethodAssociated Data approach
SwapnilGaikwad Apr 13, 2026
8f9645b
Merge main
SwapnilGaikwad Apr 14, 2026
a755fba
Fallback to DWARF for PAC unwind codes on macos
SwapnilGaikwad Apr 14, 2026
5bde929
Merge main
SwapnilGaikwad Apr 21, 2026
352b3fd
Used stripped the return address while creating a frame OnHijackWorker
SwapnilGaikwad Apr 21, 2026
264f1fe
Remove redundant lef-over changes
SwapnilGaikwad Apr 21, 2026
f455dc1
Mark PacStrip Arm64 only
SwapnilGaikwad Apr 21, 2026
d5a4abb
Merge main
SwapnilGaikwad Apr 21, 2026
a02fac8
Temporarily Revert "JIT: Restore arm64, LA64 and RISCV64 OSR callee s…
SwapnilGaikwad Apr 22, 2026
0d2d0dd
Restore changes from "JIT: Restore arm64, LA64 and RISCV64 OSR callee…
SwapnilGaikwad Apr 23, 2026
f5b520a
Merge main
SwapnilGaikwad Apr 23, 2026
396c868
Strip return address for correct signing in prolog of Tier0 OSR
SwapnilGaikwad Apr 23, 2026
f7d4548
Avoid stripping while restoring Tier0 registers for OSR
SwapnilGaikwad Apr 27, 2026
3ca8d39
Merge main
SwapnilGaikwad Apr 27, 2026
e98099e
Merge main
SwapnilGaikwad Apr 28, 2026
a1768bd
Keep encrypted LR saved in a slot while creating hijack frame
SwapnilGaikwad Apr 28, 2026
1827095
Remove todo from libunwind to use strip instead of auth
SwapnilGaikwad Apr 28, 2026
b43e5e7
Use auth instead of strip in windows unwinder
SwapnilGaikwad Apr 29, 2026
52ca210
Merge main
SwapnilGaikwad Apr 29, 2026
e5d5ca3
Keep signed return address for the hijackframe and authenticate it on…
SwapnilGaikwad Apr 30, 2026
037a0a4
Merge main
SwapnilGaikwad Apr 30, 2026
1e4ae0a
Merge main
SwapnilGaikwad Apr 30, 2026
067c38f
Fix build issues on macos
SwapnilGaikwad Apr 30, 2026
fcbcdf5
Merge main
SwapnilGaikwad Apr 30, 2026
e1a3695
Handle phantom unwind codes correctly
SwapnilGaikwad Apr 30, 2026
d288cea
Merge main
SwapnilGaikwad May 5, 2026
146da5e
Address review comments
SwapnilGaikwad May 5, 2026
ebad545
Use xpaci instead xpaclri for stripping
SwapnilGaikwad May 5, 2026
89a9ded
Incorporate review comment
SwapnilGaikwad May 5, 2026
650ef08
Merge main
SwapnilGaikwad May 5, 2026
80ed0b4
Merge main
SwapnilGaikwad May 6, 2026
e17d8e9
Refactor GetPacSignInfo
SwapnilGaikwad May 6, 2026
22dccb7
Don't assume sp offset to be zero for PAC signing
SwapnilGaikwad May 7, 2026
21bc75a
Canonicalize return addresses in StackFrameIterator for NativeAOT
SwapnilGaikwad May 7, 2026
cd162df
Merge main
SwapnilGaikwad May 7, 2026
493eff7
Track SP offset for PAC instruction separately while calculating hija…
SwapnilGaikwad May 7, 2026
84741a8
Merge main
SwapnilGaikwad May 7, 2026
bcbc1c1
Use B key on Windows and A key otherwise for PAC
SwapnilGaikwad May 7, 2026
dfac51c
Merge main
SwapnilGaikwad May 7, 2026
24d44ea
Fix formatting
SwapnilGaikwad May 7, 2026
12ca90d
Merge main
SwapnilGaikwad May 8, 2026
7df0c1f
Address review comments
SwapnilGaikwad May 8, 2026
0b6b5a2
Merge main
SwapnilGaikwad May 8, 2026
e9be308
Track PAC CFA offset while unwinding for NativeAOT
SwapnilGaikwad May 8, 2026
ddccab0
Match finding SP for PAC signing on Windows NativeAOT with the JIT
SwapnilGaikwad May 8, 2026
ff1f08e
Fix build errors
SwapnilGaikwad May 11, 2026
3a6ad11
Merge main
SwapnilGaikwad May 11, 2026
e71d980
Merge main
SwapnilGaikwad May 13, 2026
a07d3bd
Merge main
SwapnilGaikwad May 13, 2026
af97173
Remove redundant changes
SwapnilGaikwad May 13, 2026
f153e2b
Merge main
SwapnilGaikwad May 14, 2026
c40c08c
Make JitPacEnabled config variable Arm64 only
SwapnilGaikwad May 14, 2026
27f8c9b
Merge main
SwapnilGaikwad May 15, 2026
a6b6641
Restore clearing THUMB_CODE on arm32
SwapnilGaikwad May 15, 2026
f5b5954
Merge main and JIT changes
SwapnilGaikwad May 19, 2026
b6fa62e
Merge main
SwapnilGaikwad May 19, 2026
401b496
Use PAL unwinder for UNIX to retrieve signing SP for PAC
SwapnilGaikwad May 19, 2026
d21c942
Merge main
SwapnilGaikwad May 20, 2026
9a2a161
Restore missing THUMB_CODE clearing on Arm32
SwapnilGaikwad May 20, 2026
82b962d
Merge main
SwapnilGaikwad May 21, 2026
f4c7ec1
Switch to use PAL unwinder for Windows to retrieve signing SP for PAC
SwapnilGaikwad May 21, 2026
82a8ec4
Try fixing build failures on Windows
SwapnilGaikwad May 21, 2026
64c7367
Merge main
SwapnilGaikwad May 27, 2026
a24b0b7
Merge main
SwapnilGaikwad May 28, 2026
b5bd6c2
Merge main
SwapnilGaikwad May 28, 2026
e44b17a
Update JIT GUID temporarilty to enable SPMI tests
SwapnilGaikwad May 28, 2026
0645777
Merge main
SwapnilGaikwad May 29, 2026
3ef9668
Address review comments
SwapnilGaikwad May 29, 2026
6bdc21f
Merge main
SwapnilGaikwad May 29, 2026
a66dd10
Pass signing sp for managed frame to hijack frame
SwapnilGaikwad May 29, 2026
4113f04
Merge main
SwapnilGaikwad Jun 1, 2026
d539d9d
Strip return address in cdac unwinder
SwapnilGaikwad Jun 1, 2026
88b9eb2
Handle RTL_VIRTUAL_UNWIND2_VALIDATE_PAC in unwinder
SwapnilGaikwad Jun 1, 2026
363156e
Revert "Handle RTL_VIRTUAL_UNWIND2_VALIDATE_PAC in unwinder"
SwapnilGaikwad Jun 1, 2026
13cf190
Merge main
SwapnilGaikwad Jun 2, 2026
d5a1b3c
Use ARM64_ARG macro for Arm64 specific args in HijackFrame
SwapnilGaikwad Jun 2, 2026
3da8014
Merge main
SwapnilGaikwad Jun 3, 2026
b3ffd12
Switch to PAL unwinder for NativeAOT on Windows
SwapnilGaikwad Jun 3, 2026
9dfec15
Use auth instead of strip while returning from hijack in NativeAOT
SwapnilGaikwad Jun 3, 2026
0f7379b
Fix build errors on Windows
SwapnilGaikwad Jun 3, 2026
9f20273
Merge main
SwapnilGaikwad Jun 3, 2026
b7f5452
Merge main
SwapnilGaikwad Jun 4, 2026
528710b
Fix build errors on Windows
SwapnilGaikwad Jun 4, 2026
782e0d8
Try fixing arm32 and x64 build failures
SwapnilGaikwad Jun 4, 2026
ba25589
Merge main
SwapnilGaikwad Jun 4, 2026
3efd414
Try fixing build errors
SwapnilGaikwad Jun 4, 2026
98cbb04
More build fixes
SwapnilGaikwad Jun 4, 2026
e41c3ca
Limit changes to NativeAOT declartions to Arm64 only
SwapnilGaikwad Jun 4, 2026
15fe969
Merge main
SwapnilGaikwad Jun 4, 2026
0910b0a
Avoid separate definitions for NativeAOT in daccess.h
SwapnilGaikwad Jun 5, 2026
0e41b35
Avoid adding crosscomp.h for NativeAOT builds to avoid redef warnings…
SwapnilGaikwad Jun 5, 2026
dbb330a
Merge main
SwapnilGaikwad Jun 5, 2026
2f49693
Address review comments
SwapnilGaikwad Jun 8, 2026
f564983
Merge main
SwapnilGaikwad Jun 8, 2026
473a3a5
Merge main
SwapnilGaikwad Jun 9, 2026
295ab9b
Avoid parsing Apple compact unwind as PAC DWARF info
SwapnilGaikwad Jun 10, 2026
82a1e88
Merge main
SwapnilGaikwad Jun 10, 2026
ffa7fb5
Temporarily disable return address stripping in cdac unwinder
SwapnilGaikwad Jun 10, 2026
f5105ff
Merge main
SwapnilGaikwad Jun 10, 2026
48d0189
Merge main
SwapnilGaikwad Jun 10, 2026
aea1eee
Restore Linux ARM64 NativeAOT unwindability behavior
SwapnilGaikwad Jun 12, 2026
756e59c
Revert cdac unwinder changes
SwapnilGaikwad Jun 12, 2026
1f81993
Merge main
SwapnilGaikwad Jun 12, 2026
fcf77c1
Update return value explicitly when PAC info not found
SwapnilGaikwad Jun 15, 2026
faa2a32
Enable hijacking current frame when interrupted in outside prolog/epi…
SwapnilGaikwad Jun 15, 2026
ff276e4
Merge main
SwapnilGaikwad Jun 15, 2026
7de5a37
Merge main
SwapnilGaikwad Jun 17, 2026
c216dc6
Merge branch 'main' into github-add-pac
jkotas Jun 21, 2026
0ab4e9a
Apply suggestion from @jkotas
jkotas Jun 22, 2026
e4c1e75
Apply suggestion from @jkotas
jkotas Jun 22, 2026
fdcb483
Merge main
SwapnilGaikwad Jun 22, 2026
f704206
Track signing SP in unwind info to handle stack allocation before pac
SwapnilGaikwad Jun 22, 2026
e00e37b
Merge main
SwapnilGaikwad Jun 24, 2026
be49175
Strip return addresses while using in CDAC
SwapnilGaikwad Jun 24, 2026
0d6d757
Fix build errors
SwapnilGaikwad Jun 24, 2026
67a381f
Merge main
SwapnilGaikwad Jun 24, 2026
18a9ab7
Try fixing cdac test failures
SwapnilGaikwad Jun 25, 2026
9a588b5
Avoid hijacking on the return instruction for NativeAOT
SwapnilGaikwad Jun 25, 2026
564fa6a
Merge main
SwapnilGaikwad Jun 25, 2026
3b70987
Try fixing cdac tests
SwapnilGaikwad Jun 26, 2026
ddd0f17
Merge main
SwapnilGaikwad Jun 26, 2026
c520e2f
Address review comments
SwapnilGaikwad Jun 26, 2026
532df3a
Disable hardcoding pauth on Windows
SwapnilGaikwad Jun 26, 2026
59a90e3
Revert adding CFI_DEF_CFA before CFI_NEGATE_RA_STATE
SwapnilGaikwad Jun 29, 2026
ef9c416
Avoid hijacking on RET only when PAC is enabled
SwapnilGaikwad Jun 29, 2026
72a79ff
Merge main
SwapnilGaikwad Jun 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/coreclr/debug/ee/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
#include "../../vm/methoditer.h"
#include "../../vm/tailcallhelp.h"

#if defined(TARGET_ARM64)
extern "C" void* PacStripPtr(void* ptr);
#endif // TARGET_ARM64

const char *GetTType( TraceType tt);

#define IsSingleStep(exception) ((exception) == EXCEPTION_SINGLE_STEP)
Expand Down Expand Up @@ -6222,6 +6226,12 @@ static bool IsTailCall(const BYTE * ip, ControllerStackInfo* info, TailCallFunct
TailCallTls* tls = GetThread()->GetTailCallTls();
LPVOID tailCallAwareRetAddr = tls->GetFrame()->TailCallAwareReturnAddress;

#if defined(TARGET_ARM64)
//TODO-PAC: Authenticate instead of stripping the return addresses.
retAddr = PacStripPtr(retAddr);
tailCallAwareRetAddr = PacStripPtr(tailCallAwareRetAddr);
#endif // TARGET_ARM64

LOG((LF_CORDB,LL_INFO1000, "ITCTR: ret addr is %p, tailcall aware ret addr is %p\n",
retAddr, tailCallAwareRetAddr));

Expand Down
4 changes: 3 additions & 1 deletion src/coreclr/inc/cfi.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ enum CFI_OPCODE
{
CFI_ADJUST_CFA_OFFSET, // Offset is adjusted relative to the current one.
CFI_DEF_CFA_REGISTER, // New register is used to compute CFA
CFI_REL_OFFSET // Register is saved at offset from the current CFA
CFI_REL_OFFSET, // Register is saved at offset from the current CFA
CFI_DEF_CFA, // Take address from register and add offset to it
CFI_NEGATE_RA_STATE, // Sign the return address in lr with paciaz
};

struct CFI_CODE
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/inc/clrconfigvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,7 @@ RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableArm64Rcpc, W("EnableArm64Rc
RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableArm64Rcpc2, W("EnableArm64Rcpc2"), 1, "Allows Arm64 Rcpc2+ hardware intrinsics to be disabled")
RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableArm64Sve, W("EnableArm64Sve"), 1, "Allows Arm64 SVE hardware intrinsics to be disabled")
RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableArm64Sve2, W("EnableArm64Sve2"), 1, "Allows Arm64 SVE2 hardware intrinsics to be disabled")
RETAIL_CONFIG_DWORD_INFO(EXTERNAL_JitPacEnabled, W("JitPacEnabled"), 1, "Allows Arm64 Pointer Authentication (PAC) to be disabled")
#elif defined(TARGET_RISCV64)
Comment thread
SwapnilGaikwad marked this conversation as resolved.
RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableRiscV64Zba, W("EnableRiscV64Zba"), 1, "Allows RiscV64 Zba hardware intrinsics to be disabled")
RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableRiscV64Zbb, W("EnableRiscV64Zbb"), 1, "Allows RiscV64 Zbb hardware intrinsics to be disabled")
Expand Down
7 changes: 6 additions & 1 deletion src/coreclr/inc/gcinfodecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ typedef void * OBJECTREF;

#ifndef __cgencpu_h__

#if defined(TARGET_ARM64)
extern "C" void* PacStripPtr(void* ptr);
#endif // TARGET_ARM64

inline void SetIP(T_CONTEXT* context, PCODE rip)
{
_ASSERTE(!"don't call this");
Expand Down Expand Up @@ -105,7 +109,8 @@ inline PCODE GetIP(T_CONTEXT* context)
#elif defined(TARGET_ARM)
return (PCODE)context->Pc;
#elif defined(TARGET_ARM64)
return (PCODE)context->Pc;
//TODO-PAC: Authenticate instead of stripping the return address.
Comment thread
SwapnilGaikwad marked this conversation as resolved.
Outdated
return (PCODE) PacStripPtr((void *)context->Pc);
#elif defined(TARGET_LOONGARCH64)
return (PCODE)context->Pc;
#elif defined(TARGET_RISCV64)
Expand Down
174 changes: 146 additions & 28 deletions src/coreclr/jit/codegenarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,25 +213,42 @@ void CodeGen::genPopCalleeSavedRegistersAndFreeLclFrame(bool jmpEpilog)
{
case 1:
{
// Generate:
// ldp fp,lr,[sp],#framesz

GetEmitter()->emitIns_R_R_R_I(INS_ldp, EA_PTRSIZE, REG_FP, REG_LR, REG_SPBASE, totalFrameSize,
INS_OPTS_POST_INDEX);
m_compiler->unwindSaveRegPairPreindexed(REG_FP, REG_LR, -totalFrameSize);
if (JitConfig.JitPacEnabled() != 0 && !m_compiler->IsAot())
{
// Generate:
// ldp fp,lr,[sp]
// autiasp
// add sp, sp, #framesz
GetEmitter()->emitIns_R_R_R_I(INS_ldp, EA_PTRSIZE, REG_FP, REG_LR, REG_SPBASE, 0);
m_compiler->unwindSaveRegPair(REG_FP, REG_LR, 0);
GetEmitter()->emitPacInEpilog();
genStackPointerAdjustment(totalFrameSize, REG_SCRATCH, nullptr, /* reportUnwindData */ true);
}
else
{
// Generate:
// ldp fp,lr,[sp],#framesz
GetEmitter()->emitIns_R_R_R_I(INS_ldp, EA_PTRSIZE, REG_FP, REG_LR, REG_SPBASE, totalFrameSize,
INS_OPTS_POST_INDEX);
m_compiler->unwindSaveRegPairPreindexed(REG_FP, REG_LR, -totalFrameSize);
}
break;
}

case 2:
{
// Generate:
// ldp fp,lr,[sp,#outsz]
// autiasp ; if PAC is enabled
// add sp,sp,#framesz

GetEmitter()->emitIns_R_R_R_I(INS_ldp, EA_PTRSIZE, REG_FP, REG_LR, REG_SPBASE,
m_compiler->lvaOutgoingArgSpaceSize);
m_compiler->unwindSaveRegPair(REG_FP, REG_LR, m_compiler->lvaOutgoingArgSpaceSize);

if (!m_compiler->IsAot())
{
GetEmitter()->emitPacInEpilog();
}
GetEmitter()->emitIns_R_R_I(INS_add, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, totalFrameSize);
m_compiler->unwindAllocStack(totalFrameSize);
break;
Expand Down Expand Up @@ -275,6 +292,11 @@ void CodeGen::genPopCalleeSavedRegistersAndFreeLclFrame(bool jmpEpilog)
GetEmitter()->emitIns_R_R_I(INS_add, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, spAdjust);
m_compiler->unwindAllocStack(spAdjust);
}

if (m_compiler->IsAot())
{
GetEmitter()->emitPacInEpilog();
}
}

//------------------------------------------------------------------------
Expand Down Expand Up @@ -485,12 +507,28 @@ void CodeGen::genPrologSaveRegPair(regNumber reg1,
assert(!useSaveNextPair);
if ((spOffset == 0) && (spDelta >= -512))
{
// We can use pre-indexed addressing.
// stp REG, REG + 1, [SP, #spDelta]!
// 64-bit STP offset range: -512 to 504, multiple of 8.
GetEmitter()->emitIns_R_R_R_I(INS_stp, EA_PTRSIZE, reg1, reg2, REG_SPBASE, spDelta, INS_OPTS_PRE_INDEX);
m_compiler->unwindSaveRegPairPreindexed(reg1, reg2, spDelta);

// We can use pre-indexed addressing when pointer authentication PAC is disabled.
assert(reg1 != REG_LR);
Comment thread
SwapnilGaikwad marked this conversation as resolved.
if ((JitConfig.JitPacEnabled() != 0) && (reg2 == REG_LR) && !m_compiler->IsAot())
{
// Generate:
// sub SP, SP, #spDelta
// paciasp
// stp REG, REG + 1, [SP]
assert(reg1 == REG_FP);
genStackPointerAdjustment(spDelta, REG_NA, nullptr, /* reportUnwindData */ true);
GetEmitter()->emitPacInProlog();
GetEmitter()->emitIns_R_R_R_I(INS_stp, EA_PTRSIZE, REG_FP, REG_LR, REG_SPBASE, 0);
m_compiler->unwindSaveRegPair(REG_FP, REG_LR, 0);
}
else
{
// Generate:
// stp REG, REG + 1, [SP, #spDelta]!
// 64-bit STP offset range: -512 to 504, multiple of 8.
GetEmitter()->emitIns_R_R_R_I(INS_stp, EA_PTRSIZE, reg1, reg2, REG_SPBASE, spDelta, INS_OPTS_PRE_INDEX);
m_compiler->unwindSaveRegPairPreindexed(reg1, reg2, spDelta);
}
needToSaveRegs = false;
}
else // (spOffset != 0) || (spDelta < -512)
Expand All @@ -509,6 +547,13 @@ void CodeGen::genPrologSaveRegPair(regNumber reg1,
// 64-bit STP offset range: -512 to 504, multiple of 8.
assert(spOffset <= 504);
assert((spOffset % 8) == 0);
assert(reg1 != REG_LR);

if ((JitConfig.JitPacEnabled() != 0) && (reg2 == REG_LR) && !m_compiler->IsAot())
{
assert(reg1 == REG_FP);
GetEmitter()->emitPacInProlog();
}
GetEmitter()->emitIns_R_R_R_I(INS_stp, EA_PTRSIZE, reg1, reg2, REG_SPBASE, spOffset);

if (TargetOS::IsUnix && m_compiler->generateCFIUnwindCodes())
Expand Down Expand Up @@ -617,16 +662,30 @@ void CodeGen::genEpilogRestoreRegPair(regNumber reg1,
assert((spDelta % 16) == 0); // SP changes must be 16-byte aligned
assert(genIsValidFloatReg(reg1) == genIsValidFloatReg(reg2)); // registers must be both general-purpose, or both
// FP/SIMD
assert(reg1 != REG_LR);

if (spDelta != 0)
{
assert(!useSaveNextPair);
if ((spOffset == 0) && (spDelta <= 504))
{
// Fold the SP change into this instruction.
// ldp reg1, reg2, [SP], #spDelta
GetEmitter()->emitIns_R_R_R_I(INS_ldp, EA_PTRSIZE, reg1, reg2, REG_SPBASE, spDelta, INS_OPTS_POST_INDEX);
m_compiler->unwindSaveRegPairPreindexed(reg1, reg2, -spDelta);
if ((JitConfig.JitPacEnabled() != 0) && (reg2 == REG_LR) && !m_compiler->IsAot())
{
// We separate SP increment and loading FP/LR when PAC is enabled.
assert(reg1 == REG_FP);
GetEmitter()->emitIns_R_R_R_I(INS_ldp, EA_PTRSIZE, reg1, reg2, REG_SPBASE, 0);
m_compiler->unwindSaveRegPair(reg1, reg2, 0);
GetEmitter()->emitPacInEpilog();
genStackPointerAdjustment(spDelta, REG_NA, nullptr, /* reportUnwindData */ true);
}
else
{
// Fold the SP change into this instruction.
// ldp reg1, reg2, [SP], #spDelta
GetEmitter()->emitIns_R_R_R_I(INS_ldp, EA_PTRSIZE, reg1, reg2, REG_SPBASE, spDelta,
INS_OPTS_POST_INDEX);
m_compiler->unwindSaveRegPairPreindexed(reg1, reg2, -spDelta);
}
}
else // (spOffset != 0) || (spDelta > 504)
{
Expand All @@ -636,6 +695,12 @@ void CodeGen::genEpilogRestoreRegPair(regNumber reg1,
GetEmitter()->emitIns_R_R_R_I(INS_ldp, EA_PTRSIZE, reg1, reg2, REG_SPBASE, spOffset);
m_compiler->unwindSaveRegPair(reg1, reg2, spOffset);

if ((JitConfig.JitPacEnabled() != 0) && (reg2 == REG_LR) && !m_compiler->IsAot())
{
assert(reg1 == REG_FP);
GetEmitter()->emitPacInEpilog();
}

// generate add SP,SP,imm
genStackPointerAdjustment(spDelta, tmpReg, pTmpRegIsZero, /* reportUnwindData */ true);
}
Expand All @@ -644,6 +709,12 @@ void CodeGen::genEpilogRestoreRegPair(regNumber reg1,
{
GetEmitter()->emitIns_R_R_R_I(INS_ldp, EA_PTRSIZE, reg1, reg2, REG_SPBASE, spOffset);

if ((JitConfig.JitPacEnabled() != 0) && (reg2 == REG_LR) && !m_compiler->IsAot())
{
assert(reg1 == REG_FP);
GetEmitter()->emitPacInEpilog();
}

if (TargetOS::IsUnix && m_compiler->generateCFIUnwindCodes())
{
useSaveNextPair = false;
Expand Down Expand Up @@ -1347,6 +1418,11 @@ void CodeGen::genFuncletProlog(BasicBlock* block)

m_compiler->unwindBegProlog();

if (m_compiler->IsAot())
{
GetEmitter()->emitPacInProlog();
}

regMaskTP maskSaveRegsFloat = genFuncletInfo.fiSaveRegs & RBM_ALLFLOAT;
regMaskTP maskSaveRegsInt = genFuncletInfo.fiSaveRegs & ~maskSaveRegsFloat;

Expand Down Expand Up @@ -1379,14 +1455,29 @@ void CodeGen::genFuncletProlog(BasicBlock* block)
bool scratchRegIsZero = false;
genAllocLclFrame(-genFuncletInfo.fiSpDelta1, REG_SCRATCH, &scratchRegIsZero, maskArgRegsLiveIn);
genStackPointerAdjustment(genFuncletInfo.fiSpDelta1, REG_SCRATCH, nullptr, /* reportUnwindData */ true);
if (!m_compiler->IsAot())
{
GetEmitter()->emitPacInProlog();
}
GetEmitter()->emitIns_R_R_R_I(INS_stp, EA_PTRSIZE, REG_FP, REG_LR, REG_SPBASE, 0);
m_compiler->unwindSaveRegPair(REG_FP, REG_LR, 0);
}
else
{
GetEmitter()->emitIns_R_R_R_I(INS_stp, EA_PTRSIZE, REG_FP, REG_LR, REG_SPBASE, genFuncletInfo.fiSpDelta1,
INS_OPTS_PRE_INDEX);
m_compiler->unwindSaveRegPairPreindexed(REG_FP, REG_LR, genFuncletInfo.fiSpDelta1);
if (JitConfig.JitPacEnabled() != 0 && !m_compiler->IsAot())
{
// generate sub SP,SP,imm
genStackPointerAdjustment(genFuncletInfo.fiSpDelta1, REG_NA, nullptr, /* reportUnwindData */ true);
GetEmitter()->emitPacInProlog();
GetEmitter()->emitIns_R_R_R_I(INS_stp, EA_PTRSIZE, REG_FP, REG_LR, REG_SPBASE, 0);
m_compiler->unwindSaveRegPair(REG_FP, REG_LR, 0);
}
else
{
GetEmitter()->emitIns_R_R_R_I(INS_stp, EA_PTRSIZE, REG_FP, REG_LR, REG_SPBASE,
genFuncletInfo.fiSpDelta1, INS_OPTS_PRE_INDEX);
m_compiler->unwindSaveRegPairPreindexed(REG_FP, REG_LR, genFuncletInfo.fiSpDelta1);
}
}

maskSaveRegsInt &= ~(RBM_LR | RBM_FP); // We've saved these now
Expand All @@ -1405,6 +1496,10 @@ void CodeGen::genFuncletProlog(BasicBlock* block)

assert(genFuncletInfo.fiSpDelta2 == 0);

if (!m_compiler->IsAot())
{
GetEmitter()->emitPacInProlog();
}
GetEmitter()->emitIns_R_R_R_I(INS_stp, EA_PTRSIZE, REG_FP, REG_LR, REG_SPBASE,
genFuncletInfo.fiSP_to_FPLR_save_delta);
m_compiler->unwindSaveRegPair(REG_FP, REG_LR, genFuncletInfo.fiSP_to_FPLR_save_delta);
Expand All @@ -1413,13 +1508,15 @@ void CodeGen::genFuncletProlog(BasicBlock* block)
}
else if (genFuncletInfo.fiFrameType == 3)
{
if (m_compiler->opts.IsOSR())
// Avoid using pre-indexed store when PAC is enabled.
if ((m_compiler->opts.IsOSR()) || ((JitConfig.JitPacEnabled() != 0) && !m_compiler->IsAot()))
{
// With OSR we may see large values for fiSpDelta1
// We repurpose genAllocLclFram to do the necessary probing.
bool scratchRegIsZero = false;
genAllocLclFrame(-genFuncletInfo.fiSpDelta1, REG_SCRATCH, &scratchRegIsZero, maskArgRegsLiveIn);
genStackPointerAdjustment(genFuncletInfo.fiSpDelta1, REG_SCRATCH, nullptr, /* reportUnwindData */ true);
GetEmitter()->emitPacInProlog();
GetEmitter()->emitIns_R_R_R_I(INS_stp, EA_PTRSIZE, REG_FP, REG_LR, REG_SPBASE, 0);
m_compiler->unwindSaveRegPair(REG_FP, REG_LR, 0);
}
Expand Down Expand Up @@ -1549,12 +1646,24 @@ void CodeGen::genFuncletEpilog()
{
// With OSR we may see large values for fiSpDelta1
//
if (m_compiler->opts.IsOSR())
if (m_compiler->opts.IsOSR() || ((JitConfig.JitPacEnabled() != 0) && !m_compiler->IsAot()))
{
GetEmitter()->emitIns_R_R_R_I(INS_ldp, EA_PTRSIZE, REG_FP, REG_LR, REG_SPBASE, 0);
m_compiler->unwindSaveRegPair(REG_FP, REG_LR, 0);
ssize_t imm = 0;
regNumber tempReg = REG_SCRATCH;

genStackPointerAdjustment(-genFuncletInfo.fiSpDelta1, REG_SCRATCH, nullptr, /* reportUnwindData */ true);
if (JitConfig.JitPacEnabled() != 0)
{
imm = genFuncletInfo.fiSP_to_FPLR_save_delta;
tempReg = REG_NA;
}

GetEmitter()->emitIns_R_R_R_I(INS_ldp, EA_PTRSIZE, REG_FP, REG_LR, REG_SPBASE, imm);
m_compiler->unwindSaveRegPair(REG_FP, REG_LR, static_cast<int>(imm));
if (!m_compiler->IsAot())
{
GetEmitter()->emitPacInEpilog();
}
genStackPointerAdjustment(-genFuncletInfo.fiSpDelta1, tempReg, nullptr, /* reportUnwindData */ true);
}
else
{
Expand All @@ -1571,6 +1680,10 @@ void CodeGen::genFuncletEpilog()
GetEmitter()->emitIns_R_R_R_I(INS_ldp, EA_PTRSIZE, REG_FP, REG_LR, REG_SPBASE,
genFuncletInfo.fiSP_to_FPLR_save_delta);
m_compiler->unwindSaveRegPair(REG_FP, REG_LR, genFuncletInfo.fiSP_to_FPLR_save_delta);
if (!m_compiler->IsAot())
{
GetEmitter()->emitPacInEpilog();
}

// fiFrameType==2 constraints:
assert(genFuncletInfo.fiSpDelta1 < 0);
Expand All @@ -1584,12 +1697,12 @@ void CodeGen::genFuncletEpilog()
else if (genFuncletInfo.fiFrameType == 3)
{
// With OSR we may see large values for fiSpDelta1
//
if (m_compiler->opts.IsOSR())
// Avoid post-indexed load when PAC is enabled.
if (m_compiler->opts.IsOSR() || ((JitConfig.JitPacEnabled() != 0) && !m_compiler->IsAot()))
{
GetEmitter()->emitIns_R_R_R_I(INS_ldp, EA_PTRSIZE, REG_FP, REG_LR, REG_SPBASE, 0);
m_compiler->unwindSaveRegPair(REG_FP, REG_LR, 0);

GetEmitter()->emitPacInEpilog();
genStackPointerAdjustment(-genFuncletInfo.fiSpDelta1, REG_SCRATCH, nullptr, /* reportUnwindData */ true);
}
else
Expand Down Expand Up @@ -1632,6 +1745,11 @@ void CodeGen::genFuncletEpilog()
}
}

if (m_compiler->IsAot())
{
GetEmitter()->emitPacInEpilog();
}

inst_RV(INS_ret, REG_LR, TYP_I_IMPL);
m_compiler->unwindReturn(REG_LR);

Expand Down
Loading
Loading