[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