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

via cfe-commits cfe-commits at lists.llvm.org
Sun Sep 8 01:39:16 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>,
=?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>,
=?utf-8?q?Hervé?= Poussineau <hpoussin at reactos.org>,
=?utf-8?q?Hervé?= Poussineau <hpoussin at reactos.org>
Message-ID: <llvm.org/llvm/llvm-project/pull/107744 at github.com>
In-Reply-To:


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

- Add support for Windows MIPS relocations types
- Support reading MIPS COFF files in objdump
- Support generating MIPS COFF files in yaml2obj
- Support generating MIPS COFF files in llvm-lib
- Support generating MIPS COFF files in llvm-dlltool
- Support generating MIPS COFF files in clang

Compiler and library creation have been cross-tested with Microsoft counterparts.
Linker part is not yet ready (although available in my [mips-pe](https://github.com/hpoussin/llvm-project/tree/mips-pe) branch).

By using Microsoft linker (or my work-in-process work on lld), I get working executables.
![clang-20-mips](https://github.com/user-attachments/assets/6914fc93-8c07-41de-8bdc-acd64d31b376)


>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 01/13] [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 83d84c1190f32539392e99e0214350b10d6fda94 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 02/13] [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..5077c38c2de766 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 COFF::IMAGE_FILE_MACHINE_R4000:
+    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 304ca782b8cf30551b5b77ae92c36f515e08c317 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 03/13] [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 5077c38c2de766..42b8c31aea498e 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 245588c34acd340fc7aa11ac250568234a6e449d 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 04/13] [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 fc6bef383d35de695a191d4785a1be676cea741f 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 05/13] [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 42b8c31aea498e..6f02af5538642a 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 COFF::IMAGE_FILE_MACHINE_R4000:
+      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..e2fe8b9943bcb8 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 COFF::IMAGE_FILE_MACHINE_R4000:
+      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 30e6c9333368d9daa0aa9a59936208cd2b64d6bc 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 06/13] [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

>From 168f129c0e1fb419e26a351cb8f3794cdbf9b128 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:54:00 +0200
Subject: [PATCH 07/13] [MC][CodeGen][Mips] Add CodeView mapping

Also add support for new relocation types required by debug information.
---
 .../DebugInfo/CodeView/CodeViewRegisters.def  | 88 ++++++++++++++++++-
 llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp |  2 +
 .../Mips/MCTargetDesc/MipsMCTargetDesc.cpp    | 81 +++++++++++++++++
 .../Mips/MCTargetDesc/MipsMCTargetDesc.h      |  2 +
 .../MCTargetDesc/MipsWinCOFFObjectWriter.cpp  |  4 +
 llvm/lib/Target/Mips/MipsRegisterInfo.cpp     |  4 +-
 llvm/test/MC/Mips/coff-relocs.ll              | 36 ++++++++
 7 files changed, 215 insertions(+), 2 deletions(-)

diff --git a/llvm/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def b/llvm/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def
index 5d537755b2d680..7c38b536c277f0 100644
--- a/llvm/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def
+++ b/llvm/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def
@@ -16,7 +16,8 @@
 
 #if !defined(CV_REGISTERS_ALL) && !defined(CV_REGISTERS_X86) &&                \
     !defined(CV_REGISTERS_ARM) &&                                              \
-    !defined(CV_REGISTERS_ARM64)
+    !defined(CV_REGISTERS_ARM64) &&                                            \
+    !defined(CV_REGISTERS_MIPS)
 #error Need include at least one register set.
 #endif
 
@@ -793,3 +794,88 @@ CV_REGISTER(ARM64_H31, 301)
 #pragma pop_macro("ARM64_FPCR")
 
 #endif // defined(CV_REGISTERS_ALL) || defined(CV_REGISTERS_ARM64)
+
+#if defined(CV_REGISTERS_ALL) || defined(CV_REGISTERS_MIPS)
+
+// MIPS registers
+CV_REGISTER(MIPS_NOREG, 0)
+
+// General purpose integer registers
+
+CV_REGISTER(MIPS_ZERO, 10)
+CV_REGISTER(MIPS_AT, 11)
+CV_REGISTER(MIPS_V0, 12)
+CV_REGISTER(MIPS_V1, 13)
+CV_REGISTER(MIPS_A0, 14)
+CV_REGISTER(MIPS_A1, 15)
+CV_REGISTER(MIPS_A2, 16)
+CV_REGISTER(MIPS_A3, 17)
+CV_REGISTER(MIPS_T0, 18)
+CV_REGISTER(MIPS_T1, 19)
+CV_REGISTER(MIPS_T2, 20)
+CV_REGISTER(MIPS_T3, 21)
+CV_REGISTER(MIPS_T4, 22)
+CV_REGISTER(MIPS_T5, 23)
+CV_REGISTER(MIPS_T6, 24)
+CV_REGISTER(MIPS_T7, 25)
+CV_REGISTER(MIPS_S0, 26)
+CV_REGISTER(MIPS_S1, 27)
+CV_REGISTER(MIPS_S2, 28)
+CV_REGISTER(MIPS_S3, 29)
+CV_REGISTER(MIPS_S4, 30)
+CV_REGISTER(MIPS_S5, 31)
+CV_REGISTER(MIPS_S6, 32)
+CV_REGISTER(MIPS_S7, 33)
+CV_REGISTER(MIPS_T8, 34)
+CV_REGISTER(MIPS_T9, 35)
+CV_REGISTER(MIPS_K0, 36)
+CV_REGISTER(MIPS_K1, 37)
+CV_REGISTER(MIPS_GP, 38)
+CV_REGISTER(MIPS_SP, 39)
+CV_REGISTER(MIPS_S8, 40)
+CV_REGISTER(MIPS_RA, 41)
+CV_REGISTER(MIPS_LO, 42)
+CV_REGISTER(MIPS_HI, 43)
+
+// Status registers
+
+CV_REGISTER(MIPS_Fir, 50)
+CV_REGISTER(MIPS_Psr, 51)
+
+// Floating-point registers
+
+CV_REGISTER(MIPS_F0, 60)
+CV_REGISTER(MIPS_F1, 61)
+CV_REGISTER(MIPS_F2, 62)
+CV_REGISTER(MIPS_F3, 63)
+CV_REGISTER(MIPS_F4, 64)
+CV_REGISTER(MIPS_F5, 65)
+CV_REGISTER(MIPS_F6, 66)
+CV_REGISTER(MIPS_F7, 67)
+CV_REGISTER(MIPS_F8, 68)
+CV_REGISTER(MIPS_F9, 69)
+CV_REGISTER(MIPS_F10, 70)
+CV_REGISTER(MIPS_F11, 71)
+CV_REGISTER(MIPS_F12, 72)
+CV_REGISTER(MIPS_F13, 73)
+CV_REGISTER(MIPS_F14, 74)
+CV_REGISTER(MIPS_F15, 75)
+CV_REGISTER(MIPS_F16, 76)
+CV_REGISTER(MIPS_F17, 77)
+CV_REGISTER(MIPS_F18, 78)
+CV_REGISTER(MIPS_F19, 79)
+CV_REGISTER(MIPS_F20, 80)
+CV_REGISTER(MIPS_F21, 81)
+CV_REGISTER(MIPS_F22, 82)
+CV_REGISTER(MIPS_F23, 83)
+CV_REGISTER(MIPS_F24, 84)
+CV_REGISTER(MIPS_F25, 85)
+CV_REGISTER(MIPS_F26, 86)
+CV_REGISTER(MIPS_F27, 87)
+CV_REGISTER(MIPS_F28, 88)
+CV_REGISTER(MIPS_F29, 89)
+CV_REGISTER(MIPS_F30, 90)
+CV_REGISTER(MIPS_F31, 91)
+CV_REGISTER(MIPS_Fsr, 92)
+
+#endif // defined(CV_REGISTERS_ALL) || defined(CV_REGISTERS_MIPS)
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 7700ffd6da8030..e5fb2f712a4b13 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -125,6 +125,8 @@ static CPUType mapArchToCVCPUType(Triple::ArchType Type) {
     return CPUType::ARMNT;
   case Triple::ArchType::aarch64:
     return CPUType::ARM64;
+  case Triple::ArchType::mipsel:
+    return CPUType::MIPS;
   default:
     report_fatal_error("target architecture doesn't map to a CodeView CPUType");
   }
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
index 378cc12388bae3..46dada7830928d 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
@@ -19,6 +19,7 @@
 #include "MipsMCNaCl.h"
 #include "MipsTargetStreamer.h"
 #include "TargetInfo/MipsTargetInfo.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
 #include "llvm/MC/MCCodeEmitter.h"
 #include "llvm/MC/MCELFStreamer.h"
 #include "llvm/MC/MCInstrAnalysis.h"
@@ -45,6 +46,86 @@ using namespace llvm;
 #define GET_REGINFO_MC_DESC
 #include "MipsGenRegisterInfo.inc"
 
+void MIPS_MC::initLLVMToCVRegMapping(MCRegisterInfo *MRI) {
+  // Mapping from CodeView to MC register id.
+  static const struct {
+    codeview::RegisterId CVReg;
+    MCPhysReg Reg;
+  } RegMap[] = {
+      {codeview::RegisterId::MIPS_ZERO, Mips::ZERO},
+      {codeview::RegisterId::MIPS_AT, Mips::AT},
+      {codeview::RegisterId::MIPS_V0, Mips::V0},
+      {codeview::RegisterId::MIPS_V1, Mips::V1},
+      {codeview::RegisterId::MIPS_A0, Mips::A0},
+      {codeview::RegisterId::MIPS_A1, Mips::A1},
+      {codeview::RegisterId::MIPS_A2, Mips::A2},
+      {codeview::RegisterId::MIPS_A3, Mips::A3},
+      {codeview::RegisterId::MIPS_T0, Mips::T0},
+      {codeview::RegisterId::MIPS_T1, Mips::T1},
+      {codeview::RegisterId::MIPS_T2, Mips::T2},
+      {codeview::RegisterId::MIPS_T3, Mips::T3},
+      {codeview::RegisterId::MIPS_T4, Mips::T4},
+      {codeview::RegisterId::MIPS_T5, Mips::T5},
+      {codeview::RegisterId::MIPS_T6, Mips::T6},
+      {codeview::RegisterId::MIPS_T7, Mips::T7},
+      {codeview::RegisterId::MIPS_S0, Mips::S0},
+      {codeview::RegisterId::MIPS_S1, Mips::S1},
+      {codeview::RegisterId::MIPS_S2, Mips::S2},
+      {codeview::RegisterId::MIPS_S3, Mips::S3},
+      {codeview::RegisterId::MIPS_S4, Mips::S4},
+      {codeview::RegisterId::MIPS_S5, Mips::S5},
+      {codeview::RegisterId::MIPS_S6, Mips::S6},
+      {codeview::RegisterId::MIPS_S7, Mips::S7},
+      {codeview::RegisterId::MIPS_T8, Mips::T8},
+      {codeview::RegisterId::MIPS_T9, Mips::T9},
+      {codeview::RegisterId::MIPS_K0, Mips::K0},
+      {codeview::RegisterId::MIPS_K1, Mips::K1},
+      {codeview::RegisterId::MIPS_GP, Mips::GP},
+      {codeview::RegisterId::MIPS_SP, Mips::SP},
+      {codeview::RegisterId::MIPS_S8, Mips::FP},
+      {codeview::RegisterId::MIPS_RA, Mips::RA},
+      {codeview::RegisterId::MIPS_LO, Mips::HI0},
+      {codeview::RegisterId::MIPS_HI, Mips::LO0},
+      //{codeview::RegisterId::MIPS_Fir, Mips::},
+      //{codeview::RegisterId::MIPS_Psr, Mips::},
+      {codeview::RegisterId::MIPS_F0, Mips::F0},
+      {codeview::RegisterId::MIPS_F1, Mips::F1},
+      {codeview::RegisterId::MIPS_F2, Mips::F2},
+      {codeview::RegisterId::MIPS_F3, Mips::F3},
+      {codeview::RegisterId::MIPS_F4, Mips::F4},
+      {codeview::RegisterId::MIPS_F5, Mips::F5},
+      {codeview::RegisterId::MIPS_F6, Mips::F6},
+      {codeview::RegisterId::MIPS_F7, Mips::F7},
+      {codeview::RegisterId::MIPS_F8, Mips::F8},
+      {codeview::RegisterId::MIPS_F9, Mips::F9},
+      {codeview::RegisterId::MIPS_F10, Mips::F10},
+      {codeview::RegisterId::MIPS_F11, Mips::F11},
+      {codeview::RegisterId::MIPS_F12, Mips::F12},
+      {codeview::RegisterId::MIPS_F13, Mips::F13},
+      {codeview::RegisterId::MIPS_F14, Mips::F14},
+      {codeview::RegisterId::MIPS_F15, Mips::F15},
+      {codeview::RegisterId::MIPS_F16, Mips::F16},
+      {codeview::RegisterId::MIPS_F17, Mips::F17},
+      {codeview::RegisterId::MIPS_F18, Mips::F18},
+      {codeview::RegisterId::MIPS_F19, Mips::F19},
+      {codeview::RegisterId::MIPS_F20, Mips::F20},
+      {codeview::RegisterId::MIPS_F21, Mips::F21},
+      {codeview::RegisterId::MIPS_F22, Mips::F22},
+      {codeview::RegisterId::MIPS_F23, Mips::F23},
+      {codeview::RegisterId::MIPS_F24, Mips::F24},
+      {codeview::RegisterId::MIPS_F25, Mips::F25},
+      {codeview::RegisterId::MIPS_F26, Mips::F26},
+      {codeview::RegisterId::MIPS_F27, Mips::F27},
+      {codeview::RegisterId::MIPS_F28, Mips::F28},
+      {codeview::RegisterId::MIPS_F29, Mips::F29},
+      {codeview::RegisterId::MIPS_F30, Mips::F30},
+      {codeview::RegisterId::MIPS_F31, Mips::F31},
+      //{codeview::RegisterId::MIPS_Fsr, Mips::},
+  };
+  for (const auto &I : RegMap)
+    MRI->mapLLVMRegToCVReg(I.Reg, static_cast<int>(I.CVReg));
+}
+
 namespace {
 class MipsWinCOFFTargetStreamer : public MipsTargetStreamer {
 public:
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h
index a02e4fa2208880..114fec0ccc02e9 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h
@@ -58,6 +58,8 @@ std::unique_ptr<MCObjectTargetWriter>
 createMipsWinCOFFObjectWriter();
 
 namespace MIPS_MC {
+void initLLVMToCVRegMapping(MCRegisterInfo *MRI);
+
 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
index d014cc1b0c1b55..17c21bc8b1326b 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsWinCOFFObjectWriter.cpp
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsWinCOFFObjectWriter.cpp
@@ -40,6 +40,10 @@ unsigned MipsWinCOFFObjectWriter::getRelocType(MCContext &Ctx,
   switch (FixupKind) {
   case FK_Data_4:
     return COFF::IMAGE_REL_MIPS_REFWORD;
+  case FK_SecRel_2:
+    return COFF::IMAGE_REL_MIPS_SECTION;
+  case FK_SecRel_4:
+    return COFF::IMAGE_REL_MIPS_SECREL;
   case Mips::fixup_Mips_26:
     return COFF::IMAGE_REL_MIPS_JMPADDR;
   case Mips::fixup_Mips_HI16:
diff --git a/llvm/lib/Target/Mips/MipsRegisterInfo.cpp b/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
index 3b12cb35b36731..f80e8fa1631df3 100644
--- a/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
+++ b/llvm/lib/Target/Mips/MipsRegisterInfo.cpp
@@ -39,7 +39,9 @@ using namespace llvm;
 #define GET_REGINFO_TARGET_DESC
 #include "MipsGenRegisterInfo.inc"
 
-MipsRegisterInfo::MipsRegisterInfo() : MipsGenRegisterInfo(Mips::RA) {}
+MipsRegisterInfo::MipsRegisterInfo() : MipsGenRegisterInfo(Mips::RA) {
+  MIPS_MC::initLLVMToCVRegMapping(this);
+}
 
 unsigned MipsRegisterInfo::getPICCallReg() { return Mips::T9; }
 
diff --git a/llvm/test/MC/Mips/coff-relocs.ll b/llvm/test/MC/Mips/coff-relocs.ll
index 1b5c0e09033b8d..39d349b9819614 100644
--- a/llvm/test/MC/Mips/coff-relocs.ll
+++ b/llvm/test/MC/Mips/coff-relocs.ll
@@ -44,3 +44,39 @@ define i32 @foo_var() {
 ; CHECK:      - VirtualAddress:  0
 ; CHECK:        SymbolName:      var2
 ; CHECK:        Type:            IMAGE_REL_MIPS_REFWORD
+
+
+
+
+; CHECK:  - Name:            '.debug$S'
+; CHECK:    Relocations:
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, emissionKind: FullDebug)
+!1 = !DIFile(filename: "dummy.c", directory: "/tmp/private")
+!2 = !{i32 2, !"CodeView", i32 1}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 2}
+!5 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !6, scopeLine: 2, spFlags: DISPFlagDefinition, unit: !0)
+!6 = !DISubroutineType(types: !7)
+!7 = !{null}
+!8 = !DILocation(line: 3, scope: !5)
+
+define dso_local void @foo_dbg() #0 !dbg !5 {
+  ret void, !dbg !8
+; CHECK:      - VirtualAddress:  92
+; CHECK:        SymbolName:      foo_dbg
+; CHECK:        Type:            IMAGE_REL_MIPS_SECREL
+; CHECK:      - VirtualAddress:  96
+; CHECK:        SymbolName:      foo_dbg
+; CHECK:        Type:            IMAGE_REL_MIPS_SECTION
+; CHECK:      - VirtualAddress:  148
+; CHECK:        SymbolName:      foo_dbg
+; CHECK:        Type:            IMAGE_REL_MIPS_SECREL
+; CHECK:      - VirtualAddress:  152
+; CHECK:        SymbolName:      foo_dbg
+; CHECK:        Type:            IMAGE_REL_MIPS_SECTION
+}
+

>From a429ab24a556fd459a6bcece386c42fb08585f90 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= <hpoussin at reactos.org>
Date: Sun, 22 Oct 2023 11:24:08 +0200
Subject: [PATCH 08/13] [Mips] Handle declspec(dllimport) on mipsel-windows-*
 triples

---
 .../Target/Mips/MCTargetDesc/MipsBaseInfo.h   |  7 ++-
 llvm/lib/Target/Mips/MipsISelLowering.cpp     | 16 +++++-
 llvm/lib/Target/Mips/MipsISelLowering.h       | 26 +++++++++
 llvm/lib/Target/Mips/MipsMCInstLower.cpp      | 14 ++++-
 llvm/lib/Target/Mips/MipsSubtarget.h          |  2 +
 llvm/test/CodeGen/Mips/dllimport.ll           | 55 +++++++++++++++++++
 llvm/test/MC/Mips/coff-relocs-dllimport.ll    | 12 ++++
 7 files changed, 128 insertions(+), 4 deletions(-)
 create mode 100644 llvm/test/CodeGen/Mips/dllimport.ll
 create mode 100644 llvm/test/MC/Mips/coff-relocs-dllimport.ll

diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h
index aa35e7db6bda44..b9a2af3341236a 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h
@@ -92,7 +92,12 @@ namespace MipsII {
     MO_CALL_LO16,
 
     /// Helper operand used to generate R_MIPS_JALR
-    MO_JALR
+    MO_JALR,
+
+    /// MO_DLLIMPORT - On a symbol operand "FOO", this indicates that the
+    /// reference is actually to the "__imp_FOO" symbol.  This is used for
+    /// dllimport linkage on windows.
+    MO_DLLIMPORT = 0x20,
   };
 
   enum {
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index fa57a3fa9b1557..94cadfffa8794f 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -2105,6 +2105,14 @@ SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op,
   GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
   const GlobalValue *GV = N->getGlobal();
 
+  if (GV->hasDLLImportStorageClass()) {
+    assert(Subtarget.isTargetWindows() &&
+           "Windows is the only supported COFF target");
+    return getDllimportVariable(
+        N, SDLoc(N), Ty, DAG,
+        DAG.getEntryNode(), MachinePointerInfo::getGOT(DAG.getMachineFunction()));
+  }
+
   if (!isPositionIndependent()) {
     const MipsTargetObjectFile *TLOF =
         static_cast<const MipsTargetObjectFile *>(
@@ -3460,7 +3468,13 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   }
 
   if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
-    if (IsPIC) {
+    if (Subtarget.isTargetCOFF() && G->getGlobal()->hasDLLImportStorageClass()) {
+      assert(Subtarget.isTargetWindows() &&
+             "Windows is the only supported COFF target");
+      auto PtrInfo = MachinePointerInfo();
+      Callee = DAG.getLoad(Ty, DL, Chain, getDllimportSymbol(G, SDLoc(G), Ty, DAG),
+                           PtrInfo);
+    } else if (IsPIC) {
       const GlobalValue *Val = G->getGlobal();
       InternalLinkage = Val->hasInternalLinkage();
 
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h
index 2b18b299180926..12dfa6bc1c8079 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsISelLowering.h
@@ -485,6 +485,32 @@ class TargetRegisterClass;
           DAG.getNode(MipsISD::GPRel, DL, DAG.getVTList(Ty), GPRel));
     }
 
+    // This method creates the following nodes, which are necessary for
+    // loading a dllimported symbol:
+    //
+    // (lw (add (shl(%high(sym), 16), %low(sym)))
+    template <class NodeTy>
+    SDValue getDllimportSymbol(NodeTy *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG) const {
+        SDValue Hi = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_HI | MipsII::MO_DLLIMPORT);
+        SDValue Lo = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_LO | MipsII::MO_DLLIMPORT);
+        return DAG.getNode(ISD::ADD, DL, Ty,
+                           DAG.getNode(MipsISD::Lo, DL, Ty, Lo),
+                           DAG.getNode(MipsISD::Hi, DL, Ty, Hi));
+    }
+
+    // This method creates the following nodes, which are necessary for
+    // loading a dllimported global variable:
+    //
+    // (lw (lw (add (shl(%high(sym), 16), %low(sym))))
+    template <class NodeTy>
+    SDValue getDllimportVariable(NodeTy *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG,
+                                 SDValue Chain,
+                                 const MachinePointerInfo &PtrInfo) const {
+        return DAG.getLoad(Ty, DL, Chain,
+                           getDllimportSymbol(N, DL, Ty, DAG),
+                           PtrInfo);
+    }
+
     /// This function fills Ops, which is the list of operands that will later
     /// be used when a function call node is created. It also generates
     /// copyToReg nodes to set up argument registers.
diff --git a/llvm/lib/Target/Mips/MipsMCInstLower.cpp b/llvm/lib/Target/Mips/MipsMCInstLower.cpp
index b0642f3d1ff283..667cf26b60fd31 100644
--- a/llvm/lib/Target/Mips/MipsMCInstLower.cpp
+++ b/llvm/lib/Target/Mips/MipsMCInstLower.cpp
@@ -18,6 +18,7 @@
 #include "llvm/CodeGen/MachineBasicBlock.h"
 #include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCInst.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -38,8 +39,16 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
   MipsMCExpr::MipsExprKind TargetKind = MipsMCExpr::MEK_None;
   bool IsGpOff = false;
   const MCSymbol *Symbol;
+  SmallString<128> Name;
+  unsigned TargetFlags = MO.getTargetFlags();
 
-  switch(MO.getTargetFlags()) {
+  if (TargetFlags & MipsII::MO_DLLIMPORT) {
+    // Handle dllimport linkage
+    Name += "__imp_";
+    TargetFlags &= ~MipsII::MO_DLLIMPORT;
+  }
+
+  switch(TargetFlags) {
   default:
     llvm_unreachable("Invalid target flag!");
   case MipsII::MO_NO_FLAG:
@@ -125,7 +134,8 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
     break;
 
   case MachineOperand::MO_GlobalAddress:
-    Symbol = AsmPrinter.getSymbol(MO.getGlobal());
+    AsmPrinter.getNameWithPrefix(Name, MO.getGlobal());
+    Symbol = Ctx->getOrCreateSymbol(Name);
     Offset += MO.getOffset();
     break;
 
diff --git a/llvm/lib/Target/Mips/MipsSubtarget.h b/llvm/lib/Target/Mips/MipsSubtarget.h
index fea7f11fd07054..0dd349f59ea65f 100644
--- a/llvm/lib/Target/Mips/MipsSubtarget.h
+++ b/llvm/lib/Target/Mips/MipsSubtarget.h
@@ -300,6 +300,7 @@ class MipsSubtarget : public MipsGenSubtargetInfo {
     return (HasSym32 && isABI_N64()) || isABI_N32() || isABI_O32();
   }
   bool isSingleFloat() const { return IsSingleFloat; }
+  bool isTargetCOFF() const { return TargetTriple.isOSBinFormatCOFF(); }
   bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); }
   bool hasVFPU() const { return HasVFPU; }
   bool inMips16Mode() const { return InMips16Mode; }
@@ -355,6 +356,7 @@ class MipsSubtarget : public MipsGenSubtargetInfo {
   bool os16() const { return Os16; }
 
   bool isTargetNaCl() const { return TargetTriple.isOSNaCl(); }
+  bool isTargetWindows() const { return TargetTriple.isOSWindows(); }
 
   bool isXRaySupported() const override { return true; }
 
diff --git a/llvm/test/CodeGen/Mips/dllimport.ll b/llvm/test/CodeGen/Mips/dllimport.ll
new file mode 100644
index 00000000000000..385199892821e7
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/dllimport.ll
@@ -0,0 +1,55 @@
+; RUN: llc -mtriple mipsel-windows < %s | FileCheck %s
+
+ at Var1 = external dllimport global i32
+ at Var2 = available_externally dllimport unnamed_addr constant i32 1
+
+declare dllimport void @fun()
+
+define available_externally dllimport void @inline1() {
+	ret void
+}
+
+define available_externally dllimport void @inline2() alwaysinline {
+	ret void
+}
+
+declare void @dummy(...)
+
+define void @use() nounwind {
+; CHECK:     lui $1, %hi(__imp_fun)
+; CHECK:     addiu $1, $1, %lo(__imp_fun)
+; CHECK:     lw $25, 0($1)
+; CHECK:     jalr $25
+  call void @fun()
+
+; CHECK:     lui $1, %hi(__imp_inline1)
+; CHECK:     addiu $1, $1, %lo(__imp_inline1)
+; CHECK:     lw $25, 0($1)
+; CHECK:     jalr $25
+  call void @inline1()
+
+; CHECK:     lui $1, %hi(__imp_inline2)
+; CHECK:     addiu $1, $1, %lo(__imp_inline2)
+; CHECK:     lw $25, 0($1)
+; CHECK:     jalr $25
+  call void @inline2()
+
+; CHECK:     lui $1, %hi(__imp_Var2)
+; CHECK:     addiu $1, $1, %lo(__imp_Var2)
+; CHECK:     lw $1, 0($1)
+; CHECK:     lw $5, 0($1)
+; CHECK:     lui $1, %hi(__imp_Var1)
+; CHECK:     addiu $1, $1, %lo(__imp_Var1)
+; CHECK:     lw $1, 0($1)
+; CHECK:     lw $4, 0($1)
+  %1 = load i32, ptr @Var1
+  %2 = load i32, ptr @Var2
+  call void(...) @dummy(i32 %1, i32 %2)
+
+  ret void
+}
+
+; CHECK: fp:
+; CHECK-NEXT: .long fun
+ at fp = constant ptr @fun
+
diff --git a/llvm/test/MC/Mips/coff-relocs-dllimport.ll b/llvm/test/MC/Mips/coff-relocs-dllimport.ll
new file mode 100644
index 00000000000000..525f5f3b1532a4
--- /dev/null
+++ b/llvm/test/MC/Mips/coff-relocs-dllimport.ll
@@ -0,0 +1,12 @@
+; RUN: llc -mtriple mipsel-windows -filetype obj < %s | llvm-objdump --reloc - | FileCheck %s
+
+declare dllimport void @fun()
+
+define void @use() nounwind {
+; CHECK: 00000008 IMAGE_REL_MIPS_REFHI     __imp_fun
+; CHECK: 00000008 IMAGE_REL_MIPS_PAIR      __imp_fun
+; CHECK: 0000000c IMAGE_REL_MIPS_REFLO     __imp_fun
+  call void() @fun()
+
+  ret void
+}

>From 2ff487f56d35f0f5a2d119a55d3a8eacc0b64f04 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= <hpoussin at reactos.org>
Date: Sun, 22 Oct 2023 14:12:42 +0200
Subject: [PATCH 09/13] [llvm-lib] Handle MIPS architecture

---
 llvm/lib/Object/COFFImportFile.cpp          |  2 ++
 llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp |  3 +++
 llvm/test/tools/llvm-lib/machine.test       | 13 +++++++++++++
 3 files changed, 18 insertions(+)
 create mode 100644 llvm/test/tools/llvm-lib/machine.test

diff --git a/llvm/lib/Object/COFFImportFile.cpp b/llvm/lib/Object/COFFImportFile.cpp
index cc0a5da7e0d16a..8f63b828ed16f5 100644
--- a/llvm/lib/Object/COFFImportFile.cpp
+++ b/llvm/lib/Object/COFFImportFile.cpp
@@ -133,6 +133,8 @@ static uint16_t getImgRelRelocation(MachineTypes Machine) {
     return IMAGE_REL_ARM64_ADDR32NB;
   case IMAGE_FILE_MACHINE_I386:
     return IMAGE_REL_I386_DIR32NB;
+  case IMAGE_FILE_MACHINE_R4000:
+    return IMAGE_REL_MIPS_REFWORDNB;
   }
 }
 
diff --git a/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp b/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
index 07389a5ffb2b8a..617fd8f031ac87 100644
--- a/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
+++ b/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
@@ -168,6 +168,7 @@ static Expected<COFF::MachineTypes> getCOFFFileMachine(MemoryBufferRef MB) {
   uint16_t Machine = (*Obj)->getMachine();
   if (Machine != COFF::IMAGE_FILE_MACHINE_I386 &&
       Machine != COFF::IMAGE_FILE_MACHINE_AMD64 &&
+      Machine != COFF::IMAGE_FILE_MACHINE_R4000 &&
       Machine != COFF::IMAGE_FILE_MACHINE_ARMNT && !COFF::isAnyArm64(Machine)) {
     return createStringError(inconvertibleErrorCode(),
                              "unknown machine: " + std::to_string(Machine));
@@ -192,6 +193,8 @@ static Expected<COFF::MachineTypes> getBitcodeFileMachine(MemoryBufferRef MB) {
   case Triple::aarch64:
     return T.isWindowsArm64EC() ? COFF::IMAGE_FILE_MACHINE_ARM64EC
                                 : COFF::IMAGE_FILE_MACHINE_ARM64;
+  case Triple::mipsel:
+    return COFF::IMAGE_FILE_MACHINE_R4000;
   default:
     return createStringError(inconvertibleErrorCode(),
                              "unknown arch in target triple: " + *TripleStr);
diff --git a/llvm/test/tools/llvm-lib/machine.test b/llvm/test/tools/llvm-lib/machine.test
new file mode 100644
index 00000000000000..db85d589d773d7
--- /dev/null
+++ b/llvm/test/tools/llvm-lib/machine.test
@@ -0,0 +1,13 @@
+RUN: rm -f %t.lib
+
+RUN: llvm-lib /out:%t.lib /machine:i386 2>&1 | FileCheck --check-prefix=EMPTYWARN %s
+RUN: llvm-lib /out:%t.lib /machine:amd64 2>&1 | FileCheck --check-prefix=EMPTYWARN %s
+
+RUN: llvm-lib /out:%t.lib /machine:mipsel 2>&1 | FileCheck --check-prefix=EMPTYWARN %s
+
+RUN: llvm-lib /out:%t.lib /machine:arm 2>&1 | FileCheck --check-prefix=EMPTYWARN %s
+RUN: llvm-lib /out:%t.lib /machine:arm64 2>&1 | FileCheck --check-prefix=EMPTYWARN %s
+RUN: llvm-lib /out:%t.lib /machine:arm64x 2>&1 | FileCheck --check-prefix=EMPTYWARN %s
+
+EMPTYWARN: warning: no input files, not writing output file
+

>From bb68336492732909000c8a8ef7d0a850ababb40c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= <hpoussin at reactos.org>
Date: Sun, 22 Oct 2023 17:10:19 +0200
Subject: [PATCH 10/13] [llvm-dlltool] Handle MIPS architecture

---
 llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp | 1 +
 llvm/test/tools/llvm-dlltool/machine-opt.def        | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp b/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp
index 15e4cac08cd4ed..91e62b8d46dc9f 100644
--- a/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp
+++ b/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp
@@ -76,6 +76,7 @@ MachineTypes getEmulation(StringRef S) {
       .Case("arm", IMAGE_FILE_MACHINE_ARMNT)
       .Case("arm64", IMAGE_FILE_MACHINE_ARM64)
       .Case("arm64ec", IMAGE_FILE_MACHINE_ARM64EC)
+      .Case("mipsel", IMAGE_FILE_MACHINE_R4000)
       .Default(IMAGE_FILE_MACHINE_UNKNOWN);
 }
 
diff --git a/llvm/test/tools/llvm-dlltool/machine-opt.def b/llvm/test/tools/llvm-dlltool/machine-opt.def
index 6dce8255a43db3..5f28c2a1790245 100644
--- a/llvm/test/tools/llvm-dlltool/machine-opt.def
+++ b/llvm/test/tools/llvm-dlltool/machine-opt.def
@@ -6,6 +6,8 @@
 ; RUN: llvm-readobj %t.a | FileCheck --check-prefix=ARM %s
 ; RUN: llvm-dlltool -m arm64 -d %s -l %t.a
 ; RUN: llvm-readobj %t.a | FileCheck --check-prefix=ARM64 %s
+; RUN: llvm-dlltool -m mipsel -d %s -l %t.a
+; RUN: llvm-readobj %t.a | FileCheck --check-prefix=MIPSEL %s
 
 LIBRARY test.dll
 EXPORTS
@@ -15,3 +17,4 @@ TestFunction
 ; X86_64: Format: COFF-x86-64
 ; ARM: Format: COFF-ARM{{$}}
 ; ARM64: Format: COFF-ARM64
+; MIPSEL: Format: COFF-R4000

>From 9522eab04f163931c246129cc8e21ea527a513ce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= <hpoussin at reactos.org>
Date: Sun, 22 Oct 2023 17:01:02 +0200
Subject: [PATCH 11/13] [Clang][MIPS] Create specific targets for MIPS PE/COFF

Implement GNU and MSVC variants.
When using them, _WIN32 and _M_MRX000/_MIPS_ macros are correctly defined.
---
 clang/lib/Basic/Targets.cpp                   |  8 +++
 clang/lib/Basic/Targets/Mips.cpp              | 60 +++++++++++++++++++
 clang/lib/Basic/Targets/Mips.h                | 36 +++++++++++
 .../test/Preprocessor/predefined-win-macros.c | 16 +++++
 4 files changed, 120 insertions(+)

diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index 0b8e565345b6a4..5774b9d9499f37 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -297,6 +297,14 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
     case llvm::Triple::NaCl:
       return std::make_unique<NaClTargetInfo<NaClMips32TargetInfo>>(Triple,
                                                                     Opts);
+    case llvm::Triple::Win32:
+      switch (Triple.getEnvironment()) {
+      case llvm::Triple::GNU:
+        return std::make_unique<MinGWMipsTargetInfo>(Triple, Opts);
+      case llvm::Triple::MSVC:
+      default: // Assume MSVC for unknown environments
+        return std::make_unique<MicrosoftMipsTargetInfo>(Triple, Opts);
+      }
     default:
       return std::make_unique<MipsTargetInfo>(Triple, Opts);
     }
diff --git a/clang/lib/Basic/Targets/Mips.cpp b/clang/lib/Basic/Targets/Mips.cpp
index 174bc9d2ab9967..858cdd1c6f49a2 100644
--- a/clang/lib/Basic/Targets/Mips.cpp
+++ b/clang/lib/Basic/Targets/Mips.cpp
@@ -304,3 +304,63 @@ bool MipsTargetInfo::validateTarget(DiagnosticsEngine &Diags) const {
 
   return true;
 }
+
+WindowsMipsTargetInfo::WindowsMipsTargetInfo(const llvm::Triple &Triple,
+                                             const TargetOptions &Opts)
+    : WindowsTargetInfo<MipsTargetInfo>(Triple, Opts), Triple(Triple) {
+}
+
+void WindowsMipsTargetInfo::getVisualStudioDefines(const LangOptions &Opts,
+                                                   MacroBuilder &Builder) const {
+  Builder.defineMacro("_M_MRX000", "4000");
+}
+
+TargetInfo::BuiltinVaListKind
+WindowsMipsTargetInfo::getBuiltinVaListKind() const {
+  return TargetInfo::CharPtrBuiltinVaList;
+}
+
+TargetInfo::CallingConvCheckResult
+WindowsMipsTargetInfo::checkCallingConvention(CallingConv CC) const {
+  switch (CC) {
+  case CC_X86StdCall:
+  case CC_X86ThisCall:
+  case CC_X86FastCall:
+  case CC_X86VectorCall:
+    return CCCR_Ignore;
+  case CC_C:
+  case CC_OpenCLKernel:
+  case CC_PreserveMost:
+  case CC_PreserveAll:
+  case CC_Swift:
+  case CC_SwiftAsync:
+    return CCCR_OK;
+  default:
+    return CCCR_Warning;
+  }
+}
+
+// Windows MIPS, MS (C++) ABI
+MicrosoftMipsTargetInfo::MicrosoftMipsTargetInfo(const llvm::Triple &Triple,
+                                                 const TargetOptions &Opts)
+    : WindowsMipsTargetInfo(Triple, Opts) {
+  TheCXXABI.set(TargetCXXABI::Microsoft);
+}
+
+void MicrosoftMipsTargetInfo::getTargetDefines(const LangOptions &Opts,
+                                               MacroBuilder &Builder) const {
+  WindowsMipsTargetInfo::getTargetDefines(Opts, Builder);
+  WindowsMipsTargetInfo::getVisualStudioDefines(Opts, Builder);
+}
+
+MinGWMipsTargetInfo::MinGWMipsTargetInfo(const llvm::Triple &Triple,
+                                         const TargetOptions &Opts)
+    : WindowsMipsTargetInfo(Triple, Opts) {
+  TheCXXABI.set(TargetCXXABI::GenericMIPS);
+}
+
+void MinGWMipsTargetInfo::getTargetDefines(const LangOptions &Opts,
+                                           MacroBuilder &Builder) const {
+  WindowsMipsTargetInfo::getTargetDefines(Opts, Builder);
+  Builder.defineMacro("_MIPS_");
+}
diff --git a/clang/lib/Basic/Targets/Mips.h b/clang/lib/Basic/Targets/Mips.h
index b6f110249fa78e..b138710bb83d39 100644
--- a/clang/lib/Basic/Targets/Mips.h
+++ b/clang/lib/Basic/Targets/Mips.h
@@ -13,6 +13,7 @@
 #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H
 #define LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H
 
+#include "OSTargets.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/TargetOptions.h"
 #include "llvm/Support/Compiler.h"
@@ -450,6 +451,41 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {
     return std::make_pair(32, 32);
   }
 };
+
+class LLVM_LIBRARY_VISIBILITY WindowsMipsTargetInfo
+    : public WindowsTargetInfo<MipsTargetInfo> {
+  const llvm::Triple Triple;
+
+public:
+  WindowsMipsTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+
+  void getVisualStudioDefines(const LangOptions &Opts,
+                              MacroBuilder &Builder) const;
+
+  BuiltinVaListKind getBuiltinVaListKind() const override;
+
+  CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;
+};
+
+// Windows MIPS, MS (C++) ABI
+class LLVM_LIBRARY_VISIBILITY MicrosoftMipsTargetInfo
+    : public WindowsMipsTargetInfo {
+public:
+  MicrosoftMipsTargetInfo(const llvm::Triple &Triple,
+                          const TargetOptions &Opts);
+
+  void getTargetDefines(const LangOptions &Opts,
+                        MacroBuilder &Builder) const override;
+};
+
+// MIPS MinGW target
+class LLVM_LIBRARY_VISIBILITY MinGWMipsTargetInfo : public WindowsMipsTargetInfo {
+public:
+  MinGWMipsTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+
+  void getTargetDefines(const LangOptions &Opts,
+                        MacroBuilder &Builder) const override;
+};
 } // namespace targets
 } // namespace clang
 
diff --git a/clang/test/Preprocessor/predefined-win-macros.c b/clang/test/Preprocessor/predefined-win-macros.c
index 7d29e45c7d5ac6..8635724bd620b2 100644
--- a/clang/test/Preprocessor/predefined-win-macros.c
+++ b/clang/test/Preprocessor/predefined-win-macros.c
@@ -108,6 +108,13 @@
 // CHECK-ARM64EC-WIN: #define _WIN32 1
 // CHECK-ARM64EC-WIN: #define _WIN64 1
 
+// RUN: %clang_cc1 -triple mipsel-windows %s -E -dM -o - \
+// RUN:   | FileCheck -match-full-lines %s --check-prefix=CHECK-MIPSEL-WIN
+
+// CHECK-MIPSEL-WIN: #define _M_MRX000 4000
+// CHECK-MIPSEL-WIN: #define _WIN32 1
+// CHECK-MIPSEL-WIN-NOT: #define _MIPS_ 1
+
 // RUN: %clang_cc1 -triple i686-windows-gnu %s -E -dM -o - \
 // RUN:   | FileCheck -match-full-lines %s --check-prefix=CHECK-X86-MINGW
 
@@ -168,3 +175,12 @@
 // CHECK-ARM64EC-MINGW: #define __arm64ec__ 1
 // CHECK-ARM64EC-MINGW: #define __x86_64 1
 // CHECK-ARM64EC-MINGW: #define __x86_64__ 1
+
+// RUN: %clang_cc1 -triple mipsel-windows-gnu %s -E -dM -o - \
+// RUN:   | FileCheck -match-full-lines %s --check-prefix=CHECK-MIPSEL-MINGW
+
+// CHECK-MIPSEL-MINGW-NOT: #define _M_MRX000 4000
+// CHECK-MIPSEL-MINGW: #define _MIPS_ 1
+// CHECK-MIPSEL-MINGW: #define _WIN32 1
+// CHECK-MIPSEL-MINGW: #define __mips 32
+// CHECK-MIPSEL-MINGW: #define __mips__ 1

>From dd450b41a721468cefdf63f18aee7566e0e59913 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= <hpoussin at reactos.org>
Date: Fri, 10 Nov 2023 23:06:52 +0100
Subject: [PATCH 12/13] [Clang][MIPS] Create correct linker arguments for
 Windows toolchains

---
 clang/lib/CodeGen/CodeGenModule.cpp |  2 ++
 clang/lib/CodeGen/TargetInfo.h      |  3 +++
 clang/lib/CodeGen/Targets/Mips.cpp  | 23 +++++++++++++++++++++++
 clang/test/CodeGen/pragma-comment.c |  1 +
 4 files changed, 29 insertions(+)

diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index df4c13c9ad97aa..0237fdad54c1c2 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -122,6 +122,8 @@ createTargetCodeGenInfo(CodeGenModule &CGM) {
   case llvm::Triple::mipsel:
     if (Triple.getOS() == llvm::Triple::NaCl)
       return createPNaClTargetCodeGenInfo(CGM);
+    else if (Triple.getOS() == llvm::Triple::Win32)
+      return createWindowsMIPSTargetCodeGenInfo(CGM, /*IsOS32=*/true);
     return createMIPSTargetCodeGenInfo(CGM, /*IsOS32=*/true);
 
   case llvm::Triple::mips64:
diff --git a/clang/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h
index 0244ca006d498b..7ab02b21708e76 100644
--- a/clang/lib/CodeGen/TargetInfo.h
+++ b/clang/lib/CodeGen/TargetInfo.h
@@ -502,6 +502,9 @@ createM68kTargetCodeGenInfo(CodeGenModule &CGM);
 std::unique_ptr<TargetCodeGenInfo>
 createMIPSTargetCodeGenInfo(CodeGenModule &CGM, bool IsOS32);
 
+std::unique_ptr<TargetCodeGenInfo>
+createWindowsMIPSTargetCodeGenInfo(CodeGenModule &CGM, bool IsOS32);
+
 std::unique_ptr<TargetCodeGenInfo>
 createMSP430TargetCodeGenInfo(CodeGenModule &CGM);
 
diff --git a/clang/lib/CodeGen/Targets/Mips.cpp b/clang/lib/CodeGen/Targets/Mips.cpp
index 06d9b6d4a57615..e7601564f67d1d 100644
--- a/clang/lib/CodeGen/Targets/Mips.cpp
+++ b/clang/lib/CodeGen/Targets/Mips.cpp
@@ -105,6 +105,24 @@ class MIPSTargetCodeGenInfo : public TargetCodeGenInfo {
     return SizeOfUnwindException;
   }
 };
+
+class WindowsMIPSTargetCodeGenInfo : public MIPSTargetCodeGenInfo {
+public:
+  WindowsMIPSTargetCodeGenInfo(CodeGenTypes &CGT, bool IsO32)
+        : MIPSTargetCodeGenInfo(CGT, IsO32) {}
+
+  void getDependentLibraryOption(llvm::StringRef Lib,
+                                 llvm::SmallString<24> &Opt) const override {
+    Opt = "/DEFAULTLIB:";
+    Opt += qualifyWindowsLibrary(Lib);
+  }
+
+  void getDetectMismatchOption(llvm::StringRef Name,
+                               llvm::StringRef Value,
+                               llvm::SmallString<32> &Opt) const override {
+    Opt = "/FAILIFMISMATCH:\"" + Name.str() + "=" + Value.str() + "\"";
+  }
+};
 }
 
 void MipsABIInfo::CoerceToIntArgs(
@@ -436,3 +454,8 @@ std::unique_ptr<TargetCodeGenInfo>
 CodeGen::createMIPSTargetCodeGenInfo(CodeGenModule &CGM, bool IsOS32) {
   return std::make_unique<MIPSTargetCodeGenInfo>(CGM.getTypes(), IsOS32);
 }
+
+std::unique_ptr<TargetCodeGenInfo>
+CodeGen::createWindowsMIPSTargetCodeGenInfo(CodeGenModule &CGM, bool IsOS32) {
+  return std::make_unique<WindowsMIPSTargetCodeGenInfo>(CGM.getTypes(), IsOS32);
+}
diff --git a/clang/test/CodeGen/pragma-comment.c b/clang/test/CodeGen/pragma-comment.c
index a4746f5c47bf6b..a966840f7c26fc 100644
--- a/clang/test/CodeGen/pragma-comment.c
+++ b/clang/test/CodeGen/pragma-comment.c
@@ -6,6 +6,7 @@
 // RUN: %clang_cc1 %s -triple x86_64-scei-ps4 -fms-extensions -emit-llvm -o - | FileCheck -check-prefix ELF %s --implicit-check-not llvm.linker.options
 // RUN: %clang_cc1 %s -triple x86_64-sie-ps5 -fms-extensions -emit-llvm -o - | FileCheck -check-prefix ELF %s --implicit-check-not llvm.linker.options
 // RUN: %clang_cc1 %s -triple aarch64-windows-msvc -fms-extensions -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple mipsel-windows-msvc -fms-extensions -emit-llvm -o - | FileCheck %s
 
 #pragma comment(lib, "msvcrt.lib")
 #pragma comment(lib, "kernel32")

>From c5c3de2bab98cadac44c665e7967ab8b269eacf7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= <hpoussin at reactos.org>
Date: Fri, 10 Nov 2023 23:09:05 +0100
Subject: [PATCH 13/13] [Clang][MIPS] Send correct architecture for MinGW
 toolchains

'mipspe' name was chosen by binutils, when the project was able to create
executables for Windows CE/MIPS.
---
 clang/lib/Driver/ToolChains/MinGW.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp
index c81a7ed1702963..f24cc71263ddbe 100644
--- a/clang/lib/Driver/ToolChains/MinGW.cpp
+++ b/clang/lib/Driver/ToolChains/MinGW.cpp
@@ -137,6 +137,9 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     else
       CmdArgs.push_back("arm64pe");
     break;
+  case llvm::Triple::mipsel:
+    CmdArgs.push_back("mipspe");
+    break;
   default:
     D.Diag(diag::err_target_unknown_triple) << TC.getEffectiveTriple().str();
   }



More information about the cfe-commits mailing list