[lld] r278042 - Refactor getMipsEFlags.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 8 12:39:45 PDT 2016


Author: ruiu
Date: Mon Aug  8 14:39:45 2016
New Revision: 278042

URL: http://llvm.org/viewvc/llvm-project?rev=278042&view=rev
Log:
Refactor getMipsEFlags.

Previously, we incrementally updated the reuslting flag as we check
file flags, so it was not very clear who is updating what flags.
This patch makes them pure functions -- that has no side effect and
don't update arguments to improve readability.

Now each function construct a patial result, and all resutls are then
bitwise-OR'ed to construct the final result.

This patch also creates a new file, Mips.cpp, to move all these
MIPS functions to a separate file.

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

Added:
    lld/trunk/ELF/Mips.cpp
Modified:
    lld/trunk/ELF/CMakeLists.txt
    lld/trunk/ELF/Writer.cpp
    lld/trunk/ELF/Writer.h
    lld/trunk/test/ELF/mips-elf-flags-err.s

Modified: lld/trunk/ELF/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/CMakeLists.txt?rev=278042&r1=278041&r2=278042&view=diff
==============================================================================
--- lld/trunk/ELF/CMakeLists.txt (original)
+++ lld/trunk/ELF/CMakeLists.txt Mon Aug  8 14:39:45 2016
@@ -13,6 +13,7 @@ add_lld_library(lldELF
   LTO.cpp
   LinkerScript.cpp
   MarkLive.cpp
+  Mips.cpp
   OutputSections.cpp
   Relocations.cpp
   ScriptParser.cpp

Added: lld/trunk/ELF/Mips.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Mips.cpp?rev=278042&view=auto
==============================================================================
--- lld/trunk/ELF/Mips.cpp (added)
+++ lld/trunk/ELF/Mips.cpp Mon Aug  8 14:39:45 2016
@@ -0,0 +1,217 @@
+//===- 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/Object/ELF.h"
+#include "llvm/Support/ELF.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)
+      warning("linking abicalls code with non-abicalls file: " + F.Filename);
+    if (!IsPic && IsPic2)
+      warning("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
+    // MIPS64 extensions.
+    {EF_MIPS_ARCH_64R2, EF_MIPS_ARCH_64},
+    // MIPS V extensions.
+    {EF_MIPS_ARCH_64, EF_MIPS_ARCH_5},
+    // MIPS IV extensions.
+    {EF_MIPS_ARCH_5, EF_MIPS_ARCH_4},
+    // MIPS III extensions.
+    {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_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 getArchName(uint32_t Flags) {
+  switch (Flags) {
+  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";
+  }
+}
+
+static uint32_t getArchFlags(ArrayRef<FileFlags> Files) {
+  uint32_t Ret = Files[0].Flags & EF_MIPS_ARCH;
+
+  for (const FileFlags &F : Files.slice(1)) {
+    uint32_t New = F.Flags & EF_MIPS_ARCH;
+
+    // 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 (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :
+       Symtab<ELFT>::X->getObjectFiles())
+    V.push_back({F->getName(), F->getObj().getHeader()->e_flags});
+
+  checkFlags(V);
+  return getMiscFlags(V) | getPicFlags(V) | getArchFlags(V);
+}
+
+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/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=278042&r1=278041&r2=278042&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Mon Aug  8 14:39:45 2016
@@ -1142,203 +1142,6 @@ template <class ELFT> void Writer<ELFT>:
   }
 }
 
-namespace {
-struct MipsIsaTreeEdge {
-  uint32_t Child;
-  uint32_t Parent;
-};
-}
-
-static MipsIsaTreeEdge MipsIsaTree[] = {
-    // MIPS32R6 and MIPS64R6 are not compatible with other extensions
-    // MIPS64 extensions.
-    {EF_MIPS_ARCH_64R2, EF_MIPS_ARCH_64},
-    // MIPS V extensions.
-    {EF_MIPS_ARCH_64, EF_MIPS_ARCH_5},
-    // MIPS IV extensions.
-    {EF_MIPS_ARCH_5, EF_MIPS_ARCH_4},
-    // MIPS III extensions.
-    {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_2, EF_MIPS_ARCH_1},
-};
-
-static bool isMipsIsaMatched(uint32_t New, uint32_t Res) {
-  if (New == Res)
-    return true;
-  if (New == EF_MIPS_ARCH_32 && isMipsIsaMatched(EF_MIPS_ARCH_64, Res))
-    return true;
-  if (New == EF_MIPS_ARCH_32R2 && isMipsIsaMatched(EF_MIPS_ARCH_64R2, Res))
-    return true;
-  for (const auto &Edge : MipsIsaTree) {
-    if (Res == Edge.Child) {
-      Res = Edge.Parent;
-      if (Res == New)
-        return true;
-    }
-  }
-  return false;
-}
-
-static StringRef getMipsIsaName(uint32_t Flags) {
-  switch (Flags) {
-  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";
-  }
-}
-
-static StringRef getMipsAbiName(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 getMipsNanName(bool IsNan2008) {
-  return IsNan2008 ? "2008" : "legacy";
-}
-
-static StringRef getMipsFpName(bool IsFp64) { return IsFp64 ? "64" : "32"; }
-
-static uint32_t updateMipsPicFlags(uint32_t ResFlags, uint32_t NewFlags,
-                                   StringRef FName) {
-  uint32_t NewPic = NewFlags & (EF_MIPS_PIC | EF_MIPS_CPIC);
-  uint32_t ResPic = ResFlags & (EF_MIPS_PIC | EF_MIPS_CPIC);
-
-  // Check PIC / CPIC flags compatibility.
-  if (NewPic && !ResPic)
-    warning("linking non-abicalls code with abicalls file: " + FName);
-  if (!NewPic && ResPic)
-    warning("linking abicalls code with non-abicalls file: " + FName);
-
-  if (!(NewPic & EF_MIPS_PIC))
-    ResFlags &= ~EF_MIPS_PIC;
-  if (NewPic)
-    ResFlags |= EF_MIPS_CPIC;
-  return ResFlags;
-}
-
-static uint32_t updateMipsIsaFlags(uint32_t ResFlags, uint32_t NewFlags,
-                                   StringRef FName) {
-  uint32_t NewIsa = NewFlags & EF_MIPS_ARCH;
-  uint32_t ResIsa = ResFlags & EF_MIPS_ARCH;
-
-  // Check ISA compatibility.
-  if (isMipsIsaMatched(NewIsa, ResIsa))
-    return ResFlags;
-  if (!isMipsIsaMatched(ResIsa, NewIsa)) {
-    error("target isa '" + getMipsIsaName(ResIsa) + "' is incompatible with '" +
-          getMipsIsaName(NewIsa) + "': " + FName);
-    return ResFlags;
-  }
-  ResFlags &= ~EF_MIPS_ARCH;
-  ResFlags |= NewIsa;
-  return ResFlags;
-}
-
-static void checkMipsAbiFlags(uint32_t ResFlags, uint32_t NewFlags,
-                              StringRef FName) {
-  uint32_t NewAbi = NewFlags & (EF_MIPS_ABI | EF_MIPS_ABI2);
-  uint32_t ResAbi = ResFlags & (EF_MIPS_ABI | EF_MIPS_ABI2);
-  // Check ABI compatibility.
-  if (NewAbi != ResAbi)
-    error("target ABI '" + getMipsAbiName(ResAbi) + "' is incompatible with '" +
-          getMipsAbiName(NewAbi) + "': " + FName);
-}
-
-static void checkMipsNanFlags(uint32_t ResFlags, uint32_t NewFlags,
-                              StringRef FName) {
-  bool NewNan2008 = NewFlags & EF_MIPS_NAN2008;
-  bool ResNan2008 = ResFlags & EF_MIPS_NAN2008;
-  // Check -mnan flags compatibility.
-  if (NewNan2008 != ResNan2008)
-    error("target -mnan=" + getMipsNanName(ResNan2008) +
-          " is incompatible with -mnan=" + getMipsNanName(NewNan2008) + ": " +
-          FName);
-}
-
-static void checkMipsFpFlags(uint32_t ResFlags, uint32_t NewFlags,
-                             StringRef FName) {
-  bool NewFp64 = NewFlags & EF_MIPS_FP64;
-  bool ResFp64 = ResFlags & EF_MIPS_FP64;
-  // Check FP64 compatibility.
-  if (NewFp64 != ResFp64)
-    error("target -mfp" + getMipsFpName(ResFp64) +
-          " is incompatible with -mfp" + getMipsFpName(NewFp64) + ": " + FName);
-}
-
-template <class ELFT> static uint32_t getMipsEFlags() {
-  // Iterates over all object files andretrieve ELF header flags
-  // to check that ISA, ABI and features declared by these flags
-  // are compatible with each other.
-  uint32_t ResFlags = 0;
-  for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :
-       Symtab<ELFT>::X->getObjectFiles()) {
-    uint32_t NewFlags = F->getObj().getHeader()->e_flags;
-    if (ResFlags == 0) {
-      if (NewFlags & EF_MIPS_PIC)
-        // PIC code is inherently CPIC
-        // and may not set CPIC flag explicitly.
-        NewFlags |= EF_MIPS_CPIC;
-      ResFlags = NewFlags;
-      continue;
-    }
-
-    ResFlags = updateMipsPicFlags(ResFlags, NewFlags, F->getName());
-    ResFlags = updateMipsIsaFlags(ResFlags, NewFlags, F->getName());
-
-    checkMipsAbiFlags(ResFlags, NewFlags, F->getName());
-    checkMipsNanFlags(ResFlags, NewFlags, F->getName());
-    checkMipsFpFlags(ResFlags, NewFlags, F->getName());
-
-    ResFlags |= NewFlags & EF_MIPS_ARCH_ASE;
-    ResFlags |= NewFlags & EF_MIPS_NOREORDER;
-    ResFlags |= NewFlags & EF_MIPS_MICROMIPS;
-    ResFlags |= NewFlags & EF_MIPS_NAN2008;
-    ResFlags |= NewFlags & EF_MIPS_32BITMODE;
-  }
-  return ResFlags;
-}
-
 template <class ELFT> static typename ELFT::uint getEntryAddr() {
   if (Symbol *S = Config->EntrySym)
     return S->body()->getVA<ELFT>();

Modified: lld/trunk/ELF/Writer.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.h?rev=278042&r1=278041&r2=278042&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.h (original)
+++ lld/trunk/ELF/Writer.h Mon Aug  8 14:39:45 2016
@@ -45,6 +45,8 @@ template <class ELFT>
 llvm::StringRef getOutputSectionName(InputSectionBase<ELFT> *S);
 
 template <class ELFT> void reportDiscarded(InputSectionBase<ELFT> *IS);
+
+template <class ELFT> uint32_t getMipsEFlags();
 }
 }
 

Modified: lld/trunk/test/ELF/mips-elf-flags-err.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-elf-flags-err.s?rev=278042&r1=278041&r2=278042&view=diff
==============================================================================
--- lld/trunk/test/ELF/mips-elf-flags-err.s (original)
+++ lld/trunk/test/ELF/mips-elf-flags-err.s Mon Aug  8 14:39:45 2016
@@ -45,7 +45,7 @@ __start:
 # R1R2-NEXT:   EF_MIPS_CPIC
 # R1R2-NEXT: ]
 
-# R1R6: target isa 'mips32' is incompatible with 'mips32r6': {{.*}}mips-elf-flags-err.s.tmp2.o
+# R1R6: target ISA 'mips32' is incompatible with 'mips32r6': {{.*}}mips-elf-flags-err.s.tmp2.o
 
 # N32O32: target ABI 'n32' is incompatible with 'o32': {{.*}}mips-elf-flags-err.s.tmp2.o
 




More information about the llvm-commits mailing list