https://github.com/leecheechen updated https://github.com/llvm/llvm-project/pull/154883
>From f41eb0972441ef0e181375cbdc3897208225e80b Mon Sep 17 00:00:00 2001 From: chenli <che...@loongson.cn> Date: Fri, 22 Aug 2025 12:27:31 +0800 Subject: [PATCH] [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: - Added UEFI triple support in Clang driver and target info - 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> --- clang/lib/Basic/Targets.cpp | 3 ++ clang/lib/Basic/Targets/LoongArch.h | 3 ++ clang/lib/Driver/Driver.cpp | 6 ++- .../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 ++++++ 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 + 25 files changed, 285 insertions(+), 34 deletions(-) create mode 100644 clang/test/CodeGen/LoongArch/uefi-data-layout.c 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/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) { 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", ] } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits