From 9a048d6cb8272150fa0031dd0154009c50840b82 Mon Sep 17 00:00:00 2001 From: Jason Xu <40355221+JasonBrave@users.noreply.github.com> Date: Tue, 8 Jul 2025 22:56:34 -0400 Subject: [PATCH 1/6] Add RISC-V PE32+ Relocation Types --- llvm/include/llvm/BinaryFormat/COFF.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/llvm/include/llvm/BinaryFormat/COFF.h b/llvm/include/llvm/BinaryFormat/COFF.h index f3b5d5e3f23c6..7b428d0e76c67 100644 --- a/llvm/include/llvm/BinaryFormat/COFF.h +++ b/llvm/include/llvm/BinaryFormat/COFF.h @@ -132,7 +132,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) || + IMAGE_FILE_MACHINE_RISCV64; } enum Characteristics : unsigned { @@ -726,7 +727,10 @@ enum BaseRelocationType : unsigned { IMAGE_REL_BASED_HIGHADJ = 4, IMAGE_REL_BASED_MIPS_JMPADDR = 5, IMAGE_REL_BASED_ARM_MOV32A = 5, + IMAGE_REL_BASED_RISCV_HI20 = 5, IMAGE_REL_BASED_ARM_MOV32T = 7, + IMAGE_REL_BASED_RISCV_LOW12I = 7, + IMAGE_REL_BASED_RISCV_LOW12S = 8, IMAGE_REL_BASED_MIPS_JMPADDR16 = 9, IMAGE_REL_BASED_DIR64 = 10 }; From 86bb75a94d7edf1c002aa00de6deb608a142f96e Mon Sep 17 00:00:00 2001 From: Jason Xu <40355221+JasonBrave@users.noreply.github.com> Date: Thu, 10 Jul 2025 15:41:49 -0400 Subject: [PATCH 2/6] Initial adding PE/COFF file output support to RISC-V target --- .../Target/RISCV/MCTargetDesc/CMakeLists.txt | 2 + .../RISCV/MCTargetDesc/RISCVAsmBackend.cpp | 29 +++++++++++ .../RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp | 12 +++++ .../RISCV/MCTargetDesc/RISCVMCAsmInfo.h | 8 +++ .../RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp | 18 ++++++- .../RISCV/MCTargetDesc/RISCVMCTargetDesc.h | 12 +++++ .../MCTargetDesc/RISCVWinCOFFObjectWriter.cpp | 51 +++++++++++++++++++ .../MCTargetDesc/RISCVWinCOFFStreamer.cpp | 33 ++++++++++++ 8 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 llvm/lib/Target/RISCV/MCTargetDesc/RISCVWinCOFFObjectWriter.cpp create mode 100644 llvm/lib/Target/RISCV/MCTargetDesc/RISCVWinCOFFStreamer.cpp diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/RISCV/MCTargetDesc/CMakeLists.txt index e68c956f888e4..19f8ab17bf32e 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/CMakeLists.txt +++ b/llvm/lib/Target/RISCV/MCTargetDesc/CMakeLists.txt @@ -11,6 +11,8 @@ add_llvm_component_library(LLVMRISCVDesc RISCVMatInt.cpp RISCVTargetStreamer.cpp RISCVELFStreamer.cpp + RISCVWinCOFFObjectWriter.cpp + RISCVWinCOFFStreamer.cpp LINK_COMPONENTS MC diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp index 89a87798d71e4..b10f3e2174f81 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp @@ -895,6 +895,30 @@ bool RISCVAsmBackend::shouldInsertFixupForCodeAlign(MCAssembler &Asm, return true; } +namespace { + +class WindowsRISCVAsmBackend : public RISCVAsmBackend { + bool is64Bit; + +public: + WindowsRISCVAsmBackend(const Target &T, const MCSubtargetInfo &STI, + const MCRegisterInfo &MRI, + const MCTargetOptions &Options) + : RISCVAsmBackend( + STI, + MCELFObjectTargetWriter::getOSABI(STI.getTargetTriple().getOS()), + STI.getTargetTriple().isArch64Bit(), Options) { + is64Bit = STI.getTargetTriple().isArch64Bit(); + } + + std::unique_ptr + createObjectTargetWriter() const override { + return createRISCVWinCOFFObjectWriter(is64Bit); + } +}; + +} // namespace + std::unique_ptr RISCVAsmBackend::createObjectTargetWriter() const { return createRISCVELFObjectWriter(OSABI, Is64Bit); @@ -905,6 +929,11 @@ MCAsmBackend *llvm::createRISCVAsmBackend(const Target &T, const MCRegisterInfo &MRI, const MCTargetOptions &Options) { const Triple &TT = STI.getTargetTriple(); + + if (TT.isOSWindows() && TT.isOSBinFormatCOFF()) { + return new WindowsRISCVAsmBackend(T, STI, MRI, Options); + } + uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS()); return new RISCVAsmBackend(STI, OSABI, TT.isArch64Bit(), Options); } diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp index 090d331d99cab..8b6b13f239707 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp @@ -57,3 +57,15 @@ void RISCVMCAsmInfo::printSpecifierExpr(raw_ostream &OS, if (HasSpecifier) OS << ')'; } + + +void RISCVCOFFMCAsmInfo::anchor() {} + +RISCVCOFFMCAsmInfo::RISCVCOFFMCAsmInfo() { + HasSingleParameterDotFile = true; + WinEHEncodingType = WinEH::EncodingType::Itanium; + + ExceptionsType = ExceptionHandling::WinEH; + + AllowAtInName = true; +} diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.h index 097e94b6117c7..1403f07bb7888 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.h @@ -13,6 +13,7 @@ #ifndef LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVMCASMINFO_H #define LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVMCASMINFO_H +#include "llvm/MC/MCAsmInfoCOFF.h" #include "llvm/MC/MCAsmInfoELF.h" #include "llvm/MC/MCFixup.h" @@ -31,6 +32,13 @@ class RISCVMCAsmInfo : public MCAsmInfoELF { const MCSpecifierExpr &Expr) const override; }; +class RISCVCOFFMCAsmInfo : public MCAsmInfoGNUCOFF { + void anchor() override; + +public: + explicit RISCVCOFFMCAsmInfo(); +}; + namespace RISCV { using Specifier = uint16_t; // Specifiers mapping to relocation types below FirstTargetFixupKind are diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp index f66c2d5f99cb3..75de3eeb096ba 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp @@ -44,6 +44,13 @@ using namespace llvm; +namespace { +class RISCVWinCOFFTargetStreamer : public RISCVTargetStreamer { +public: + RISCVWinCOFFTargetStreamer(MCStreamer &S) : RISCVTargetStreamer(S) {} +}; +} // end namespace + static MCInstrInfo *createRISCVMCInstrInfo() { MCInstrInfo *X = new MCInstrInfo(); InitRISCVMCInstrInfo(X); @@ -59,7 +66,13 @@ static MCRegisterInfo *createRISCVMCRegisterInfo(const Triple &TT) { static MCAsmInfo *createRISCVMCAsmInfo(const MCRegisterInfo &MRI, const Triple &TT, const MCTargetOptions &Options) { - MCAsmInfo *MAI = new RISCVMCAsmInfo(TT); + MCAsmInfo *MAI; + + if(TT.isOSWindows()){ + MAI = new RISCVCOFFMCAsmInfo(); + } else { + MAI = new RISCVMCAsmInfo(TT); + } unsigned SP = MRI.getDwarfRegNum(RISCV::X2, true); MCCFIInstruction Inst = MCCFIInstruction::cfiDefCfa(nullptr, SP, 0); @@ -110,6 +123,8 @@ static MCInstPrinter *createRISCVMCInstPrinter(const Triple &T, static MCTargetStreamer * createRISCVObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) { const Triple &TT = STI.getTargetTriple(); + if(TT.isOSBinFormatCOFF()) + return new RISCVWinCOFFTargetStreamer(S); if (TT.isOSBinFormatELF()) return new RISCVTargetELFStreamer(S, STI); return nullptr; @@ -344,6 +359,7 @@ LLVMInitializeRISCVTargetMC() { TargetRegistry::RegisterMCInstPrinter(*T, createRISCVMCInstPrinter); TargetRegistry::RegisterMCSubtargetInfo(*T, createRISCVMCSubtargetInfo); TargetRegistry::RegisterELFStreamer(*T, createRISCVELFStreamer); + TargetRegistry::RegisterCOFFStreamer(*T, createRISCVWinCOFFStreamer); TargetRegistry::RegisterObjectTargetStreamer( *T, createRISCVObjectTargetStreamer); TargetRegistry::RegisterMCInstrAnalysis(*T, createRISCVInstrAnalysis); diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h index bdee7ed4f011e..2cfd1abdc12b3 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.h @@ -13,6 +13,8 @@ #ifndef LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVMCTARGETDESC_H #define LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVMCTARGETDESC_H +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCTargetOptions.h" #include "llvm/Support/DataTypes.h" #include @@ -23,7 +25,9 @@ class MCCodeEmitter; class MCContext; class MCInstrInfo; class MCObjectTargetWriter; +class MCObjectWriter; class MCRegisterInfo; +class MCStreamer; class MCSubtargetInfo; class Target; @@ -34,8 +38,16 @@ MCAsmBackend *createRISCVAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options); +MCStreamer *createRISCVWinCOFFStreamer(MCContext &C, + std::unique_ptr &&AB, + std::unique_ptr &&OW, + std::unique_ptr &&CE); + std::unique_ptr createRISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit); + +std::unique_ptr createRISCVWinCOFFObjectWriter(bool Is64Bit); + } // namespace llvm // Defines symbolic names for RISC-V registers. diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVWinCOFFObjectWriter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVWinCOFFObjectWriter.cpp new file mode 100644 index 0000000000000..207c81cd8c598 --- /dev/null +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVWinCOFFObjectWriter.cpp @@ -0,0 +1,51 @@ +//===- RISCVWinCOFFObjectWriter.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/RISCVFixupKinds.h" +#include "MCTargetDesc/RISCVMCTargetDesc.h" +#include "llvm/BinaryFormat/COFF.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCWinCOFFObjectWriter.h" + +using namespace llvm; + +namespace { + +class RISCVWinCOFFObjectWriter : public MCWinCOFFObjectTargetWriter { +public: + RISCVWinCOFFObjectWriter(bool Is64Bit); + + unsigned getRelocType(MCContext &Ctx, const MCValue &Target, + const MCFixup &Fixup, bool IsCrossSection, + const MCAsmBackend &MAB) const override; +}; + +} // namespace + +RISCVWinCOFFObjectWriter::RISCVWinCOFFObjectWriter(bool Is64Bit) + : MCWinCOFFObjectTargetWriter(Is64Bit ? COFF::IMAGE_FILE_MACHINE_RISCV64 + : COFF::IMAGE_FILE_MACHINE_RISCV32) {} + +unsigned RISCVWinCOFFObjectWriter::getRelocType(MCContext &Ctx, + const MCValue &Target, + const MCFixup &Fixup, + bool IsCrossSection, + const MCAsmBackend &MAB) const { + unsigned FixupKind = Fixup.getKind(); + + switch (FixupKind) { + default: + Ctx.reportError(Fixup.getLoc(), "unsupported relocation type"); + return COFF::IMAGE_REL_BASED_RISCV_HI20; // FIXME + } +} + +std::unique_ptr +llvm::createRISCVWinCOFFObjectWriter(bool Is64Bit) { + return std::make_unique(Is64Bit); +} diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVWinCOFFStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVWinCOFFStreamer.cpp new file mode 100644 index 0000000000000..7cc6dea804a83 --- /dev/null +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVWinCOFFStreamer.cpp @@ -0,0 +1,33 @@ +//===- RISCVWinCOFFStreamer.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 "RISCVMCTargetDesc.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 RISCVWinCOFFStreamer : public MCWinCOFFStreamer { +public: + RISCVWinCOFFStreamer(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::createRISCVWinCOFFStreamer( + MCContext &C, std::unique_ptr &&AB, + std::unique_ptr &&OW, std::unique_ptr &&CE) { + return new RISCVWinCOFFStreamer(C, std::move(AB), std::move(CE), + std::move(OW)); +} From 0f13e8d2993dca06532bebde299b319f590eb2e6 Mon Sep 17 00:00:00 2001 From: Jason Xu <40355221+JasonBrave@users.noreply.github.com> Date: Thu, 10 Jul 2025 16:52:32 -0400 Subject: [PATCH 3/6] Update documentation --- llvm/docs/CodeGenerator.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/docs/CodeGenerator.rst b/llvm/docs/CodeGenerator.rst index 020eb09ba7e1e..21c6b289e8c26 100644 --- a/llvm/docs/CodeGenerator.rst +++ b/llvm/docs/CodeGenerator.rst @@ -723,7 +723,7 @@ The table below captures a snapshot of object file support in LLVM: ================== ======================================================== Format Supported Targets ================== ======================================================== - ``COFF`` AArch64, ARM, X86 + ``COFF`` AArch64, ARM, RISCV, X86 ``DXContainer`` DirectX ``ELF`` AArch64, AMDGPU, ARM, AVR, BPF, CSKY, Hexagon, Lanai, LoongArch, M86k, MSP430, MIPS, PowerPC, RISCV, SPARC, SystemZ, VE, X86 ``GOFF`` SystemZ From eca9f8d69ceffd959454814c0a5388a94044047b Mon Sep 17 00:00:00 2001 From: Jason Xu <40355221+JasonBrave@users.noreply.github.com> Date: Thu, 10 Jul 2025 17:10:28 -0400 Subject: [PATCH 4/6] Add COFF to RISCV Windows/UEFI Target Triple --- llvm/lib/TargetParser/Triple.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp index 0584c941d2e6e..00ee55fd61726 100644 --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -927,6 +927,8 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) { case Triple::aarch64: case Triple::aarch64_32: case Triple::arm: + case Triple::riscv32: + case Triple::riscv64: case Triple::thumb: case Triple::x86: case Triple::x86_64: @@ -966,8 +968,6 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) { case Triple::r600: case Triple::renderscript32: case Triple::renderscript64: - case Triple::riscv32: - case Triple::riscv64: case Triple::shave: case Triple::sparc: case Triple::sparcel: From fffebf350e5c2436f345f559713ab059f1f56863 Mon Sep 17 00:00:00 2001 From: Jason Xu <40355221+JasonBrave@users.noreply.github.com> Date: Thu, 10 Jul 2025 17:38:07 -0400 Subject: [PATCH 5/6] Add RISCV to CodeViewDebug --- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index bc74daf983e40..277afa384927f 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -32,6 +32,7 @@ #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/Config/llvm-config.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/CodeViewRecordIO.h" #include "llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h" #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" @@ -125,6 +126,9 @@ static CPUType mapArchToCVCPUType(Triple::ArchType Type) { return CPUType::ARM64; case Triple::ArchType::mipsel: return CPUType::MIPS; + case llvm::Triple::ArchType::riscv32: + case llvm::Triple::ArchType::riscv64: + return CPUType::Unknown; case Triple::ArchType::UnknownArch: return CPUType::Unknown; default: From 95160b68bf7b1726e2a045ac500eb847d82fefa0 Mon Sep 17 00:00:00 2001 From: Jason Xu <40355221+JasonBrave@users.noreply.github.com> Date: Thu, 10 Jul 2025 18:01:29 -0400 Subject: [PATCH 6/6] Add riscv to COFFObjectFile --- llvm/lib/Object/COFFObjectFile.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Object/COFFObjectFile.cpp b/llvm/lib/Object/COFFObjectFile.cpp index 242c123665f76..4c50507f697eb 100644 --- a/llvm/lib/Object/COFFObjectFile.cpp +++ b/llvm/lib/Object/COFFObjectFile.cpp @@ -1115,11 +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; + return getArch() == Triple::x86_64 || getArch() == Triple::aarch64 || + getArch() == Triple::riscv64 + ? 8 + : 4; } StringRef COFFObjectFile::getFileFormatName() const { - switch(getMachine()) { + switch (getMachine()) { case COFF::IMAGE_FILE_MACHINE_I386: return "COFF-i386"; case COFF::IMAGE_FILE_MACHINE_AMD64: @@ -1134,6 +1137,10 @@ StringRef COFFObjectFile::getFileFormatName() const { return "COFF-ARM64X"; case COFF::IMAGE_FILE_MACHINE_R4000: return "COFF-MIPS"; + case COFF::IMAGE_FILE_MACHINE_RISCV32: + return "COFF-RISCV32"; + case COFF::IMAGE_FILE_MACHINE_RISCV64: + return "COFF-RISCV64"; default: return "COFF-"; }