https://github.com/leecheechen updated 
https://github.com/llvm/llvm-project/pull/154883

>From a47f54c2e99751b6e5f9e1984cb2e9864b302a94 Mon Sep 17 00:00:00 2001
From: chenli <che...@loongson.cn>
Date: Fri, 22 Aug 2025 12:27:31 +0800
Subject: [PATCH 1/2] [LoongArch] Add basic UEFI support

This patch adds initial UEFI support for LoongArch64, enabling the
compilation and generation of UEFI applications for LoongArch targets.

Key changes include:

1. Target support enhancements:
   - Updated data layout for UEFI target (Windows-style instead of ELF)
   - Added LoongArch64 (0x6264) COFF machine type definitions. See:
     
https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#machine-types

2. COFF object file support:
   - Added LoongArch64 machine type recognition in COFF headers
   - Enhanced magic number detection for LoongArch COFF files
   - Updated COFF object file handling for LoongArch64 architecture

3. Code generation infrastructure:
   - Implemented Windows COFF object writer for LoongArch
   - Added COFF streamer support for UEFI target
   - Created COFF-specific MCAsmInfo for Microsoft compatibility
   - Enhanced AsmBackend to support both ELF and COFF output formats

4. Toolchain updates:
   - Extended llvm-readobj to recognize LoongArch64 COFF files
   - Updated triple handling to default to COFF format for UEFI targets
   - Added build system support for new COFF components

The implementation provides the foundational infrastructure for generating
UEFI-compatible PE/COFF binaries for LoongArch64 systems.

Co-Authored-By: WANG Rui <wang...@loongson.cn>
---
 llvm/include/llvm/BinaryFormat/COFF.h         |  4 +-
 llvm/include/llvm/Object/WindowsMachineFlag.h |  2 +
 llvm/lib/BinaryFormat/Magic.cpp               |  5 +-
 llvm/lib/Object/COFFObjectFile.cpp            | 11 ++++-
 .../LoongArch/LoongArchTargetMachine.cpp      | 13 +++++-
 .../LoongArch/MCTargetDesc/CMakeLists.txt     |  2 +
 .../MCTargetDesc/LoongArchAsmBackend.cpp      | 46 +++++++++++++++----
 .../MCTargetDesc/LoongArchAsmBackend.h        | 13 +++---
 .../MCTargetDesc/LoongArchMCAsmInfo.cpp       | 28 +++++++++--
 .../MCTargetDesc/LoongArchMCAsmInfo.h         | 12 ++++-
 .../MCTargetDesc/LoongArchMCTargetDesc.cpp    | 18 ++++++--
 .../MCTargetDesc/LoongArchMCTargetDesc.h      |  2 +
 .../LoongArchWinCOFFObjectWriter.cpp          | 43 +++++++++++++++++
 .../MCTargetDesc/LoongArchWinCOFFStreamer.cpp | 34 ++++++++++++++
 .../MCTargetDesc/LoongArchWinCOFFStreamer.h   | 28 +++++++++++
 llvm/lib/TargetParser/Triple.cpp              |  6 ++-
 llvm/tools/llvm-readobj/COFFDumper.cpp        |  1 +
 .../Target/LoongArch/MCTargetDesc/BUILD.gn    |  2 +
 18 files changed, 238 insertions(+), 32 deletions(-)
 create mode 100644 
llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchWinCOFFObjectWriter.cpp
 create mode 100644 
llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchWinCOFFStreamer.cpp
 create mode 100644 
llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchWinCOFFStreamer.h

diff --git a/llvm/include/llvm/BinaryFormat/COFF.h 
b/llvm/include/llvm/BinaryFormat/COFF.h
index 64fe2160f9970..8732a4969bc33 100644
--- a/llvm/include/llvm/BinaryFormat/COFF.h
+++ b/llvm/include/llvm/BinaryFormat/COFF.h
@@ -104,6 +104,7 @@ enum MachineTypes : unsigned {
   IMAGE_FILE_MACHINE_EBC = 0xEBC,
   IMAGE_FILE_MACHINE_I386 = 0x14C,
   IMAGE_FILE_MACHINE_IA64 = 0x200,
+  IMAGE_FILE_MACHINE_LOONGARCH64 = 0x6264,
   IMAGE_FILE_MACHINE_M32R = 0x9041,
   IMAGE_FILE_MACHINE_MIPS16 = 0x266,
   IMAGE_FILE_MACHINE_MIPSFPU = 0x366,
@@ -132,7 +133,8 @@ template <typename T> bool isAnyArm64(T Machine) {
 }
 
 template <typename T> bool is64Bit(T Machine) {
-  return Machine == IMAGE_FILE_MACHINE_AMD64 || isAnyArm64(Machine);
+  return Machine == IMAGE_FILE_MACHINE_AMD64 || isAnyArm64(Machine) ||
+         Machine == IMAGE_FILE_MACHINE_LOONGARCH64;
 }
 
 enum Characteristics : unsigned {
diff --git a/llvm/include/llvm/Object/WindowsMachineFlag.h 
b/llvm/include/llvm/Object/WindowsMachineFlag.h
index 7655819ef50fd..82148de4b7c3b 100644
--- a/llvm/include/llvm/Object/WindowsMachineFlag.h
+++ b/llvm/include/llvm/Object/WindowsMachineFlag.h
@@ -44,6 +44,8 @@ template <typename T> Triple::ArchType getMachineArchType(T 
machine) {
   case COFF::IMAGE_FILE_MACHINE_ARM64EC:
   case COFF::IMAGE_FILE_MACHINE_ARM64X:
     return llvm::Triple::ArchType::aarch64;
+  case COFF::IMAGE_FILE_MACHINE_LOONGARCH64:
+    return llvm::Triple::ArchType::loongarch64;
   case COFF::IMAGE_FILE_MACHINE_R4000:
     return llvm::Triple::ArchType::mipsel;
   default:
diff --git a/llvm/lib/BinaryFormat/Magic.cpp b/llvm/lib/BinaryFormat/Magic.cpp
index bd378337ed333..05d9e83822269 100644
--- a/llvm/lib/BinaryFormat/Magic.cpp
+++ b/llvm/lib/BinaryFormat/Magic.cpp
@@ -237,8 +237,9 @@ file_magic llvm::identify_magic(StringRef Magic) {
       return file_magic::minidump;
     break;
 
-  case 0x64: // x86-64 or ARM64 Windows.
-    if (Magic[1] == char(0x86) || Magic[1] == char(0xaa))
+  case 0x64: // x86-64 or ARM64 Windows or loongarch64.
+    if (Magic[1] == char(0x86) || Magic[1] == char(0xaa) ||
+        Magic[1] == char(0x62))
       return file_magic::coff_object;
     break;
 
diff --git a/llvm/lib/Object/COFFObjectFile.cpp 
b/llvm/lib/Object/COFFObjectFile.cpp
index 242c123665f76..46280e9e4bd40 100644
--- a/llvm/lib/Object/COFFObjectFile.cpp
+++ b/llvm/lib/Object/COFFObjectFile.cpp
@@ -1115,7 +1115,14 @@ dynamic_reloc_iterator 
COFFObjectFile::dynamic_reloc_end() const {
 }
 
 uint8_t COFFObjectFile::getBytesInAddress() const {
-  return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 ? 8 : 4;
+  switch (getArch()) {
+  case Triple::x86_64:
+  case Triple::aarch64:
+  case Triple::loongarch64:
+    return 8;
+  default:
+    return 4;
+  }
 }
 
 StringRef COFFObjectFile::getFileFormatName() const {
@@ -1132,6 +1139,8 @@ StringRef COFFObjectFile::getFileFormatName() const {
     return "COFF-ARM64EC";
   case COFF::IMAGE_FILE_MACHINE_ARM64X:
     return "COFF-ARM64X";
+  case COFF::IMAGE_FILE_MACHINE_LOONGARCH64:
+    return "COFF-loongarch64";
   case COFF::IMAGE_FILE_MACHINE_R4000:
     return "COFF-MIPS";
   default:
diff --git a/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp 
b/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
index c36db9c75dd3a..1cb48a7c76162 100644
--- a/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
@@ -58,8 +58,11 @@ static cl::opt<bool>
                            cl::init(false));
 
 static std::string computeDataLayout(const Triple &TT) {
-  if (TT.isArch64Bit())
+  if (TT.isArch64Bit()) {
+    if (TT.isUEFI())
+      return "e-m:w-p:64:64-i64:64-i128:128-n32:64-S128";
     return "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128";
+  }
   assert(TT.isArch32Bit() && "only LA32 and LA64 are currently supported");
   return "e-m:e-p:32:32-i64:64-n32-S128";
 }
@@ -89,6 +92,12 @@ getEffectiveLoongArchCodeModel(const Triple &TT,
   }
 }
 
+static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {
+  if (TT.isOSBinFormatCOFF())
+    return std::make_unique<TargetLoweringObjectFileCOFF>();
+  return std::make_unique<TargetLoweringObjectFileELF>();
+}
+
 LoongArchTargetMachine::LoongArchTargetMachine(
     const Target &T, const Triple &TT, StringRef CPU, StringRef FS,
     const TargetOptions &Options, std::optional<Reloc::Model> RM,
@@ -96,7 +105,7 @@ LoongArchTargetMachine::LoongArchTargetMachine(
     : CodeGenTargetMachineImpl(T, computeDataLayout(TT), TT, CPU, FS, Options,
                                getEffectiveRelocModel(TT, RM),
                                getEffectiveLoongArchCodeModel(TT, CM), OL),
-      TLOF(std::make_unique<TargetLoweringObjectFileELF>()) {
+      TLOF(createTLOF(getTargetTriple())) {
   initAsmInfo();
 }
 
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/CMakeLists.txt 
b/llvm/lib/Target/LoongArch/MCTargetDesc/CMakeLists.txt
index 39b4423a63623..ae9077a7935c1 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/CMakeLists.txt
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/CMakeLists.txt
@@ -9,6 +9,8 @@ add_llvm_component_library(LLVMLoongArchDesc
   LoongArchMCTargetDesc.cpp
   LoongArchMatInt.cpp
   LoongArchTargetStreamer.cpp
+  LoongArchWinCOFFObjectWriter.cpp
+  LoongArchWinCOFFStreamer.cpp
 
   LINK_COMPONENTS
   MC
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp 
b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
index 3b38ac95dcafa..d95b32e6d28e1 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
@@ -29,10 +29,10 @@
 using namespace llvm;
 
 LoongArchAsmBackend::LoongArchAsmBackend(const MCSubtargetInfo &STI,
-                                         uint8_t OSABI, bool Is64Bit,
+                                         bool Is64Bit,
                                          const MCTargetOptions &Options)
-    : MCAsmBackend(llvm::endianness::little), STI(STI), OSABI(OSABI),
-      Is64Bit(Is64Bit), TargetOptions(Options) {}
+    : MCAsmBackend(llvm::endianness::little), STI(STI), TargetOptions(Options),
+      Is64Bit(Is64Bit) {}
 
 std::optional<MCFixupKind>
 LoongArchAsmBackend::getFixupKind(StringRef Name) const {
@@ -494,16 +494,46 @@ bool LoongArchAsmBackend::addReloc(const MCFragment &F, 
const MCFixup &Fixup,
   return true;
 }
 
-std::unique_ptr<MCObjectTargetWriter>
-LoongArchAsmBackend::createObjectTargetWriter() const {
-  return createLoongArchELFObjectWriter(OSABI, Is64Bit);
-}
+namespace {
+class ELFLoongArchAsmBackend : public LoongArchAsmBackend {
+  uint8_t OSABI;
+
+public:
+  ELFLoongArchAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI,
+                         bool Is64Bit, const MCTargetOptions &Options)
+      : LoongArchAsmBackend(STI, Is64Bit, Options), OSABI(OSABI) {}
+
+  std::unique_ptr<MCObjectTargetWriter>
+  createObjectTargetWriter() const override {
+    return createLoongArchELFObjectWriter(OSABI, Is64Bit);
+  }
+};
+} // namespace
+
+namespace {
+class COFFLoongArchAsmBackend : public LoongArchAsmBackend {
+public:
+  COFFLoongArchAsmBackend(const MCSubtargetInfo &STI, bool Is64Bit,
+                          const MCTargetOptions &Options)
+      : LoongArchAsmBackend(STI, Is64Bit, Options) {}
+
+  std::unique_ptr<MCObjectTargetWriter>
+  createObjectTargetWriter() const override {
+    return createLoongArchWinCOFFObjectWriter(Is64Bit);
+  }
+};
+} // namespace
 
 MCAsmBackend *llvm::createLoongArchAsmBackend(const Target &T,
                                               const MCSubtargetInfo &STI,
                                               const MCRegisterInfo &MRI,
                                               const MCTargetOptions &Options) {
   const Triple &TT = STI.getTargetTriple();
+  if (TT.isOSBinFormatCOFF())
+    return new COFFLoongArchAsmBackend(STI, TT.isArch64Bit(), Options);
+
+  assert(TT.isOSBinFormatELF() && "Invalid target");
+
   uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS());
-  return new LoongArchAsmBackend(STI, OSABI, TT.isArch64Bit(), Options);
+  return new ELFLoongArchAsmBackend(STI, OSABI, TT.isArch64Bit(), Options);
 }
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h 
b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h
index f79d3aa48c54c..b03282ba029a7 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h
@@ -24,18 +24,19 @@
 namespace llvm {
 
 class LoongArchAsmBackend : public MCAsmBackend {
-  const MCSubtargetInfo &STI;
-  uint8_t OSABI;
-  bool Is64Bit;
-  const MCTargetOptions &TargetOptions;
   DenseMap<MCSection *, const MCSymbolRefExpr *> SecToAlignSym;
   // Temporary symbol used to check whether a PC-relative fixup is resolved.
   MCSymbol *PCRelTemp = nullptr;
 
   bool isPCRelFixupResolved(const MCSymbol *SymA, const MCFragment &F);
 
+protected:
+  const MCSubtargetInfo &STI;
+  const MCTargetOptions &TargetOptions;
+  bool Is64Bit;
+
 public:
-  LoongArchAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit,
+  LoongArchAsmBackend(const MCSubtargetInfo &STI, bool Is64Bit,
                       const MCTargetOptions &Options);
 
   bool addReloc(const MCFragment &, const MCFixup &, const MCValue &,
@@ -57,8 +58,6 @@ class LoongArchAsmBackend : public MCAsmBackend {
   bool writeNopData(raw_ostream &OS, uint64_t Count,
                     const MCSubtargetInfo *STI) const override;
 
-  std::unique_ptr<MCObjectTargetWriter>
-  createObjectTargetWriter() const override;
   const MCTargetOptions &getTargetOptions() const { return TargetOptions; }
   DenseMap<MCSection *, const MCSymbolRefExpr *> &getSecToAlignSym() {
     return SecToAlignSym;
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp 
b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp
index 0d7761777cb7d..e72bf3a5b7ff0 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp
@@ -14,6 +14,7 @@
 #include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/BinaryFormat/ELF.h"
 #include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/TargetParser/Triple.h"
 
@@ -194,9 +195,9 @@ LoongArchMCExpr::Specifier 
LoongArch::parseSpecifier(StringRef name) {
       .Default(0);
 }
 
-void LoongArchMCAsmInfo::anchor() {}
+void LoongArchMCAsmInfoELF::anchor() {}
 
-LoongArchMCAsmInfo::LoongArchMCAsmInfo(const Triple &TT) {
+LoongArchMCAsmInfoELF::LoongArchMCAsmInfoELF(const Triple &TT) {
   CodePointerSize = CalleeSaveStackSlotSize = TT.isArch64Bit() ? 8 : 4;
   AlignmentIsInBytes = false;
   Data8bitsDirective = "\t.byte\t";
@@ -211,8 +212,8 @@ LoongArchMCAsmInfo::LoongArchMCAsmInfo(const Triple &TT) {
   ExceptionsType = ExceptionHandling::DwarfCFI;
 }
 
-void LoongArchMCAsmInfo::printSpecifierExpr(raw_ostream &OS,
-                                            const MCSpecifierExpr &Expr) const 
{
+void LoongArchMCAsmInfoELF::printSpecifierExpr(
+    raw_ostream &OS, const MCSpecifierExpr &Expr) const {
   auto S = Expr.getSpecifier();
   bool HasSpecifier = S != 0 && S != ELF::R_LARCH_B26;
   if (HasSpecifier)
@@ -221,3 +222,22 @@ void LoongArchMCAsmInfo::printSpecifierExpr(raw_ostream 
&OS,
   if (HasSpecifier)
     OS << ')';
 }
+
+void LoongArchMCAsmInfoMicrosoftCOFF::anchor() {}
+
+LoongArchMCAsmInfoMicrosoftCOFF::LoongArchMCAsmInfoMicrosoftCOFF(
+    const Triple &TT) {
+  PrivateGlobalPrefix = ".L";
+  PrivateLabelPrefix = ".L";
+
+  Data16bitsDirective = "\t.hword\t";
+  Data32bitsDirective = "\t.word\t";
+
+  AlignmentIsInBytes = false;
+  SupportsDebugInformation = true;
+  CodePointerSize = 8;
+
+  CommentString = "//";
+  ExceptionsType = ExceptionHandling::WinEH;
+  WinEHEncodingType = WinEH::EncodingType::Itanium;
+}
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.h 
b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.h
index e4b29b2741fed..8a50dc23c42b9 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.h
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.h
@@ -13,6 +13,7 @@
 #ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCASMINFO_H
 #define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCASMINFO_H
 
+#include "llvm/MC/MCAsmInfoCOFF.h"
 #include "llvm/MC/MCAsmInfoELF.h"
 #include "llvm/MC/MCExpr.h"
 
@@ -38,15 +39,22 @@ class LoongArchMCExpr : public MCSpecifierExpr {
   bool getRelaxHint() const { return RelaxHint; }
 };
 
-class LoongArchMCAsmInfo : public MCAsmInfoELF {
+class LoongArchMCAsmInfoELF : public MCAsmInfoELF {
   void anchor() override;
 
 public:
-  explicit LoongArchMCAsmInfo(const Triple &TargetTriple);
+  explicit LoongArchMCAsmInfoELF(const Triple &TargetTriple);
   void printSpecifierExpr(raw_ostream &OS,
                           const MCSpecifierExpr &Expr) const override;
 };
 
+class LoongArchMCAsmInfoMicrosoftCOFF : public MCAsmInfoMicrosoft {
+  void anchor() override;
+
+public:
+  explicit LoongArchMCAsmInfoMicrosoftCOFF(const Triple &Triple);
+};
+
 namespace LoongArch {
 uint16_t parseSpecifier(StringRef name);
 } // namespace LoongArch
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp 
b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp
index 35277ce094a7d..ec4c4c96b6f8a 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp
@@ -14,6 +14,7 @@
 #include "LoongArchELFStreamer.h"
 #include "LoongArchInstPrinter.h"
 #include "LoongArchMCAsmInfo.h"
+#include "LoongArchWinCOFFStreamer.h"
 #include "TargetInfo/LoongArchTargetInfo.h"
 #include "llvm/MC/MCAsmBackend.h"
 #include "llvm/MC/MCAsmInfo.h"
@@ -61,7 +62,13 @@ createLoongArchMCSubtargetInfo(const Triple &TT, StringRef 
CPU, StringRef FS) {
 static MCAsmInfo *createLoongArchMCAsmInfo(const MCRegisterInfo &MRI,
                                            const Triple &TT,
                                            const MCTargetOptions &Options) {
-  MCAsmInfo *MAI = new LoongArchMCAsmInfo(TT);
+  MCAsmInfo *MAI;
+  if (TT.isOSBinFormatCOFF()) {
+    MAI = new LoongArchMCAsmInfoMicrosoftCOFF(TT);
+  } else {
+    assert(TT.isOSBinFormatELF() && "Invalid target");
+    MAI = new LoongArchMCAsmInfoELF(TT);
+  }
 
   // Initial state of the frame pointer is sp(r3).
   unsigned SP = MRI.getDwarfRegNum(LoongArch::R3, true);
@@ -81,9 +88,11 @@ static MCInstPrinter *createLoongArchMCInstPrinter(const 
Triple &T,
 
 static MCTargetStreamer *
 createLoongArchObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) 
{
-  return STI.getTargetTriple().isOSBinFormatELF()
-             ? new LoongArchTargetELFStreamer(S, STI)
-             : nullptr;
+  if (STI.getTargetTriple().isOSBinFormatELF())
+    return new LoongArchTargetELFStreamer(S, STI);
+  if (STI.getTargetTriple().isOSBinFormatCOFF())
+    return new LoongArchTargetWinCOFFStreamer(S);
+  return nullptr;
 }
 
 static MCTargetStreamer *
@@ -216,6 +225,7 @@ LLVMInitializeLoongArchTargetMC() {
     TargetRegistry::RegisterMCInstPrinter(*T, createLoongArchMCInstPrinter);
     TargetRegistry::RegisterMCInstrAnalysis(*T, createLoongArchInstrAnalysis);
     TargetRegistry::RegisterELFStreamer(*T, createLoongArchELFStreamer);
+    TargetRegistry::RegisterCOFFStreamer(*T, createLoongArchWinCOFFStreamer);
     TargetRegistry::RegisterObjectTargetStreamer(
         *T, createLoongArchObjectTargetStreamer);
     TargetRegistry::RegisterAsmTargetStreamer(*T,
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h 
b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h
index ab35a0096c8a2..cbb5d51ed8662 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h
@@ -37,6 +37,8 @@ MCAsmBackend *createLoongArchAsmBackend(const Target &T,
 
 std::unique_ptr<MCObjectTargetWriter>
 createLoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit);
+std::unique_ptr<MCObjectTargetWriter>
+createLoongArchWinCOFFObjectWriter(bool Is64Bit);
 
 } // end namespace llvm
 
diff --git 
a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchWinCOFFObjectWriter.cpp 
b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchWinCOFFObjectWriter.cpp
new file mode 100644
index 0000000000000..057cb3bcf4ed6
--- /dev/null
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchWinCOFFObjectWriter.cpp
@@ -0,0 +1,43 @@
+//===- LoongArchWinCOFFObjectWriter.cpp -----------------------*- C++ 
-*---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/LoongArchFixupKinds.h"
+#include "MCTargetDesc/LoongArchMCTargetDesc.h"
+#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCWinCOFFObjectWriter.h"
+
+using namespace llvm;
+
+namespace {
+
+class LoongArchWinCOFFObjectWriter : public MCWinCOFFObjectTargetWriter {
+public:
+  LoongArchWinCOFFObjectWriter(bool Is64Bit);
+
+  unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
+                        const MCFixup &Fixup, bool IsCrossSection,
+                        const MCAsmBackend &MAB) const override;
+};
+
+} // end anonymous namespace
+
+LoongArchWinCOFFObjectWriter::LoongArchWinCOFFObjectWriter(bool Is64Bit)
+    : MCWinCOFFObjectTargetWriter(COFF::IMAGE_FILE_MACHINE_LOONGARCH64) {}
+
+unsigned LoongArchWinCOFFObjectWriter::getRelocType(
+    MCContext &Ctx, const MCValue &Target, const MCFixup &Fixup,
+    bool IsCrossSection, const MCAsmBackend &MAB) const {
+  // UEFI TODO: convert fixup to coff relocation
+  return Fixup.getKind();
+}
+
+std::unique_ptr<MCObjectTargetWriter>
+llvm::createLoongArchWinCOFFObjectWriter(bool Is64Bit) {
+  return std::make_unique<LoongArchWinCOFFObjectWriter>(Is64Bit);
+}
diff --git 
a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchWinCOFFStreamer.cpp 
b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchWinCOFFStreamer.cpp
new file mode 100644
index 0000000000000..a0b6c1aff1d30
--- /dev/null
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchWinCOFFStreamer.cpp
@@ -0,0 +1,34 @@
+//===- LoongArchWinCOFFStreamer.cpp -----------------------------*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "LoongArchWinCOFFStreamer.h"
+#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCWinCOFFStreamer.h"
+
+using namespace llvm;
+
+namespace {
+class LoongArchWinCOFFStreamer : public MCWinCOFFStreamer {
+public:
+  LoongArchWinCOFFStreamer(MCContext &C, std::unique_ptr<MCAsmBackend> AB,
+                           std::unique_ptr<MCCodeEmitter> CE,
+                           std::unique_ptr<MCObjectWriter> OW)
+      : MCWinCOFFStreamer(C, std::move(AB), std::move(CE), std::move(OW)) {}
+};
+} // namespace
+
+MCStreamer *
+llvm::createLoongArchWinCOFFStreamer(MCContext &C, 
std::unique_ptr<MCAsmBackend> &&AB,
+                               std::unique_ptr<MCObjectWriter> &&OW,
+                               std::unique_ptr<MCCodeEmitter> &&CE) {
+  return new LoongArchWinCOFFStreamer(C, std::move(AB), std::move(CE),
+                                      std::move(OW));
+}
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchWinCOFFStreamer.h 
b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchWinCOFFStreamer.h
new file mode 100644
index 0000000000000..852cdbc6f0cba
--- /dev/null
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchWinCOFFStreamer.h
@@ -0,0 +1,28 @@
+//===-- LoongArchWinCOFFStreamer.h -----------------------------*- C++ 
-*--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHWINCOFFSTREAMER_H
+#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHWINCOFFSTREAMER_H
+
+#include "LoongArchTargetStreamer.h"
+#include "llvm/MC/MCWinCOFFStreamer.h"
+
+namespace llvm {
+
+class LoongArchTargetWinCOFFStreamer : public LoongArchTargetStreamer {
+public:
+  LoongArchTargetWinCOFFStreamer(MCStreamer &S) : LoongArchTargetStreamer(S) {}
+};
+
+MCStreamer *
+createLoongArchWinCOFFStreamer(MCContext &C,
+                               std::unique_ptr<MCAsmBackend> &&MAB,
+                               std::unique_ptr<MCObjectWriter> &&MOW,
+                               std::unique_ptr<MCCodeEmitter> &&MCE);
+} // end namespace llvm
+#endif
diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp
index 6acb0bc49ecfe..b4a877c50fa84 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -966,7 +966,6 @@ static Triple::ObjectFormatType getDefaultFormat(const 
Triple &T) {
   case Triple::kalimba:
   case Triple::lanai:
   case Triple::loongarch32:
-  case Triple::loongarch64:
   case Triple::m68k:
   case Triple::mips64:
   case Triple::mips64el:
@@ -997,6 +996,11 @@ static Triple::ObjectFormatType getDefaultFormat(const 
Triple &T) {
   case Triple::xtensa:
     return Triple::ELF;
 
+  case Triple::loongarch64:
+    if (T.isUEFI())
+      return Triple::COFF;
+    return Triple::ELF;
+
   case Triple::mipsel:
     if (T.isOSWindows())
       return Triple::COFF;
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp 
b/llvm/tools/llvm-readobj/COFFDumper.cpp
index 96e0a634648e4..cc5a48dd25300 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -352,6 +352,7 @@ const EnumEntry<COFF::MachineTypes> ImageFileMachineType[] 
= {
   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_I386     ),
   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_IA64     ),
   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_M32R     ),
+  LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_LOONGARCH64),
   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPS16   ),
   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPSFPU  ),
   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPSFPU16),
diff --git 
a/llvm/utils/gn/secondary/llvm/lib/Target/LoongArch/MCTargetDesc/BUILD.gn 
b/llvm/utils/gn/secondary/llvm/lib/Target/LoongArch/MCTargetDesc/BUILD.gn
index 1ec5591cd6596..d5a99541bd36f 100644
--- a/llvm/utils/gn/secondary/llvm/lib/Target/LoongArch/MCTargetDesc/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/lib/Target/LoongArch/MCTargetDesc/BUILD.gn
@@ -61,5 +61,7 @@ static_library("MCTargetDesc") {
     "LoongArchMCTargetDesc.cpp",
     "LoongArchMatInt.cpp",
     "LoongArchTargetStreamer.cpp",
+    "LoongArchWinCOFFObjectWriter.cpp",
+    "LoongArchWinCOFFStreamer.cpp",
   ]
 }

>From 7efe0439a5ae895f9ce1271b1d59b968017ea176 Mon Sep 17 00:00:00 2001
From: chenli <che...@loongson.cn>
Date: Fri, 22 Aug 2025 18:02:23 +0800
Subject: [PATCH 2/2] [Clang][LoongArch] Add support for UEFI target

This patch adds basic UEFI target support for loongarch64.
It enable Clang to recognize and handle `loongarch64-unknown-uefi`
target triple.
---
 clang/lib/Basic/Targets.cpp                     |  3 +++
 clang/lib/Basic/Targets/LoongArch.h             |  3 +++
 clang/lib/Driver/Driver.cpp                     |  6 ++++--
 clang/test/CodeGen/LoongArch/uefi-data-layout.c |  3 +++
 clang/test/Driver/uefi-constructed-args.c       | 15 +++++++++++++++
 clang/test/Driver/unsupported-target-arch.c     |  6 ++++++
 clang/unittests/Driver/ToolChainTest.cpp        | 13 +++++++++++++
 7 files changed, 47 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/CodeGen/LoongArch/uefi-data-layout.c

diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index e3f9760ac7ce3..ea854e42e4396 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -760,6 +760,9 @@ std::unique_ptr<TargetInfo> AllocateTarget(const 
llvm::Triple &Triple,
     case llvm::Triple::OpenBSD:
       return std::make_unique<OpenBSDTargetInfo<LoongArch64TargetInfo>>(Triple,
                                                                         Opts);
+    case llvm::Triple::UEFI:
+      return std::make_unique<UEFITargetInfo<LoongArch64TargetInfo>>(Triple,
+                                                                     Opts);
     default:
       return std::make_unique<LoongArch64TargetInfo>(Triple, Opts);
     }
diff --git a/clang/lib/Basic/Targets/LoongArch.h 
b/clang/lib/Basic/Targets/LoongArch.h
index 88dc433924d6c..ae0838a58dd63 100644
--- a/clang/lib/Basic/Targets/LoongArch.h
+++ b/clang/lib/Basic/Targets/LoongArch.h
@@ -13,6 +13,7 @@
 #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_LOONGARCH_H
 #define LLVM_CLANG_LIB_BASIC_TARGETS_LOONGARCH_H
 
+#include "OSTargets.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/TargetOptions.h"
 #include "llvm/Support/Compiler.h"
@@ -159,6 +160,8 @@ class LLVM_LIBRARY_VISIBILITY LoongArch64TargetInfo
     IntMaxType = Int64Type = SignedLong;
     HasUnalignedAccess = true;
     resetDataLayout("e-m:e-p:64:64-i64:64-i128:128-n32:64-S128");
+    if (Triple.isUEFI())
+      resetDataLayout("e-m:w-p:64:64-i64:64-i128:128-n32:64-S128");
     // TODO: select appropriate ABI.
     setABI("lp64d");
   }
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index d682ffc832c83..9faeb33ba10b6 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -698,8 +698,10 @@ static llvm::Triple computeTargetTriple(const Driver &D,
     }
   }
 
-  // Currently the only architecture supported by *-uefi triples are x86_64.
-  if (Target.isUEFI() && Target.getArch() != llvm::Triple::x86_64)
+  // Currently the only architectures supported by *-uefi triples are
+  // x86_64 and loongarch64.
+  if (Target.isUEFI() && Target.getArch() != llvm::Triple::x86_64 &&
+      Target.getArch() != llvm::Triple::loongarch64)
     D.Diag(diag::err_target_unknown_triple) << Target.str();
 
   // The `-maix[32|64]` flags are only valid for AIX targets.
diff --git a/clang/test/CodeGen/LoongArch/uefi-data-layout.c 
b/clang/test/CodeGen/LoongArch/uefi-data-layout.c
new file mode 100644
index 0000000000000..8c3e0b00d9d05
--- /dev/null
+++ b/clang/test/CodeGen/LoongArch/uefi-data-layout.c
@@ -0,0 +1,3 @@
+// RUN: %clang -target loongarch64-unknown-uefi -S -emit-llvm -o - %s | \
+// RUN:     FileCheck --check-prefix=LA64_UEFI %s
+// LA64_UEFI: target datalayout = "e-m:w-p:64:64-i64:64-i128:128-n32:64-S128"
diff --git a/clang/test/Driver/uefi-constructed-args.c 
b/clang/test/Driver/uefi-constructed-args.c
index 49ede47a8953e..c9f3cbaf105d3 100644
--- a/clang/test/Driver/uefi-constructed-args.c
+++ b/clang/test/Driver/uefi-constructed-args.c
@@ -12,3 +12,18 @@
 // CHECK-SAME: "-entry:EfiMain"
 // CHECK-SAME: "-tsaware:no"
 // CHECK-SAME: "-debug"
+
+// RUN: %clang -### --target=loongarch64-unknown-uefi -g -- %s 2>&1 \
+// RUN:     | FileCheck -check-prefixes=LA64 %s
+// RUN: %clang_cl -### --target=loongarch64-unknown-uefi -g -- %s 2>&1 \
+// RUN:     | FileCheck -check-prefixes=LA64 %s
+// LA64: "-cc1"
+// LA64-SAME: "-triple" "loongarch64-unknown-uefi"
+// LA64-SAME: "-mrelocation-model" "pic" "-pic-level" "2"
+// LA64-SAME: "-mframe-pointer=all"
+// LA64-SAME: "-fms-extensions"
+// LA64-NEXT: "-nologo"
+// LA64-SAME: "-subsystem:efi_application"
+// LA64-SAME: "-entry:EfiMain"
+// LA64-SAME: "-tsaware:no"
+// LA64-SAME: "-debug"
diff --git a/clang/test/Driver/unsupported-target-arch.c 
b/clang/test/Driver/unsupported-target-arch.c
index 426f646db50b0..2f2fa4f8244df 100644
--- a/clang/test/Driver/unsupported-target-arch.c
+++ b/clang/test/Driver/unsupported-target-arch.c
@@ -77,3 +77,9 @@
 // RUN: not %clang_cl --target=x86-unknown-uefi -o %t.o %s 2> %t.err
 // RUN: FileCheck --input-file=%t.err -check-prefixes=CHECK-x86 %s
 // CHECK-x86: error: unknown target triple 'x86-unknown-uefi'{{$}}
+
+// RUN: not %clang --target=loongarch-unknown-uefi -o %t.o %s 2> %t.err
+// RUN: FileCheck --input-file=%t.err -check-prefixes=CHECK-la %s
+// RUN: not %clang_cl --target=loongarch-unknown-uefi -o %t.o %s 2> %t.err
+// RUN: FileCheck --input-file=%t.err -check-prefixes=CHECK-la %s
+// CHECK-la: error: unknown target triple 'loongarch-unknown-uefi'{{$}}
diff --git a/clang/unittests/Driver/ToolChainTest.cpp 
b/clang/unittests/Driver/ToolChainTest.cpp
index 4fa27297cfd87..c61a7d69d2dbc 100644
--- a/clang/unittests/Driver/ToolChainTest.cpp
+++ b/clang/unittests/Driver/ToolChainTest.cpp
@@ -594,6 +594,19 @@ TEST(ToolChainTest, UEFICallingConventionTest) {
 
   EXPECT_EQ(compiler.getTarget().getCallingConvKind(true),
             TargetInfo::CallingConvKind::CCK_MicrosoftWin64);
+
+  TrStr = "loongarch64-unknown-uefi";
+  Tr.setOS(llvm::Triple::OSType::UEFI);
+  Tr.setVendor(llvm::Triple::VendorType::UnknownVendor);
+  Tr.setEnvironment(llvm::Triple::EnvironmentType::UnknownEnvironment);
+  Tr.setArch(llvm::Triple::ArchType::loongarch64);
+
+  compiler.getTargetOpts().Triple = Tr.getTriple();
+  compiler.setTarget(clang::TargetInfo::CreateTargetInfo(
+      compiler.getDiagnostics(), compiler.getTargetOpts()));
+
+  EXPECT_EQ(compiler.getTarget().getCallingConvKind(true),
+            TargetInfo::CallingConvKind::CCK_Default);
 }
 
 TEST(ToolChainTest, UEFIDefaultDebugFormatTest) {

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to