[lld] r305742 - LLD: Move ELF/Mips.cpp to ELF/Arch/MipsArchTree.cpp

Konstantin Zhuravlyov via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 19 14:03:58 PDT 2017


Author: kzhuravl
Date: Mon Jun 19 16:03:57 2017
New Revision: 305742

URL: http://llvm.org/viewvc/llvm-project?rev=305742&view=rev
Log:
LLD: Move ELF/Mips.cpp to ELF/Arch/MipsArchTree.cpp

Differential Revision: https://reviews.llvm.org/D34358

Added:
    lld/trunk/ELF/Arch/MipsArchTree.cpp
Removed:
    lld/trunk/ELF/Mips.cpp
Modified:
    lld/trunk/ELF/CMakeLists.txt

Added: lld/trunk/ELF/Arch/MipsArchTree.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/MipsArchTree.cpp?rev=305742&view=auto
==============================================================================
--- lld/trunk/ELF/Arch/MipsArchTree.cpp (added)
+++ lld/trunk/ELF/Arch/MipsArchTree.cpp Mon Jun 19 16:03:57 2017
@@ -0,0 +1,369 @@
+//===- MipsArchTree.cpp --------------------------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+//
+// This file contains a helper function for the Writer.
+//
+//===---------------------------------------------------------------------===//
+
+#include "Error.h"
+#include "InputFiles.h"
+#include "SymbolTable.h"
+#include "Writer.h"
+
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/Object/ELF.h"
+#include "llvm/Support/MipsABIFlags.h"
+
+using namespace llvm;
+using namespace llvm::object;
+using namespace llvm::ELF;
+
+using namespace lld;
+using namespace lld::elf;
+
+namespace {
+struct ArchTreeEdge {
+  uint32_t Child;
+  uint32_t Parent;
+};
+
+struct FileFlags {
+  StringRef Filename;
+  uint32_t Flags;
+};
+}
+
+static StringRef getAbiName(uint32_t Flags) {
+  switch (Flags) {
+  case 0:
+    return "n64";
+  case EF_MIPS_ABI2:
+    return "n32";
+  case EF_MIPS_ABI_O32:
+    return "o32";
+  case EF_MIPS_ABI_O64:
+    return "o64";
+  case EF_MIPS_ABI_EABI32:
+    return "eabi32";
+  case EF_MIPS_ABI_EABI64:
+    return "eabi64";
+  default:
+    return "unknown";
+  }
+}
+
+static StringRef getNanName(bool IsNan2008) {
+  return IsNan2008 ? "2008" : "legacy";
+}
+
+static StringRef getFpName(bool IsFp64) { return IsFp64 ? "64" : "32"; }
+
+static void checkFlags(ArrayRef<FileFlags> Files) {
+  uint32_t ABI = Files[0].Flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
+  bool Nan = Files[0].Flags & EF_MIPS_NAN2008;
+  bool Fp = Files[0].Flags & EF_MIPS_FP64;
+
+  for (const FileFlags &F : Files.slice(1)) {
+    uint32_t ABI2 = F.Flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
+    if (ABI != ABI2)
+      error("target ABI '" + getAbiName(ABI) + "' is incompatible with '" +
+            getAbiName(ABI2) + "': " + F.Filename);
+
+    bool Nan2 = F.Flags & EF_MIPS_NAN2008;
+    if (Nan != Nan2)
+      error("target -mnan=" + getNanName(Nan) + " is incompatible with -mnan=" +
+            getNanName(Nan2) + ": " + F.Filename);
+
+    bool Fp2 = F.Flags & EF_MIPS_FP64;
+    if (Fp != Fp2)
+      error("target -mfp" + getFpName(Fp) + " is incompatible with -mfp" +
+            getFpName(Fp2) + ": " + F.Filename);
+  }
+}
+
+static uint32_t getMiscFlags(ArrayRef<FileFlags> Files) {
+  uint32_t Ret = 0;
+  for (const FileFlags &F : Files)
+    Ret |= F.Flags &
+           (EF_MIPS_ABI | EF_MIPS_ABI2 | EF_MIPS_ARCH_ASE | EF_MIPS_NOREORDER |
+            EF_MIPS_MICROMIPS | EF_MIPS_NAN2008 | EF_MIPS_32BITMODE);
+  return Ret;
+}
+
+static uint32_t getPicFlags(ArrayRef<FileFlags> Files) {
+  // Check PIC/non-PIC compatibility.
+  bool IsPic = Files[0].Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
+  for (const FileFlags &F : Files.slice(1)) {
+    bool IsPic2 = F.Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
+    if (IsPic && !IsPic2)
+      warn("linking abicalls code with non-abicalls file: " + F.Filename);
+    if (!IsPic && IsPic2)
+      warn("linking non-abicalls code with abicalls file: " + F.Filename);
+  }
+
+  // Compute the result PIC/non-PIC flag.
+  uint32_t Ret = Files[0].Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
+  for (const FileFlags &F : Files.slice(1))
+    Ret &= F.Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
+
+  // PIC code is inherently CPIC and may not set CPIC flag explicitly.
+  if (Ret & EF_MIPS_PIC)
+    Ret |= EF_MIPS_CPIC;
+  return Ret;
+}
+
+static ArchTreeEdge ArchTree[] = {
+    // MIPS32R6 and MIPS64R6 are not compatible with other extensions
+    // MIPS64R2 extensions.
+    {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON3, EF_MIPS_ARCH_64R2},
+    {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON2, EF_MIPS_ARCH_64R2},
+    {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON, EF_MIPS_ARCH_64R2},
+    {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_LS3A, EF_MIPS_ARCH_64R2},
+    // MIPS64 extensions.
+    {EF_MIPS_ARCH_64 | EF_MIPS_MACH_SB1, EF_MIPS_ARCH_64},
+    {EF_MIPS_ARCH_64 | EF_MIPS_MACH_XLR, EF_MIPS_ARCH_64},
+    {EF_MIPS_ARCH_64R2, EF_MIPS_ARCH_64},
+    // MIPS V extensions.
+    {EF_MIPS_ARCH_64, EF_MIPS_ARCH_5},
+    // R5000 extensions.
+    {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5500, EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400},
+    // MIPS IV extensions.
+    {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400, EF_MIPS_ARCH_4},
+    {EF_MIPS_ARCH_4 | EF_MIPS_MACH_9000, EF_MIPS_ARCH_4},
+    {EF_MIPS_ARCH_5, EF_MIPS_ARCH_4},
+    // VR4100 extensions.
+    {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4111, EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100},
+    {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4120, EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100},
+    // MIPS III extensions.
+    {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4010, EF_MIPS_ARCH_3},
+    {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100, EF_MIPS_ARCH_3},
+    {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4650, EF_MIPS_ARCH_3},
+    {EF_MIPS_ARCH_3 | EF_MIPS_MACH_5900, EF_MIPS_ARCH_3},
+    {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2E, EF_MIPS_ARCH_3},
+    {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2F, EF_MIPS_ARCH_3},
+    {EF_MIPS_ARCH_4, EF_MIPS_ARCH_3},
+    // MIPS32 extensions.
+    {EF_MIPS_ARCH_32R2, EF_MIPS_ARCH_32},
+    // MIPS II extensions.
+    {EF_MIPS_ARCH_3, EF_MIPS_ARCH_2},
+    {EF_MIPS_ARCH_32, EF_MIPS_ARCH_2},
+    // MIPS I extensions.
+    {EF_MIPS_ARCH_1 | EF_MIPS_MACH_3900, EF_MIPS_ARCH_1},
+    {EF_MIPS_ARCH_2, EF_MIPS_ARCH_1},
+};
+
+static bool isArchMatched(uint32_t New, uint32_t Res) {
+  if (New == Res)
+    return true;
+  if (New == EF_MIPS_ARCH_32 && isArchMatched(EF_MIPS_ARCH_64, Res))
+    return true;
+  if (New == EF_MIPS_ARCH_32R2 && isArchMatched(EF_MIPS_ARCH_64R2, Res))
+    return true;
+  for (const auto &Edge : ArchTree) {
+    if (Res == Edge.Child) {
+      Res = Edge.Parent;
+      if (Res == New)
+        return true;
+    }
+  }
+  return false;
+}
+
+static StringRef getMachName(uint32_t Flags) {
+  switch (Flags & EF_MIPS_MACH) {
+  case EF_MIPS_MACH_NONE:
+    return "";
+  case EF_MIPS_MACH_3900:
+    return "r3900";
+  case EF_MIPS_MACH_4010:
+    return "r4010";
+  case EF_MIPS_MACH_4100:
+    return "r4100";
+  case EF_MIPS_MACH_4650:
+    return "r4650";
+  case EF_MIPS_MACH_4120:
+    return "r4120";
+  case EF_MIPS_MACH_4111:
+    return "r4111";
+  case EF_MIPS_MACH_5400:
+    return "vr5400";
+  case EF_MIPS_MACH_5900:
+    return "vr5900";
+  case EF_MIPS_MACH_5500:
+    return "vr5500";
+  case EF_MIPS_MACH_9000:
+    return "rm9000";
+  case EF_MIPS_MACH_LS2E:
+    return "loongson2e";
+  case EF_MIPS_MACH_LS2F:
+    return "loongson2f";
+  case EF_MIPS_MACH_LS3A:
+    return "loongson3a";
+  case EF_MIPS_MACH_OCTEON:
+    return "octeon";
+  case EF_MIPS_MACH_OCTEON2:
+    return "octeon2";
+  case EF_MIPS_MACH_OCTEON3:
+    return "octeon3";
+  case EF_MIPS_MACH_SB1:
+    return "sb1";
+  case EF_MIPS_MACH_XLR:
+    return "xlr";
+  default:
+    return "unknown machine";
+  }
+}
+
+static StringRef getArchName(uint32_t Flags) {
+  StringRef S = getMachName(Flags);
+  if (!S.empty())
+    return S;
+
+  switch (Flags & EF_MIPS_ARCH) {
+  case EF_MIPS_ARCH_1:
+    return "mips1";
+  case EF_MIPS_ARCH_2:
+    return "mips2";
+  case EF_MIPS_ARCH_3:
+    return "mips3";
+  case EF_MIPS_ARCH_4:
+    return "mips4";
+  case EF_MIPS_ARCH_5:
+    return "mips5";
+  case EF_MIPS_ARCH_32:
+    return "mips32";
+  case EF_MIPS_ARCH_64:
+    return "mips64";
+  case EF_MIPS_ARCH_32R2:
+    return "mips32r2";
+  case EF_MIPS_ARCH_64R2:
+    return "mips64r2";
+  case EF_MIPS_ARCH_32R6:
+    return "mips32r6";
+  case EF_MIPS_ARCH_64R6:
+    return "mips64r6";
+  default:
+    return "unknown arch";
+  }
+}
+
+// There are (arguably too) many MIPS ISAs out there. Their relationships
+// can be represented as a forest. If all input files have ISAs which
+// reachable by repeated proceeding from the single child to the parent,
+// these input files are compatible. In that case we need to return "highest"
+// ISA. If there are incompatible input files, we show an error.
+// For example, mips1 is a "parent" of mips2 and such files are compatible.
+// Output file gets EF_MIPS_ARCH_2 flag. From the other side mips3 and mips32
+// are incompatible because nor mips3 is a parent for misp32, nor mips32
+// is a parent for mips3.
+static uint32_t getArchFlags(ArrayRef<FileFlags> Files) {
+  uint32_t Ret = Files[0].Flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
+
+  for (const FileFlags &F : Files.slice(1)) {
+    uint32_t New = F.Flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
+
+    // Check ISA compatibility.
+    if (isArchMatched(New, Ret))
+      continue;
+    if (!isArchMatched(Ret, New)) {
+      error("target ISA '" + getArchName(Ret) + "' is incompatible with '" +
+            getArchName(New) + "': " + F.Filename);
+      return 0;
+    }
+    Ret = New;
+  }
+  return Ret;
+}
+
+template <class ELFT> uint32_t elf::getMipsEFlags() {
+  std::vector<FileFlags> V;
+  for (elf::ObjectFile<ELFT> *F : Symtab<ELFT>::X->getObjectFiles())
+    V.push_back({F->getName(), F->getObj().getHeader()->e_flags});
+  if (V.empty())
+    return 0;
+  checkFlags(V);
+  return getMiscFlags(V) | getPicFlags(V) | getArchFlags(V);
+}
+
+static int compareMipsFpAbi(uint8_t FpA, uint8_t FpB) {
+  if (FpA == FpB)
+    return 0;
+  if (FpB == Mips::Val_GNU_MIPS_ABI_FP_ANY)
+    return 1;
+  if (FpB == Mips::Val_GNU_MIPS_ABI_FP_64A &&
+      FpA == Mips::Val_GNU_MIPS_ABI_FP_64)
+    return 1;
+  if (FpB != Mips::Val_GNU_MIPS_ABI_FP_XX)
+    return -1;
+  if (FpA == Mips::Val_GNU_MIPS_ABI_FP_DOUBLE ||
+      FpA == Mips::Val_GNU_MIPS_ABI_FP_64 ||
+      FpA == Mips::Val_GNU_MIPS_ABI_FP_64A)
+    return 1;
+  return -1;
+}
+
+static StringRef getMipsFpAbiName(uint8_t FpAbi) {
+  switch (FpAbi) {
+  case Mips::Val_GNU_MIPS_ABI_FP_ANY:
+    return "any";
+  case Mips::Val_GNU_MIPS_ABI_FP_DOUBLE:
+    return "-mdouble-float";
+  case Mips::Val_GNU_MIPS_ABI_FP_SINGLE:
+    return "-msingle-float";
+  case Mips::Val_GNU_MIPS_ABI_FP_SOFT:
+    return "-msoft-float";
+  case Mips::Val_GNU_MIPS_ABI_FP_OLD_64:
+    return "-mips32r2 -mfp64 (old)";
+  case Mips::Val_GNU_MIPS_ABI_FP_XX:
+    return "-mfpxx";
+  case Mips::Val_GNU_MIPS_ABI_FP_64:
+    return "-mgp32 -mfp64";
+  case Mips::Val_GNU_MIPS_ABI_FP_64A:
+    return "-mgp32 -mfp64 -mno-odd-spreg";
+  default:
+    return "unknown";
+  }
+}
+
+uint8_t elf::getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag,
+                              StringRef FileName) {
+  if (compareMipsFpAbi(NewFlag, OldFlag) >= 0)
+    return NewFlag;
+  if (compareMipsFpAbi(OldFlag, NewFlag) < 0)
+    error("target floating point ABI '" + getMipsFpAbiName(OldFlag) +
+          "' is incompatible with '" + getMipsFpAbiName(NewFlag) + "': " +
+          FileName);
+  return OldFlag;
+}
+
+template <class ELFT> static bool isN32Abi(const InputFile *F) {
+  if (auto *EF = dyn_cast<ELFFileBase<ELFT>>(F))
+    return EF->getObj().getHeader()->e_flags & EF_MIPS_ABI2;
+  return false;
+}
+
+bool elf::isMipsN32Abi(const InputFile *F) {
+  switch (Config->EKind) {
+  case ELF32LEKind:
+    return isN32Abi<ELF32LE>(F);
+  case ELF32BEKind:
+    return isN32Abi<ELF32BE>(F);
+  case ELF64LEKind:
+    return isN32Abi<ELF64LE>(F);
+  case ELF64BEKind:
+    return isN32Abi<ELF64BE>(F);
+  default:
+    llvm_unreachable("unknown Config->EKind");
+  }
+}
+
+template uint32_t elf::getMipsEFlags<ELF32LE>();
+template uint32_t elf::getMipsEFlags<ELF32BE>();
+template uint32_t elf::getMipsEFlags<ELF64LE>();
+template uint32_t elf::getMipsEFlags<ELF64BE>();

Modified: lld/trunk/ELF/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/CMakeLists.txt?rev=305742&r1=305741&r2=305742&view=diff
==============================================================================
--- lld/trunk/ELF/CMakeLists.txt (original)
+++ lld/trunk/ELF/CMakeLists.txt Mon Jun 19 16:03:57 2017
@@ -12,6 +12,7 @@ add_lld_library(lldELF
   Arch/ARM.cpp
   Arch/AVR.cpp
   Arch/Mips.cpp
+  Arch/MipsArchTree.cpp
   Arch/PPC.cpp
   Arch/PPC64.cpp
   Arch/X86.cpp
@@ -29,7 +30,6 @@ add_lld_library(lldELF
   LinkerScript.cpp
   MapFile.cpp
   MarkLive.cpp
-  Mips.cpp
   OutputSections.cpp
   Relocations.cpp
   ScriptLexer.cpp

Removed: lld/trunk/ELF/Mips.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Mips.cpp?rev=305741&view=auto
==============================================================================
--- lld/trunk/ELF/Mips.cpp (original)
+++ lld/trunk/ELF/Mips.cpp (removed)
@@ -1,369 +0,0 @@
-//===- Mips.cpp ----------------------------------------------------------===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===---------------------------------------------------------------------===//
-//
-// This file contains a helper function for the Writer.
-//
-//===---------------------------------------------------------------------===//
-
-#include "Error.h"
-#include "InputFiles.h"
-#include "SymbolTable.h"
-#include "Writer.h"
-
-#include "llvm/BinaryFormat/ELF.h"
-#include "llvm/Object/ELF.h"
-#include "llvm/Support/MipsABIFlags.h"
-
-using namespace llvm;
-using namespace llvm::object;
-using namespace llvm::ELF;
-
-using namespace lld;
-using namespace lld::elf;
-
-namespace {
-struct ArchTreeEdge {
-  uint32_t Child;
-  uint32_t Parent;
-};
-
-struct FileFlags {
-  StringRef Filename;
-  uint32_t Flags;
-};
-}
-
-static StringRef getAbiName(uint32_t Flags) {
-  switch (Flags) {
-  case 0:
-    return "n64";
-  case EF_MIPS_ABI2:
-    return "n32";
-  case EF_MIPS_ABI_O32:
-    return "o32";
-  case EF_MIPS_ABI_O64:
-    return "o64";
-  case EF_MIPS_ABI_EABI32:
-    return "eabi32";
-  case EF_MIPS_ABI_EABI64:
-    return "eabi64";
-  default:
-    return "unknown";
-  }
-}
-
-static StringRef getNanName(bool IsNan2008) {
-  return IsNan2008 ? "2008" : "legacy";
-}
-
-static StringRef getFpName(bool IsFp64) { return IsFp64 ? "64" : "32"; }
-
-static void checkFlags(ArrayRef<FileFlags> Files) {
-  uint32_t ABI = Files[0].Flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
-  bool Nan = Files[0].Flags & EF_MIPS_NAN2008;
-  bool Fp = Files[0].Flags & EF_MIPS_FP64;
-
-  for (const FileFlags &F : Files.slice(1)) {
-    uint32_t ABI2 = F.Flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
-    if (ABI != ABI2)
-      error("target ABI '" + getAbiName(ABI) + "' is incompatible with '" +
-            getAbiName(ABI2) + "': " + F.Filename);
-
-    bool Nan2 = F.Flags & EF_MIPS_NAN2008;
-    if (Nan != Nan2)
-      error("target -mnan=" + getNanName(Nan) + " is incompatible with -mnan=" +
-            getNanName(Nan2) + ": " + F.Filename);
-
-    bool Fp2 = F.Flags & EF_MIPS_FP64;
-    if (Fp != Fp2)
-      error("target -mfp" + getFpName(Fp) + " is incompatible with -mfp" +
-            getFpName(Fp2) + ": " + F.Filename);
-  }
-}
-
-static uint32_t getMiscFlags(ArrayRef<FileFlags> Files) {
-  uint32_t Ret = 0;
-  for (const FileFlags &F : Files)
-    Ret |= F.Flags &
-           (EF_MIPS_ABI | EF_MIPS_ABI2 | EF_MIPS_ARCH_ASE | EF_MIPS_NOREORDER |
-            EF_MIPS_MICROMIPS | EF_MIPS_NAN2008 | EF_MIPS_32BITMODE);
-  return Ret;
-}
-
-static uint32_t getPicFlags(ArrayRef<FileFlags> Files) {
-  // Check PIC/non-PIC compatibility.
-  bool IsPic = Files[0].Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
-  for (const FileFlags &F : Files.slice(1)) {
-    bool IsPic2 = F.Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
-    if (IsPic && !IsPic2)
-      warn("linking abicalls code with non-abicalls file: " + F.Filename);
-    if (!IsPic && IsPic2)
-      warn("linking non-abicalls code with abicalls file: " + F.Filename);
-  }
-
-  // Compute the result PIC/non-PIC flag.
-  uint32_t Ret = Files[0].Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
-  for (const FileFlags &F : Files.slice(1))
-    Ret &= F.Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
-
-  // PIC code is inherently CPIC and may not set CPIC flag explicitly.
-  if (Ret & EF_MIPS_PIC)
-    Ret |= EF_MIPS_CPIC;
-  return Ret;
-}
-
-static ArchTreeEdge ArchTree[] = {
-    // MIPS32R6 and MIPS64R6 are not compatible with other extensions
-    // MIPS64R2 extensions.
-    {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON3, EF_MIPS_ARCH_64R2},
-    {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON2, EF_MIPS_ARCH_64R2},
-    {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON, EF_MIPS_ARCH_64R2},
-    {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_LS3A, EF_MIPS_ARCH_64R2},
-    // MIPS64 extensions.
-    {EF_MIPS_ARCH_64 | EF_MIPS_MACH_SB1, EF_MIPS_ARCH_64},
-    {EF_MIPS_ARCH_64 | EF_MIPS_MACH_XLR, EF_MIPS_ARCH_64},
-    {EF_MIPS_ARCH_64R2, EF_MIPS_ARCH_64},
-    // MIPS V extensions.
-    {EF_MIPS_ARCH_64, EF_MIPS_ARCH_5},
-    // R5000 extensions.
-    {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5500, EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400},
-    // MIPS IV extensions.
-    {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400, EF_MIPS_ARCH_4},
-    {EF_MIPS_ARCH_4 | EF_MIPS_MACH_9000, EF_MIPS_ARCH_4},
-    {EF_MIPS_ARCH_5, EF_MIPS_ARCH_4},
-    // VR4100 extensions.
-    {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4111, EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100},
-    {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4120, EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100},
-    // MIPS III extensions.
-    {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4010, EF_MIPS_ARCH_3},
-    {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100, EF_MIPS_ARCH_3},
-    {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4650, EF_MIPS_ARCH_3},
-    {EF_MIPS_ARCH_3 | EF_MIPS_MACH_5900, EF_MIPS_ARCH_3},
-    {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2E, EF_MIPS_ARCH_3},
-    {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2F, EF_MIPS_ARCH_3},
-    {EF_MIPS_ARCH_4, EF_MIPS_ARCH_3},
-    // MIPS32 extensions.
-    {EF_MIPS_ARCH_32R2, EF_MIPS_ARCH_32},
-    // MIPS II extensions.
-    {EF_MIPS_ARCH_3, EF_MIPS_ARCH_2},
-    {EF_MIPS_ARCH_32, EF_MIPS_ARCH_2},
-    // MIPS I extensions.
-    {EF_MIPS_ARCH_1 | EF_MIPS_MACH_3900, EF_MIPS_ARCH_1},
-    {EF_MIPS_ARCH_2, EF_MIPS_ARCH_1},
-};
-
-static bool isArchMatched(uint32_t New, uint32_t Res) {
-  if (New == Res)
-    return true;
-  if (New == EF_MIPS_ARCH_32 && isArchMatched(EF_MIPS_ARCH_64, Res))
-    return true;
-  if (New == EF_MIPS_ARCH_32R2 && isArchMatched(EF_MIPS_ARCH_64R2, Res))
-    return true;
-  for (const auto &Edge : ArchTree) {
-    if (Res == Edge.Child) {
-      Res = Edge.Parent;
-      if (Res == New)
-        return true;
-    }
-  }
-  return false;
-}
-
-static StringRef getMachName(uint32_t Flags) {
-  switch (Flags & EF_MIPS_MACH) {
-  case EF_MIPS_MACH_NONE:
-    return "";
-  case EF_MIPS_MACH_3900:
-    return "r3900";
-  case EF_MIPS_MACH_4010:
-    return "r4010";
-  case EF_MIPS_MACH_4100:
-    return "r4100";
-  case EF_MIPS_MACH_4650:
-    return "r4650";
-  case EF_MIPS_MACH_4120:
-    return "r4120";
-  case EF_MIPS_MACH_4111:
-    return "r4111";
-  case EF_MIPS_MACH_5400:
-    return "vr5400";
-  case EF_MIPS_MACH_5900:
-    return "vr5900";
-  case EF_MIPS_MACH_5500:
-    return "vr5500";
-  case EF_MIPS_MACH_9000:
-    return "rm9000";
-  case EF_MIPS_MACH_LS2E:
-    return "loongson2e";
-  case EF_MIPS_MACH_LS2F:
-    return "loongson2f";
-  case EF_MIPS_MACH_LS3A:
-    return "loongson3a";
-  case EF_MIPS_MACH_OCTEON:
-    return "octeon";
-  case EF_MIPS_MACH_OCTEON2:
-    return "octeon2";
-  case EF_MIPS_MACH_OCTEON3:
-    return "octeon3";
-  case EF_MIPS_MACH_SB1:
-    return "sb1";
-  case EF_MIPS_MACH_XLR:
-    return "xlr";
-  default:
-    return "unknown machine";
-  }
-}
-
-static StringRef getArchName(uint32_t Flags) {
-  StringRef S = getMachName(Flags);
-  if (!S.empty())
-    return S;
-
-  switch (Flags & EF_MIPS_ARCH) {
-  case EF_MIPS_ARCH_1:
-    return "mips1";
-  case EF_MIPS_ARCH_2:
-    return "mips2";
-  case EF_MIPS_ARCH_3:
-    return "mips3";
-  case EF_MIPS_ARCH_4:
-    return "mips4";
-  case EF_MIPS_ARCH_5:
-    return "mips5";
-  case EF_MIPS_ARCH_32:
-    return "mips32";
-  case EF_MIPS_ARCH_64:
-    return "mips64";
-  case EF_MIPS_ARCH_32R2:
-    return "mips32r2";
-  case EF_MIPS_ARCH_64R2:
-    return "mips64r2";
-  case EF_MIPS_ARCH_32R6:
-    return "mips32r6";
-  case EF_MIPS_ARCH_64R6:
-    return "mips64r6";
-  default:
-    return "unknown arch";
-  }
-}
-
-// There are (arguably too) many MIPS ISAs out there. Their relationships
-// can be represented as a forest. If all input files have ISAs which
-// reachable by repeated proceeding from the single child to the parent,
-// these input files are compatible. In that case we need to return "highest"
-// ISA. If there are incompatible input files, we show an error.
-// For example, mips1 is a "parent" of mips2 and such files are compatible.
-// Output file gets EF_MIPS_ARCH_2 flag. From the other side mips3 and mips32
-// are incompatible because nor mips3 is a parent for misp32, nor mips32
-// is a parent for mips3.
-static uint32_t getArchFlags(ArrayRef<FileFlags> Files) {
-  uint32_t Ret = Files[0].Flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
-
-  for (const FileFlags &F : Files.slice(1)) {
-    uint32_t New = F.Flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
-
-    // Check ISA compatibility.
-    if (isArchMatched(New, Ret))
-      continue;
-    if (!isArchMatched(Ret, New)) {
-      error("target ISA '" + getArchName(Ret) + "' is incompatible with '" +
-            getArchName(New) + "': " + F.Filename);
-      return 0;
-    }
-    Ret = New;
-  }
-  return Ret;
-}
-
-template <class ELFT> uint32_t elf::getMipsEFlags() {
-  std::vector<FileFlags> V;
-  for (elf::ObjectFile<ELFT> *F : Symtab<ELFT>::X->getObjectFiles())
-    V.push_back({F->getName(), F->getObj().getHeader()->e_flags});
-  if (V.empty())
-    return 0;
-  checkFlags(V);
-  return getMiscFlags(V) | getPicFlags(V) | getArchFlags(V);
-}
-
-static int compareMipsFpAbi(uint8_t FpA, uint8_t FpB) {
-  if (FpA == FpB)
-    return 0;
-  if (FpB == Mips::Val_GNU_MIPS_ABI_FP_ANY)
-    return 1;
-  if (FpB == Mips::Val_GNU_MIPS_ABI_FP_64A &&
-      FpA == Mips::Val_GNU_MIPS_ABI_FP_64)
-    return 1;
-  if (FpB != Mips::Val_GNU_MIPS_ABI_FP_XX)
-    return -1;
-  if (FpA == Mips::Val_GNU_MIPS_ABI_FP_DOUBLE ||
-      FpA == Mips::Val_GNU_MIPS_ABI_FP_64 ||
-      FpA == Mips::Val_GNU_MIPS_ABI_FP_64A)
-    return 1;
-  return -1;
-}
-
-static StringRef getMipsFpAbiName(uint8_t FpAbi) {
-  switch (FpAbi) {
-  case Mips::Val_GNU_MIPS_ABI_FP_ANY:
-    return "any";
-  case Mips::Val_GNU_MIPS_ABI_FP_DOUBLE:
-    return "-mdouble-float";
-  case Mips::Val_GNU_MIPS_ABI_FP_SINGLE:
-    return "-msingle-float";
-  case Mips::Val_GNU_MIPS_ABI_FP_SOFT:
-    return "-msoft-float";
-  case Mips::Val_GNU_MIPS_ABI_FP_OLD_64:
-    return "-mips32r2 -mfp64 (old)";
-  case Mips::Val_GNU_MIPS_ABI_FP_XX:
-    return "-mfpxx";
-  case Mips::Val_GNU_MIPS_ABI_FP_64:
-    return "-mgp32 -mfp64";
-  case Mips::Val_GNU_MIPS_ABI_FP_64A:
-    return "-mgp32 -mfp64 -mno-odd-spreg";
-  default:
-    return "unknown";
-  }
-}
-
-uint8_t elf::getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag,
-                              StringRef FileName) {
-  if (compareMipsFpAbi(NewFlag, OldFlag) >= 0)
-    return NewFlag;
-  if (compareMipsFpAbi(OldFlag, NewFlag) < 0)
-    error("target floating point ABI '" + getMipsFpAbiName(OldFlag) +
-          "' is incompatible with '" + getMipsFpAbiName(NewFlag) + "': " +
-          FileName);
-  return OldFlag;
-}
-
-template <class ELFT> static bool isN32Abi(const InputFile *F) {
-  if (auto *EF = dyn_cast<ELFFileBase<ELFT>>(F))
-    return EF->getObj().getHeader()->e_flags & EF_MIPS_ABI2;
-  return false;
-}
-
-bool elf::isMipsN32Abi(const InputFile *F) {
-  switch (Config->EKind) {
-  case ELF32LEKind:
-    return isN32Abi<ELF32LE>(F);
-  case ELF32BEKind:
-    return isN32Abi<ELF32BE>(F);
-  case ELF64LEKind:
-    return isN32Abi<ELF64LE>(F);
-  case ELF64BEKind:
-    return isN32Abi<ELF64BE>(F);
-  default:
-    llvm_unreachable("unknown Config->EKind");
-  }
-}
-
-template uint32_t elf::getMipsEFlags<ELF32LE>();
-template uint32_t elf::getMipsEFlags<ELF32BE>();
-template uint32_t elf::getMipsEFlags<ELF64LE>();
-template uint32_t elf::getMipsEFlags<ELF64BE>();




More information about the llvm-commits mailing list