[lld] r238686 - [Mips] Reading, merging and writing .MIPS.abiflags section

Simon Atanasyan simon at atanasyan.com
Sun May 31 13:36:43 PDT 2015


Author: atanasyan
Date: Sun May 31 15:36:43 2015
New Revision: 238686

URL: http://llvm.org/viewvc/llvm-project?rev=238686&view=rev
Log:
[Mips] Reading, merging and writing .MIPS.abiflags section

http://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking

Added:
    lld/trunk/test/elf/Mips/abi-flags-01.test
    lld/trunk/test/elf/Mips/abi-flags-02.test
    lld/trunk/test/elf/Mips/abi-flags-03.test
    lld/trunk/test/elf/Mips/abi-flags-04.test
    lld/trunk/test/elf/Mips/abi-flags-05.test
    lld/trunk/test/elf/Mips/abi-flags-06.test
    lld/trunk/test/elf/Mips/abi-flags-07.test
    lld/trunk/test/elf/Mips/abi-flags-08.test
Modified:
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.cpp
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.h
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFWriters.cpp
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFWriters.h
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.cpp
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.h

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp?rev=238686&r1=238685&r2=238686&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp Sun May 31 15:36:43 2015
@@ -12,41 +12,246 @@
 #include "lld/ReaderWriter/ELFLinkingContext.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Support/ELF.h"
+#include "llvm/Support/MipsABIFlags.h"
 #include "llvm/Support/raw_ostream.h"
 
+using namespace lld;
+using namespace lld::elf;
+using namespace llvm;
 using namespace llvm::ELF;
+using namespace llvm::Mips;
+
+namespace {
+
+// The joined set of MIPS ISAs and MIPS ISA extensions.
+enum MipsISAs {
+  ArchNone,
+
+  // General ISAs
+  Arch1,
+  Arch2,
+  Arch3,
+  Arch4,
+  Arch5,
+  Arch32,
+  Arch32r2,
+  Arch32r3,
+  Arch32r5,
+  Arch32r6,
+  Arch64,
+  Arch64r2,
+  Arch64r3,
+  Arch64r5,
+  Arch64r6,
+
+  // CPU specific ISAs
+  Arch3900,
+  Arch4010,
+  Arch4100,
+  Arch4111,
+  Arch4120,
+  Arch4650,
+  Arch5400,
+  Arch5500,
+  Arch5900,
+  Arch9000,
+  Arch10000,
+  ArchLs2e,
+  ArchLs2f,
+  ArchLs3a,
+  ArchOcteon,
+  ArchOcteonP,
+  ArchOcteon2,
+  ArchOcteon3,
+  ArchSB1,
+  ArchXLR
+};
 
 struct MipsISATreeEdge {
-  unsigned child;
-  unsigned parent;
+  MipsISAs child;
+  MipsISAs parent;
+};
+
+struct ElfArchPair {
+  uint32_t _elfFlag;
+  MipsISAs _arch;
+};
+
+struct AbiIsaArchPair {
+  uint8_t _isaLevel;
+  uint8_t _isaRev;
+  uint8_t _isaExt;
+  MipsISAs _arch;
+};
+}
+
+static const MipsISATreeEdge isaTree[] = {
+  // MIPS32R6 and MIPS64R6 are not compatible with other extensions
+
+  // MIPS64R2 extensions.
+  {ArchOcteon3, ArchOcteon2},
+  {ArchOcteon2, ArchOcteonP},
+  {ArchOcteonP, ArchOcteon},
+  {ArchOcteon,  Arch64r2},
+  {ArchLs3a,    Arch64r2},
+
+  // MIPS64 extensions.
+  {Arch64r2, Arch64},
+  {ArchSB1,  Arch64},
+  {ArchXLR,  Arch64},
+
+  // MIPS V extensions.
+  {Arch64, Arch5},
+
+  // R5000 extensions.
+  {Arch5500, Arch5400},
+
+  // MIPS IV extensions.
+  {Arch5, Arch4},
+  {Arch5400, Arch4},
+  {Arch9000, Arch4},
+
+  // VR4100 extensions.
+  {Arch4120, Arch4100},
+  {Arch4111, Arch4100},
+
+  // MIPS III extensions.
+  {ArchLs2e, Arch3},
+  {ArchLs2f, Arch3},
+  {Arch4650, Arch3},
+  {Arch4100, Arch3},
+  {Arch4010, Arch3},
+  {Arch5900, Arch3},
+  {Arch4,    Arch3},
+
+  // MIPS32 extensions.
+  {Arch32r2, Arch32},
+
+  // MIPS II extensions.
+  {Arch3, Arch2},
+  {Arch32, Arch2},
+
+  // MIPS I extensions.
+  {Arch3900, Arch1},
+  {Arch2,    Arch1},
 };
 
-static MipsISATreeEdge isaTree[] = {
-    // MIPS32R6 and MIPS64R6 are not compatible with other extensions
+// Conversion ELF arch flags => MipsISAs
+static const ElfArchPair elfArchPairs[] = {
+  {EF_MIPS_ARCH_1    | EF_MIPS_MACH_3900,    Arch3900},
+  {EF_MIPS_ARCH_3    | EF_MIPS_MACH_4010,    Arch4010},
+  {EF_MIPS_ARCH_3    | EF_MIPS_MACH_4100,    Arch4100},
+  {EF_MIPS_ARCH_3    | EF_MIPS_MACH_4111,    Arch4111},
+  {EF_MIPS_ARCH_3    | EF_MIPS_MACH_4120,    Arch4120},
+  {EF_MIPS_ARCH_3    | EF_MIPS_MACH_4650,    Arch4650},
+  {EF_MIPS_ARCH_4    | EF_MIPS_MACH_5400,    Arch5400},
+  {EF_MIPS_ARCH_4    | EF_MIPS_MACH_5500,    Arch5500},
+  {EF_MIPS_ARCH_3    | EF_MIPS_MACH_5900,    Arch5900},
+  {EF_MIPS_ARCH_4    | EF_MIPS_MACH_9000,    Arch9000},
+  {EF_MIPS_ARCH_3    | EF_MIPS_MACH_LS2E,    ArchLs2e},
+  {EF_MIPS_ARCH_3    | EF_MIPS_MACH_LS2F,    ArchLs2f},
+  {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_LS3A,    ArchLs3a},
+  {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON,  ArchOcteon},
+  {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON2, ArchOcteon2},
+  {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON3, ArchOcteon3},
+  {EF_MIPS_ARCH_64   | EF_MIPS_MACH_SB1,     ArchSB1},
+  {EF_MIPS_ARCH_64   | EF_MIPS_MACH_XLR,     ArchXLR},
+  {EF_MIPS_ARCH_1,    Arch1},
+  {EF_MIPS_ARCH_2,    Arch2},
+  {EF_MIPS_ARCH_3,    Arch3},
+  {EF_MIPS_ARCH_4,    Arch4},
+  {EF_MIPS_ARCH_5,    Arch5},
+  {EF_MIPS_ARCH_32,   Arch32},
+  {EF_MIPS_ARCH_32R2, Arch32r2},
+  {EF_MIPS_ARCH_32R6, Arch32r6},
+  {EF_MIPS_ARCH_64,   Arch64},
+  {EF_MIPS_ARCH_64R2, Arch64r2},
+  {EF_MIPS_ARCH_64R6, Arch64r6}
+};
 
-    // 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},
+// Conversion MipsISAs => ELF arch flags
+static const ElfArchPair archElfPairs[] = {
+  {EF_MIPS_ARCH_1,    Arch1},
+  {EF_MIPS_ARCH_2,    Arch2},
+  {EF_MIPS_ARCH_3,    Arch3},
+  {EF_MIPS_ARCH_4,    Arch4},
+  {EF_MIPS_ARCH_5,    Arch5},
+  {EF_MIPS_ARCH_32,   Arch32},
+  {EF_MIPS_ARCH_32R2, Arch32r2},
+  {EF_MIPS_ARCH_32R2, Arch32r3},
+  {EF_MIPS_ARCH_32R2, Arch32r5},
+  {EF_MIPS_ARCH_32R6, Arch32r6},
+  {EF_MIPS_ARCH_64,   Arch64},
+  {EF_MIPS_ARCH_64R2, Arch64r2},
+  {EF_MIPS_ARCH_64R2, Arch64r3},
+  {EF_MIPS_ARCH_64R2, Arch64r5},
+  {EF_MIPS_ARCH_64R6, Arch64r6},
+  {EF_MIPS_ARCH_1    | EF_MIPS_MACH_3900,    Arch3900},
+  {EF_MIPS_ARCH_3    | EF_MIPS_MACH_4010,    Arch4010},
+  {EF_MIPS_ARCH_3    | EF_MIPS_MACH_4100,    Arch4100},
+  {EF_MIPS_ARCH_3    | EF_MIPS_MACH_4111,    Arch4111},
+  {EF_MIPS_ARCH_3    | EF_MIPS_MACH_4120,    Arch4120},
+  {EF_MIPS_ARCH_3    | EF_MIPS_MACH_4650,    Arch4650},
+  {EF_MIPS_ARCH_4    | EF_MIPS_MACH_5400,    Arch5400},
+  {EF_MIPS_ARCH_4    | EF_MIPS_MACH_5500,    Arch5500},
+  {EF_MIPS_ARCH_3    | EF_MIPS_MACH_5900,    Arch5900},
+  {EF_MIPS_ARCH_4    | EF_MIPS_MACH_9000,    Arch9000},
+  {EF_MIPS_ARCH_4,                           Arch10000},
+  {EF_MIPS_ARCH_3    | EF_MIPS_MACH_LS2E,    ArchLs2e},
+  {EF_MIPS_ARCH_3    | EF_MIPS_MACH_LS2F,    ArchLs2f},
+  {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_LS3A,    ArchLs3a},
+  {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON,  ArchOcteon},
+  {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON,  ArchOcteonP},
+  {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON2, ArchOcteon2},
+  {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON3, ArchOcteon3},
+  {EF_MIPS_ARCH_64   | EF_MIPS_MACH_SB1,     ArchSB1},
+  {EF_MIPS_ARCH_64   | EF_MIPS_MACH_SB1,     ArchXLR}
 };
 
-static bool matchMipsISA(unsigned base, unsigned ext) {
+// Conversion .MIPS.abiflags isa/level/extension <=> MipsISAs
+static const AbiIsaArchPair abiIsaArchPair[] = {
+  { 0, 0, 0, ArchNone},
+  { 1, 0, 0, Arch1},
+  { 2, 0, 0, Arch2},
+  { 3, 0, 0, Arch3},
+  { 4, 0, 0, Arch4},
+  { 5, 0, 0, Arch5},
+  {32, 1, 0, Arch32},
+  {32, 2, 0, Arch32r2},
+  {32, 3, 0, Arch32r3},
+  {32, 5, 0, Arch32r5},
+  {32, 6, 0, Arch32r6},
+  {64, 1, 0, Arch64},
+  {64, 2, 0, Arch64r2},
+  {64, 3, 0, Arch64r3},
+  {64, 5, 0, Arch64r5},
+  {64, 6, 0, Arch64r6},
+  { 1, 0, AFL_EXT_3900,  Arch3900},
+  { 3, 0, AFL_EXT_4010,  Arch4010},
+  { 3, 0, AFL_EXT_4100,  Arch4100},
+  { 3, 0, AFL_EXT_4111,  Arch4111},
+  { 3, 0, AFL_EXT_4120,  Arch4120},
+  { 3, 0, AFL_EXT_4650,  Arch4650},
+  { 4, 0, AFL_EXT_5400,  Arch5400},
+  { 4, 0, AFL_EXT_5500,  Arch5500},
+  { 3, 0, AFL_EXT_5900,  Arch5900},
+  { 4, 0, AFL_EXT_10000, Arch10000},
+  { 3, 0, AFL_EXT_LOONGSON_2E, ArchLs2e},
+  { 3, 0, AFL_EXT_LOONGSON_2F, ArchLs2f},
+  {64, 2, AFL_EXT_LOONGSON_3A, ArchLs3a},
+  {64, 2, AFL_EXT_OCTEON,  ArchOcteon},
+  {64, 2, AFL_EXT_OCTEON2, ArchOcteon2},
+  {64, 2, AFL_EXT_OCTEON3, ArchOcteon3},
+  {64, 1, AFL_EXT_SB1,     ArchSB1},
+  {64, 1, AFL_EXT_XLR,     ArchXLR}
+};
+
+static bool matchMipsISA(MipsISAs base, MipsISAs ext) {
   if (base == ext)
     return true;
-  if (base == EF_MIPS_ARCH_32 && matchMipsISA(EF_MIPS_ARCH_64, ext))
+  if (base == Arch32 && matchMipsISA(Arch64, ext))
     return true;
-  if (base == EF_MIPS_ARCH_32R2 && matchMipsISA(EF_MIPS_ARCH_64R2, ext))
+  if (base == Arch32r2 && matchMipsISA(Arch64r2, ext))
     return true;
   for (const auto &edge : isaTree) {
     if (ext == edge.child) {
@@ -58,84 +263,272 @@ static bool matchMipsISA(unsigned base,
   return false;
 }
 
+static bool is32BitElfFlags(unsigned flags) {
+  if (flags & EF_MIPS_32BITMODE)
+    return true;
+
+  unsigned arch = flags & EF_MIPS_ARCH;
+  if (arch == EF_MIPS_ARCH_1 || arch == EF_MIPS_ARCH_2 ||
+      arch == EF_MIPS_ARCH_32 || arch == EF_MIPS_ARCH_32R2 ||
+      arch == EF_MIPS_ARCH_32R6)
+    return true;
+
+  unsigned abi = flags & EF_MIPS_ABI;
+  if (abi == EF_MIPS_ABI_O32 || abi == EF_MIPS_ABI_EABI32)
+    return true;
+
+  return false;
+}
+
+static ErrorOr<MipsISAs> headerFlagsToIsa(uint32_t flags) {
+  uint32_t arch = flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
+  for (const auto &p : elfArchPairs)
+    if (p._elfFlag == arch)
+      return p._arch;
+  return make_dynamic_error_code(
+      StringRef("Unknown EF_MIPS_ARCH | EF_MIPS_MACH flags (0x") +
+      Twine::utohexstr(arch) + ")");
+}
+
+static uint32_t isaToHeaderFlags(unsigned isa) {
+  for (const auto &p : archElfPairs)
+    if (p._arch == isa)
+      return p._elfFlag;
+  llvm_unreachable("Unknown MIPS ISA");
+}
+
+static ErrorOr<uint32_t> flagsToAses(uint32_t flags) {
+  uint32_t ases = flags & EF_MIPS_ARCH_ASE;
+  switch (ases) {
+  case 0:
+    return 0;
+  case EF_MIPS_MICROMIPS:
+    return AFL_ASE_MICROMIPS;
+  case EF_MIPS_ARCH_ASE_M16:
+    return AFL_ASE_MIPS16;
+  case EF_MIPS_ARCH_ASE_MDMX:
+    return AFL_ASE_MDMX;
+  default:
+    return make_dynamic_error_code(
+        StringRef("Unknown EF_MIPS_ARCH_ASE flag (0x") +
+        Twine::utohexstr(ases) + ")");
+  }
+}
+
+static uint32_t asesToFlags(uint32_t ases) {
+  switch (ases) {
+  case AFL_ASE_MICROMIPS:
+    return EF_MIPS_MICROMIPS;
+  case AFL_ASE_MIPS16:
+    return EF_MIPS_ARCH_ASE_M16;
+  case AFL_ASE_MDMX:
+    return EF_MIPS_ARCH_ASE_MDMX;
+  default:
+    return 0;
+  }
+}
+
+static ErrorOr<MipsISAs> sectionFlagsToIsa(uint8_t isaLevel, uint8_t isaRev,
+                                           uint8_t isaExt) {
+  for (const auto &p : abiIsaArchPair)
+    if (p._isaLevel == isaLevel && p._isaRev == isaRev && p._isaExt == isaExt)
+      return p._arch;
+  return make_dynamic_error_code(
+      StringRef("Unknown ISA level/revision/extension ") + Twine(isaLevel) +
+      "/" + Twine(isaRev) + "/" + Twine(isaExt));
+}
+
+static std::tuple<uint8_t, uint8_t, uint32_t> isaToSectionFlags(unsigned isa) {
+  for (const auto &p : abiIsaArchPair)
+    if (p._arch == isa)
+      return std::make_tuple(p._isaLevel, p._isaRev, p._isaExt);
+  llvm_unreachable("Unknown MIPS ISA");
+}
+
+static bool checkCompatibility(const MipsAbiFlags &hdr,
+                               const MipsAbiFlags &sec) {
+  uint32_t secIsa = ArchNone;
+  switch (sec._isa) {
+  case Arch32r3:
+  case Arch32r5:
+    secIsa = Arch32r2;
+    break;
+  case Arch64r3:
+  case Arch64r5:
+    secIsa = Arch64r2;
+    break;
+  default:
+    secIsa = sec._isa;
+    break;
+  }
+  if (secIsa != hdr._isa) {
+    llvm::errs() << "inconsistent ISA between .MIPS.abiflags "
+                    "and ELF header e_flags field\n";
+    return false;
+  }
+  if ((sec._ases & hdr._ases) != hdr._ases) {
+    llvm::errs() << "inconsistent ASEs between .MIPS.abiflags "
+                    "and ELF header e_flags field\n";
+    return false;
+  }
+  return true;
+}
+
+static int compareFpAbi(uint32_t fpA, uint32_t fpB) {
+  if (fpA == fpB)
+    return 0;
+  if (fpB == Val_GNU_MIPS_ABI_FP_ANY)
+    return 1;
+  if (fpB == Val_GNU_MIPS_ABI_FP_64A && fpA == Val_GNU_MIPS_ABI_FP_64)
+    return 1;
+  if (fpB != Val_GNU_MIPS_ABI_FP_XX)
+    return -1;
+  if (fpA == Val_GNU_MIPS_ABI_FP_DOUBLE || fpA == Val_GNU_MIPS_ABI_FP_64 ||
+      fpA == Val_GNU_MIPS_ABI_FP_64A)
+    return 1;
+  return -1;
+}
+
+static StringRef getFpAbiName(uint32_t fpAbi) {
+  switch (fpAbi) {
+  case Val_GNU_MIPS_ABI_FP_ANY:
+    return "<any>";
+  case Val_GNU_MIPS_ABI_FP_DOUBLE:
+    return "-mdouble-float";
+  case Val_GNU_MIPS_ABI_FP_SINGLE:
+    return "-msingle-float";
+  case Val_GNU_MIPS_ABI_FP_SOFT:
+    return "-msoft-float";
+  case Val_GNU_MIPS_ABI_FP_OLD_64:
+    return "-mips32r2 -mfp64 (old)";
+  case Val_GNU_MIPS_ABI_FP_XX:
+    return "-mfpxx";
+  case Val_GNU_MIPS_ABI_FP_64:
+    return "-mgp32 -mfp64";
+  case Val_GNU_MIPS_ABI_FP_64A:
+    return "-mgp32 -mfp64 -mno-odd-spreg";
+  default:
+    return "<unknown>";
+  }
+}
+
+static uint32_t selectFpAbiFlag(uint32_t oldFp, uint32_t newFp) {
+  if (compareFpAbi(newFp, oldFp) >= 0)
+    return newFp;
+  if (compareFpAbi(oldFp, newFp) < 0)
+    llvm::errs() << "FP ABI " << getFpAbiName(oldFp) << " is incompatible with "
+                 << getFpAbiName(newFp) << "\n";
+  return oldFp;
+}
+
 namespace lld {
 namespace elf {
 
+template <class ELFT> uint32_t MipsAbiInfoHandler<ELFT>::getFlags() const {
+  std::lock_guard<std::mutex> lock(_mutex);
+  uint32_t flags = 0;
+  if (_abiFlags.hasValue()) {
+    flags |= isaToHeaderFlags(_abiFlags->_isa);
+    flags |= asesToFlags(_abiFlags->_ases);
+    flags |= _abiFlags->_abi;
+    flags |= _abiFlags->_isPic ? EF_MIPS_PIC : 0;
+    flags |= _abiFlags->_isCPic ? EF_MIPS_CPIC : 0;
+    flags |= _abiFlags->_isNoReorder ? EF_MIPS_NOREORDER : 0;
+    flags |= _abiFlags->_is32BitMode ? EF_MIPS_32BITMODE : 0;
+    flags |= _abiFlags->_isNan2008 ? EF_MIPS_NAN2008 : 0;
+  }
+  return flags;
+}
+
+template <class ELFT>
+llvm::Optional<typename MipsAbiInfoHandler<ELFT>::Elf_Mips_RegInfo>
+MipsAbiInfoHandler<ELFT>::getRegistersMask() const {
+  std::lock_guard<std::mutex> lock(_mutex);
+  return _regMask;
+}
+
+template <class ELFT>
+llvm::Optional<typename MipsAbiInfoHandler<ELFT>::Elf_Mips_ABIFlags>
+MipsAbiInfoHandler<ELFT>::getAbiFlags() const {
+  std::lock_guard<std::mutex> lock(_mutex);
+  if (!_hasAbiSection)
+    return llvm::Optional<Elf_Mips_ABIFlags>();
+
+  Elf_Mips_ABIFlags sec;
+  sec.version = 0;
+  std::tie(sec.isa_level, sec.isa_rev, sec.isa_ext) =
+      isaToSectionFlags(_abiFlags->_isa);
+  sec.gpr_size = _abiFlags->_gprSize;
+  sec.cpr1_size = _abiFlags->_cpr1Size;
+  sec.cpr2_size = _abiFlags->_cpr2Size;
+  sec.fp_abi = _abiFlags->_fpAbi;
+  sec.ases = _abiFlags->_ases;
+  sec.flags1 = _abiFlags->_flags1;
+  sec.flags2 = 0;
+  return sec;
+}
+
 template <class ELFT>
-std::error_code MipsAbiInfoHandler<ELFT>::mergeFlags(uint32_t newFlags) {
+std::error_code
+MipsAbiInfoHandler<ELFT>::mergeFlags(uint32_t newFlags,
+                                     const Elf_Mips_ABIFlags *newSec) {
+  std::lock_guard<std::mutex> lock(_mutex);
+
+  ErrorOr<MipsAbiFlags> abiFlags = createAbiFlags(newFlags, newSec);
+  if (auto ec = abiFlags.getError())
+    return ec;
+
   // We support two ABI: O32 and N64. The last one does not have
   // the corresponding ELF flag.
-  uint32_t inAbi = newFlags & EF_MIPS_ABI;
   uint32_t supportedAbi = ELFT::Is64Bits ? 0 : uint32_t(EF_MIPS_ABI_O32);
-  if (inAbi != supportedAbi)
+  if (abiFlags->_abi != supportedAbi)
     return make_dynamic_error_code("Unsupported ABI");
 
-  // ... and reduced set of architectures ...
-  uint32_t newArch = newFlags & EF_MIPS_ARCH;
-  switch (newArch) {
-  case EF_MIPS_ARCH_1:
-  case EF_MIPS_ARCH_2:
-  case EF_MIPS_ARCH_3:
-  case EF_MIPS_ARCH_4:
-  case EF_MIPS_ARCH_5:
-  case EF_MIPS_ARCH_32:
-  case EF_MIPS_ARCH_64:
-  case EF_MIPS_ARCH_32R2:
-  case EF_MIPS_ARCH_64R2:
-  case EF_MIPS_ARCH_32R6:
-  case EF_MIPS_ARCH_64R6:
-    break;
-  default:
-    return make_dynamic_error_code("Unsupported instruction set");
-  }
-
   // ... and still do not support MIPS-16 extension.
-  if (newFlags & EF_MIPS_ARCH_ASE_M16)
+  if (abiFlags->_ases & AFL_ASE_MIPS16)
     return make_dynamic_error_code("Unsupported extension: MIPS16");
 
   // PIC code is inherently CPIC and may not set CPIC flag explicitly.
   // Ensure that this flag will exist in the linked file.
-  if (newFlags & EF_MIPS_PIC)
-    newFlags |= EF_MIPS_CPIC;
-
-  std::lock_guard<std::mutex> lock(_mutex);
+  if (abiFlags->_isPic)
+    abiFlags->_isCPic = true;
 
   // If the old set of flags is empty, use the new one as a result.
-  if (!_flags) {
-    _flags = newFlags;
+  if (!_abiFlags.hasValue()) {
+    _abiFlags = *abiFlags;
     return std::error_code();
   }
 
   // Check PIC / CPIC flags compatibility.
-  uint32_t newPic = newFlags & (EF_MIPS_PIC | EF_MIPS_CPIC);
-  uint32_t oldPic = _flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
-
-  if ((newPic != 0) != (oldPic != 0))
+  if (abiFlags->_isCPic != _abiFlags->_isCPic)
     llvm::errs() << "lld warning: linking abicalls and non-abicalls files\n";
 
-  if (!(newPic & EF_MIPS_PIC))
-    _flags &= ~EF_MIPS_PIC;
-  if (newPic)
-    _flags |= EF_MIPS_CPIC;
+  if (!abiFlags->_isPic)
+    _abiFlags->_isPic = false;
+  if (abiFlags->_isCPic)
+    _abiFlags->_isCPic = true;
 
   // Check mixing -mnan=2008 / -mnan=legacy modules.
-  if ((newFlags & EF_MIPS_NAN2008) != (_flags & EF_MIPS_NAN2008))
+  if (abiFlags->_isNan2008 != _abiFlags->_isNan2008)
     return make_dynamic_error_code(
         "Linking -mnan=2008 and -mnan=legacy modules");
 
   // Check ISA compatibility and update the extension flag.
-  uint32_t oldArch = _flags & EF_MIPS_ARCH;
-  if (!matchMipsISA(newArch, oldArch)) {
-    if (!matchMipsISA(oldArch, newArch))
+  if (!matchMipsISA(MipsISAs(abiFlags->_isa), MipsISAs(_abiFlags->_isa))) {
+    if (!matchMipsISA(MipsISAs(_abiFlags->_isa), MipsISAs(abiFlags->_isa)))
       return make_dynamic_error_code("Linking modules with incompatible ISA");
-    _flags &= ~EF_MIPS_ARCH;
-    _flags |= newArch;
+    _abiFlags->_isa = abiFlags->_isa;
   }
 
-  _flags |= newFlags & EF_MIPS_NOREORDER;
-  _flags |= newFlags & EF_MIPS_MICROMIPS;
-  _flags |= newFlags & EF_MIPS_NAN2008;
-  _flags |= newFlags & EF_MIPS_32BITMODE;
+  _abiFlags->_ases |= abiFlags->_ases;
+  _abiFlags->_isNoReorder = _abiFlags->_isNoReorder || abiFlags->_isNoReorder;
+  _abiFlags->_is32BitMode = _abiFlags->_is32BitMode || abiFlags->_is32BitMode;
+
+  _abiFlags->_fpAbi = selectFpAbiFlag(_abiFlags->_fpAbi, abiFlags->_fpAbi);
+  _abiFlags->_gprSize = std::max(_abiFlags->_gprSize, abiFlags->_gprSize);
+  _abiFlags->_cpr1Size = std::max(_abiFlags->_cpr1Size, abiFlags->_cpr1Size);
+  _abiFlags->_cpr2Size = std::max(_abiFlags->_cpr2Size, abiFlags->_cpr2Size);
+  _abiFlags->_flags1 |= abiFlags->_flags1;
 
   return std::error_code();
 }
@@ -155,6 +548,80 @@ void MipsAbiInfoHandler<ELFT>::mergeRegi
   _regMask->ri_cprmask[3] = _regMask->ri_cprmask[3] | info.ri_cprmask[3];
 }
 
+template <class ELFT>
+ErrorOr<MipsAbiFlags>
+MipsAbiInfoHandler<ELFT>::createAbiFlags(uint32_t flags,
+                                         const Elf_Mips_ABIFlags *sec) {
+  ErrorOr<MipsAbiFlags> hdrFlags = createAbiFromHeaderFlags(flags);
+  if (auto ec = hdrFlags.getError())
+    return ec;
+  if (!sec)
+    return *hdrFlags;
+  ErrorOr<MipsAbiFlags> secFlags = createAbiFromSection(*sec);
+  if (auto ec = secFlags.getError())
+    return ec;
+  if (!checkCompatibility(*hdrFlags, *secFlags))
+    return *hdrFlags;
+
+  _hasAbiSection = true;
+
+  secFlags->_abi = hdrFlags->_abi;
+  secFlags->_isPic = hdrFlags->_isPic;
+  secFlags->_isCPic = hdrFlags->_isCPic;
+  secFlags->_isNoReorder = hdrFlags->_isNoReorder;
+  secFlags->_is32BitMode = hdrFlags->_is32BitMode;
+  secFlags->_isNan2008 = hdrFlags->_isNan2008;
+  return *secFlags;
+}
+
+template <class ELFT>
+ErrorOr<MipsAbiFlags>
+MipsAbiInfoHandler<ELFT>::createAbiFromHeaderFlags(uint32_t flags) {
+  MipsAbiFlags abi;
+  ErrorOr<MipsISAs> isa = headerFlagsToIsa(flags);
+  if (auto ec = isa.getError())
+    return ec;
+  abi._isa = *isa;
+
+  abi._fpAbi = Val_GNU_MIPS_ABI_FP_ANY;
+  abi._cpr1Size = AFL_REG_NONE;
+  abi._cpr2Size = AFL_REG_NONE;
+  abi._gprSize = is32BitElfFlags(flags) ? AFL_REG_32 : AFL_REG_64;
+
+  ErrorOr<uint32_t> ases = flagsToAses(flags);
+  if (auto ec = ases.getError())
+    return ec;
+  abi._ases = *ases;
+  abi._flags1 = 0;
+  abi._abi = flags & EF_MIPS_ABI;
+  abi._isPic = flags & EF_MIPS_PIC;
+  abi._isCPic = flags & EF_MIPS_CPIC;
+  abi._isNoReorder = flags & EF_MIPS_NOREORDER;
+  abi._is32BitMode = flags & EF_MIPS_32BITMODE;
+  abi._isNan2008 = flags & EF_MIPS_NAN2008;
+  return abi;
+}
+
+template <class ELFT>
+ErrorOr<MipsAbiFlags>
+MipsAbiInfoHandler<ELFT>::createAbiFromSection(const Elf_Mips_ABIFlags &sec) {
+  MipsAbiFlags abi;
+  ErrorOr<MipsISAs> isa =
+      sectionFlagsToIsa(sec.isa_level, sec.isa_rev, sec.isa_ext);
+  if (auto ec = isa.getError())
+    return ec;
+  abi._isa = *isa;
+  abi._fpAbi = sec.fp_abi;
+  abi._cpr1Size = sec.cpr1_size;
+  abi._cpr2Size = sec.cpr2_size;
+  abi._gprSize = sec.gpr_size;
+  abi._ases = sec.ases;
+  abi._flags1 = sec.flags1;
+  if (sec.flags2 != 0)
+    return make_dynamic_error_code("unexpected non-zero 'flags2' value");
+  return abi;
+}
+
 template class MipsAbiInfoHandler<ELF32LE>;
 template class MipsAbiInfoHandler<ELF64LE>;
 

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h?rev=238686&r1=238685&r2=238686&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h Sun May 31 15:36:43 2015
@@ -11,33 +11,60 @@
 
 #include "llvm/ADT/Optional.h"
 #include "llvm/Object/ELFTypes.h"
+#include "llvm/Support/ErrorOr.h"
 #include <mutex>
 #include <system_error>
 
 namespace lld {
 namespace elf {
 
+struct MipsAbiFlags {
+  unsigned _isa = 0;
+  unsigned _fpAbi = 0;
+  unsigned _ases = 0;
+  unsigned _flags1 = 0;
+  unsigned _gprSize = 0;
+  unsigned _cpr1Size = 0;
+  unsigned _cpr2Size = 0;
+
+  unsigned _abi = 0;
+
+  bool _isPic = false;
+  bool _isCPic = false;
+  bool _isNoReorder = false;
+  bool _is32BitMode = false;
+  bool _isNan2008 = false;
+};
+
 template <class ELFT> class MipsAbiInfoHandler {
 public:
   typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
+  typedef llvm::object::Elf_Mips_ABIFlags<ELFT> Elf_Mips_ABIFlags;
 
   MipsAbiInfoHandler() = default;
 
-  uint32_t getFlags() const { return _flags; }
-  const llvm::Optional<Elf_Mips_RegInfo> &getRegistersMask() const {
-    return _regMask;
-  }
+  uint32_t getFlags() const;
+  llvm::Optional<Elf_Mips_RegInfo> getRegistersMask() const;
+  llvm::Optional<Elf_Mips_ABIFlags> getAbiFlags() const;
 
   /// \brief Merge saved ELF header flags and the new set of flags.
-  std::error_code mergeFlags(uint32_t newFlags);
+  std::error_code mergeFlags(uint32_t newFlags,
+                             const Elf_Mips_ABIFlags *newAbi);
 
   /// \brief Merge saved and new sets of registers usage masks.
   void mergeRegistersMask(const Elf_Mips_RegInfo &info);
 
 private:
-  std::mutex _mutex;
-  uint32_t _flags = 0;
+  mutable std::mutex _mutex;
+  bool _hasAbiSection = false;
+  llvm::Optional<MipsAbiFlags> _abiFlags;
   llvm::Optional<Elf_Mips_RegInfo> _regMask;
+
+  llvm::ErrorOr<MipsAbiFlags> createAbiFlags(uint32_t flags,
+                                             const Elf_Mips_ABIFlags *sec);
+  static llvm::ErrorOr<MipsAbiFlags> createAbiFromHeaderFlags(uint32_t flags);
+  static llvm::ErrorOr<MipsAbiFlags>
+  createAbiFromSection(const Elf_Mips_ABIFlags &sec);
 };
 
 } // namespace elf

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.cpp?rev=238686&r1=238685&r2=238686&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.cpp Sun May 31 15:36:43 2015
@@ -9,6 +9,7 @@
 
 #include "MipsELFFile.h"
 #include "MipsTargetHandler.h"
+#include "llvm/ADT/StringExtras.h"
 
 namespace lld {
 namespace elf {
@@ -156,6 +157,31 @@ MipsELFFile<ELFT>::findRegInfoSec() cons
   return nullptr;
 }
 
+template <class ELFT>
+ErrorOr<const typename MipsELFFile<ELFT>::Elf_Mips_ABIFlags *>
+MipsELFFile<ELFT>::findAbiFlagsSec() const {
+  const Elf_Shdr *sec = findSectionByType(SHT_MIPS_ABIFLAGS);
+  if (!sec)
+    return nullptr;
+
+  auto contents = this->getSectionContents(sec);
+  if (std::error_code ec = contents.getError())
+    return ec;
+
+  ArrayRef<uint8_t> raw = contents.get();
+  if (raw.size() != sizeof(Elf_Mips_ABIFlags))
+    return make_dynamic_error_code(
+        StringRef("Invalid size of MIPS_ABIFLAGS section"));
+
+  const auto *abi = reinterpret_cast<const Elf_Mips_ABIFlags *>(raw.data());
+  if (abi->version != 0)
+    return make_dynamic_error_code(
+        StringRef(".MIPS.abiflags section has unsupported version '") +
+        llvm::utostr(abi->version) + "'");
+
+  return abi;
+}
+
 template <class ELFT> std::error_code MipsELFFile<ELFT>::readAuxData() {
   using namespace llvm::ELF;
   if (const Elf_Shdr *sec = findSectionByFlags(SHF_TLS)) {
@@ -175,8 +201,12 @@ template <class ELFT> std::error_code Mi
     _gp0 = regInfo->ri_gp_value;
   }
 
+  ErrorOr<const Elf_Mips_ABIFlags *> abiFlagsSec = findAbiFlagsSec();
+  if (auto ec = abiFlagsSec.getError())
+    return ec;
+
   const Elf_Ehdr *hdr = this->_objFile->getHeader();
-  if (std::error_code ec = abi.mergeFlags(hdr->e_flags))
+  if (std::error_code ec = abi.mergeFlags(hdr->e_flags, abiFlagsSec.get()))
     return ec;
 
   return std::error_code();

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.h?rev=238686&r1=238685&r2=238686&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.h Sun May 31 15:36:43 2015
@@ -100,8 +100,10 @@ private:
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Ehdr Elf_Ehdr;
   typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
   typedef llvm::object::Elf_Mips_Options<ELFT> Elf_Mips_Options;
+  typedef llvm::object::Elf_Mips_ABIFlags<ELFT> Elf_Mips_ABIFlags;
 
   ErrorOr<const Elf_Mips_RegInfo *> findRegInfoSec() const;
+  ErrorOr<const Elf_Mips_ABIFlags*> findAbiFlagsSec() const;
 
   std::error_code readAuxData();
 

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFWriters.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFWriters.cpp?rev=238686&r1=238685&r2=238686&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFWriters.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFWriters.cpp Sun May 31 15:36:43 2015
@@ -85,6 +85,16 @@ MipsELFWriter<ELFT>::createOptionsSectio
 }
 
 template <class ELFT>
+unique_bump_ptr<Section<ELFT>>
+MipsELFWriter<ELFT>::createAbiFlagsSection(llvm::BumpPtrAllocator &alloc) {
+  typedef unique_bump_ptr<Section<ELFT>> Ptr;
+  const auto &abi = _abiInfo.getAbiFlags();
+  if (!abi.hasValue())
+    return Ptr();
+  return Ptr(new (alloc) MipsAbiFlagsSection<ELFT>(_ctx, _targetLayout, *abi));
+}
+
+template <class ELFT>
 void MipsELFWriter<ELFT>::setAtomValue(StringRef name, uint64_t value) {
   AtomLayout *atom = _targetLayout.findAbsoluteAtom(name);
   assert(atom);
@@ -117,6 +127,9 @@ void MipsDynamicLibraryWriter<ELFT>::cre
   _reginfo = _writeHelper.createOptionsSection(this->_alloc);
   if (_reginfo)
     this->_layout.addSection(_reginfo.get());
+  _abiFlags = _writeHelper.createAbiFlagsSection(this->_alloc);
+  if (_abiFlags)
+    this->_layout.addSection(_abiFlags.get());
 }
 
 template <class ELFT>
@@ -235,6 +248,9 @@ template <class ELFT> void MipsExecutabl
   _reginfo = _writeHelper.createOptionsSection(this->_alloc);
   if (_reginfo)
     this->_layout.addSection(_reginfo.get());
+  _abiFlags = _writeHelper.createAbiFlagsSection(this->_alloc);
+  if (_abiFlags)
+    this->_layout.addSection(_abiFlags.get());
 }
 
 template <class ELFT>

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFWriters.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFWriters.h?rev=238686&r1=238685&r2=238686&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFWriters.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFWriters.h Sun May 31 15:36:43 2015
@@ -31,6 +31,8 @@ public:
   std::unique_ptr<RuntimeFile<ELFT>> createRuntimeFile();
   unique_bump_ptr<Section<ELFT>>
   createOptionsSection(llvm::BumpPtrAllocator &alloc);
+  unique_bump_ptr<Section<ELFT>>
+  createAbiFlagsSection(llvm::BumpPtrAllocator &alloc);
 
 private:
   MipsLinkingContext &_ctx;
@@ -64,6 +66,7 @@ private:
   MipsELFWriter<ELFT> _writeHelper;
   MipsTargetLayout<ELFT> &_targetLayout;
   unique_bump_ptr<Section<ELFT>> _reginfo;
+  unique_bump_ptr<Section<ELFT>> _abiFlags;
 };
 
 template <class ELFT>
@@ -90,6 +93,7 @@ private:
   MipsELFWriter<ELFT> _writeHelper;
   MipsTargetLayout<ELFT> &_targetLayout;
   unique_bump_ptr<Section<ELFT>> _reginfo;
+  unique_bump_ptr<Section<ELFT>> _abiFlags;
 };
 
 } // elf

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.cpp?rev=238686&r1=238685&r2=238686&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.cpp Sun May 31 15:36:43 2015
@@ -89,6 +89,37 @@ template class MipsOptionsSection<ELF32L
 template class MipsOptionsSection<ELF64LE>;
 
 template <class ELFT>
+MipsAbiFlagsSection<ELFT>::MipsAbiFlagsSection(
+    const ELFLinkingContext &ctx, MipsTargetLayout<ELFT> &targetLayout,
+    const Elf_Mips_ABIFlags &abiFlags)
+    : Section<ELFT>(ctx, ".MIPS.abiflags", "MipsAbiFlags"), _abiFlags(abiFlags),
+      _targetLayout(targetLayout) {
+  this->setOrder(MipsTargetLayout<ELFT>::ORDER_MIPS_ABI_FLAGS);
+  this->_alignment = 8;
+  this->_fsize = llvm::RoundUpToAlignment(sizeof(_abiFlags), this->_alignment);
+  this->_msize = this->_fsize;
+  this->_entSize = this->_fsize;
+  this->_type = SHT_MIPS_ABIFLAGS;
+  this->_flags = SHF_ALLOC;
+}
+
+template <class ELFT>
+void MipsAbiFlagsSection<ELFT>::write(ELFWriter *writer,
+                                      TargetLayout<ELFT> &layout,
+                                      llvm::FileOutputBuffer &buffer) {
+  uint8_t *dest = buffer.getBufferStart() + this->fileOffset();
+  std::memcpy(dest, &_abiFlags, this->_fsize);
+}
+
+template <class ELFT> void MipsAbiFlagsSection<ELFT>::finalize() {
+  if (this->_outputSection)
+    this->_outputSection->setType(this->_type);
+}
+
+template class MipsAbiFlagsSection<ELF32LE>;
+template class MipsAbiFlagsSection<ELF64LE>;
+
+template <class ELFT>
 MipsGOTSection<ELFT>::MipsGOTSection(const MipsLinkingContext &ctx)
     : AtomSection<ELFT>(ctx, ".got", DefinedAtom::typeGOT, DefinedAtom::permRW_,
                         MipsTargetLayout<ELFT>::ORDER_GOT),

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h?rev=238686&r1=238685&r2=238686&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h Sun May 31 15:36:43 2015
@@ -60,6 +60,26 @@ private:
   MipsTargetLayout<ELFT> &_targetLayout;
 };
 
+/// \brief Handle .MIPS.abiflags section
+template <class ELFT> class MipsAbiFlagsSection : public Section<ELFT> {
+public:
+  typedef llvm::object::Elf_Mips_ABIFlags<ELFT> Elf_Mips_ABIFlags;
+
+  MipsAbiFlagsSection(const ELFLinkingContext &ctx,
+                      MipsTargetLayout<ELFT> &targetLayout,
+                      const Elf_Mips_ABIFlags &abiFlags);
+
+  bool hasOutputSegment() const override { return true; }
+
+  void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
+             llvm::FileOutputBuffer &buffer) override;
+  void finalize() override;
+
+private:
+  Elf_Mips_ABIFlags _abiFlags;
+  MipsTargetLayout<ELFT> &_targetLayout;
+};
+
 /// \brief Handle Mips GOT section
 template <class ELFT> class MipsGOTSection : public AtomSection<ELFT> {
 public:

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp?rev=238686&r1=238685&r2=238686&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp Sun May 31 15:36:43 2015
@@ -38,6 +38,8 @@ MipsTargetLayout<ELFT>::getSegmentType(S
     return llvm::ELF::PT_MIPS_REGINFO;
   case ORDER_MIPS_OPTIONS:
     return llvm::ELF::PT_LOAD;
+  case ORDER_MIPS_ABI_FLAGS:
+    return llvm::ELF::PT_MIPS_ABIFLAGS;
   default:
     return TargetLayout<ELFT>::getSegmentType(section);
   }

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.h?rev=238686&r1=238685&r2=238686&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.h Sun May 31 15:36:43 2015
@@ -21,8 +21,9 @@ class MipsLinkingContext;
 template <class ELFT> class MipsTargetLayout final : public TargetLayout<ELFT> {
 public:
   enum MipsSectionOrder {
-    ORDER_MIPS_REGINFO = TargetLayout<ELFT>::ORDER_RO_NOTE + 1,
-    ORDER_MIPS_OPTIONS
+    ORDER_MIPS_ABI_FLAGS = TargetLayout<ELFT>::ORDER_RO_NOTE + 1,
+    ORDER_MIPS_REGINFO,
+    ORDER_MIPS_OPTIONS,
   };
 
   MipsTargetLayout(MipsLinkingContext &ctx);

Added: lld/trunk/test/elf/Mips/abi-flags-01.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/abi-flags-01.test?rev=238686&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/abi-flags-01.test (added)
+++ lld/trunk/test/elf/Mips/abi-flags-01.test Sun May 31 15:36:43 2015
@@ -0,0 +1,35 @@
+# Check rejecting .MIPS.abiflags section with a wrong version.
+
+# RUN: yaml2obj -format=elf %s > %t.o
+# RUN: not lld -flavor gnu -target mipsel -shared -o %t.so %t.o 2>&1 \
+# RUN:       | FileCheck %s
+
+# CHECK: {{.*}}abi-flags-01.test.tmp.o: .MIPS.abiflags section has unsupported version '1'
+
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6]
+
+Sections:
+- Name:         .text
+  Type:         SHT_PROGBITS
+  Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+  Size:         4
+  AddressAlign: 16
+
+- Name: .MIPS.abiflags
+  Type: SHT_MIPS_ABIFLAGS
+  AddressAlign: 8
+  Version:      1
+  ISA:          MIPS32
+
+Symbols:
+  Global:
+    - Name:    T0
+      Section: .text
+      Type:    STT_FUNC
+      Value:   0
+      Size:    4

Added: lld/trunk/test/elf/Mips/abi-flags-02.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/abi-flags-02.test?rev=238686&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/abi-flags-02.test (added)
+++ lld/trunk/test/elf/Mips/abi-flags-02.test Sun May 31 15:36:43 2015
@@ -0,0 +1,92 @@
+# Check generation of .MIPS.abiflags section under the following conditions:
+# - There is the only input object file
+# - The input file has valid .MIPS.abiflags section
+#
+# The .MIPS.abiflags section in the output file should have the same
+# settings as the input section.
+
+# RUN: yaml2obj -format=elf %s > %t.o
+# RUN: lld -flavor gnu -target mipsel -shared -o %t.so %t.o
+# RUN: llvm-readobj -s -program-headers -mips-abi-flags %t.so | FileCheck %s
+
+# CHECK:      Section {
+# CHECK:        Index: 1
+# CHECK-NEXT:   Name: .MIPS.abiflags
+# CHECK-NEXT:   Type: SHT_MIPS_ABIFLAGS
+# CHECK-NEXT:   Flags [
+# CHECK-NEXT:     SHF_ALLOC
+# CHECK-NEXT:   ]
+# CHECK-NEXT:   Address: 0x{{[0-9A-F]+}}
+# CHECK-NEXT:   Offset: 0x{{[0-9A-F]+}}
+# CHECK-NEXT:   Size: 24
+# CHECK-NEXT:   Link: 0
+# CHECK-NEXT:   Info: 0
+# CHECK-NEXT:   AddressAlignment: 8
+# CHECK-NEXT:   EntrySize: 24
+# CHECK-NEXT: }
+
+# CHECK:      ProgramHeaders [
+# CHECK:        ProgramHeader {
+# CHECK:          Type: PT_MIPS_ABIFLAGS (0x70000003)
+# CHECK-NEXT:     Offset: 0x{{[0-9A-F]+}}
+# CHECK-NEXT:     VirtualAddress: 0x{{[0-9A-F]+}}
+# CHECK-NEXT:     PhysicalAddress: 0x{{[0-9A-F]+}}
+# CHECK-NEXT:     FileSize: 24
+# CHECK-NEXT:     MemSize: 24
+# CHECK-NEXT:     Flags [
+# CHECK-NEXT:       PF_R
+# CHECK-NEXT:     ]
+# CHECK-NEXT:     Alignment: 8
+# CHECK-NEXT:   }
+
+# CHECK:      MIPS ABI Flags {
+# CHECK-NEXT:   Version: 0
+# CHECK-NEXT:   ISA: MIPS32r2
+# CHECK-NEXT:   ISA Extension: None (0x0)
+# CHECK-NEXT:   ASEs [ (0x800)
+# CHECK-NEXT:     microMIPS (0x800)
+# CHECK-NEXT:   ]
+# CHECK-NEXT:   FP ABI: Hard float (32-bit CPU, Any FPU) (0x5)
+# CHECK-NEXT:   GPR size: 32
+# CHECK-NEXT:   CPR1 size: 32
+# CHECK-NEXT:   CPR2 size: 0
+# CHECK-NEXT:   Flags 1 [ (0x0)
+# CHECK-NEXT:   ]
+# CHECK-NEXT:   Flags 2: 0x0
+# CHECK-NEXT: }
+
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
+
+Sections:
+- Name:         .text
+  Type:         SHT_PROGBITS
+  Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+  Size:         4
+  AddressAlign: 16
+
+- Name: .MIPS.abiflags
+  Type: SHT_MIPS_ABIFLAGS
+  AddressAlign: 8
+  ISA:          MIPS32
+  ISARevision:  2
+  ISAExtension: EXT_NONE
+  ASEs:         [ MICROMIPS ]
+  FpABI:        FP_XX
+  GPRSize:      REG_32
+  CPR1Size:     REG_32
+  CPR2Size:     REG_NONE
+  Flags1:       [ ]
+  Flags2:       0x0
+
+Symbols:
+  Global:
+    - Name:    T0
+      Section: .text
+      Type:    STT_FUNC
+      Value:   0
+      Size:    4

Added: lld/trunk/test/elf/Mips/abi-flags-03.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/abi-flags-03.test?rev=238686&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/abi-flags-03.test (added)
+++ lld/trunk/test/elf/Mips/abi-flags-03.test Sun May 31 15:36:43 2015
@@ -0,0 +1,149 @@
+# Check generation of .MIPS.abiflags section under the following conditions:
+# - There are multiple input object files
+# - Every input file has valid .MIPS.abiflags section
+# - All .MIPS.abiflags sections are compatible with each other
+#
+# The .MIPS.abiflags section in the output file should reproduce result
+# of merging input object file sections.
+
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.o
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.o
+# RUN: yaml2obj -format=elf -docnum 3 %s > %t3.o
+# RUN: lld -flavor gnu -target mipsel -shared -o %t.so %t1.o %t2.o %t3.o
+# RUN: llvm-readobj -mips-abi-flags %t.so | FileCheck %s
+
+# CHECK:      MIPS ABI Flags {
+# CHECK-NEXT:   Version: 0
+# CHECK-NEXT:   ISA: MIPS32r2
+# CHECK-NEXT:   ISA Extension: None (0x0)
+# CHECK-NEXT:   ASEs [ (0x810)
+# CHECK-NEXT:     MDMX (0x10)
+# CHECK-NEXT:     microMIPS (0x800)
+# CHECK-NEXT:   ]
+# CHECK-NEXT:   FP ABI: Hard float (double precision) (0x1)
+# CHECK-NEXT:   GPR size: 32
+# CHECK-NEXT:   CPR1 size: 64
+# CHECK-NEXT:   CPR2 size: 0
+# CHECK-NEXT:   Flags 1 [ (0x1)
+# CHECK-NEXT:     ODDSPREG
+# CHECK-NEXT:   ]
+# CHECK-NEXT:   Flags 2: 0x0
+# CHECK-NEXT: }
+
+# o1.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_ABI_O32,
+            EF_MIPS_ARCH_32, EF_MIPS_ARCH_ASE_MDMX]
+
+Sections:
+- Name:         .text
+  Type:         SHT_PROGBITS
+  Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+  Size:         4
+  AddressAlign: 16
+
+- Name: .MIPS.abiflags
+  Type: SHT_MIPS_ABIFLAGS
+  AddressAlign: 8
+  ISA:          MIPS32
+  ISARevision:  1
+  ISAExtension: EXT_NONE
+  ASEs:         [ MDMX ]
+  FpABI:        FP_DOUBLE
+  GPRSize:      REG_32
+  CPR1Size:     REG_64
+  CPR2Size:     REG_NONE
+  Flags1:       [ ]
+  Flags2:       0x0
+
+Symbols:
+  Global:
+    - Name:    T1
+      Section: .text
+      Type:    STT_FUNC
+      Value:   0
+      Size:    4
+
+# o2.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_ABI_O32,
+            EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
+
+Sections:
+- Name:         .text
+  Type:         SHT_PROGBITS
+  Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+  Size:         4
+  AddressAlign: 16
+
+- Name: .MIPS.abiflags
+  Type: SHT_MIPS_ABIFLAGS
+  AddressAlign: 8
+  ISA:          MIPS32
+  ISARevision:  2
+  ISAExtension: EXT_NONE
+  ASEs:         [ MICROMIPS ]
+  FpABI:        FP_XX
+  GPRSize:      REG_32
+  CPR1Size:     REG_32
+  CPR2Size:     REG_NONE
+  Flags1:       [ODDSPREG]
+  Flags2:       0x0
+
+Symbols:
+  Global:
+    - Name:    T2
+      Section: .text
+      Type:    STT_FUNC
+      Value:   0
+      Size:    4
+
+# o3.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_ABI_O32,
+            EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
+
+Sections:
+- Name:         .text
+  Type:         SHT_PROGBITS
+  Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+  Size:         4
+  AddressAlign: 16
+
+- Name: .MIPS.abiflags
+  Type: SHT_MIPS_ABIFLAGS
+  AddressAlign: 8
+  ISA:          MIPS32
+  ISARevision:  2
+  ISAExtension: EXT_NONE
+  ASEs:         [ MICROMIPS ]
+  FpABI:        FP_XX
+  GPRSize:      REG_32
+  CPR1Size:     REG_32
+  CPR2Size:     REG_NONE
+  Flags1:       [ ]
+  Flags2:       0x0
+
+Symbols:
+  Global:
+    - Name:    T3
+      Section: .text
+      Type:    STT_FUNC
+      Value:   0
+      Size:    4
+...

Added: lld/trunk/test/elf/Mips/abi-flags-04.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/abi-flags-04.test?rev=238686&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/abi-flags-04.test (added)
+++ lld/trunk/test/elf/Mips/abi-flags-04.test Sun May 31 15:36:43 2015
@@ -0,0 +1,125 @@
+# Check generation of .MIPS.abiflags section under the following conditions:
+# - There are multiple input object files
+# - Every input file has valid .MIPS.abiflags section
+# - .MIPS.abiflags sections have different but compatible FP ABI
+#
+# The .MIPS.abiflags section in the output file should reproduce result
+# of merging FP ABI flags.
+
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t-xx.o
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t-double.o
+# RUN: yaml2obj -format=elf -docnum 3 %s > %t-64.o
+# RUN: yaml2obj -format=elf -docnum 4 %s > %t-64a.o
+
+# RUN: lld -flavor gnu -target mipsel -shared -o %t1 %t-xx.o %t-double.o
+# RUN: llvm-readobj -mips-abi-flags %t1 | FileCheck -check-prefix=XX-DOUBLE %s
+
+# XX-DOUBLE:  FP ABI:     Hard float (double precision) (0x1)
+# XX-DOUBLE:  GPR size:   32
+# XX-DOUBLE:  CPR1 size:  32
+# XX-DOUBLE:  Flags 1     [ (0x0)
+
+# RUN: lld -flavor gnu -target mipsel -shared -o %t2 %t-xx.o %t-64.o
+# RUN: llvm-readobj -mips-abi-flags %t2 | FileCheck -check-prefix=XX-64 %s
+
+# XX-64:  FP ABI:     Hard float (32-bit CPU, 64-bit FPU) (0x6)
+# XX-64:  GPR size:   32
+# XX-64:  CPR1 size:  64
+# XX-64:  Flags 1     [ (0x1)
+# XX-64:    ODDSPREG (0x1)
+
+# RUN: lld -flavor gnu -target mipsel -shared -o %t3 %t-xx.o %t-64a.o
+# RUN: llvm-readobj -mips-abi-flags %t3 | FileCheck -check-prefix=XX-64A %s
+
+# XX-64A:  FP ABI:     Hard float compat (32-bit CPU, 64-bit FPU) (0x7)
+# XX-64A:  GPR size:   32
+# XX-64A:  CPR1 size:  64
+# XX-64A:  Flags 1     [ (0x0)
+
+# RUN: lld -flavor gnu -target mipsel -shared -o %t4 %t-64.o %t-64a.o
+# RUN: llvm-readobj -mips-abi-flags %t4 | FileCheck -check-prefix=64-64A %s
+
+# 64-64A:  FP ABI:     Hard float (32-bit CPU, 64-bit FPU) (0x6)
+# 64-64A:  GPR size:   32
+# 64-64A:  CPR1 size:  64
+# 64-64A:  Flags 1     [ (0x1)
+# 64-64A:    ODDSPREG (0x1)
+
+# xx.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
+
+Sections:
+- Name: .MIPS.abiflags
+  Type: SHT_MIPS_ABIFLAGS
+  AddressAlign: 8
+  ISA:          MIPS32
+  ISARevision:  1
+  FpABI:        FP_XX
+  GPRSize:      REG_32
+  CPR1Size:     REG_32
+
+# double.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
+
+Sections:
+- Name: .MIPS.abiflags
+  Type: SHT_MIPS_ABIFLAGS
+  AddressAlign: 8
+  ISA:          MIPS32
+  ISARevision:  1
+  FpABI:        FP_DOUBLE
+  GPRSize:      REG_32
+  CPR1Size:     REG_32
+
+# 64.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
+
+Sections:
+- Name: .MIPS.abiflags
+  Type: SHT_MIPS_ABIFLAGS
+  AddressAlign: 8
+  ISA:          MIPS32
+  ISARevision:  2
+  FpABI:        FP_64
+  GPRSize:      REG_32
+  CPR1Size:     REG_64
+  Flags1:       [ODDSPREG]
+
+# 64a.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
+
+Sections:
+- Name: .MIPS.abiflags
+  Type: SHT_MIPS_ABIFLAGS
+  AddressAlign: 8
+  ISA:          MIPS32
+  ISARevision:  2
+  FpABI:        FP_64A
+  GPRSize:      REG_32
+  CPR1Size:     REG_64
+  Flags1:       []
+...

Added: lld/trunk/test/elf/Mips/abi-flags-05.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/abi-flags-05.test?rev=238686&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/abi-flags-05.test (added)
+++ lld/trunk/test/elf/Mips/abi-flags-05.test Sun May 31 15:36:43 2015
@@ -0,0 +1,186 @@
+# Check generation of .MIPS.abiflags section under the following conditions:
+# - There are multiple input object files
+# - Every input file has valid .MIPS.abiflags section
+# - .MIPS.abiflags sections have different and incompatible FP ABI
+#
+# The .MIPS.abiflags section in the output file should reproduce result
+# of merging FP ABI flags but the linker must show a warning.
+
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t-xx.o
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t-dbl.o
+# RUN: yaml2obj -format=elf -docnum 3 %s > %t-sgl.o
+# RUN: yaml2obj -format=elf -docnum 4 %s > %t-soft.o
+# RUN: yaml2obj -format=elf -docnum 5 %s > %t-64.o
+# RUN: yaml2obj -format=elf -docnum 6 %s > %t-64a.o
+
+# RUN: lld -flavor gnu -target mipsel -shared -o %t1 %t-xx.o %t-sgl.o 2>&1 \
+# RUN:   | FileCheck -check-prefix=XX-SINGLE-WARN %s
+
+# XX-SINGLE-WARN:  FP ABI {{-mfpxx|-msingle-float}} is incompatible with {{-msingle-float|-mfpxx}}
+
+# RUN: lld -flavor gnu -target mipsel -shared -o %t2 %t-xx.o %t-soft.o 2>&1 \
+# RUN:   | FileCheck -check-prefix=XX-SOFT-WARN %s
+
+# XX-SOFT-WARN:  FP ABI {{-mfpxx|-msoft-float}} is incompatible with {{-msoft-float|-mfpxx}}
+
+# RUN: lld -flavor gnu -target mipsel -shared -o %t3 %t-dbl.o %t-sgl.o 2>&1 \
+# RUN:   | FileCheck -check-prefix=DOUBLE-SINGLE-WARN %s
+
+# DOUBLE-SINGLE-WARN:  FP ABI {{-mdouble-float|-msingle-float}} is incompatible with {{-msingle-float|-mdouble-float}}
+
+# RUN: lld -flavor gnu -target mipsel -shared -o %t4 %t-dbl.o %t-soft.o 2>&1 \
+# RUN:   | FileCheck -check-prefix=DOUBLE-SOFT-WARN %s
+
+# DOUBLE-SOFT-WARN:  FP ABI {{-mdouble-float|-msoft-float}} is incompatible with {{-msoft-float|-mdouble-float}}
+
+# RUN: lld -flavor gnu -target mipsel -shared -o %t5 %t-dbl.o %t-64.o 2>&1 \
+# RUN:   | FileCheck -check-prefix=DOUBLE-64-WARN %s
+
+# DOUBLE-64-WARN:  FP ABI {{-mdouble-float|-mgp32 -mfp64}} is incompatible with {{-mgp32 -mfp64|-mdouble-float}}
+
+# RUN: lld -flavor gnu -target mipsel -shared -o %t6 %t-dbl.o %t-64a.o 2>&1 \
+# RUN:   | FileCheck -check-prefix=DOUBLE-64A-WARN %s
+
+# DOUBLE-64A-WARN:  FP ABI {{-mdouble-float|-mgp32 -mfp64 -mno-odd-spreg}} is incompatible with {{-mgp32 -mfp64 -mno-odd-spreg|-mdouble-float}}
+
+# RUN: lld -flavor gnu -target mipsel -shared -o %t7 %t-sgl.o %t-soft.o 2>&1 \
+# RUN:   | FileCheck -check-prefix=SINGLE-SOFT-WARN %s
+
+# SINGLE-SOFT-WARN:  FP ABI {{-msingle-float|-msoft-float}} is incompatible with {{-msoft-float|-msingle-float}}
+
+# RUN: lld -flavor gnu -target mipsel -shared -o %t8 %t-sgl.o %t-64.o 2>&1 \
+# RUN:   | FileCheck -check-prefix=SINGLE-64-WARN %s
+
+# SINGLE-64-WARN:  FP ABI {{-msingle-float|-mgp32 -mfp64}} is incompatible with {{-mgp32 -mfp64|-msingle-float}}
+
+# RUN: lld -flavor gnu -target mipsel -shared -o %t9 %t-sgl.o %t-64a.o 2>&1 \
+# RUN:   | FileCheck -check-prefix=SINGLE-64A-WARN %s
+
+# SINGLE-64A-WARN:  FP ABI {{-msingle-float|-mgp32 -mfp64 -mno-odd-spreg}} is incompatible with {{-mgp32 -mfp64 -mno-odd-spreg|-msingle-float}}
+
+# RUN: lld -flavor gnu -target mipsel -shared -o %t10 %t-soft.o %t-64.o 2>&1 \
+# RUN:   | FileCheck -check-prefix=SOFT-64-WARN %s
+
+# SOFT-64-WARN:  FP ABI {{-msoft-float|-mgp32 -mfp64}} is incompatible with {{-mgp32 -mfp64|-msoft-float}}
+
+# RUN: lld -flavor gnu -target mipsel -shared -o %t11 %t-soft.o %t-64a.o 2>&1 \
+# RUN:   | FileCheck -check-prefix=SOFT-64A-WARN %s
+
+# SOFT-64A-WARN:  FP ABI {{-msoft-float|-mgp32 -mfp64 -mno-odd-spreg}} is incompatible with {{-mgp32 -mfp64 -mno-odd-spreg|-msoft-float}}
+
+# xx.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
+
+Sections:
+- Name: .MIPS.abiflags
+  Type: SHT_MIPS_ABIFLAGS
+  AddressAlign: 8
+  ISA:          MIPS32
+  ISARevision:  1
+  FpABI:        FP_XX
+  GPRSize:      REG_32
+  CPR1Size:     REG_32
+
+# double.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
+
+Sections:
+- Name: .MIPS.abiflags
+  Type: SHT_MIPS_ABIFLAGS
+  AddressAlign: 8
+  ISA:          MIPS32
+  ISARevision:  1
+  FpABI:        FP_DOUBLE
+  GPRSize:      REG_32
+  CPR1Size:     REG_32
+
+# single.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
+
+Sections:
+- Name: .MIPS.abiflags
+  Type: SHT_MIPS_ABIFLAGS
+  AddressAlign: 8
+  ISA:          MIPS32
+  ISARevision:  1
+  FpABI:        FP_SINGLE
+  GPRSize:      REG_32
+  CPR1Size:     REG_32
+
+# soft.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
+
+Sections:
+- Name: .MIPS.abiflags
+  Type: SHT_MIPS_ABIFLAGS
+  AddressAlign: 8
+  ISA:          MIPS32
+  ISARevision:  1
+  FpABI:        FP_SOFT
+  GPRSize:      REG_32
+  CPR1Size:     REG_NONE
+
+# 64.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
+
+Sections:
+- Name: .MIPS.abiflags
+  Type: SHT_MIPS_ABIFLAGS
+  AddressAlign: 8
+  ISA:          MIPS32
+  ISARevision:  2
+  FpABI:        FP_64
+  GPRSize:      REG_32
+  CPR1Size:     REG_64
+  Flags1:       [ODDSPREG]
+
+# 64a.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2]
+
+Sections:
+- Name: .MIPS.abiflags
+  Type: SHT_MIPS_ABIFLAGS
+  AddressAlign: 8
+  ISA:          MIPS32
+  ISARevision:  2
+  FpABI:        FP_64A
+  GPRSize:      REG_32
+  CPR1Size:     REG_64
+  Flags1:       []
+...

Added: lld/trunk/test/elf/Mips/abi-flags-06.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/abi-flags-06.test?rev=238686&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/abi-flags-06.test (added)
+++ lld/trunk/test/elf/Mips/abi-flags-06.test Sun May 31 15:36:43 2015
@@ -0,0 +1,79 @@
+# Check generation of .MIPS.abiflags section under the following conditions:
+# - There are multiple input object files
+# - Not all input files have a .MIPS.abiflags section
+#
+# The .MIPS.abiflags section in the output file should reproduce result
+# of merging input object file sections and data come from ELF header flags.
+
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t-abi.o
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t-elf.o
+# RUN: lld -flavor gnu -target mipsel -shared -o %t.so %t-abi.o %t-elf.o
+# RUN: llvm-readobj -mips-abi-flags %t.so | FileCheck %s
+
+# CHECK:      MIPS ABI Flags {
+# CHECK-NEXT:   Version: 0
+# CHECK-NEXT:   ISA: MIPS32r2
+# CHECK-NEXT:   ISA Extension: None (0x0)
+# CHECK-NEXT:   ASEs [ (0x810)
+# CHECK-NEXT:     MDMX (0x10)
+# CHECK-NEXT:     microMIPS (0x800)
+# CHECK-NEXT:   ]
+# CHECK-NEXT:   FP ABI: Hard float (double precision) (0x1)
+# CHECK-NEXT:   GPR size: 32
+# CHECK-NEXT:   CPR1 size: 64
+# CHECK-NEXT:   CPR2 size: 0
+# CHECK-NEXT:   Flags 1 [ (0x0)
+# CHECK-NEXT:   ]
+# CHECK-NEXT:   Flags 2: 0x0
+# CHECK-NEXT: }
+
+# abi.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_ABI_O32,
+            EF_MIPS_ARCH_32, EF_MIPS_ARCH_ASE_MDMX]
+
+Sections:
+- Name: .MIPS.abiflags
+  Type: SHT_MIPS_ABIFLAGS
+  AddressAlign: 8
+  ISA:          MIPS32
+  ISARevision:  1
+  ISAExtension: EXT_NONE
+  ASEs:         [ MDMX ]
+  FpABI:        FP_DOUBLE
+  GPRSize:      REG_32
+  CPR1Size:     REG_64
+  CPR2Size:     REG_NONE
+  Flags1:       [ ]
+  Flags2:       0x0
+
+# elf.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_ABI_O32,
+            EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
+
+Sections:
+- Name:         .text
+  Type:         SHT_PROGBITS
+  Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+  Size:         4
+  AddressAlign: 16
+
+Symbols:
+  Global:
+    - Name:    T0
+      Section: .text
+      Type:    STT_FUNC
+      Value:   0
+      Size:    4
+...

Added: lld/trunk/test/elf/Mips/abi-flags-07.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/abi-flags-07.test?rev=238686&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/abi-flags-07.test (added)
+++ lld/trunk/test/elf/Mips/abi-flags-07.test Sun May 31 15:36:43 2015
@@ -0,0 +1,60 @@
+# Check that .MIPS.abiflags section is not written if no input object files
+# contain that section.
+
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.o
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.o
+# RUN: lld -flavor gnu -target mipsel -shared -o %t.so %t1.o %t2.o
+# RUN: llvm-readobj -mips-abi-flags %t.so | FileCheck %s
+
+# CHECK: There is no .MIPS.abiflags section in the file.
+
+# abi.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_ABI_O32,
+            EF_MIPS_ARCH_32, EF_MIPS_ARCH_ASE_MDMX]
+
+Sections:
+- Name:         .text
+  Type:         SHT_PROGBITS
+  Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+  Size:         4
+  AddressAlign: 16
+
+Symbols:
+  Global:
+    - Name:    T0
+      Section: .text
+      Type:    STT_FUNC
+      Value:   0
+      Size:    4
+
+# elf.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_ABI_O32,
+            EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
+
+Sections:
+- Name:         .text
+  Type:         SHT_PROGBITS
+  Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+  Size:         4
+  AddressAlign: 16
+
+Symbols:
+  Global:
+    - Name:    T1
+      Section: .text
+      Type:    STT_FUNC
+      Value:   0
+      Size:    4
+...

Added: lld/trunk/test/elf/Mips/abi-flags-08.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/abi-flags-08.test?rev=238686&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/abi-flags-08.test (added)
+++ lld/trunk/test/elf/Mips/abi-flags-08.test Sun May 31 15:36:43 2015
@@ -0,0 +1,71 @@
+# Check that the linker shows errors if ELF header flags
+# and .MIPS.abiflags section are incompatible.
+
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t-isa.o
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t-ext.o
+# RUN: yaml2obj -format=elf -docnum 3 %s > %t-ases.o
+# RUN: lld -flavor gnu -target mipsel -shared -o %t1.so %t-isa.o 2>&1 \
+# RUN:   | FileCheck -check-prefix=ISA-ERR %s
+# RUN: lld -flavor gnu -target mipsel -shared -o %t2.so %t-ext.o 2>&1 \
+# RUN:   | FileCheck -check-prefix=EXT-ERR %s
+# RUN: lld -flavor gnu -target mipsel -shared -o %t3.so %t-ases.o 2>&1 \
+# RUN:   | FileCheck -check-prefix=ASE-ERR %s
+# RUN: llvm-readobj -mips-abi-flags %t1.so %t2.so %t3.so \
+# RUN:   | FileCheck -check-prefix=SEC %s
+
+# ISA-ERR: inconsistent ISA between .MIPS.abiflags and ELF header e_flags field
+# EXT-ERR: inconsistent ISA between .MIPS.abiflags and ELF header e_flags field
+# ASE-ERR: inconsistent ASEs between .MIPS.abiflags and ELF header e_flags field
+
+# SEC: There is no .MIPS.abiflags section in the file.
+
+# isa.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
+
+Sections:
+- Name: .MIPS.abiflags
+  Type: SHT_MIPS_ABIFLAGS
+  AddressAlign: 8
+  ISA:          MIPS32
+  ISARevision:  2
+
+# ext.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_3, EF_MIPS_MACH_4650]
+
+Sections:
+- Name: .MIPS.abiflags
+  Type: SHT_MIPS_ABIFLAGS
+  AddressAlign: 8
+  ISA:          MIPS3
+  ISAExtension: EXT_4120
+
+# ases.o
+---
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
+
+Sections:
+- Name: .MIPS.abiflags
+  Type: SHT_MIPS_ABIFLAGS
+  AddressAlign: 8
+  ISA:          MIPS32
+  ISARevision:  2
+  ASEs:         []
+
+...





More information about the llvm-commits mailing list