llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-aarch64

Author: Paul (paulober)

<details>
<summary>Changes</summary>

Adds `aarch64-unknown-uefi` as a target, mirroring the existing
`x86_64-unknown-uefi` support so Clang/LLVM can emit PE/COFF `.efi` binaries for
AArch64 UEFI firmware. UEFI on AArch64 uses PE/COFF images and the Microsoft
ARM64 ABI, so it reuses the Windows COFF paths rather than the ELF ones.

**Clang**
- New `UEFIAArch64TargetInfo` (PE/COFF, Microsoft ARM64 ABI, LLP64) with the 
COFF
  data layout; the AArch64 triple maps to it.
- Allow `aarch64` in the driver's UEFI arch guard (previously x86_64-only).

**AArch64 backend**
- Add `AArch64Subtarget::isTargetUEFI()`.
- Relax the `AArch64MCInstLower` "Windows is the only supported COFF target"
  assertion to also accept UEFI.
- Treat UEFI like Windows for frame-record layout and Windows CFI
  (`AArch64FrameLowering::isTargetWindows`, 
`AArch64RegisterInfo::getCalleeSavedRegs`),
  keeping the callee-saved register lists aligned so the (FP, LR) pairing stays
  consistent. This answers the pre-existing `// TODO: Should this include 
targets
  like UEFI (which use Windows CFI)?` in `isTargetWindows()`.

### Motivation

Enabling Embedded Swift to target AArch64 UEFI firmware; companion
`swiftlang/swift` and `swiftlang/swift-driver` changes add the Swift-side
support. This PR is the canonical upstream home for the change. A downstream
cherry-pick exists at swiftlang/llvm-project#<!-- -->13596 purely to unblock 
that Swift
work ahead of the upstream→downstream merge, and will be dropped once this 
lands.

### Status / testing

Initial patch — it does **not yet include lit tests**, and I'd welcome guidance
on the preferred coverage (a Clang `-target` data-layout test plus an AArch64
CodeGen COFF test seem natural). In an out-of-tree build, freestanding C and
Embedded Swift compile for `aarch64-unknown-uefi` to valid `coff-arm64` objects
with a correct frame record.


---
Full diff: https://github.com/llvm/llvm-project/pull/213275.diff


8 Files Affected:

- (modified) clang/lib/Basic/Targets.cpp (+2) 
- (modified) clang/lib/Basic/Targets/AArch64.cpp (+37) 
- (modified) clang/lib/Basic/Targets/AArch64.h (+11) 
- (modified) clang/lib/Driver/Driver.cpp (+4-2) 
- (modified) llvm/lib/Target/AArch64/AArch64FrameLowering.cpp (+6-5) 
- (modified) llvm/lib/Target/AArch64/AArch64MCInstLower.cpp (+2-2) 
- (modified) llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp (+5-1) 
- (modified) llvm/lib/Target/AArch64/AArch64Subtarget.h (+1) 


``````````diff
diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index 8c01cfca8ccb4..823a2f08943ff 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -190,6 +190,8 @@ std::unique_ptr<TargetInfo> AllocateTarget(const 
llvm::Triple &Triple,
       default: // Assume MSVC for unknown environments
         return std::make_unique<MicrosoftARM64TargetInfo>(Triple, Opts);
       }
+    case llvm::Triple::UEFI:
+      return std::make_unique<UEFIAArch64TargetInfo>(Triple, Opts);
     default:
       return std::make_unique<AArch64leTargetInfo>(Triple, Opts);
     }
diff --git a/clang/lib/Basic/Targets/AArch64.cpp 
b/clang/lib/Basic/Targets/AArch64.cpp
index d531e26ade84a..126791d725cd2 100644
--- a/clang/lib/Basic/Targets/AArch64.cpp
+++ b/clang/lib/Basic/Targets/AArch64.cpp
@@ -1859,6 +1859,43 @@ MinGWARM64TargetInfo::MinGWARM64TargetInfo(const 
llvm::Triple &Triple,
   TheCXXABI.set(TargetCXXABI::GenericAArch64);
 }
 
+UEFIAArch64TargetInfo::UEFIAArch64TargetInfo(const llvm::Triple &Triple,
+                                             const TargetOptions &Opts)
+    : UEFITargetInfo<AArch64leTargetInfo>(Triple, Opts) {
+  // UEFI images are PE/COFF and follow the Microsoft ARM64 ABI. The UEFI spec
+  // does not mandate a specific C++ ABI or integer model, so we match the
+  // Windows ARM64 target -- the only supported way to produce AArch64 EFI
+  // binaries with Clang/LLVM today.
+  TheCXXABI.set(TargetCXXABI::Microsoft);
+
+  // LLP64 data model: int:4, long:4, long long:8, long double:8.
+  IntWidth = IntAlign = 32;
+  LongWidth = LongAlign = 32;
+  DoubleAlign = LongLongAlign = 64;
+  LongDoubleWidth = LongDoubleAlign = 64;
+  LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+  IntMaxType = SignedLongLong;
+  Int64Type = SignedLongLong;
+  SizeType = UnsignedLongLong;
+  PtrDiffType = SignedLongLong;
+  IntPtrType = SignedLongLong;
+}
+
+void UEFIAArch64TargetInfo::setDataLayout() {
+  // PE/COFF image: use the same data layout the LLVM AArch64 TargetMachine
+  // computes for COFF. This must be an override (not just a ctor call) because
+  // handleTargetFeatures() re-invokes setDataLayout() after construction, and
+  // the AArch64le base only knows MachO/ELF -- it would otherwise revert to an
+  // ELF layout that mismatches the backend.
+  resetDataLayout("e-m:w-p270:32:32-p271:32:32-p272:64:64-p:64:64-i32:32-"
+                  "i64:64-i128:128-n32:64-S128-Fn32");
+}
+
+AArch64TargetInfo::BuiltinVaListKind
+UEFIAArch64TargetInfo::getBuiltinVaListKind() const {
+  return TargetInfo::CharPtrBuiltinVaList;
+}
+
 AppleMachOAArch64TargetInfo::AppleMachOAArch64TargetInfo(
     const llvm::Triple &Triple, const TargetOptions &Opts)
     : AppleMachOTargetInfo<AArch64leTargetInfo>(Triple, Opts) {}
diff --git a/clang/lib/Basic/Targets/AArch64.h 
b/clang/lib/Basic/Targets/AArch64.h
index 3ccfa265399be..046713668bb1e 100644
--- a/clang/lib/Basic/Targets/AArch64.h
+++ b/clang/lib/Basic/Targets/AArch64.h
@@ -316,6 +316,17 @@ class LLVM_LIBRARY_VISIBILITY MinGWARM64TargetInfo
   MinGWARM64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
 };
 
+// ARM64 UEFI target (PE/COFF image, Microsoft ARM64 ABI)
+class LLVM_LIBRARY_VISIBILITY UEFIAArch64TargetInfo
+    : public UEFITargetInfo<AArch64leTargetInfo> {
+public:
+  UEFIAArch64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+
+  void setDataLayout() override;
+
+  BuiltinVaListKind getBuiltinVaListKind() const override;
+};
+
 class LLVM_LIBRARY_VISIBILITY AArch64beTargetInfo : public AArch64TargetInfo {
 public:
   AArch64beTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 38795f7c2ae7a..5bb1716902f1c 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -714,8 +714,10 @@ static llvm::Triple computeTargetTriple(const Driver &D, 
StringRef TargetTriple,
   }
 #endif
 
-  // Currently the only architecture supported by *-uefi triples are x86_64.
-  if (Target.isUEFI() && Target.getArch() != llvm::Triple::x86_64)
+  // The architectures currently supported by *-uefi triples are x86_64 and
+  // aarch64 (both emit PE/COFF images under the Microsoft ABI).
+  if (Target.isUEFI() && Target.getArch() != llvm::Triple::x86_64 &&
+      Target.getArch() != llvm::Triple::aarch64)
     D.Diag(diag::err_target_unknown_triple) << Target.str();
 
   // The `-maix[32|64]` flags are only valid for AIX targets.
diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp 
b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
index 6ef64b06932ab..3eeea74c98453 100644
--- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
@@ -384,12 +384,13 @@ static bool isLikelyToHaveSVEStack(const 
AArch64FrameLowering &AFL,
 }
 
 static bool isTargetWindows(const MachineFunction &MF) {
-  // TODO: Should this include targets like UEFI (which use Windows CFI)?
-  // Note: Currently, there is not AArch64 support for UEFI. The value returned
-  // here must align with the predicate used for returning the list of callee
-  // saved regs in AArch64RegisterInfo::getCalleeSavedRegs(), so that we use
+  // UEFI images are PE/COFF and use Windows CFI, so for frame-record layout 
and
+  // unwind they behave like Windows. This value must align with the predicate
+  // used for returning the list of callee saved regs in
+  // AArch64RegisterInfo::getCalleeSavedRegs(), so that we use
   // invalidateWindowsRegisterPairing() where appropriate.
-  return MF.getSubtarget<AArch64Subtarget>().isTargetWindows();
+  const AArch64Subtarget &STI = MF.getSubtarget<AArch64Subtarget>();
+  return STI.isTargetWindows() || STI.isTargetUEFI();
 }
 
 bool AArch64FrameLowering::hasSVECalleeSavesAboveFrameRecord(
diff --git a/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp 
b/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp
index d3a38624488e8..ce0e0ef39ad0e 100644
--- a/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp
+++ b/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp
@@ -49,8 +49,8 @@ MCSymbol *AArch64MCInstLower::GetGlobalValueSymbol(const 
GlobalValue *GV,
   if (!TheTriple.isOSBinFormatCOFF())
     return Printer.getSymbolPreferLocal(*GV);
 
-  assert(TheTriple.isOSWindows() &&
-         "Windows is the only supported COFF target");
+  assert((TheTriple.isOSWindows() || TheTriple.isUEFI()) &&
+         "COFF is only supported on Windows and UEFI targets");
 
   bool IsIndirect =
       (TargetFlags & (AArch64II::MO_DLLIMPORT | AArch64II::MO_COFFSTUB));
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp 
b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
index 502c91fe3e531..920c1bf29963c 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
@@ -76,7 +76,11 @@ AArch64RegisterInfo::getCalleeSavedRegs(const 
MachineFunction *MF) const {
   const auto &F = MF->getFunction();
   const auto *TLI = MF->getSubtarget<AArch64Subtarget>().getTargetLowering();
   const bool Darwin = MF->getSubtarget<AArch64Subtarget>().isTargetDarwin();
-  const bool Windows = MF->getSubtarget<AArch64Subtarget>().isTargetWindows();
+  // UEFI uses the Windows PE/COFF ABI, so it takes the same callee-saved
+  // register lists (this must align with isTargetWindows() in
+  // AArch64FrameLowering, which drives invalidateWindowsRegisterPairing()).
+  const bool Windows = MF->getSubtarget<AArch64Subtarget>().isTargetWindows() 
||
+                       MF->getSubtarget<AArch64Subtarget>().isTargetUEFI();
 
   if (TLI->supportSwiftError() &&
       F.getAttributes().hasAttrSomewhere(Attribute::SwiftError)) {
diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.h 
b/llvm/lib/Target/AArch64/AArch64Subtarget.h
index 380c3e11fcbf2..68a9947e8e88d 100644
--- a/llvm/lib/Target/AArch64/AArch64Subtarget.h
+++ b/llvm/lib/Target/AArch64/AArch64Subtarget.h
@@ -312,6 +312,7 @@ class AArch64Subtarget final : public 
AArch64GenSubtargetInfo {
   bool isTargetIOS() const { return TargetTriple.isiOS(); }
   bool isTargetLinux() const { return TargetTriple.isOSLinux(); }
   bool isTargetWindows() const { return TargetTriple.isOSWindows(); }
+  bool isTargetUEFI() const { return TargetTriple.isUEFI(); }
   bool isTargetAndroid() const { return TargetTriple.isAndroid(); }
   bool isTargetFuchsia() const { return TargetTriple.isOSFuchsia(); }
   bool isWindowsArm64EC() const { return TargetTriple.isWindowsArm64EC(); }

``````````

</details>


https://github.com/llvm/llvm-project/pull/213275
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to