[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