-
Notifications
You must be signed in to change notification settings - Fork 14.5k
[RISCV] RFC: Add PE/COFF file output support #148045
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
9a048d6
86bb75a
0f13e8d
eca9f8d
fffebf3
95160b6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 || | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why isn't this just is64Bit? |
||
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"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there some standard these need to conform to (if so, where is this documented?) or are they whatever we want them to be? |
||
case COFF::IMAGE_FILE_MACHINE_RISCV64: | ||
return "COFF-RISCV64"; | ||
default: | ||
return "COFF-<unknown arch>"; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -895,6 +895,30 @@ bool RISCVAsmBackend::shouldInsertFixupForCodeAlign(MCAssembler &Asm, | |
return true; | ||
} | ||
|
||
namespace { | ||
|
||
class WindowsRISCVAsmBackend : public RISCVAsmBackend { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. COFF rather than Windows?... AFAIK there is no Windows for RISC-V in existence anywhere, but PE/COFF is broader than Windows and does exist. |
||
bool is64Bit; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. RISCVAsmBackend already has an Is64Bit member you can just read in createObjectTargetWriter |
||
|
||
public: | ||
WindowsRISCVAsmBackend(const Target &T, const MCSubtargetInfo &STI, | ||
const MCRegisterInfo &MRI, | ||
const MCTargetOptions &Options) | ||
: RISCVAsmBackend( | ||
STI, | ||
MCELFObjectTargetWriter::getOSABI(STI.getTargetTriple().getOS()), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems dubious |
||
STI.getTargetTriple().isArch64Bit(), Options) { | ||
is64Bit = STI.getTargetTriple().isArch64Bit(); | ||
} | ||
|
||
std::unique_ptr<MCObjectTargetWriter> | ||
createObjectTargetWriter() const override { | ||
return createRISCVWinCOFFObjectWriter(is64Bit); | ||
} | ||
}; | ||
|
||
} // namespace | ||
|
||
std::unique_ptr<MCObjectTargetWriter> | ||
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()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are no Windows RISC-V systems. Why is this not just isOSBinFormatCOFF like AArch64? |
||
return new WindowsRISCVAsmBackend(T, STI, MRI, Options); | ||
} | ||
|
||
uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS()); | ||
return new RISCVAsmBackend(STI, OSABI, TT.isArch64Bit(), Options); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AArch64 calls this AArch64MCAsmInfoGNUCOFF |
||
void anchor() override; | ||
|
||
public: | ||
explicit RISCVCOFFMCAsmInfo(); | ||
}; | ||
|
||
namespace RISCV { | ||
using Specifier = uint16_t; | ||
// Specifiers mapping to relocation types below FirstTargetFixupKind are | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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(); | ||
Comment on lines
+71
to
+72
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Confused between Windows and PE/COFF again, not to mention the obvious formatting problems |
||
} 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); | ||
Comment on lines
+126
to
+127
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ditto |
||
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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Formatting? |
||
TargetRegistry::RegisterObjectTargetStreamer( | ||
*T, createRISCVObjectTargetStreamer); | ||
TargetRegistry::RegisterMCInstrAnalysis(*T, createRISCVInstrAnalysis); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<MCObjectTargetWriter> | ||
llvm::createRISCVWinCOFFObjectWriter(bool Is64Bit) { | ||
return std::make_unique<RISCVWinCOFFObjectWriter>(Is64Bit); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<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::createRISCVWinCOFFStreamer( | ||
MCContext &C, std::unique_ptr<MCAsmBackend> &&AB, | ||
std::unique_ptr<MCObjectWriter> &&OW, std::unique_ptr<MCCodeEmitter> &&CE) { | ||
return new RISCVWinCOFFStreamer(C, std::move(AB), std::move(CE), | ||
std::move(OW)); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This adds both Darwin and Win32 support, but AFAIK UEFI is the only extra case that should be handled? |
||
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: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like IMAGE_REL_BASED_RISCV_HI20 already appears in other code according to google.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well they're wrong... https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#base-relocation-types is the canonical location for the specification and is as I wrote