[lld] [llvm] [clang][MIPS] Add support for mipsel-windows-* targets (PR #107744)

via llvm-commits llvm-commits at lists.llvm.org
Sun Sep 8 09:36:45 PDT 2024


=?utf-8?q?Hervé?= Poussineau <hpoussin at reactos.org>,
=?utf-8?q?Hervé?= Poussineau <hpoussin at reactos.org>,
=?utf-8?q?Hervé?= Poussineau <hpoussin at reactos.org>,
=?utf-8?q?Hervé?= Poussineau <hpoussin at reactos.org>,
=?utf-8?q?Hervé?= Poussineau <hpoussin at reactos.org>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/107744 at github.com>


https://github.com/hpoussin updated https://github.com/llvm/llvm-project/pull/107744

>From 193f3d3d60c2c9742db50dcb47d689b7968b08d9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= <hpoussin at reactos.org>
Date: Sun, 22 Oct 2023 07:19:08 +0200
Subject: [PATCH 1/6] [Triple] Make mipsel-*-windows-* use COFF files by
 default

Windows NT/MIPS and Windows CE/MIPS always used COFF format.
---
 llvm/lib/TargetParser/Triple.cpp           | 6 +++++-
 llvm/unittests/TargetParser/TripleTest.cpp | 3 +++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp
index 55911a7d71ac70..18e2d4fa465f8f 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -905,7 +905,6 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) {
   case Triple::mips64:
   case Triple::mips64el:
   case Triple::mips:
-  case Triple::mipsel:
   case Triple::msp430:
   case Triple::nvptx64:
   case Triple::nvptx:
@@ -930,6 +929,11 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) {
   case Triple::xtensa:
     return Triple::ELF;
 
+  case Triple::mipsel:
+    if (T.isOSWindows())
+      return Triple::COFF;
+    return Triple::ELF;
+
   case Triple::ppc64:
   case Triple::ppc:
     if (T.isOSAIX())
diff --git a/llvm/unittests/TargetParser/TripleTest.cpp b/llvm/unittests/TargetParser/TripleTest.cpp
index 0aecfc64da2080..1beb52088941e9 100644
--- a/llvm/unittests/TargetParser/TripleTest.cpp
+++ b/llvm/unittests/TargetParser/TripleTest.cpp
@@ -2302,6 +2302,9 @@ TEST(TripleTest, NormalizeWindows) {
             Triple::normalize("i686-pc-windows-elf-elf"));
 
   EXPECT_TRUE(Triple("x86_64-pc-win32").isWindowsMSVCEnvironment());
+
+  EXPECT_TRUE(Triple(Triple::normalize("mipsel-windows-msvccoff")).isOSBinFormatCOFF());
+  EXPECT_TRUE(Triple(Triple::normalize("mipsel-windows-msvc")).isOSBinFormatCOFF());
 }
 
 TEST(TripleTest, NormalizeAndroid) {

>From f99b2ea9f3f744500acaab0c05a346250e0e7751 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= <hpoussin at reactos.org>
Date: Sun, 22 Oct 2023 07:30:37 +0200
Subject: [PATCH 2/6] [COFF] Add MIPS relocation types

Add the MIPS COFF relocation types. They will be needed to add support for
MIPS Windows object file.
---
 llvm/include/llvm/BinaryFormat/COFF.h | 18 ++++++++++++++++++
 llvm/lib/Object/COFFObjectFile.cpp    | 21 +++++++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/llvm/include/llvm/BinaryFormat/COFF.h b/llvm/include/llvm/BinaryFormat/COFF.h
index 3fc543f73c49db..bbc5264d17872a 100644
--- a/llvm/include/llvm/BinaryFormat/COFF.h
+++ b/llvm/include/llvm/BinaryFormat/COFF.h
@@ -417,6 +417,24 @@ enum RelocationTypesARM64 : unsigned {
   IMAGE_REL_ARM64_REL32 = 0x0011,
 };
 
+enum RelocationTypesMips : unsigned {
+  IMAGE_REL_MIPS_ABSOLUTE = 0x0000,
+  IMAGE_REL_MIPS_REFHALF = 0x0001,
+  IMAGE_REL_MIPS_REFWORD = 0x0002,
+  IMAGE_REL_MIPS_JMPADDR = 0x0003,
+  IMAGE_REL_MIPS_REFHI = 0x0004,
+  IMAGE_REL_MIPS_REFLO = 0x0005,
+  IMAGE_REL_MIPS_GPREL = 0x0006,
+  IMAGE_REL_MIPS_LITERAL = 0x0007,
+  IMAGE_REL_MIPS_SECTION = 0x000A,
+  IMAGE_REL_MIPS_SECREL = 0x000B,
+  IMAGE_REL_MIPS_SECRELLO = 0x000C,
+  IMAGE_REL_MIPS_SECRELHI = 0x000D,
+  IMAGE_REL_MIPS_JMPADDR16 = 0x0010,
+  IMAGE_REL_MIPS_REFWORDNB = 0x0022,
+  IMAGE_REL_MIPS_PAIR = 0x0025,
+};
+
 enum DynamicRelocationType : unsigned {
   IMAGE_DYNAMIC_RELOCATION_GUARD_RF_PROLOGUE = 1,
   IMAGE_DYNAMIC_RELOCATION_GUARD_RF_EPILOGUE = 2,
diff --git a/llvm/lib/Object/COFFObjectFile.cpp b/llvm/lib/Object/COFFObjectFile.cpp
index 5fdf3baf8c02cc..f55138bb23907a 100644
--- a/llvm/lib/Object/COFFObjectFile.cpp
+++ b/llvm/lib/Object/COFFObjectFile.cpp
@@ -1465,6 +1465,27 @@ StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {
       return "Unknown";
     }
     break;
+  case Triple::mipsel:
+    switch (Type) {
+    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_ABSOLUTE);
+    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_REFHALF);
+    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_REFWORD);
+    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_JMPADDR);
+    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_REFHI);
+    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_REFLO);
+    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_GPREL);
+    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_LITERAL);
+    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_SECTION);
+    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_SECREL);
+    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_SECRELLO);
+    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_SECRELHI);
+    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_JMPADDR16);
+    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_REFWORDNB);
+    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_MIPS_PAIR);
+    default:
+      return "Unknown";
+    }
+    break;
   default:
     return "Unknown";
   }

>From db61c9193d3e7c6eeffce98314d349fa94d0381d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= <hpoussin at reactos.org>
Date: Sun, 22 Oct 2023 08:00:06 +0200
Subject: [PATCH 3/6] [yaml2obj][objdump] Handle IMAGE_FILE_MACHINE_R4000
 machine type and MIPS COFF relocations

llvm-objdump can now parse MIPS COFF files.
---
 lld/COFF/Config.h                             |  1 +
 llvm/include/llvm/Object/WindowsMachineFlag.h |  2 ++
 llvm/include/llvm/ObjectYAML/COFFYAML.h       |  5 ++++
 llvm/lib/Object/COFFObjectFile.cpp            |  2 ++
 llvm/lib/Object/WindowsMachineFlag.cpp        |  4 ++++
 llvm/lib/ObjectYAML/COFFYAML.cpp              | 23 +++++++++++++++++++
 llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp   |  3 +++
 llvm/test/Object/Inputs/COFF/mipsel.yaml      |  8 +++++++
 llvm/test/Object/objdump-section-content.test |  4 ++++
 9 files changed, 52 insertions(+)
 create mode 100644 llvm/test/Object/Inputs/COFF/mipsel.yaml

diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h
index 947f3fead54e03..a7984753c7e917 100644
--- a/lld/COFF/Config.h
+++ b/lld/COFF/Config.h
@@ -40,6 +40,7 @@ static const auto ARM64EC = llvm::COFF::IMAGE_FILE_MACHINE_ARM64EC;
 static const auto ARM64X = llvm::COFF::IMAGE_FILE_MACHINE_ARM64X;
 static const auto ARMNT = llvm::COFF::IMAGE_FILE_MACHINE_ARMNT;
 static const auto I386 = llvm::COFF::IMAGE_FILE_MACHINE_I386;
+static const auto MIPS = llvm::COFF::IMAGE_FILE_MACHINE_R4000;
 
 enum class ExportSource {
   Unset,
diff --git a/llvm/include/llvm/Object/WindowsMachineFlag.h b/llvm/include/llvm/Object/WindowsMachineFlag.h
index 1cb408ed13d420..ce5b356f8bfeed 100644
--- a/llvm/include/llvm/Object/WindowsMachineFlag.h
+++ b/llvm/include/llvm/Object/WindowsMachineFlag.h
@@ -43,6 +43,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_R4000:
+    return llvm::Triple::ArchType::mipsel;
   default:
     return llvm::Triple::ArchType::UnknownArch;
   }
diff --git a/llvm/include/llvm/ObjectYAML/COFFYAML.h b/llvm/include/llvm/ObjectYAML/COFFYAML.h
index 2f9a1aae0eb05a..f7797fc7f67bcd 100644
--- a/llvm/include/llvm/ObjectYAML/COFFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/COFFYAML.h
@@ -179,6 +179,11 @@ struct ScalarEnumerationTraits<COFF::RelocationTypeAMD64> {
   static void enumeration(IO &IO, COFF::RelocationTypeAMD64 &Value);
 };
 
+template <>
+struct ScalarEnumerationTraits<COFF::RelocationTypesMips> {
+  static void enumeration(IO &IO, COFF::RelocationTypesMips &Value);
+};
+
 template <>
 struct ScalarEnumerationTraits<COFF::RelocationTypesARM> {
   static void enumeration(IO &IO, COFF::RelocationTypesARM &Value);
diff --git a/llvm/lib/Object/COFFObjectFile.cpp b/llvm/lib/Object/COFFObjectFile.cpp
index f55138bb23907a..4b3999126c89fb 100644
--- a/llvm/lib/Object/COFFObjectFile.cpp
+++ b/llvm/lib/Object/COFFObjectFile.cpp
@@ -1132,6 +1132,8 @@ StringRef COFFObjectFile::getFileFormatName() const {
     return "COFF-ARM64EC";
   case COFF::IMAGE_FILE_MACHINE_ARM64X:
     return "COFF-ARM64X";
+  case COFF::IMAGE_FILE_MACHINE_R4000:
+    return "COFF-R4000";
   default:
     return "COFF-<unknown arch>";
   }
diff --git a/llvm/lib/Object/WindowsMachineFlag.cpp b/llvm/lib/Object/WindowsMachineFlag.cpp
index b9f818775768a2..bade2d4f0f6a74 100644
--- a/llvm/lib/Object/WindowsMachineFlag.cpp
+++ b/llvm/lib/Object/WindowsMachineFlag.cpp
@@ -28,6 +28,8 @@ COFF::MachineTypes llvm::getMachineType(StringRef S) {
       .Case("arm64", COFF::IMAGE_FILE_MACHINE_ARM64)
       .Case("arm64ec", COFF::IMAGE_FILE_MACHINE_ARM64EC)
       .Case("arm64x", COFF::IMAGE_FILE_MACHINE_ARM64X)
+      .Case("mips", COFF::IMAGE_FILE_MACHINE_R4000) // also handle mips (big-endian) because we want to support '/machine:MIPS'
+      .Case("mipsel", COFF::IMAGE_FILE_MACHINE_R4000)
       .Default(COFF::IMAGE_FILE_MACHINE_UNKNOWN);
 }
 
@@ -45,6 +47,8 @@ StringRef llvm::machineToStr(COFF::MachineTypes MT) {
     return "x64";
   case COFF::IMAGE_FILE_MACHINE_I386:
     return "x86";
+  case COFF::IMAGE_FILE_MACHINE_R4000:
+    return "mipsel";
   default:
     llvm_unreachable("unknown machine type");
   }
diff --git a/llvm/lib/ObjectYAML/COFFYAML.cpp b/llvm/lib/ObjectYAML/COFFYAML.cpp
index e14e1b5e467b41..53ea40a0354cea 100644
--- a/llvm/lib/ObjectYAML/COFFYAML.cpp
+++ b/llvm/lib/ObjectYAML/COFFYAML.cpp
@@ -183,6 +183,25 @@ void ScalarEnumerationTraits<COFF::RelocationTypeAMD64>::enumeration(
   ECase(IMAGE_REL_AMD64_SSPAN32);
 }
 
+void ScalarEnumerationTraits<COFF::RelocationTypesMips>::enumeration(
+    IO &IO, COFF::RelocationTypesMips &Value) {
+  ECase(IMAGE_REL_MIPS_ABSOLUTE);
+  ECase(IMAGE_REL_MIPS_REFHALF);
+  ECase(IMAGE_REL_MIPS_REFWORD);
+  ECase(IMAGE_REL_MIPS_JMPADDR);
+  ECase(IMAGE_REL_MIPS_REFHI);
+  ECase(IMAGE_REL_MIPS_REFLO);
+  ECase(IMAGE_REL_MIPS_GPREL);
+  ECase(IMAGE_REL_MIPS_LITERAL);
+  ECase(IMAGE_REL_MIPS_SECTION);
+  ECase(IMAGE_REL_MIPS_SECREL);
+  ECase(IMAGE_REL_MIPS_SECRELLO);
+  ECase(IMAGE_REL_MIPS_SECRELHI);
+  ECase(IMAGE_REL_MIPS_JMPADDR16);
+  ECase(IMAGE_REL_MIPS_REFWORDNB);
+  ECase(IMAGE_REL_MIPS_PAIR);
+}
+
 void ScalarEnumerationTraits<COFF::RelocationTypesARM>::enumeration(
     IO &IO, COFF::RelocationTypesARM &Value) {
   ECase(IMAGE_REL_ARM_ABSOLUTE);
@@ -427,6 +446,10 @@ void MappingTraits<COFFYAML::Relocation>::mapping(IO &IO,
     MappingNormalization<NType<COFF::RelocationTypeAMD64>, uint16_t> NT(
         IO, Rel.Type);
     IO.mapRequired("Type", NT->Type);
+  } else if (H.Machine == COFF::IMAGE_FILE_MACHINE_R4000) {
+    MappingNormalization<NType<COFF::RelocationTypesMips>, uint16_t> NT(
+        IO, Rel.Type);
+    IO.mapRequired("Type", NT->Type);
   } else if (H.Machine == COFF::IMAGE_FILE_MACHINE_ARMNT) {
     MappingNormalization<NType<COFF::RelocationTypesARM>, uint16_t> NT(
         IO, Rel.Type);
diff --git a/llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp b/llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp
index e1d2700623ec3c..26d71e624aee5b 100644
--- a/llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp
+++ b/llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp
@@ -171,6 +171,9 @@ void ScalarEnumerationTraits<RegisterId>::enumeration(IO &io, RegisterId &Reg) {
   case COFF::IMAGE_FILE_MACHINE_ARM64X:
     CpuType = CPUType::ARM64;
     break;
+  case COFF::IMAGE_FILE_MACHINE_R4000:
+    CpuType = CPUType::MIPSIII;
+    break;
   }
 
   if (CpuType)
diff --git a/llvm/test/Object/Inputs/COFF/mipsel.yaml b/llvm/test/Object/Inputs/COFF/mipsel.yaml
new file mode 100644
index 00000000000000..0d23dfb77ac0bf
--- /dev/null
+++ b/llvm/test/Object/Inputs/COFF/mipsel.yaml
@@ -0,0 +1,8 @@
+!COFF
+header: !Header
+  Machine: IMAGE_FILE_MACHINE_R4000 # (0x166)
+  Characteristics: [ IMAGE_FILE_DEBUG_STRIPPED ]
+
+sections:
+
+symbols:
diff --git a/llvm/test/Object/objdump-section-content.test b/llvm/test/Object/objdump-section-content.test
index d4c2cd8190b7c1..ce084677a980bf 100644
--- a/llvm/test/Object/objdump-section-content.test
+++ b/llvm/test/Object/objdump-section-content.test
@@ -39,3 +39,7 @@ Sections:
 
 # BSS: Contents of section .bss:
 # BSS-NEXT: <skipping contents of bss section at [12c8, 12cc)>
+
+# RUN: yaml2obj %p/Inputs/COFF/mipsel.yaml | llvm-objdump -s - | FileCheck %s --check-prefix=COFF-R4000
+
+# COFF-R4000: <stdin>:     file format coff-r4000

>From 38bcda668912f9c6e9b899daba9666482c069c2b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= <hpoussin at reactos.org>
Date: Sun, 22 Oct 2023 08:12:10 +0200
Subject: [PATCH 4/6] [MC][Mips] Rename MipsMCAsmInfo to MipsELFMCAsmInfo

Also change MipsAsmPrinter::emitStartOfAsmFile to emit ELF-related
sections only when using ELF output file format.
---
 .../Mips/MCTargetDesc/MipsMCAsmInfo.cpp       |   6 +-
 .../Target/Mips/MCTargetDesc/MipsMCAsmInfo.h  |   6 +-
 .../Mips/MCTargetDesc/MipsMCTargetDesc.cpp    |   2 +-
 llvm/lib/Target/Mips/MipsAsmPrinter.cpp       | 115 +++++++++---------
 llvm/lib/Target/Mips/MipsTargetMachine.cpp    |   6 +-
 5 files changed, 71 insertions(+), 64 deletions(-)

diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
index f89c78e75d3ee7..c112b3abe0ba75 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
@@ -16,10 +16,10 @@
 
 using namespace llvm;
 
-void MipsMCAsmInfo::anchor() { }
+void MipsELFMCAsmInfo::anchor() { }
 
-MipsMCAsmInfo::MipsMCAsmInfo(const Triple &TheTriple,
-                             const MCTargetOptions &Options) {
+MipsELFMCAsmInfo::MipsELFMCAsmInfo(const Triple &TheTriple,
+                                   const MCTargetOptions &Options) {
   IsLittleEndian = TheTriple.isLittleEndian();
 
   MipsABIInfo ABI = MipsABIInfo::computeTargetABI(TheTriple, "", Options);
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h
index d8bfe58d24a838..b52ed12d3a0e77 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h
@@ -18,12 +18,12 @@
 namespace llvm {
 class Triple;
 
-class MipsMCAsmInfo : public MCAsmInfoELF {
+class MipsELFMCAsmInfo : public MCAsmInfoELF {
   void anchor() override;
 
 public:
-  explicit MipsMCAsmInfo(const Triple &TheTriple,
-                         const MCTargetOptions &Options);
+  explicit MipsELFMCAsmInfo(const Triple &TheTriple,
+                            const MCTargetOptions &Options);
 };
 
 } // namespace llvm
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
index ca95f67174da1e..eff9ecf0d53d31 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
@@ -84,7 +84,7 @@ static MCSubtargetInfo *createMipsMCSubtargetInfo(const Triple &TT,
 static MCAsmInfo *createMipsMCAsmInfo(const MCRegisterInfo &MRI,
                                       const Triple &TT,
                                       const MCTargetOptions &Options) {
-  MCAsmInfo *MAI = new MipsMCAsmInfo(TT, Options);
+  MCAsmInfo *MAI = new MipsELFMCAsmInfo(TT, Options);
 
   unsigned SP = MRI.getDwarfRegNum(Mips::SP, true);
   MCCFIInstruction Inst = MCCFIInstruction::createDefCfaRegister(nullptr, SP);
diff --git a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp
index e267a6d0844c64..89b79693a83dcf 100644
--- a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp
+++ b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp
@@ -734,70 +734,73 @@ printRegisterList(const MachineInstr *MI, int opNum, raw_ostream &O) {
 }
 
 void MipsAsmPrinter::emitStartOfAsmFile(Module &M) {
-  MipsTargetStreamer &TS = getTargetStreamer();
-
-  // MipsTargetStreamer has an initialization order problem when emitting an
-  // object file directly (see MipsTargetELFStreamer for full details). Work
-  // around it by re-initializing the PIC state here.
-  TS.setPic(OutContext.getObjectFileInfo()->isPositionIndependent());
-
-  // Try to get target-features from the first function.
-  StringRef FS = TM.getTargetFeatureString();
-  Module::iterator F = M.begin();
-  if (FS.empty() && M.size() && F->hasFnAttribute("target-features"))
-    FS = F->getFnAttribute("target-features").getValueAsString();
-
-  // Compute MIPS architecture attributes based on the default subtarget
-  // that we'd have constructed.
-  // FIXME: For ifunc related functions we could iterate over and look
-  // for a feature string that doesn't match the default one.
   const Triple &TT = TM.getTargetTriple();
-  StringRef CPU = MIPS_MC::selectMipsCPU(TT, TM.getTargetCPU());
-  const MipsTargetMachine &MTM = static_cast<const MipsTargetMachine &>(TM);
-  const MipsSubtarget STI(TT, CPU, FS, MTM.isLittleEndian(), MTM, std::nullopt);
-
-  bool IsABICalls = STI.isABICalls();
-  const MipsABIInfo &ABI = MTM.getABI();
-  if (IsABICalls) {
-    TS.emitDirectiveAbiCalls();
-    // FIXME: This condition should be a lot more complicated that it is here.
-    //        Ideally it should test for properties of the ABI and not the ABI
-    //        itself.
-    //        For the moment, I'm only correcting enough to make MIPS-IV work.
-    if (!isPositionIndependent() && STI.hasSym32())
-      TS.emitDirectiveOptionPic0();
-  }
 
-  // Tell the assembler which ABI we are using
-  std::string SectionName = std::string(".mdebug.") + getCurrentABIString();
-  OutStreamer->switchSection(
-      OutContext.getELFSection(SectionName, ELF::SHT_PROGBITS, 0));
+  if (TT.isOSBinFormatELF()) {
+    MipsTargetStreamer &TS = getTargetStreamer();
+
+    // MipsTargetStreamer has an initialization order problem when emitting an
+    // object file directly (see MipsTargetELFStreamer for full details). Work
+    // around it by re-initializing the PIC state here.
+    TS.setPic(OutContext.getObjectFileInfo()->isPositionIndependent());
+
+    // Try to get target-features from the first function.
+    StringRef FS = TM.getTargetFeatureString();
+    Module::iterator F = M.begin();
+    if (FS.empty() && M.size() && F->hasFnAttribute("target-features"))
+      FS = F->getFnAttribute("target-features").getValueAsString();
+
+    // Compute MIPS architecture attributes based on the default subtarget
+    // that we'd have constructed.
+    // FIXME: For ifunc related functions we could iterate over and look
+    // for a feature string that doesn't match the default one.
+    StringRef CPU = MIPS_MC::selectMipsCPU(TT, TM.getTargetCPU());
+    const MipsTargetMachine &MTM = static_cast<const MipsTargetMachine &>(TM);
+    const MipsSubtarget STI(TT, CPU, FS, MTM.isLittleEndian(), MTM, std::nullopt);
+
+    bool IsABICalls = STI.isABICalls();
+    const MipsABIInfo &ABI = MTM.getABI();
+    if (IsABICalls) {
+      TS.emitDirectiveAbiCalls();
+      // FIXME: This condition should be a lot more complicated that it is here.
+      //        Ideally it should test for properties of the ABI and not the ABI
+      //        itself.
+      //        For the moment, I'm only correcting enough to make MIPS-IV work.
+      if (!isPositionIndependent() && STI.hasSym32())
+        TS.emitDirectiveOptionPic0();
+    }
+
+    // Tell the assembler which ABI we are using
+    std::string SectionName = std::string(".mdebug.") + getCurrentABIString();
+    OutStreamer->switchSection(
+        OutContext.getELFSection(SectionName, ELF::SHT_PROGBITS, 0));
 
-  // NaN: At the moment we only support:
-  // 1. .nan legacy (default)
-  // 2. .nan 2008
-  STI.isNaN2008() ? TS.emitDirectiveNaN2008()
-                  : TS.emitDirectiveNaNLegacy();
+    // NaN: At the moment we only support:
+    // 1. .nan legacy (default)
+    // 2. .nan 2008
+    STI.isNaN2008() ? TS.emitDirectiveNaN2008()
+                    : TS.emitDirectiveNaNLegacy();
 
-  // TODO: handle O64 ABI
+    // TODO: handle O64 ABI
 
-  TS.updateABIInfo(STI);
+    TS.updateABIInfo(STI);
 
-  // We should always emit a '.module fp=...' but binutils 2.24 does not accept
-  // it. We therefore emit it when it contradicts the ABI defaults (-mfpxx or
-  // -mfp64) and omit it otherwise.
-  if ((ABI.IsO32() && (STI.isABI_FPXX() || STI.isFP64bit())) ||
-      STI.useSoftFloat())
-    TS.emitDirectiveModuleFP();
+    // We should always emit a '.module fp=...' but binutils 2.24 does not accept
+    // it. We therefore emit it when it contradicts the ABI defaults (-mfpxx or
+    // -mfp64) and omit it otherwise.
+    if ((ABI.IsO32() && (STI.isABI_FPXX() || STI.isFP64bit())) ||
+        STI.useSoftFloat())
+      TS.emitDirectiveModuleFP();
 
-  // We should always emit a '.module [no]oddspreg' but binutils 2.24 does not
-  // accept it. We therefore emit it when it contradicts the default or an
-  // option has changed the default (i.e. FPXX) and omit it otherwise.
-  if (ABI.IsO32() && (!STI.useOddSPReg() || STI.isABI_FPXX()))
-    TS.emitDirectiveModuleOddSPReg();
+    // We should always emit a '.module [no]oddspreg' but binutils 2.24 does not
+    // accept it. We therefore emit it when it contradicts the default or an
+    // option has changed the default (i.e. FPXX) and omit it otherwise.
+    if (ABI.IsO32() && (!STI.useOddSPReg() || STI.isABI_FPXX()))
+      TS.emitDirectiveModuleOddSPReg();
 
-  // Switch to the .text section.
-  OutStreamer->switchSection(getObjFileLowering().getTextSection());
+    // Switch to the .text section.
+    OutStreamer->switchSection(getObjFileLowering().getTextSection());
+  }
 }
 
 void MipsAsmPrinter::emitInlineAsmStart() const {
diff --git a/llvm/lib/Target/Mips/MipsTargetMachine.cpp b/llvm/lib/Target/Mips/MipsTargetMachine.cpp
index 7802767e31c2f6..c7dbcc80148ae4 100644
--- a/llvm/lib/Target/Mips/MipsTargetMachine.cpp
+++ b/llvm/lib/Target/Mips/MipsTargetMachine.cpp
@@ -70,6 +70,10 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMipsTarget() {
   initializeMipsDAGToDAGISelLegacyPass(*PR);
 }
 
+static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {
+  return std::make_unique<MipsTargetObjectFile>();
+}
+
 static std::string computeDataLayout(const Triple &TT, StringRef CPU,
                                      const TargetOptions &Options,
                                      bool isLittle) {
@@ -128,7 +132,7 @@ MipsTargetMachine::MipsTargetMachine(const Target &T, const Triple &TT,
     : LLVMTargetMachine(T, computeDataLayout(TT, CPU, Options, isLittle), TT,
                         CPU, FS, Options, getEffectiveRelocModel(JIT, RM),
                         getEffectiveCodeModel(CM, CodeModel::Small), OL),
-      isLittle(isLittle), TLOF(std::make_unique<MipsTargetObjectFile>()),
+      isLittle(isLittle), TLOF(createTLOF(getTargetTriple())),
       ABI(MipsABIInfo::computeTargetABI(TT, CPU, Options.MCOptions)),
       Subtarget(nullptr),
       DefaultSubtarget(TT, CPU, FS, isLittle, *this, std::nullopt),

>From b02203d8120a99ac5c3b042245cdd1c0f6815a4b 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 5/6] [MC][Mips] Add
 MipsWinCOFFObjectWriter/MipsWinCOFFStreamer

Implement GNU and MSVC variants.
---
 llvm/lib/Object/COFFObjectFile.cpp            |  3 +
 llvm/lib/Object/WindowsResource.cpp           |  3 +
 .../Target/Mips/MCTargetDesc/CMakeLists.txt   |  2 +
 .../Mips/MCTargetDesc/MipsAsmBackend.cpp      | 21 +++++++
 .../Mips/MCTargetDesc/MipsMCAsmInfo.cpp       | 22 +++++++
 .../Target/Mips/MCTargetDesc/MipsMCAsmInfo.h  | 15 +++++
 .../Mips/MCTargetDesc/MipsMCTargetDesc.cpp    | 20 ++++++-
 .../Mips/MCTargetDesc/MipsMCTargetDesc.h      | 15 +++++
 .../MCTargetDesc/MipsWinCOFFObjectWriter.cpp  | 58 +++++++++++++++++++
 .../Mips/MCTargetDesc/MipsWinCOFFStreamer.cpp | 33 +++++++++++
 llvm/lib/Target/Mips/MipsTargetMachine.cpp    |  2 +
 llvm/test/MC/Mips/coff-basic.ll               |  8 +++
 llvm/test/MC/Mips/coff-relocs.ll              | 43 ++++++++++++++
 13 files changed, 244 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/Object/COFFObjectFile.cpp b/llvm/lib/Object/COFFObjectFile.cpp
index 4b3999126c89fb..ad15d42135b319 100644
--- a/llvm/lib/Object/COFFObjectFile.cpp
+++ b/llvm/lib/Object/COFFObjectFile.cpp
@@ -2349,6 +2349,9 @@ ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) {
     case Triple::aarch64:
       RVAReloc = COFF::IMAGE_REL_ARM64_ADDR32NB;
       break;
+    case Triple::mipsel:
+      RVAReloc = COFF::IMAGE_REL_MIPS_REFWORDNB;
+      break;
     default:
       return createStringError(object_error::parse_failed,
                                "unsupported architecture");
diff --git a/llvm/lib/Object/WindowsResource.cpp b/llvm/lib/Object/WindowsResource.cpp
index 306e8ec542068b..211e581a7da6a9 100644
--- a/llvm/lib/Object/WindowsResource.cpp
+++ b/llvm/lib/Object/WindowsResource.cpp
@@ -992,6 +992,9 @@ void WindowsResourceCOFFWriter::writeFirstSectionRelocations() {
     case Triple::aarch64:
       Reloc->Type = COFF::IMAGE_REL_ARM64_ADDR32NB;
       break;
+    case Triple::mipsel:
+      Reloc->Type = COFF::IMAGE_REL_MIPS_REFWORDNB;
+      break;
     default:
       llvm_unreachable("unknown machine type");
     }
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..16318cffd7470e 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
@@ -597,10 +597,31 @@ 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())
+    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 c112b3abe0ba75..960256bc38f244 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
@@ -51,3 +51,25 @@ MipsELFMCAsmInfo::MipsELFMCAsmInfo(const Triple &TheTriple,
   DwarfRegNumForCFI = true;
   HasMipsExpressions = true;
 }
+
+void MipsCOFFMCAsmInfoMicrosoft::anchor() { }
+
+MipsCOFFMCAsmInfoMicrosoft::MipsCOFFMCAsmInfoMicrosoft() {
+  WinEHEncodingType = WinEH::EncodingType::Itanium;
+  CommentString = ";";
+
+  ExceptionsType = ExceptionHandling::WinEH;
+
+  AllowAtInName = true;
+}
+
+void MipsCOFFMCAsmInfoGNU::anchor() { }
+
+MipsCOFFMCAsmInfoGNU::MipsCOFFMCAsmInfoGNU() {
+  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..96348b17e57696 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,20 @@ class MipsELFMCAsmInfo : public MCAsmInfoELF {
                             const MCTargetOptions &Options);
 };
 
+class MipsCOFFMCAsmInfoMicrosoft : public MCAsmInfoMicrosoft {
+  void anchor() override;
+
+public:
+  explicit MipsCOFFMCAsmInfoMicrosoft();
+};
+
+class MipsCOFFMCAsmInfoGNU : public MCAsmInfoGNUCOFF {
+  void anchor() override;
+
+public:
+  explicit MipsCOFFMCAsmInfoGNU();
+};
+
 } // namespace llvm
 
 #endif
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
index eff9ecf0d53d31..378cc12388bae3 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,14 @@ 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.isWindowsMSVCEnvironment())
+    MAI = new MipsCOFFMCAsmInfoMicrosoft();
+  else if (TT.isOSWindows())
+    MAI = new MipsCOFFMCAsmInfoGNU();
+  else
+    MAI = new MipsELFMCAsmInfo(TT, Options);
 
   unsigned SP = MRI.getDwarfRegNum(Mips::SP, true);
   MCCFIInstruction Inst = MCCFIInstruction::createDefCfaRegister(nullptr, SP);
@@ -127,6 +141,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 +202,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..a02e4fa2208880 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,21 @@ 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..d014cc1b0c1b55
--- /dev/null
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsWinCOFFObjectWriter.cpp
@@ -0,0 +1,58 @@
+//===-- MipsWinCOFFObjectWriter.cpp - Mips Win COFF Writer -----------------===//
+//
+// 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..77044a0ff3357e
--- /dev/null
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsWinCOFFStreamer.cpp
@@ -0,0 +1,33 @@
+//===-- MipsWinCOFFStreamer.cpp - MIPS Target WinCOFF Streamer --*- 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..21e355fc4883b9
--- /dev/null
+++ b/llvm/test/MC/Mips/coff-basic.ll
@@ -0,0 +1,8 @@
+; RUN: llc -mtriple mipsel-windows-msvc -filetype=obj < %s | obj2yaml | FileCheck %s
+; RUN: llc -mtriple mipsel-windows-gnu -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..bbe732c3d76ff2
--- /dev/null
+++ b/llvm/test/MC/Mips/coff-relocs.ll
@@ -0,0 +1,43 @@
+; RUN: llc -mtriple mipsel-windows-msvc -filetype=obj < %s | obj2yaml | FileCheck %s
+; RUN: llc -mtriple mipsel-windows-gnu -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

>From 95a56b62088c3133c11da4d11f1b66956fa4121e 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:52:31 +0200
Subject: [PATCH 6/6] [MC][Mips] Add the required IMAGE_REL_MIPS_PAIR
 relocation after IMAGE_REL_MIPS_REFHI/IMAGE_REL_MIPS_SECRELHI

---
 llvm/lib/MC/WinCOFFObjectWriter.cpp | 17 +++++++++++++++--
 llvm/test/MC/Mips/coff-relocs.ll    |  3 +++
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/MC/WinCOFFObjectWriter.cpp b/llvm/lib/MC/WinCOFFObjectWriter.cpp
index 62f53423126ea9..d5a30d332d2b92 100644
--- a/llvm/lib/MC/WinCOFFObjectWriter.cpp
+++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp
@@ -773,7 +773,10 @@ void WinCOFFWriter::assignFileOffsets(MCAssembler &Asm) {
 
       for (auto &Relocation : Sec->Relocations) {
         assert(Relocation.Symb->getIndex() != -1);
-        Relocation.Data.SymbolTableIndex = Relocation.Symb->getIndex();
+        if (Header.Machine != COFF::IMAGE_FILE_MACHINE_R4000 ||
+            Relocation.Data.Type != COFF::IMAGE_REL_MIPS_PAIR) {
+          Relocation.Data.SymbolTableIndex = Relocation.Symb->getIndex();
+        }
       }
     }
 
@@ -967,8 +970,18 @@ void WinCOFFWriter::recordRelocation(MCAssembler &Asm,
   if (Fixup.getKind() == FK_SecRel_2)
     FixedValue = 0;
 
-  if (OWriter.TargetObjectWriter->recordRelocation(Fixup))
+  if (OWriter.TargetObjectWriter->recordRelocation(Fixup)) {
     Sec->Relocations.push_back(Reloc);
+    if (Header.Machine == COFF::IMAGE_FILE_MACHINE_R4000 &&
+        (Reloc.Data.Type == COFF::IMAGE_REL_MIPS_REFHI ||
+         Reloc.Data.Type == COFF::IMAGE_REL_MIPS_SECRELHI)) {
+      // IMAGE_REL_MIPS_REFHI and IMAGE_REL_MIPS_SECRELHI *must*
+      // be followed by IMAGE_REL_MIPS_PAIR
+      auto RelocPair = Reloc;
+      RelocPair.Data.Type = COFF::IMAGE_REL_MIPS_PAIR;
+      Sec->Relocations.push_back(RelocPair);
+    }
+  }
 }
 
 static std::time_t getTime() {
diff --git a/llvm/test/MC/Mips/coff-relocs.ll b/llvm/test/MC/Mips/coff-relocs.ll
index bbe732c3d76ff2..1b5c0e09033b8d 100644
--- a/llvm/test/MC/Mips/coff-relocs.ll
+++ b/llvm/test/MC/Mips/coff-relocs.ll
@@ -23,6 +23,9 @@ define i32 @foo_var() {
 ; CHECK:      - VirtualAddress:  32
 ; CHECK:        SymbolName:      var
 ; CHECK:        Type:            IMAGE_REL_MIPS_REFHI
+; CHECK:      - VirtualAddress:  32
+; CHECK:        SymbolName:      .text
+; CHECK:        Type:            IMAGE_REL_MIPS_PAIR
 ; CHECK:      - VirtualAddress:  40
 ; CHECK:        SymbolName:      var
 ; CHECK:        Type:            IMAGE_REL_MIPS_REFLO



More information about the llvm-commits mailing list