[llvm] [AArch64] Fix the emission of WinCFI for pac-ret+leaf and SCS (PR #147518)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 9 09:47:01 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-aarch64
Author: Anatoly Trosinenko (atrosinenko)
<details>
<summary>Changes</summary>
This commit fixes WinCFI opcodes being incorrectly emitted for test cases in sign-return-address.ll.
Emit SEH_Nop opcode in emitShadowCallStackEpilogue the same way it is done in emitShadowCallStackPrologue function - this fixes
12 bytes of instructions in range, but .seh directives corresponding to 8 bytes
error being reported for the epilogue of non_leaf_scs function.
Emit SEH_PrologEnd on the code path in emitPrologue function that may be taken when pac-ret protection is emitted for a leaf function - this fixes errors like the following:
starting epilogue (.seh_startepilogue) before prologue has ended (.seh_endprologue) in leaf_sign_all_v83
Stray .seh_endepilogue in leaf_sign_all_v83
---
Full diff: https://github.com/llvm/llvm-project/pull/147518.diff
2 Files Affected:
- (modified) llvm/lib/Target/AArch64/AArch64FrameLowering.cpp (+23-9)
- (modified) llvm/test/CodeGen/AArch64/sign-return-address.ll (+5)
``````````diff
diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
index 666ff8bbab42a..00fbeef9d35df 100644
--- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
@@ -1746,7 +1746,7 @@ static void emitShadowCallStackEpilogue(const TargetInstrInfo &TII,
MachineFunction &MF,
MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
- const DebugLoc &DL) {
+ const DebugLoc &DL, bool NeedsWinCFI) {
// Shadow call stack epilog: ldr x30, [x18, #-8]!
BuildMI(MBB, MBBI, DL, TII.get(AArch64::LDRXpre))
.addReg(AArch64::X18, RegState::Define)
@@ -1755,6 +1755,10 @@ static void emitShadowCallStackEpilogue(const TargetInstrInfo &TII,
.addImm(-8)
.setMIFlag(MachineInstr::FrameDestroy);
+ if (NeedsWinCFI)
+ BuildMI(MBB, MBBI, DL, TII.get(AArch64::SEH_Nop))
+ .setMIFlag(MachineInstr::FrameDestroy);
+
if (MF.getInfo<AArch64FunctionInfo>()->needsAsyncDwarfUnwindInfo(MF))
CFIInstBuilder(MBB, MBBI, MachineInstr::FrameDestroy)
.buildRestore(AArch64::X18);
@@ -1899,13 +1903,15 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
BuildMI(MBB, MBBI, DL, TII->get(AArch64::PAUTH_PROLOGUE))
.setMIFlag(MachineInstr::FrameSetup);
}
- if (NeedsWinCFI)
- HasWinCFI = true; // AArch64PointerAuth pass will insert SEH_PACSignLR
+ // AArch64PointerAuth pass will insert SEH_PACSignLR
+ HasWinCFI |= NeedsWinCFI;
}
- if (MFnI.needsShadowCallStackPrologueEpilogue(MF))
+ if (MFnI.needsShadowCallStackPrologueEpilogue(MF)) {
emitShadowCallStackPrologue(*TII, MF, MBB, MBBI, DL, NeedsWinCFI,
MFnI.needsDwarfUnwindInfo(MF));
+ HasWinCFI |= NeedsWinCFI;
+ }
if (EmitCFI && MFnI.isMTETagged()) {
BuildMI(MBB, MBBI, DL, TII->get(AArch64::EMITMTETAGGED))
@@ -1990,8 +1996,13 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
"unexpected function without stack frame but with SVE objects");
// All of the stack allocation is for locals.
AFI->setLocalStackSize(NumBytes);
- if (!NumBytes)
+ if (!NumBytes) {
+ if (NeedsWinCFI && HasWinCFI) {
+ BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_PrologEnd))
+ .setMIFlag(MachineInstr::FrameSetup);
+ }
return;
+ }
// REDZONE: If the stack size is less than 128 bytes, we don't need
// to actually allocate.
if (canUseRedZone(MF)) {
@@ -2460,8 +2471,11 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock::iterator EpilogStartI = MBB.end();
auto FinishingTouches = make_scope_exit([&]() {
- if (AFI->needsShadowCallStackPrologueEpilogue(MF))
- emitShadowCallStackEpilogue(*TII, MF, MBB, MBB.getFirstTerminator(), DL);
+ if (AFI->needsShadowCallStackPrologueEpilogue(MF)) {
+ emitShadowCallStackEpilogue(*TII, MF, MBB, MBB.getFirstTerminator(), DL,
+ NeedsWinCFI);
+ HasWinCFI |= NeedsWinCFI;
+ }
if (EmitCFI)
emitCalleeSavedGPRRestores(MBB, MBB.getFirstTerminator());
if (AFI->shouldSignReturnAddress(MF)) {
@@ -2472,8 +2486,8 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
TII->get(AArch64::PAUTH_EPILOGUE))
.setMIFlag(MachineInstr::FrameDestroy);
}
- if (NeedsWinCFI)
- HasWinCFI = true; // AArch64PointerAuth pass will insert SEH_PACSignLR
+ // AArch64PointerAuth pass will insert SEH_PACSignLR
+ HasWinCFI |= NeedsWinCFI;
}
if (HasWinCFI) {
BuildMI(MBB, MBB.getFirstTerminator(), DL,
diff --git a/llvm/test/CodeGen/AArch64/sign-return-address.ll b/llvm/test/CodeGen/AArch64/sign-return-address.ll
index b0ab4775cb388..a1e819240f888 100644
--- a/llvm/test/CodeGen/AArch64/sign-return-address.ll
+++ b/llvm/test/CodeGen/AArch64/sign-return-address.ll
@@ -5,6 +5,11 @@
; v9.5-A is not expected to change codegen without -mbranch-protection=+pc, so reuse V83A.
; RUN: llc -mtriple=aarch64 -mattr=v9.5a < %s | FileCheck --check-prefixes=CHECK,V83A %s
+; Make sure no errors are detected when emitting SEH opcodes.
+; Errors are only checked for when generating a binary, so emit a dummy object
+; file and make sure llc produces zero exit code.
+; RUN: llc -mtriple=aarch64-windows -o %t.dummy.o --filetype=obj < %s
+
define i32 @leaf(i32 %x) {
; CHECK-LABEL: leaf:
; CHECK: // %bb.0:
``````````
</details>
https://github.com/llvm/llvm-project/pull/147518
More information about the llvm-commits
mailing list