[llvm] [MC][Mips] Add MipsWinCOFFObjectWriter/MipsWinCOFFStreamer (PR #114611)
Hervé Poussineau via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 1 15:06:18 PDT 2024
https://github.com/hpoussin created https://github.com/llvm/llvm-project/pull/114611
llc is now able to create MIPS COFF files for simple cases.
>From 97455c223b8104d153828008541ce68f5fcd32e2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= <hpoussin at reactos.org>
Date: Sun, 22 Oct 2023 09:07:52 +0200
Subject: [PATCH] [MC][Mips] Add MipsWinCOFFObjectWriter/MipsWinCOFFStreamer
---
.../Target/Mips/MCTargetDesc/CMakeLists.txt | 2 +
.../Mips/MCTargetDesc/MipsAsmBackend.cpp | 20 +++++++
.../Mips/MCTargetDesc/MipsMCAsmInfo.cpp | 11 ++++
.../Target/Mips/MCTargetDesc/MipsMCAsmInfo.h | 8 +++
.../Mips/MCTargetDesc/MipsMCTargetDesc.cpp | 18 +++++-
.../Mips/MCTargetDesc/MipsMCTargetDesc.h | 14 +++++
.../MCTargetDesc/MipsWinCOFFObjectWriter.cpp | 57 +++++++++++++++++++
.../Mips/MCTargetDesc/MipsWinCOFFStreamer.cpp | 33 +++++++++++
llvm/lib/Target/Mips/MipsTargetMachine.cpp | 2 +
llvm/test/MC/Mips/coff-basic.ll | 7 +++
llvm/test/MC/Mips/coff-relocs.ll | 42 ++++++++++++++
11 files changed, 213 insertions(+), 1 deletion(-)
create mode 100644 llvm/lib/Target/Mips/MCTargetDesc/MipsWinCOFFObjectWriter.cpp
create mode 100644 llvm/lib/Target/Mips/MCTargetDesc/MipsWinCOFFStreamer.cpp
create mode 100644 llvm/test/MC/Mips/coff-basic.ll
create mode 100644 llvm/test/MC/Mips/coff-relocs.ll
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/Mips/MCTargetDesc/CMakeLists.txt
index 97a6f886d114ec..d3f16e5042c3ac 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/CMakeLists.txt
+++ b/llvm/lib/Target/Mips/MCTargetDesc/CMakeLists.txt
@@ -12,6 +12,8 @@ add_llvm_component_library(LLVMMipsDesc
MipsNaClELFStreamer.cpp
MipsOptionRecord.cpp
MipsTargetStreamer.cpp
+ MipsWinCOFFObjectWriter.cpp
+ MipsWinCOFFStreamer.cpp
LINK_COMPONENTS
CodeGenTypes
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
index f8172e576ce4c1..c40372995a9126 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
@@ -597,10 +597,30 @@ bool MipsAsmBackend::isMicroMips(const MCSymbol *Sym) const {
return false;
}
+namespace {
+
+class WindowsMipsAsmBackend : public MipsAsmBackend {
+public:
+ WindowsMipsAsmBackend(const Target &T, const MCRegisterInfo &MRI,
+ const MCSubtargetInfo &STI)
+ : MipsAsmBackend(T, MRI, STI.getTargetTriple(), STI.getCPU(), false) {}
+
+ std::unique_ptr<MCObjectTargetWriter>
+ createObjectTargetWriter() const override {
+ return createMipsWinCOFFObjectWriter();
+ }
+};
+
+} // end anonymous namespace
+
MCAsmBackend *llvm::createMipsAsmBackend(const Target &T,
const MCSubtargetInfo &STI,
const MCRegisterInfo &MRI,
const MCTargetOptions &Options) {
+ const Triple &TheTriple = STI.getTargetTriple();
+ if (TheTriple.isOSWindows() && TheTriple.isOSBinFormatCOFF())
+ return new WindowsMipsAsmBackend(T, MRI, STI);
+
MipsABIInfo ABI = MipsABIInfo::computeTargetABI(STI.getTargetTriple(),
STI.getCPU(), Options);
return new MipsAsmBackend(T, MRI, STI.getTargetTriple(), STI.getCPU(),
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
index 074a58cadb556d..fa09a14b3e2380 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
@@ -51,3 +51,14 @@ MipsELFMCAsmInfo::MipsELFMCAsmInfo(const Triple &TheTriple,
DwarfRegNumForCFI = true;
HasMipsExpressions = true;
}
+
+void MipsCOFFMCAsmInfo::anchor() {}
+
+MipsCOFFMCAsmInfo::MipsCOFFMCAsmInfo() {
+ HasSingleParameterDotFile = true;
+ WinEHEncodingType = WinEH::EncodingType::Itanium;
+
+ ExceptionsType = ExceptionHandling::WinEH;
+
+ AllowAtInName = true;
+}
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h
index b52ed12d3a0e77..3a2895a79f9c7f 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h
@@ -13,6 +13,7 @@
#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCASMINFO_H
#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSMCASMINFO_H
+#include "llvm/MC/MCAsmInfoCOFF.h"
#include "llvm/MC/MCAsmInfoELF.h"
namespace llvm {
@@ -26,6 +27,13 @@ class MipsELFMCAsmInfo : public MCAsmInfoELF {
const MCTargetOptions &Options);
};
+class MipsCOFFMCAsmInfo : public MCAsmInfoGNUCOFF {
+ void anchor() override;
+
+public:
+ explicit MipsCOFFMCAsmInfo();
+};
+
} // namespace llvm
#endif
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
index eff9ecf0d53d31..2d44a8582b1364 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
@@ -45,6 +45,13 @@ using namespace llvm;
#define GET_REGINFO_MC_DESC
#include "MipsGenRegisterInfo.inc"
+namespace {
+class MipsWinCOFFTargetStreamer : public MipsTargetStreamer {
+public:
+ MipsWinCOFFTargetStreamer(MCStreamer &S) : MipsTargetStreamer(S) {}
+};
+} // end namespace
+
/// Select the Mips CPU for the given triple and cpu name.
StringRef MIPS_MC::selectMipsCPU(const Triple &TT, StringRef CPU) {
if (CPU.empty() || CPU == "generic") {
@@ -84,7 +91,12 @@ static MCSubtargetInfo *createMipsMCSubtargetInfo(const Triple &TT,
static MCAsmInfo *createMipsMCAsmInfo(const MCRegisterInfo &MRI,
const Triple &TT,
const MCTargetOptions &Options) {
- MCAsmInfo *MAI = new MipsELFMCAsmInfo(TT, Options);
+ MCAsmInfo *MAI;
+
+ if (TT.isOSWindows())
+ MAI = new MipsCOFFMCAsmInfo();
+ else
+ MAI = new MipsELFMCAsmInfo(TT, Options);
unsigned SP = MRI.getDwarfRegNum(Mips::SP, true);
MCCFIInstruction Inst = MCCFIInstruction::createDefCfaRegister(nullptr, SP);
@@ -127,6 +139,8 @@ static MCTargetStreamer *createMipsNullTargetStreamer(MCStreamer &S) {
static MCTargetStreamer *
createMipsObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
+ if (STI.getTargetTriple().isOSBinFormatCOFF())
+ return new MipsWinCOFFTargetStreamer(S);
return new MipsTargetELFStreamer(S, STI);
}
@@ -186,6 +200,8 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMipsTargetMC() {
TargetRegistry::RegisterNullTargetStreamer(*T,
createMipsNullTargetStreamer);
+ TargetRegistry::RegisterCOFFStreamer(*T, createMipsWinCOFFStreamer);
+
// Register the MC subtarget info.
TargetRegistry::RegisterMCSubtargetInfo(*T, createMipsMCSubtargetInfo);
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h
index d51f3b9abcfd1b..c5293b03b0ac5a 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h
@@ -23,7 +23,9 @@ class MCCodeEmitter;
class MCContext;
class MCInstrInfo;
class MCObjectTargetWriter;
+class MCObjectWriter;
class MCRegisterInfo;
+class MCStreamer;
class MCSubtargetInfo;
class MCTargetOptions;
class StringRef;
@@ -39,8 +41,20 @@ MCAsmBackend *createMipsAsmBackend(const Target &T, const MCSubtargetInfo &STI,
const MCRegisterInfo &MRI,
const MCTargetOptions &Options);
+/// Construct an MIPS Windows COFF machine code streamer which will generate
+/// PE/COFF format object files.
+///
+/// Takes ownership of \p AB and \p CE.
+MCStreamer *createMipsWinCOFFStreamer(MCContext &C,
+ std::unique_ptr<MCAsmBackend> &&AB,
+ std::unique_ptr<MCObjectWriter> &&OW,
+ std::unique_ptr<MCCodeEmitter> &&CE);
+
+/// Construct a Mips ELF object writer.
std::unique_ptr<MCObjectTargetWriter>
createMipsELFObjectWriter(const Triple &TT, bool IsN32);
+/// Construct a Mips Win COFF object writer.
+std::unique_ptr<MCObjectTargetWriter> createMipsWinCOFFObjectWriter();
namespace MIPS_MC {
StringRef selectMipsCPU(const Triple &TT, StringRef CPU);
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsWinCOFFObjectWriter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsWinCOFFObjectWriter.cpp
new file mode 100644
index 00000000000000..94187c71ba70d6
--- /dev/null
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsWinCOFFObjectWriter.cpp
@@ -0,0 +1,57 @@
+//===- MipsWinCOFFObjectWriter.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/MipsFixupKinds.h"
+#include "MCTargetDesc/MipsMCTargetDesc.h"
+#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCWinCOFFObjectWriter.h"
+
+using namespace llvm;
+
+namespace {
+
+class MipsWinCOFFObjectWriter : public MCWinCOFFObjectTargetWriter {
+public:
+ MipsWinCOFFObjectWriter();
+
+ unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
+ const MCFixup &Fixup, bool IsCrossSection,
+ const MCAsmBackend &MAB) const override;
+};
+
+} // end anonymous namespace
+
+MipsWinCOFFObjectWriter::MipsWinCOFFObjectWriter()
+ : MCWinCOFFObjectTargetWriter(COFF::IMAGE_FILE_MACHINE_R4000) {}
+
+unsigned MipsWinCOFFObjectWriter::getRelocType(MCContext &Ctx,
+ const MCValue &Target,
+ const MCFixup &Fixup,
+ bool IsCrossSection,
+ const MCAsmBackend &MAB) const {
+ unsigned FixupKind = Fixup.getKind();
+
+ switch (FixupKind) {
+ case FK_Data_4:
+ return COFF::IMAGE_REL_MIPS_REFWORD;
+ case Mips::fixup_Mips_26:
+ return COFF::IMAGE_REL_MIPS_JMPADDR;
+ case Mips::fixup_Mips_HI16:
+ return COFF::IMAGE_REL_MIPS_REFHI;
+ case Mips::fixup_Mips_LO16:
+ return COFF::IMAGE_REL_MIPS_REFLO;
+ default:
+ Ctx.reportError(Fixup.getLoc(), "unsupported relocation type");
+ return COFF::IMAGE_REL_MIPS_REFWORD;
+ }
+}
+
+std::unique_ptr<MCObjectTargetWriter> llvm::createMipsWinCOFFObjectWriter() {
+ return std::make_unique<MipsWinCOFFObjectWriter>();
+}
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsWinCOFFStreamer.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsWinCOFFStreamer.cpp
new file mode 100644
index 00000000000000..22bf2e1be203cf
--- /dev/null
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsWinCOFFStreamer.cpp
@@ -0,0 +1,33 @@
+//===- MipsWinCOFFStreamer.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 "MipsMCTargetDesc.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 MipsWinCOFFStreamer : public MCWinCOFFStreamer {
+public:
+ MipsWinCOFFStreamer(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::createMipsWinCOFFStreamer(
+ MCContext &C, std::unique_ptr<MCAsmBackend> &&AB,
+ std::unique_ptr<MCObjectWriter> &&OW, std::unique_ptr<MCCodeEmitter> &&CE) {
+ return new MipsWinCOFFStreamer(C, std::move(AB), std::move(CE),
+ std::move(OW));
+}
diff --git a/llvm/lib/Target/Mips/MipsTargetMachine.cpp b/llvm/lib/Target/Mips/MipsTargetMachine.cpp
index c7dbcc80148ae4..a98f636d5d867a 100644
--- a/llvm/lib/Target/Mips/MipsTargetMachine.cpp
+++ b/llvm/lib/Target/Mips/MipsTargetMachine.cpp
@@ -71,6 +71,8 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMipsTarget() {
}
static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {
+ if (TT.isOSBinFormatCOFF())
+ return std::make_unique<TargetLoweringObjectFileCOFF>();
return std::make_unique<MipsTargetObjectFile>();
}
diff --git a/llvm/test/MC/Mips/coff-basic.ll b/llvm/test/MC/Mips/coff-basic.ll
new file mode 100644
index 00000000000000..4c25cd659c5c79
--- /dev/null
+++ b/llvm/test/MC/Mips/coff-basic.ll
@@ -0,0 +1,7 @@
+; RUN: llc -mtriple mipsel-windows -filetype=obj < %s | obj2yaml | FileCheck %s
+
+define i32 @foo() {
+ ret i32 0
+}
+
+; CHECK: Machine: IMAGE_FILE_MACHINE_R4000
diff --git a/llvm/test/MC/Mips/coff-relocs.ll b/llvm/test/MC/Mips/coff-relocs.ll
new file mode 100644
index 00000000000000..1d8b3f192d7af6
--- /dev/null
+++ b/llvm/test/MC/Mips/coff-relocs.ll
@@ -0,0 +1,42 @@
+; RUN: llc -mtriple mipsel-windows -filetype=obj < %s | obj2yaml | FileCheck %s
+
+; CHECK: Machine: IMAGE_FILE_MACHINE_R4000
+
+
+
+; CHECK: - Name: .text
+; CHECK: Relocations:
+
+declare void @bar()
+define i32 @foo_jmp() {
+ call i32 @bar()
+; CHECK: - VirtualAddress: 8
+; CHECK: SymbolName: bar
+; CHECK: Type: IMAGE_REL_MIPS_JMPADDR
+ ret i32 0
+}
+
+ at var = external global i32
+define i32 @foo_var() {
+ %1 = load i32, i32* @var
+; CHECK: - VirtualAddress: 32
+; CHECK: SymbolName: var
+; CHECK: Type: IMAGE_REL_MIPS_REFHI
+; CHECK: - VirtualAddress: 40
+; CHECK: SymbolName: var
+; CHECK: Type: IMAGE_REL_MIPS_REFLO
+ ret i32 %1
+}
+
+
+
+; CHECK: - Name: .data
+; CHECK: Relocations:
+
+%struct._PTR = type { ptr }
+
+ at var1 = internal global %struct._PTR { ptr @var2 }
+ at var2 = external global i32
+; CHECK: - VirtualAddress: 0
+; CHECK: SymbolName: var2
+; CHECK: Type: IMAGE_REL_MIPS_REFWORD
More information about the llvm-commits
mailing list