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 bool isAnyArm64(T Machine) { } template 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 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..6720c90fde237 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, 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 d0a8ababe8e58..df3b457eecec0 100644 --- a/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp @@ -82,6 +82,12 @@ getEffectiveLoongArchCodeModel(const Triple &TT, } } +static std::unique_ptr createTLOF(const Triple &TT) { + if (TT.isOSBinFormatCOFF()) + return std::make_unique(); + return std::make_unique(); +} + LoongArchTargetMachine::LoongArchTargetMachine( const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, std::optional RM, @@ -89,7 +95,7 @@ LoongArchTargetMachine::LoongArchTargetMachine( : CodeGenTargetMachineImpl(T, TT.computeDataLayout(), TT, CPU, FS, Options, getEffectiveRelocModel(TT, RM), getEffectiveLoongArchCodeModel(TT, CM), OL), - TLOF(std::make_unique()) { + 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 0696813040654..036aa7d6ad669 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 LoongArchAsmBackend::getFixupKind(StringRef Name) const { @@ -484,16 +484,46 @@ bool LoongArchAsmBackend::addReloc(const MCFragment &F, const MCFixup &Fixup, return true; } -std::unique_ptr -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 + 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 + 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 8236e300a6ab2..c1f3ccffd6b94 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 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 - createObjectTargetWriter() const override; const MCTargetOptions &getTargetOptions() const { return TargetOptions; } DenseMap &getSecToAlignSym() { return SecToAlignSym; diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp index 0d7761777cb7d..2b518785712a8 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,21 @@ 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; + + 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 e5bd1c91edec9..1ac754dec18bc 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" @@ -62,7 +63,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); @@ -82,9 +89,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 * @@ -296,6 +305,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 createLoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit); +std::unique_ptr +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 +llvm::createLoongArchWinCOFFObjectWriter(bool Is64Bit) { + return std::make_unique(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..2a129989cc46e --- /dev/null +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchWinCOFFStreamer.cpp @@ -0,0 +1,33 @@ +//===- 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 AB, + std::unique_ptr CE, + std::unique_ptr OW) + : MCWinCOFFStreamer(C, std::move(AB), std::move(CE), std::move(OW)) {} +}; +} // namespace + +MCStreamer *llvm::createLoongArchWinCOFFStreamer( + MCContext &C, std::unique_ptr &&AB, + std::unique_ptr &&OW, std::unique_ptr &&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 &&MAB, + std::unique_ptr &&MOW, + std::unique_ptr &&MCE); +} // end namespace llvm +#endif diff --git a/llvm/lib/TargetParser/TargetDataLayout.cpp b/llvm/lib/TargetParser/TargetDataLayout.cpp index cea246e9527bd..e73155a8a054b 100644 --- a/llvm/lib/TargetParser/TargetDataLayout.cpp +++ b/llvm/lib/TargetParser/TargetDataLayout.cpp @@ -116,8 +116,11 @@ static std::string computeCSKYDataLayout(const Triple &TT) { } static std::string computeLoongArchDataLayout(const Triple &TT) { - if (TT.isLoongArch64()) + if (TT.isLoongArch64()) { + 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.isLoongArch32() && "only LA32 and LA64 are currently supported"); return "e-m:e-p:32:32-i64:64-n32-S128"; } diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp index ac3626db46ea9..e68978244e3f6 100644 --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -977,7 +977,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: @@ -1008,6 +1007,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/test/CodeGen/LoongArch/efi-main.ll b/llvm/test/CodeGen/LoongArch/efi-main.ll new file mode 100644 index 0000000000000..207b9ce0e985e --- /dev/null +++ b/llvm/test/CodeGen/LoongArch/efi-main.ll @@ -0,0 +1,19 @@ +; RUN: llc --mtriple=loongarch64-unknown-uefi < %s | FileCheck %s + +define i64 @efi_main(ptr noundef %handle, ptr noundef %system_table) { +entry: + %system_table.addr = alloca ptr, align 8 + %handle.addr = alloca ptr, align 8 + store ptr %system_table, ptr %system_table.addr, align 8 + store ptr %handle, ptr %handle.addr, align 8 + ret i64 0 +} + +; UEFI: .section .text.efi,"ax",@progbits +; CHECK-LABEL: efi_main: +; CHECK: addi.d $sp, $sp, -16 +; CHECK: st.d $a1, $sp, 8 +; CHECK: st.d $a0, $sp, 0 +; CHECK: move $a0, $zero +; CHECK: addi.d $sp, $sp, 16 +; CHECK: ret diff --git a/llvm/test/MC/LoongArch/uefi/coff-sections.s b/llvm/test/MC/LoongArch/uefi/coff-sections.s new file mode 100644 index 0000000000000..b73a138ea24cf --- /dev/null +++ b/llvm/test/MC/LoongArch/uefi/coff-sections.s @@ -0,0 +1,25 @@ +# Test COFF section handling for LoongArch64 UEFI targets + +# RUN: llvm-mc -triple=loongarch64-unknown-uefi -filetype=obj -o %t.coff %s +# RUN: llvm-readobj --sections %t.coff | FileCheck %s + +.text +.globl _DriverEntry +_DriverEntry: + addi.d $a0, $zero, 0 + jirl $zero, $ra, 0 + +.data +.global DriverData +DriverData: + .dword 0x12345678 + +.section .rdata +ReadOnlyData: + .asciz "UEFI Driver" + +# CHECK: Sections [ +# CHECK: Name: .text +# CHECK: Name: .data +# CHECK: Name: .rdata +# CHECK: ] diff --git a/llvm/test/MC/LoongArch/uefi/uefi-basic.s b/llvm/test/MC/LoongArch/uefi/uefi-basic.s new file mode 100644 index 0000000000000..87ccae1e5a137 --- /dev/null +++ b/llvm/test/MC/LoongArch/uefi/uefi-basic.s @@ -0,0 +1,16 @@ +# Test basic LoongArch64 UEFI assembly and COFF object generation + +# RUN: llvm-mc -triple=loongarch64-unknown-uefi -filetype=obj -o %t.coff %s +# RUN: llvm-readobj --file-headers %t.coff | FileCheck %s + +.text +.globl _start +_start: + addi.d $a0, $zero, 42 + b _exit + +_exit: + addi.d $a7, $zero, 93 + syscall 0 + +# CHECK: Machine: IMAGE_FILE_MACHINE_LOONGARCH64 (0x6264) diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp index 73115fbb7e55e..a030d6cb11017 100644 --- a/llvm/tools/llvm-readobj/COFFDumper.cpp +++ b/llvm/tools/llvm-readobj/COFFDumper.cpp @@ -341,31 +341,31 @@ void COFFDumper::printBinaryBlockWithRelocs(StringRef Label, } const EnumEntry ImageFileMachineType[] = { - LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_UNKNOWN ), - LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_AM33 ), - LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_AMD64 ), - LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM ), - LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM64 ), - LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM64EC ), - LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM64X ), - LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARMNT ), - LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_EBC ), - 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_MIPS16 ), - LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPSFPU ), - LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPSFPU16), - LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_POWERPC ), - LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_POWERPCFP), - LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_R4000 ), - LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH3 ), - LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH3DSP ), - LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH4 ), - LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH5 ), - LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_THUMB ), - LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_WCEMIPSV2) -}; + LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_UNKNOWN), + LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_AM33), + LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_AMD64), + LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM), + LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM64), + LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM64EC), + LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM64X), + LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARMNT), + LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_EBC), + 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), + LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_POWERPC), + LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_POWERPCFP), + LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_R4000), + LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH3), + LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH3DSP), + LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH4), + LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH5), + LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_THUMB), + LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_WCEMIPSV2)}; const EnumEntry ImageFileCharacteristics[] = { LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_RELOCS_STRIPPED ), 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", ] }