https://github.com/dpaoliello created https://github.com/llvm/llvm-project/pull/146582
There is no way in Arm64 Windows to indicate that a given function has used the Frame Pointer as a General Purpose Register, as such stack walks will always assume that the frame chain is valid and will follow whatever value has been saved for the Frame Pointer (even if it is pointing to data, etc.). This change makes the Frame Pointer always reserved when building for Arm64 Windows to avoid this issue. We will be updating the official Windows ABI documentation to reflect this requirement, and I will provide a link once it's available. cc @pmsjt >From 7397fec459dc6ec502efe7361ebb6946b45e485e Mon Sep 17 00:00:00 2001 From: Daniel Paoliello <dan...@microsoft.com> Date: Tue, 1 Jul 2025 10:47:15 -0700 Subject: [PATCH] [win][aarch64] Always reserve frame pointers for Arm64 Windows --- clang/lib/Driver/ToolChains/CommonArgs.cpp | 15 +++++++++++++-- clang/test/Driver/frame-pointer-elim.c | 6 ++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 070901f037823..2fcf9b28dc746 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -174,7 +174,13 @@ static bool mustUseNonLeafFramePointerForTarget(const llvm::Triple &Triple) { // even if new frame records are not created. static bool mustMaintainValidFrameChain(const llvm::opt::ArgList &Args, const llvm::Triple &Triple) { - if (Triple.isARM() || Triple.isThumb()) { + switch (Triple.getArch()) { + default: + return false; + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: // For 32-bit Arm, the -mframe-chain=aapcs and -mframe-chain=aapcs+leaf // options require the frame pointer register to be reserved (or point to a // new AAPCS-compilant frame record), even with -fno-omit-frame-pointer. @@ -183,8 +189,13 @@ static bool mustMaintainValidFrameChain(const llvm::opt::ArgList &Args, return V != "none"; } return false; + + case llvm::Triple::aarch64: + // Arm64 Windows requires that the frame chain is valid, as there is no + // way to indicate during a stack walk that a frame has used the frame + // pointer as a general purpose register. + return Triple.isOSWindows(); } - return false; } // True if a target-specific option causes -fno-omit-frame-pointer to also diff --git a/clang/test/Driver/frame-pointer-elim.c b/clang/test/Driver/frame-pointer-elim.c index f64ff6efc7261..0dd7eb0c738db 100644 --- a/clang/test/Driver/frame-pointer-elim.c +++ b/clang/test/Driver/frame-pointer-elim.c @@ -4,6 +4,8 @@ // KEEP-NON-LEAF: "-mframe-pointer=non-leaf" // KEEP-NONE-NOT: warning: argument unused // KEEP-NONE: "-mframe-pointer=none" +// KEEP-RESERVED-NOT: warning: argument unused +// KEEP-RESERVED: "-mframe-pointer=reserved" // On Linux x86, omit frame pointer when optimization is enabled. // RUN: %clang -### --target=i386-linux -S -fomit-frame-pointer %s 2>&1 | \ @@ -215,5 +217,9 @@ // RUN: %clang -### --target=aarch64-none-elf -S -O1 -fno-omit-frame-pointer %s 2>&1 | \ // RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s +// AArch64 Windows requires that the frame pointer be reserved +// RUN: %clang -### --target=aarch64-pc-windows-msvc -S -fomit-frame-pointer %s 2>&1 | \ +// RUN: FileCheck --check-prefix=KEEP-RESERVED %s + void f0() {} void f1() { f0(); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits