[lld] r204606 - [Mips] Sort R_MIPS_LO16 / R_MIPS_HI16 / R_MIPS_GOT16 before finding

Simon Atanasyan simon at atanasyan.com
Mon Mar 24 07:09:17 PDT 2014


Author: atanasyan
Date: Mon Mar 24 09:09:17 2014
New Revision: 204606

URL: http://llvm.org/viewvc/llvm-project?rev=204606&view=rev
Log:
[Mips] Sort R_MIPS_LO16 / R_MIPS_HI16 / R_MIPS_GOT16 before finding
pairs and calculate AHL addend.

Added:
    lld/trunk/test/elf/Mips/hilo16-4.test
Modified:
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp?rev=204606&r1=204605&r2=204606&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp Mon Mar 24 09:09:17 2014
@@ -266,27 +266,47 @@ inline int64_t calcAHL(int64_t AHI, int6
 
 template <typename ELFT>
 void RelocationPass<ELFT>::calculateAHLs(const DefinedAtom &atom) {
-  std::vector<Reference *> references;
+  std::vector<const Reference *> lo16Refs;
+  std::vector<Reference *> hi16Refs;
   for (const auto &ref : atom) {
     if (ref->kindNamespace() != lld::Reference::KindNamespace::ELF)
       continue;
     assert(ref->kindArch() == Reference::KindArch::Mips);
     switch (ref->kindValue()) {
     case R_MIPS_HI16:
-      references.push_back(const_cast<Reference *>(ref));
+      hi16Refs.push_back(const_cast<Reference *>(ref));
+    case R_MIPS_LO16:
+      lo16Refs.push_back(ref);
       break;
     case R_MIPS_GOT16:
       if (isLocal(ref->target()))
-        references.push_back(const_cast<Reference *>(ref));
-      break;
-    case R_MIPS_LO16:
-      for (auto &sr : references)
-        sr->setAddend(calcAHL(sr->addend(), ref->addend()));
-      references.clear();
+        hi16Refs.push_back(const_cast<Reference *>(ref));
       break;
     }
   }
-  assert(references.empty());
+
+  std::sort(lo16Refs.begin(), lo16Refs.end(),
+            [](const Reference *a, const Reference *b) {
+    return a->offsetInAtom() < b->offsetInAtom();
+  });
+  std::sort(hi16Refs.begin(), hi16Refs.end(),
+            [](const Reference *a, const Reference *b) {
+    return a->offsetInAtom() < b->offsetInAtom();
+  });
+
+  // Iterate over R_MIPS_LO16 relocations sorted by theirs offsets in the atom.
+  // Calculate AHL addend for each R_MIPS_HI16 amd R_MIPS_GOT16 relocation
+  // precedes the current R_MIPS_LO16 one.
+
+  auto hic = hi16Refs.begin();
+  for (const auto &lo : lo16Refs) {
+    for (; hic != hi16Refs.end(); ++hic) {
+      if ((*hic)->offsetInAtom() > lo->offsetInAtom())
+        break;
+      (*hic)->setAddend(calcAHL((*hic)->addend(), lo->addend()));
+    }
+  }
+  assert(hic == hi16Refs.end());
 }
 
 template <typename ELFT>

Added: lld/trunk/test/elf/Mips/hilo16-4.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/hilo16-4.test?rev=204606&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/hilo16-4.test (added)
+++ lld/trunk/test/elf/Mips/hilo16-4.test Mon Mar 24 09:09:17 2014
@@ -0,0 +1,40 @@
+# Check handling HI16/LO16 relocations go in mixed order.
+#
+# RUN: llvm-mc -triple=mipsel -filetype=obj -o=%t-obj %s
+# RUN: lld -flavor gnu -target mipsel -e A -o %t-exe %t-obj
+# RUN: llvm-objdump -t -disassemble %t-exe | FileCheck %s
+
+# CHECK: Disassembly of section .text:
+# CHECK: A:
+# CHECK-NEXT: 400128:  42 00 08 3c  lui  $8, 66
+# CHECK-NEXT: 40012c:  40 00 08 3c  lui  $8, 64
+# CHECK-NEXT: 400130:  28 01 08 85  lh   $8, 296($8)
+# CHECK-NEXT: 400134:  38 01 08 85  lh   $8, 312($8)
+
+# CHECK: B:
+# CHECK-NEXT: 400138:  42 00 08 3c  lui  $8, 66
+# CHECK-NEXT: 40013c:  40 00 08 3c  lui  $8, 64
+# CHECK-NEXT: 400140:  38 01 08 85  lh   $8, 312($8)
+# CHECK-NEXT: 400144:  28 01 08 85  lh   $8, 296($8)
+
+# CHECK: SYMBOL TABLE:
+# CHECK: 00400128 g F .text  00000010 A
+# CHECK: 00400138 g F .text  00000010 B
+
+    .global A
+    .ent    A
+A:
+    lui     $t0,%hi(A+0x1ffff)
+    lui     $t0,%hi(B)
+    lh      $t0,%lo(A)($t0)
+    lh      $t0,%lo(B)($t0)
+    .end    A
+
+    .global B
+    .ent    B
+B:
+    lui     $t0,%hi(A+0x1ffff)
+    lui     $t0,%hi(B)
+    lh      $t0,%lo(B)($t0)
+    lh      $t0,%lo(A)($t0)
+    .end    B





More information about the llvm-commits mailing list