[llvm-branch-commits] [llvm] [AArch64] Apply the Windows SEH and CRT codegen constraints to UEFI (PR #232704)
Prabhu Rajasekaran via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sat Oct 17 23:03:42 PDT 2026
https://github.com/Prabhuk updated https://github.com/llvm/llvm-project/pull/232704
>From 43eb3d3c3a1ddbc6a3c33c813818eeeb13292625 Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Fri, 16 Oct 2026 04:49:24 -0700
Subject: [PATCH] [AArch64] Apply the Windows SEH and CRT codegen constraints
to UEFI
aarch64-unknown-uefi uses SEH unwind information and has no C runtime
library, so the remaining Windows specific codegen decisions that follow
from this apply to it too:
* do not align loops or basic blocks, since SEH unwind info generation
needs the exact function layout before alignment padding is inserted,
* sign return addresses with the B key by default and reject A key
signing, matching the pac_sign_lr unwind code used by the unwinder;
the branch protection parser defaults to the B key for UEFI as well,
so that -mbranch-protection=pac-ret keeps working,
* do not lower wide shifts to libcalls at -Oz, as those helpers are not
available.
The corresponding Windows tests gain aarch64-unknown-uefi run lines and
the LLVM release notes announce the new target, which completes the
backend side of aarch64-unknown-uefi support.
Assisted-by: Claude
---
llvm/docs/ReleaseNotes.md | 4 ++++
.../Target/AArch64/AArch64CodeLayoutOpt.cpp | 2 +-
.../lib/Target/AArch64/AArch64ISelLowering.cpp | 10 +++++-----
.../AArch64/AArch64MachineFunctionInfo.cpp | 4 ++--
.../lib/TargetParser/ARMTargetParserCommon.cpp | 4 ++--
.../AArch64/windows-pac-invalid-a-key.ll | 1 +
llvm/test/CodeGen/AArch64/windows-trap.ll | 1 +
llvm/test/CodeGen/AArch64/wineh-pac.ll | 1 +
.../TargetParser/TargetParserTest.cpp | 18 ++++++++++++++++++
9 files changed, 35 insertions(+), 10 deletions(-)
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 302aa57396105e..0b41fd223d3030 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -271,6 +271,10 @@ Makes programs 10x faster by doing Special New Thing.
* Assembler/disassembler support has been added for Armv9.8-A (2026)
architecture extensions.
+* Added support for the `aarch64-unknown-uefi` target. It follows the Windows
+ ARM64 ABI (calling convention, callee saved registers, stack probing and SEH
+ unwind information) and produces PE/COFF objects.
+
### Changes to the AMDGPU Backend
* Replaced `xnack` and `sramecc` target features with `amdgpu.xnack`
diff --git a/llvm/lib/Target/AArch64/AArch64CodeLayoutOpt.cpp b/llvm/lib/Target/AArch64/AArch64CodeLayoutOpt.cpp
index 73e641da816063..cdbdd0994e77f2 100644
--- a/llvm/lib/Target/AArch64/AArch64CodeLayoutOpt.cpp
+++ b/llvm/lib/Target/AArch64/AArch64CodeLayoutOpt.cpp
@@ -163,7 +163,7 @@ bool AArch64CodeLayoutOpt::runOnMachineFunction(MachineFunction &MF) {
const auto *Subtarget = &MF.getSubtarget<AArch64Subtarget>();
// Aligning basic blocks currently isn't compatible with Windows unwind info.
- if (Subtarget->isTargetWindows())
+ if (Subtarget->isTargetWindowsOrUEFI())
return false;
TII = Subtarget->getInstrInfo();
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 6d6cd21f25be20..8a2677f647aec0 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -1171,10 +1171,10 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
setMinFunctionAlignment(Align(4));
// Set preferred alignments.
- // Don't align loops on Windows. The SEH unwind info generation needs to
- // know the exact length of functions before the alignments have been
- // expanded.
- if (!Subtarget->isTargetWindows())
+ // Don't align loops on Windows and UEFI. The SEH unwind info generation
+ // needs to know the exact length of functions before the alignments have
+ // been expanded.
+ if (!Subtarget->isTargetWindowsOrUEFI())
setPrefLoopAlignment(STI.getPrefLoopAlignment());
setMaxBytesForAlignment(STI.getMaxBytesForLoopAlignment());
setPrefFunctionAlignment(STI.getPrefFunctionAlignment());
@@ -33850,7 +33850,7 @@ TargetLowering::ShiftLegalizationStrategy
AArch64TargetLowering::preferredShiftLegalizationStrategy(
SelectionDAG &DAG, SDNode *N, unsigned int ExpansionFactor) const {
if (DAG.getMachineFunction().getFunction().hasMinSize() &&
- !Subtarget->isTargetWindows() && !Subtarget->isTargetDarwin())
+ !Subtarget->isTargetWindowsOrUEFI() && !Subtarget->isTargetDarwin())
return ShiftLegalizationStrategy::LowerToLibcall;
return TargetLowering::preferredShiftLegalizationStrategy(DAG, N,
ExpansionFactor);
diff --git a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp
index 07a9230b63dc97..7129e332585fa8 100644
--- a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp
@@ -86,7 +86,7 @@ static bool ShouldSignWithBKey(const Function &F, const AArch64Subtarget &STI) {
if (F.hasFnAttribute("ptrauth-returns"))
return true;
if (!F.hasFnAttribute("sign-return-address-key")) {
- if (STI.getTargetTriple().isOSWindows())
+ if (STI.getTargetTriple().isOSWindowsOrUEFI())
return true;
return false;
}
@@ -94,7 +94,7 @@ static bool ShouldSignWithBKey(const Function &F, const AArch64Subtarget &STI) {
const StringRef Key =
F.getFnAttribute("sign-return-address-key").getValueAsString();
assert(Key == "a_key" || Key == "b_key");
- if (STI.getTargetTriple().isOSWindows() && Key == "a_key" &&
+ if (STI.getTargetTriple().isOSWindowsOrUEFI() && Key == "a_key" &&
GetSignReturnAddress(F) != SignReturnAddress::None) {
F.getContext().diagnose(DiagnosticInfoUnsupported{
F, "A-key return address signing is unsupported on AArch64 Windows"});
diff --git a/llvm/lib/TargetParser/ARMTargetParserCommon.cpp b/llvm/lib/TargetParser/ARMTargetParserCommon.cpp
index 818fb64d2e10d2..af5c96133abcf4 100644
--- a/llvm/lib/TargetParser/ARMTargetParserCommon.cpp
+++ b/llvm/lib/TargetParser/ARMTargetParserCommon.cpp
@@ -153,7 +153,7 @@ bool ARM::parseBranchProtection(StringRef Spec, ParsedBranchProtection &PBP,
PBP.BranchTargetEnforcement = true;
PBP.GuardedControlStack = true;
PBP.BranchProtectionPAuthLR = EnablePAuthLR;
- if (Triple.isAArch64() && Triple.isOSWindows())
+ if (Triple.isAArch64() && Triple.isOSWindowsOrUEFI())
PBP.Key = "b_key";
return true;
}
@@ -168,7 +168,7 @@ bool ARM::parseBranchProtection(StringRef Spec, ParsedBranchProtection &PBP,
}
if (Opt == "pac-ret") {
PBP.Scope = "non-leaf";
- if (Triple.isAArch64() && Triple.isOSWindows())
+ if (Triple.isAArch64() && Triple.isOSWindowsOrUEFI())
PBP.Key = "b_key";
for (; I + 1 != E; ++I) {
diff --git a/llvm/test/CodeGen/AArch64/windows-pac-invalid-a-key.ll b/llvm/test/CodeGen/AArch64/windows-pac-invalid-a-key.ll
index 7203e10e4b2003..5b8ab7fdf6b15a 100644
--- a/llvm/test/CodeGen/AArch64/windows-pac-invalid-a-key.ll
+++ b/llvm/test/CodeGen/AArch64/windows-pac-invalid-a-key.ll
@@ -1,4 +1,5 @@
; RUN: not llc -mtriple=aarch64-windows-msvc -filetype=null %s 2>&1 | FileCheck %s
+; RUN: not llc -mtriple=aarch64-unknown-uefi -filetype=null %s 2>&1 | FileCheck %s
; CHECK: error:
; CHECK-SAME: A-key return address signing is unsupported on AArch64 Windows
diff --git a/llvm/test/CodeGen/AArch64/windows-trap.ll b/llvm/test/CodeGen/AArch64/windows-trap.ll
index 5cf0ece48e97d1..9165fb0d2e7cdb 100644
--- a/llvm/test/CodeGen/AArch64/windows-trap.ll
+++ b/llvm/test/CodeGen/AArch64/windows-trap.ll
@@ -1,4 +1,5 @@
; RUN: llc -mtriple=aarch64-win32 %s -o - | FileCheck %s
+; RUN: llc -mtriple=aarch64-unknown-uefi %s -o - | FileCheck %s
declare void @callee() noreturn
diff --git a/llvm/test/CodeGen/AArch64/wineh-pac.ll b/llvm/test/CodeGen/AArch64/wineh-pac.ll
index 71dcaa3b826512..13075447eeef41 100644
--- a/llvm/test/CodeGen/AArch64/wineh-pac.ll
+++ b/llvm/test/CodeGen/AArch64/wineh-pac.ll
@@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc < %s -mtriple=aarch64-windows | FileCheck %s
+; RUN: llc < %s -mtriple=aarch64-unknown-uefi | FileCheck %s
define dso_local i32 @func(ptr %g, i32 %a) "sign-return-address"="non-leaf" "sign-return-address-key"="b_key" {
; CHECK-LABEL: func:
diff --git a/llvm/unittests/TargetParser/TargetParserTest.cpp b/llvm/unittests/TargetParser/TargetParserTest.cpp
index c32ec6a5b4f927..b176aa5ae54c3b 100644
--- a/llvm/unittests/TargetParser/TargetParserTest.cpp
+++ b/llvm/unittests/TargetParser/TargetParserTest.cpp
@@ -1087,6 +1087,24 @@ TEST(TargetParserTest, ARMPrintSupportedExtensions) {
EXPECT_EQ(std::string::npos, captured.find("xscale"));
}
+TEST(TargetParserTest, ARMParseBranchProtectionDefaultKey) {
+ // AArch64 Windows and UEFI only support B key return address signing, so it
+ // is the default there; everywhere else the A key is.
+ for (const auto &[TripleName, ExpectedKey] :
+ {std::pair{"aarch64-unknown-linux-gnu", "a_key"},
+ std::pair{"aarch64-pc-windows-msvc", "b_key"},
+ std::pair{"aarch64-unknown-uefi", "b_key"}}) {
+ const Triple T(TripleName);
+ for (StringRef Spec : {"standard", "pac-ret", "pac-ret+leaf+bti"}) {
+ ARM::ParsedBranchProtection PBP;
+ StringRef Err;
+ EXPECT_TRUE(ARM::parseBranchProtection(Spec, PBP, Err, T))
+ << TripleName << " " << Spec;
+ EXPECT_EQ(PBP.Key, ExpectedKey) << TripleName << " " << Spec;
+ }
+ }
+}
+
struct AArch64CPUTestParams
: public ARMCPUTestParams<AArch64::ExtensionBitset> {
AArch64CPUTestParams(StringRef CPUName, StringRef ExpectedArch)
More information about the llvm-branch-commits
mailing list