summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/Thunks.cpp195
-rw-r--r--lld/test/ELF/Inputs/arm-long-thunk-converge.lds4
-rw-r--r--lld/test/ELF/Inputs/far-long-arm-abs.s13
-rw-r--r--lld/test/ELF/arm-branch-rangethunk.s51
-rw-r--r--lld/test/ELF/arm-long-thunk-converge.s28
-rw-r--r--lld/test/ELF/arm-thumb-condbranch-thunk.s24
-rw-r--r--lld/test/ELF/arm-thumb-range-thunk-os.s44
-rw-r--r--lld/test/ELF/arm-thumb-thunk-empty-pass.s14
-rw-r--r--lld/test/ELF/arm-thunk-largesection.s20
-rw-r--r--lld/test/ELF/arm-thunk-linkerscript-large.s4
-rw-r--r--lld/test/ELF/arm-thunk-linkerscript-sort.s4
-rw-r--r--lld/test/ELF/arm-thunk-multipass.s20
12 files changed, 278 insertions, 143 deletions
diff --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp
index 6662ed2df01..4db4990a1ef 100644
--- a/lld/ELF/Thunks.cpp
+++ b/lld/ELF/Thunks.cpp
@@ -64,46 +64,99 @@ public:
void addSymbols(ThunkSection &IS) override;
};
-// Specific ARM Thunk implementations. The naming convention is:
-// Source State, TargetState, Target Requirement, ABS or PI, Range
-class ARMV7ABSLongThunk final : public Thunk {
+// Base class for ARM thunks.
+//
+// An ARM thunk may be either short or long. A short thunk is simply a branch
+// (B) instruction, and it may be used to call ARM functions when the distance
+// from the thunk to the target is less than 32MB. Long thunks can branch to any
+// virtual address and can switch between ARM and Thumb, and they are
+// implemented in the derived classes. This class tries to create a short thunk
+// if the target is in range, otherwise it creates a long thunk.
+class ARMThunk : public Thunk {
public:
- ARMV7ABSLongThunk(Symbol &Dest) : Thunk(Dest) {}
+ ARMThunk(Symbol &Dest) : Thunk(Dest) {}
- uint32_t size() override { return 12; }
+ bool mayUseShortThunk();
+ uint32_t size() override { return mayUseShortThunk() ? 4 : sizeLong(); }
void writeTo(uint8_t *Buf) override;
- void addSymbols(ThunkSection &IS) override;
bool isCompatibleWith(RelType Type) const override;
+
+ // Returns the size of a long thunk.
+ virtual uint32_t sizeLong() = 0;
+
+ // Writes a long thunk to Buf.
+ virtual void writeLong(uint8_t *Buf) = 0;
+
+private:
+ // This field tracks whether all previously considered layouts would allow
+ // this thunk to be short. If we have ever needed a long thunk, we always
+ // create a long thunk, even if the thunk may be short given the current
+ // distance to the target. We do this because transitioning from long to short
+ // can create layout oscillations in certain corner cases which would prevent
+ // the layout from converging.
+ bool MayUseShortThunk = true;
};
-class ARMV7PILongThunk final : public Thunk {
+// Base class for Thumb-2 thunks.
+//
+// This class is similar to ARMThunk, but it uses the Thumb-2 B.W instruction
+// which has a range of 16MB.
+class ThumbThunk : public Thunk {
public:
- ARMV7PILongThunk(Symbol &Dest) : Thunk(Dest) {}
+ ThumbThunk(Symbol &Dest) : Thunk(Dest) { Alignment = 2; }
- uint32_t size() override { return 16; }
+ bool mayUseShortThunk();
+ uint32_t size() override { return mayUseShortThunk() ? 4 : sizeLong(); }
void writeTo(uint8_t *Buf) override;
- void addSymbols(ThunkSection &IS) override;
bool isCompatibleWith(RelType Type) const override;
+
+ // Returns the size of a long thunk.
+ virtual uint32_t sizeLong() = 0;
+
+ // Writes a long thunk to Buf.
+ virtual void writeLong(uint8_t *Buf) = 0;
+
+private:
+ // See comment in ARMThunk above.
+ bool MayUseShortThunk = true;
};
-class ThumbV7ABSLongThunk final : public Thunk {
+// Specific ARM Thunk implementations. The naming convention is:
+// Source State, TargetState, Target Requirement, ABS or PI, Range
+class ARMV7ABSLongThunk final : public ARMThunk {
public:
- ThumbV7ABSLongThunk(Symbol &Dest) : Thunk(Dest) { Alignment = 2; }
+ ARMV7ABSLongThunk(Symbol &Dest) : ARMThunk(Dest) {}
- uint32_t size() override { return 10; }
- void writeTo(uint8_t *Buf) override;
+ uint32_t sizeLong() override { return 12; }
+ void writeLong(uint8_t *Buf) override;
void addSymbols(ThunkSection &IS) override;
- bool isCompatibleWith(RelType Type) const override;
};
-class ThumbV7PILongThunk final : public Thunk {
+class ARMV7PILongThunk final : public ARMThunk {
public:
- ThumbV7PILongThunk(Symbol &Dest) : Thunk(Dest) { Alignment = 2; }
+ ARMV7PILongThunk(Symbol &Dest) : ARMThunk(Dest) {}
- uint32_t size() override { return 12; }
- void writeTo(uint8_t *Buf) override;
+ uint32_t sizeLong() override { return 16; }
+ void writeLong(uint8_t *Buf) override;
+ void addSymbols(ThunkSection &IS) override;
+};
+
+class ThumbV7ABSLongThunk final : public ThumbThunk {
+public:
+ ThumbV7ABSLongThunk(Symbol &Dest) : ThumbThunk(Dest) {}
+
+ uint32_t sizeLong() override { return 10; }
+ void writeLong(uint8_t *Buf) override;
+ void addSymbols(ThunkSection &IS) override;
+};
+
+class ThumbV7PILongThunk final : public ThumbThunk {
+public:
+ ThumbV7PILongThunk(Symbol &Dest) : ThumbThunk(Dest) {}
+
+ uint32_t sizeLong() override { return 12; }
+ void writeLong(uint8_t *Buf) override;
void addSymbols(ThunkSection &IS) override;
- bool isCompatibleWith(RelType Type) const override;
};
// MIPS LA25 thunk
@@ -211,7 +264,81 @@ static uint64_t getARMThunkDestVA(const Symbol &S) {
return SignExtend64<32>(V);
}
-void ARMV7ABSLongThunk::writeTo(uint8_t *Buf) {
+// This function returns true if the target is not Thumb and is within 2^26, and
+// it has not previously returned false (see comment for MayUseShortThunk).
+bool ARMThunk::mayUseShortThunk() {
+ if (!MayUseShortThunk)
+ return false;
+ uint64_t S = getARMThunkDestVA(Destination);
+ if (S & 1) {
+ MayUseShortThunk = false;
+ return false;
+ }
+ uint64_t P = getThunkTargetSym()->getVA();
+ int64_t Offset = S - P - 8;
+ MayUseShortThunk = llvm::isInt<26>(Offset);
+ return MayUseShortThunk;
+}
+
+void ARMThunk::writeTo(uint8_t *Buf) {
+ if (!mayUseShortThunk()) {
+ writeLong(Buf);
+ return;
+ }
+
+ uint64_t S = getARMThunkDestVA(Destination);
+ uint64_t P = getThunkTargetSym()->getVA();
+ int64_t Offset = S - P - 8;
+ const uint8_t Data[] = {
+ 0x00, 0x00, 0x00, 0xea, // b S
+ };
+ memcpy(Buf, Data, sizeof(Data));
+ Target->relocateOne(Buf, R_ARM_JUMP24, Offset);
+}
+
+bool ARMThunk::isCompatibleWith(RelType Type) const {
+ // Thumb branch relocations can't use BLX
+ return Type != R_ARM_THM_JUMP19 && Type != R_ARM_THM_JUMP24;
+}
+
+// This function returns true if the target is Thumb and is within 2^25, and
+// it has not previously returned false (see comment for MayUseShortThunk).
+bool ThumbThunk::mayUseShortThunk() {
+ if (!MayUseShortThunk)
+ return false;
+ uint64_t S = getARMThunkDestVA(Destination);
+ if ((S & 1) == 0) {
+ MayUseShortThunk = false;
+ return false;
+ }
+ uint64_t P = getThunkTargetSym()->getVA() & ~1;
+ int64_t Offset = S - P - 4;
+ MayUseShortThunk = llvm::isInt<25>(Offset);
+ return MayUseShortThunk;
+}
+
+void ThumbThunk::writeTo(uint8_t *Buf) {
+ if (!mayUseShortThunk()) {
+ writeLong(Buf);
+ return;
+ }
+
+ uint64_t S = getARMThunkDestVA(Destination);
+ uint64_t P = getThunkTargetSym()->getVA();
+ int64_t Offset = S - P - 4;
+ const uint8_t Data[] = {
+ 0x00, 0xf0, 0x00, 0xb0, // b.w S
+ };
+ memcpy(Buf, Data, sizeof(Data));
+ Target->relocateOne(Buf, R_ARM_THM_JUMP24, Offset);
+}
+
+bool ThumbThunk::isCompatibleWith(RelType Type) const {
+ // ARM branch relocations can't use BLX
+ return Type != R_ARM_JUMP24 && Type != R_ARM_PC24 && Type != R_ARM_PLT32;
+}
+
+void ARMV7ABSLongThunk::writeLong(uint8_t *Buf) {
const uint8_t Data[] = {
0x00, 0xc0, 0x00, 0xe3, // movw ip,:lower16:S
0x00, 0xc0, 0x40, 0xe3, // movt ip,:upper16:S
@@ -229,12 +356,7 @@ void ARMV7ABSLongThunk::addSymbols(ThunkSection &IS) {
addSymbol("$a", STT_NOTYPE, 0, IS);
}
-bool ARMV7ABSLongThunk::isCompatibleWith(RelType Type) const {
- // Thumb branch relocations can't use BLX
- return Type != R_ARM_THM_JUMP19 && Type != R_ARM_THM_JUMP24;
-}
-
-void ThumbV7ABSLongThunk::writeTo(uint8_t *Buf) {
+void ThumbV7ABSLongThunk::writeLong(uint8_t *Buf) {
const uint8_t Data[] = {
0x40, 0xf2, 0x00, 0x0c, // movw ip, :lower16:S
0xc0, 0xf2, 0x00, 0x0c, // movt ip, :upper16:S
@@ -252,12 +374,7 @@ void ThumbV7ABSLongThunk::addSymbols(ThunkSection &IS) {
addSymbol("$t", STT_NOTYPE, 0, IS);
}
-bool ThumbV7ABSLongThunk::isCompatibleWith(RelType Type) const {
- // ARM branch relocations can't use BLX
- return Type != R_ARM_JUMP24 && Type != R_ARM_PC24 && Type != R_ARM_PLT32;
-}
-
-void ARMV7PILongThunk::writeTo(uint8_t *Buf) {
+void ARMV7PILongThunk::writeLong(uint8_t *Buf) {
const uint8_t Data[] = {
0xf0, 0xcf, 0x0f, 0xe3, // P: movw ip,:lower16:S - (P + (L1-P) + 8)
0x00, 0xc0, 0x40, 0xe3, // movt ip,:upper16:S - (P + (L1-P) + 8)
@@ -278,12 +395,7 @@ void ARMV7PILongThunk::addSymbols(ThunkSection &IS) {
addSymbol("$a", STT_NOTYPE, 0, IS);
}
-bool ARMV7PILongThunk::isCompatibleWith(RelType Type) const {
- // Thumb branch relocations can't use BLX
- return Type != R_ARM_THM_JUMP19 && Type != R_ARM_THM_JUMP24;
-}
-
-void ThumbV7PILongThunk::writeTo(uint8_t *Buf) {
+void ThumbV7PILongThunk::writeLong(uint8_t *Buf) {
const uint8_t Data[] = {
0x4f, 0xf6, 0xf4, 0x7c, // P: movw ip,:lower16:S - (P + (L1-P) + 4)
0xc0, 0xf2, 0x00, 0x0c, // movt ip,:upper16:S - (P + (L1-P) + 4)
@@ -304,11 +416,6 @@ void ThumbV7PILongThunk::addSymbols(ThunkSection &IS) {
addSymbol("$t", STT_NOTYPE, 0, IS);
}
-bool ThumbV7PILongThunk::isCompatibleWith(RelType Type) const {
- // ARM branch relocations can't use BLX
- return Type != R_ARM_JUMP24 && Type != R_ARM_PC24 && Type != R_ARM_PLT32;
-}
-
// Write MIPS LA25 thunk code to call PIC function from the non-PIC one.
void MipsThunk::writeTo(uint8_t *Buf) {
uint64_t S = Destination.getVA();
diff --git a/lld/test/ELF/Inputs/arm-long-thunk-converge.lds b/lld/test/ELF/Inputs/arm-long-thunk-converge.lds
new file mode 100644
index 00000000000..592d400c8dc
--- /dev/null
+++ b/lld/test/ELF/Inputs/arm-long-thunk-converge.lds
@@ -0,0 +1,4 @@
+SECTIONS {
+ .foo : { *(.foo) }
+ .bar 0x2000000 : { *(.bar) }
+}
diff --git a/lld/test/ELF/Inputs/far-long-arm-abs.s b/lld/test/ELF/Inputs/far-long-arm-abs.s
new file mode 100644
index 00000000000..10d9d0292ea
--- /dev/null
+++ b/lld/test/ELF/Inputs/far-long-arm-abs.s
@@ -0,0 +1,13 @@
+.global far
+.type far,%function
+far = 0x201001c
+
+.global too_far1
+.type too_far1,%function
+too_far1 = 0x2020014
+.global too_far2
+.type too_far2,%function
+too_far2 = 0x2020020
+.global too_far3
+.type too_far3,%function
+too_far3 = 0x202002c
diff --git a/lld/test/ELF/arm-branch-rangethunk.s b/lld/test/ELF/arm-branch-rangethunk.s
index c61ec899ada..e541f98d181 100644
--- a/lld/test/ELF/arm-branch-rangethunk.s
+++ b/lld/test/ELF/arm-branch-rangethunk.s
@@ -1,7 +1,10 @@
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/far-arm-abs.s -o %tfar
// RUN: ld.lld %t %tfar -o %t2 2>&1
-// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s
+// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck --check-prefix=SHORT %s
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/far-long-arm-abs.s -o %tfarlong
+// RUN: ld.lld %t %tfarlong -o %t3 2>&1
+// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t3 | FileCheck --check-prefix=LONG %s
// REQUIRES: arm
.syntax unified
.section .text, "ax",%progbits
@@ -15,20 +18,32 @@ _start:
b too_far2
beq too_far3
-// CHECK: Disassembly of section .text:
-// CHECK-NEXT: _start:
-// CHECK-NEXT: 20000: 01 00 00 eb bl #4 <__ARMv7ABSLongThunk_too_far1>
-// CHECK-NEXT: 20004: 03 00 00 ea b #12 <__ARMv7ABSLongThunk_too_far2>
-// CHECK-NEXT: 20008: 05 00 00 0a beq #20 <__ARMv7ABSLongThunk_too_far3>
-// CHECK: __ARMv7ABSLongThunk_too_far1:
-// CHECK-NEXT: 2000c: 08 c0 00 e3 movw r12, #8
-// CHECK-NEXT: 20010: 02 c2 40 e3 movt r12, #514
-// CHECK-NEXT: 20014: 1c ff 2f e1 bx r12
-// CHECK: __ARMv7ABSLongThunk_too_far2:
-// CHECK-NEXT: 20018: 0c c0 00 e3 movw r12, #12
-// CHECK-NEXT: 2001c: 02 c2 40 e3 movt r12, #514
-// CHECK-NEXT: 20020: 1c ff 2f e1 bx r12
-// CHECK: __ARMv7ABSLongThunk_too_far3:
-// CHECK-NEXT: 20024: 10 c0 00 e3 movw r12, #16
-// CHECK-NEXT: 20028: 02 c2 40 e3 movt r12, #514
-// CHECK-NEXT: 2002c: 1c ff 2f e1 bx r12
+// SHORT: Disassembly of section .text:
+// SHORT-NEXT: _start:
+// SHORT-NEXT: 20000: 01 00 00 eb bl #4 <__ARMv7ABSLongThunk_too_far1>
+// SHORT-NEXT: 20004: 01 00 00 ea b #4 <__ARMv7ABSLongThunk_too_far2>
+// SHORT-NEXT: 20008: 01 00 00 0a beq #4 <__ARMv7ABSLongThunk_too_far3>
+// SHORT: __ARMv7ABSLongThunk_too_far1:
+// SHORT-NEXT: 2000c: fd ff 7f ea b #33554420 <__ARMv7ABSLongThunk_too_far3+0x1fffff4>
+// SHORT: __ARMv7ABSLongThunk_too_far2:
+// SHORT-NEXT: 20010: fd ff 7f ea b #33554420 <__ARMv7ABSLongThunk_too_far3+0x1fffff8>
+// SHORT: __ARMv7ABSLongThunk_too_far3:
+// SHORT-NEXT: 20014: fd ff 7f ea b #33554420 <__ARMv7ABSLongThunk_too_far3+0x1fffffc>
+
+// LONG: Disassembly of section .text:
+// LONG-NEXT: _start:
+// LONG-NEXT: 20000: 01 00 00 eb bl #4 <__ARMv7ABSLongThunk_too_far1>
+// LONG-NEXT: 20004: 03 00 00 ea b #12 <__ARMv7ABSLongThunk_too_far2>
+// LONG-NEXT: 20008: 05 00 00 0a beq #20 <__ARMv7ABSLongThunk_too_far3>
+// LONG: __ARMv7ABSLongThunk_too_far1:
+// LONG-NEXT: 2000c: 14 c0 00 e3 movw r12, #20
+// LONG-NEXT: 20010: 02 c2 40 e3 movt r12, #514
+// LONG-NEXT: 20014: 1c ff 2f e1 bx r12
+// LONG: __ARMv7ABSLongThunk_too_far2:
+// LONG-NEXT: 20018: 20 c0 00 e3 movw r12, #32
+// LONG-NEXT: 2001c: 02 c2 40 e3 movt r12, #514
+// LONG-NEXT: 20020: 1c ff 2f e1 bx r12
+// LONG: __ARMv7ABSLongThunk_too_far3:
+// LONG-NEXT: 20024: 2c c0 00 e3 movw r12, #44
+// LONG-NEXT: 20028: 02 c2 40 e3 movt r12, #514
+// LONG-NEXT: 2002c: 1c ff 2f e1 bx r12
diff --git a/lld/test/ELF/arm-long-thunk-converge.s b/lld/test/ELF/arm-long-thunk-converge.s
new file mode 100644
index 00000000000..774e819f26a
--- /dev/null
+++ b/lld/test/ELF/arm-long-thunk-converge.s
@@ -0,0 +1,28 @@
+// RUN: llvm-mc -triple armv7-unknown-gnu -filetype=obj -o %t %s
+// RUN: ld.lld %t %S/Inputs/arm-long-thunk-converge.lds -o %t2
+// RUN: llvm-objdump -d -start-address=0x00000000 -stop-address=0x00000010 -triple=armv7a-linux-gnueabihf %t2 | FileCheck --check-prefix=CHECK1 %s
+// RUN: llvm-objdump -d -start-address=0x02000000 -stop-address=0x02000010 -triple=armv7a-linux-gnueabihf %t2 | FileCheck --check-prefix=CHECK2 %s
+// RUN: rm -f %t2
+
+// CHECK1: __ARMv7ABSLongThunk_bar:
+// CHECK1-NEXT: 0: 0c c0 00 e3 movw r12, #12
+// CHECK1-NEXT: 4: 00 c2 40 e3 movt r12, #512
+// CHECK1-NEXT: 8: 1c ff 2f e1 bx r12
+// CHECK1: foo:
+// CHECK1-NEXT: c: fb ff ff eb bl #-20
+
+.section .foo,"ax",%progbits,unique,1
+foo:
+bl bar
+
+// CHECK2: __ARMv7ABSLongThunk_foo:
+// CHECK2-NEXT: 2000000: 0c c0 00 e3 movw r12, #12
+// CHECK2-NEXT: 2000004: 00 c0 40 e3 movt r12, #0
+// CHECK2-NEXT: 2000008: 1c ff 2f e1 bx r12
+// CHECK2: bar:
+// CHECK2-NEXT: 200000c: fb ff ff eb bl #-20 <__ARMv7ABSLongThunk_foo>
+
+.section .bar,"ax",%progbits,unique,1
+bar:
+bl foo
+.zero 0x1000000
diff --git a/lld/test/ELF/arm-thumb-condbranch-thunk.s b/lld/test/ELF/arm-thumb-condbranch-thunk.s
index c527e5df297..c9365efb73a 100644
--- a/lld/test/ELF/arm-thumb-condbranch-thunk.s
+++ b/lld/test/ELF/arm-thumb-condbranch-thunk.s
@@ -38,13 +38,9 @@ _start:
// CHECK1-NEXT: 80000: 70 47 bx lr
// CHECK1-NEXT: 80002: 7f f3 ff d7 bl #16252926
// CHECK1: __Thumbv7ABSLongThunk_tfunc05:
-// CHECK1-NEXT: 80008: 40 f2 01 0c movw r12, #1
-// CHECK1-NEXT: 8000c: c0 f2 30 0c movt r12, #48
-// CHECK1-NEXT: 80010: 60 47 bx r12
+// CHECK1-NEXT: 80008: 7f f2 fa bf b.w #2621428 <tfunc05>
// CHECK1: __Thumbv7ABSLongThunk_tfunc00:
-// CHECK1-NEXT: 80012: 40 f2 01 0c movw r12, #1
-// CHECK1-NEXT: 80016: c0 f2 08 0c movt r12, #8
-// CHECK1-NEXT: 8001a: 60 47 bx r12
+// CHECK1-NEXT: 8000c: ff f7 f8 bf b.w #-16 <tfunc00>
FUNCTION 01
// tfunc02 is within range of tfunc02
beq.w tfunc02
@@ -61,7 +57,7 @@ _start:
beq.w tfunc00
// CHECK3: 180000: 70 47 bx lr
// CHECK3-NEXT: 180002: 40 f4 01 80 bne.w #-1048574 <__Thumbv7ABSLongThunk_tfunc05>
-// CHECK3-NEXT: 180006: 00 f4 04 80 beq.w #-1048568 <__Thumbv7ABSLongThunk_tfunc00>
+// CHECK3-NEXT: 180006: 00 f4 01 80 beq.w #-1048574 <__Thumbv7ABSLongThunk_tfunc00>
FUNCTION 03
FUNCTION 04
FUNCTION 05
@@ -70,9 +66,7 @@ _start:
FUNCTION 08
FUNCTION 09
// CHECK4: __Thumbv7ABSLongThunk_tfunc03:
-// CHECK4-NEXT: 500004: 40 f2 01 0c movw r12, #1
-// CHECK4-NEXT: 500008: c0 f2 20 0c movt r12, #32
-// CHECK4-NEXT: 50000c: 60 47 bx r12
+// CHECK4-NEXT: 500004: ff f4 fc bf b.w #-3145736 <tfunc03>
FUNCTION 10
// We can't reach any Thunk Section, create a new one
beq.w tfunc03
@@ -101,17 +95,13 @@ _start:
FUNCTION 30
FUNCTION 31
// CHECK6: __Thumbv7ABSLongThunk_tfunc33:
-// CHECK6-NEXT: 1000004: 40 f2 01 0c movw r12, #1
-// CHECK6-NEXT: 1000008: c0 f2 10 1c movt r12, #272
-// CHECK6-NEXT: 100000c: 60 47 bx r12
+// CHECK6-NEXT: 1000004: ff f0 fc bf b.w #1048568 <tfunc33>
// CHECK6: __Thumbv7ABSLongThunk_tfunc00:
-// CHECK6-NEXT: 100000e: 40 f2 01 0c movw r12, #1
-// CHECK6-NEXT: 1000012: c0 f2 08 0c movt r12, #8
-// CHECK6-NEXT: 1000016: 60 47 bx r12
+// CHECK6-NEXT: 1000008: 7f f4 fa 97 b.w #-16252940 <tfunc00>
FUNCTION 32
FUNCTION 33
// We should be able to reach an existing ThunkSection.
b.w tfunc00
// CHECK7: tfunc33:
// CHECK7-NEXT: 1100000: 70 47 bx lr
-// CHECK7-NEXT: 1100002: 00 f7 04 b8 b.w #-1048568 <__Thumbv7ABSLongThunk_tfunc00>
+// CHECK7-NEXT: 1100002: 00 f7 01 b8 b.w #-1048574 <__Thumbv7ABSLongThunk_tfunc00>
diff --git a/lld/test/ELF/arm-thumb-range-thunk-os.s b/lld/test/ELF/arm-thumb-range-thunk-os.s
index 588539ddab8..ae8c704b94f 100644
--- a/lld/test/ELF/arm-thumb-range-thunk-os.s
+++ b/lld/test/ELF/arm-thumb-range-thunk-os.s
@@ -60,7 +60,7 @@ _start:
b.w tfunc28
// CHECK4: tfunc02:
// CHECK4-NEXT: 400000: 70 47 bx lr
-// CHECK4-NEXT: 400002: 00 f0 04 90 b.w #12582920 <__Thumbv7ABSLongThunk_tfunc28>
+// CHECK4-NEXT: 400002: 00 f0 01 90 b.w #12582914 <__Thumbv7ABSLongThunk_tfunc28>
FUNCTION 03
FUNCTION 04
FUNCTION 05
@@ -75,25 +75,19 @@ _start:
FUNCTION 14
// Expect precreated ThunkSection here
// CHECK5: __Thumbv7ABSLongThunk_tfunc16:
-// CHECK5-NEXT: 1000004: 40 f2 01 0c movw r12, #1
-// CHECK5-NEXT: 1000008: c0 f2 20 1c movt r12, #288
-// CHECK5-NEXT: 100000c: 60 47 bx r12
+// CHECK5-NEXT: 1000004: ff f1 fc bf b.w #2097144 <tfunc16>
// CHECK5: __Thumbv7ABSLongThunk_tfunc28:
-// CHECK5-NEXT: 100000e: 40 f2 01 0c movw r12, #1
-// CHECK5-NEXT: 1000012: c0 f2 e0 1c movt r12, #480
-// CHECK5-NEXT: 1000016: 60 47 bx r12
+// CHECK5-NEXT: 1000008: ff f1 fa 97 b.w #14680052 <tfunc28>
// CHECK5: __Thumbv7ABSLongThunk_tfunc32:
-// CHECK5-NEXT: 1000018: 40 f2 01 0c movw r12, #1
-// CHECK5-NEXT: 100001c: c0 f2 20 2c movt r12, #544
-// CHECK5-NEXT: 1000020: 60 47 bx r12
+// CHECK5-NEXT: 100000c: 40 f2 01 0c movw r12, #1
+// CHECK5-NEXT: 1000010: c0 f2 20 2c movt r12, #544
+// CHECK5-NEXT: 1000014: 60 47 bx r12
// CHECK5: __Thumbv7ABSLongThunk_tfunc33:
-// CHECK5-NEXT: 1000022: 40 f2 01 0c movw r12, #1
-// CHECK5-NEXT: 1000026: c0 f2 30 2c movt r12, #560
-// CHECK5-NEXT: 100002a: 60 47 bx r12
+// CHECK5-NEXT: 1000016: 40 f2 01 0c movw r12, #1
+// CHECK5-NEXT: 100001a: c0 f2 30 2c movt r12, #560
+// CHECK5-NEXT: 100001e: 60 47 bx r12
// CHECK5: __Thumbv7ABSLongThunk_tfunc02:
-// CHECK5-NEXT: 100002c: 40 f2 01 0c movw r12, #1
-// CHECK5-NEXT: 1000030: c0 f2 40 0c movt r12, #64
-// CHECK5-NEXT: 1000034: 60 47 bx r12
+// CHECK5-NEXT: 1000020: ff f7 ee 97 b.w #-12582948 <tfunc02>
FUNCTION 15
// tfunc00 and tfunc01 are < 16Mb away, expect no range extension thunks
bl tfunc00
@@ -106,8 +100,8 @@ _start:
// CHECK6-NEXT: 1100000: 70 47 bx lr
// CHECK6-NEXT: 1100002: ff f4 fd d7 bl #-15728646
// CHECK6-NEXT: 1100006: ff f5 fb d7 bl #-14680074
-// CHECK6-NEXT: 110000a: 00 f7 05 f8 bl #-1048566
-// CHECK6-NEXT: 110000e: 00 f7 08 f8 bl #-1048560
+// CHECK6-NEXT: 110000a: ff f6 ff ff bl #-1048578
+// CHECK6-NEXT: 110000e: 00 f7 02 f8 bl #-1048572
FUNCTION 16
FUNCTION 17
FUNCTION 18
@@ -125,19 +119,15 @@ _start:
// section
// CHECK7: tfunc28:
// CHECK7-NEXT: 1e00000: 70 47 bx lr
-// CHECK7-NEXT: 1e00002: 00 f6 13 90 b.w #-14680026 <__Thumbv7ABSLongThunk_tfunc02>
+// CHECK7-NEXT: 1e00002: 00 f6 0d 90 b.w #-14680038 <__Thumbv7ABSLongThunk_tfunc02>
b.w tfunc02
FUNCTION 29
// Expect another precreated thunk section here
// CHECK8: __Thumbv7ABSLongThunk_tfunc15:
-// CHECK8-NEXT: 1f00004: 40 f2 01 0c movw r12, #1
-// CHECK8-NEXT: 1f00008: c0 f2 10 1c movt r12, #272
-// CHECK8-NEXT: 1f0000c: 60 47 bx r12
+// CHECK8-NEXT: 1f00004: ff f5 fc 97 b.w #-14680072 <tfunc15>
// CHECK8: __Thumbv7ABSLongThunk_tfunc16:
-// CHECK8-NEXT: 1f0000e: 40 f2 01 0c movw r12, #1
-// CHECK8-NEXT: 1f00012: c0 f2 20 1c movt r12, #288
-// CHECK8-NEXT: 1f00016: 60 47 bx r12
+// CHECK8-NEXT: 1f00008: ff f6 fa 97 b.w #-13631500 <tfunc16>
FUNCTION 30
FUNCTION 31
FUNCTION 32
@@ -148,7 +138,7 @@ _start:
// CHECK9: tfunc32:
// CHECK9: 2200000: 70 47 bx lr
// CHECK9-NEXT: 2200002: ff f4 ff ff bl #-3145730
-// CHECK9-NEXT: 2200006: 00 f5 02 f8 bl #-3145724
+// CHECK9-NEXT: 2200006: ff f4 ff ff bl #-3145730
FUNCTION 33
bl tfunc15
@@ -156,4 +146,4 @@ _start:
// CHECK10: tfunc33:
// CHECK10: 2300000: 70 47 bx lr
// CHECK10-NEXT: 2300002: ff f7 ff f7 bl #-4194306
-// CHECK10-NEXT: 2300006: 00 f4 02 f8 bl #-4194300
+// CHECK10-NEXT: 2300006: ff f7 ff f7 bl #-4194306
diff --git a/lld/test/ELF/arm-thumb-thunk-empty-pass.s b/lld/test/ELF/arm-thumb-thunk-empty-pass.s
index 9ff6ed6a780..ab9da1b8a2c 100644
--- a/lld/test/ELF/arm-thumb-thunk-empty-pass.s
+++ b/lld/test/ELF/arm-thumb-thunk-empty-pass.s
@@ -2,7 +2,7 @@
// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
// RUN: ld.lld %t -o %t2 2>&1
// RUN: llvm-objdump -d %t2 -start-address=69632 -stop-address=69646 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s
-// RUN: llvm-objdump -d %t2 -start-address=16846860 -stop-address=16846874 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s
+// RUN: llvm-objdump -d %t2 -start-address=16846856 -stop-address=16846874 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s
.syntax unified
.global _start, foo
.type _start, %function
@@ -20,13 +20,11 @@ foo:
// CHECK1-NEXT: _start:
// CHECK1-NEXT: 11000: ff f7 fe ff bl #-4
// CHECK1: __Thumbv7ABSLongThunk__start:
-// CHECK1-NEXT: 11004: 41 f2 01 0c movw r12, #4097
-// CHECK1-NEXT: 11008: c0 f2 01 0c movt r12, #1
-// CHECK1-NEXT: 1100c: 60 47 bx r12
+// CHECK1-NEXT: 11004: ff f7 fc bf b.w #-8 <_start>
// CHECK2: __Thumbv7ABSLongThunk__start:
-// CHECK2: 101100c: 41 f2 01 0c movw r12, #4097
-// CHECK2-NEXT: 1011010: c0 f2 01 0c movt r12, #1
-// CHECK2-NEXT: 1011014: 60 47 bx r12
+// CHECK2: 1011008: 41 f2 01 0c movw r12, #4097
+// CHECK2-NEXT: 101100c: c0 f2 01 0c movt r12, #1
+// CHECK2-NEXT: 1011010: 60 47 bx r12
// CHECK2: foo:
-// CHECK2-NEXT: 1011016: ff f7 f9 ff bl #-14
+// CHECK2-NEXT: 1011012: ff f7 f9 ff bl #-14
diff --git a/lld/test/ELF/arm-thunk-largesection.s b/lld/test/ELF/arm-thunk-largesection.s
index 950f789764a..5e882a90605 100644
--- a/lld/test/ELF/arm-thunk-largesection.s
+++ b/lld/test/ELF/arm-thunk-largesection.s
@@ -2,9 +2,9 @@
// RUN: ld.lld %t -o %t2 2>&1
// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=69632 -stop-address=69636 %t2 | FileCheck -check-prefix=CHECK1 %s
// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=73732 -stop-address=73742 %t2 | FileCheck -check-prefix=CHECK2 %s
-// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=16850944 -stop-address=16850948 %t2 | FileCheck -check-prefix=CHECK3 %s
-// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=33628160 -stop-address=33628164 %t2 | FileCheck -check-prefix=CHECK4 %s
-// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=50405364 -stop-address=50405376 %t2 | FileCheck -check-prefix=CHECK5 %s
+// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=16850936 -stop-address=16850940 %t2 | FileCheck -check-prefix=CHECK3 %s
+// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=33628152 -stop-address=33628156 %t2 | FileCheck -check-prefix=CHECK4 %s
+// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=50405356 -stop-address=50405376 %t2 | FileCheck -check-prefix=CHECK5 %s
// REQUIRES: arm
.syntax unified
.balign 0x1000
@@ -21,9 +21,7 @@ _start:
// CHECK1-NEXT: 11002: 00 00 movs r0, r0
// CHECK2: __Thumbv7ABSLongThunk__start:
-// CHECK2-NEXT: 12004: 41 f2 01 0c movw r12, #4097
-// CHECK2-NEXT: 12008: c0 f2 01 0c movt r12, #1
-// CHECK2-NEXT: 1200c: 60 47 bx r12
+// CHECK2-NEXT: 12004: fe f7 fc bf b.w #-4104 <_start>
// Gigantic section where we need a ThunkSection either side of it
.section .text.large1, "ax", %progbits
@@ -33,10 +31,10 @@ _start:
.space (16 * 1024 * 1024) - 4
bl _start
.space (16 * 1024 * 1024) - 16
-// CHECK3: 1012000: 00 f4 00 d0 bl #-16777216
-// CHECK4: 2012000: ff f3 f8 d7 bl #16777200
+// CHECK3: 1011ff8: 00 f4 04 d0 bl #-16777208
+// CHECK4: 2011ff8: ff f3 f8 d7 bl #16777200
// CHECK5: __Thumbv7ABSLongThunk__start:
-// CHECK5-NEXT: 3011ff4: 41 f2 01 0c movw r12, #4097
-// CHECK5-NEXT: 3011ff8: c0 f2 01 0c movt r12, #1
-// CHECK5-NEXT: 3011ffc: 60 47 bx r12
+// CHECK5-NEXT: 3011fec: 41 f2 01 0c movw r12, #4097
+// CHECK5-NEXT: 3011ff0: c0 f2 01 0c movt r12, #1
+// CHECK5-NEXT: 3011ff4: 60 47 bx r12
diff --git a/lld/test/ELF/arm-thunk-linkerscript-large.s b/lld/test/ELF/arm-thunk-linkerscript-large.s
index 07cd1dd8797..839d7716c27 100644
--- a/lld/test/ELF/arm-thunk-linkerscript-large.s
+++ b/lld/test/ELF/arm-thunk-linkerscript-large.s
@@ -79,9 +79,7 @@ _start:
FUNCTIONL 08
FUNCTIONL 09
// CHECK3: __Thumbv7ABSLongThunk_tfuncl24:
-// CHECK3-NEXT: b00004: 40 f2 01 0c movw r12, #1
-// CHECK3-NEXT: b00008: c0 f2 a0 1c movt r12, #416
-// CHECK3-NEXT: b0000c: 60 47 bx r12
+// CHECK3-NEXT: b00004: ff f2 fc 97 b.w #15728632 <tfuncl24>
FUNCTIONL 10
FUNCTIONL 11
FUNCTIONL 12
diff --git a/lld/test/ELF/arm-thunk-linkerscript-sort.s b/lld/test/ELF/arm-thunk-linkerscript-sort.s
index 69d17676578..62ea41363f4 100644
--- a/lld/test/ELF/arm-thunk-linkerscript-sort.s
+++ b/lld/test/ELF/arm-thunk-linkerscript-sort.s
@@ -41,9 +41,7 @@ tfunc\suff\():
FUNCTION 16
FUNCTION 15
// CHECK2: __Thumbv7ABSLongThunk_tfunc31:
-// CHECK2-NEXT: 1000004: 40 f2 01 0c movw r12, #1
-// CHECK2-NEXT: 1000008: c0 f2 00 2c movt r12, #512
-// CHECK2-NEXT: 100000c: 60 47 bx r12
+// CHECK2-NEXT: 1000004: ff f3 fc 97 b.w #16777208 <tfunc31>
FUNCTION 14
FUNCTION 13
FUNCTION 12
diff --git a/lld/test/ELF/arm-thunk-multipass.s b/lld/test/ELF/arm-thunk-multipass.s
index 25bf5235f75..b353bb148ff 100644
--- a/lld/test/ELF/arm-thunk-multipass.s
+++ b/lld/test/ELF/arm-thunk-multipass.s
@@ -5,7 +5,7 @@
// parts we need to speed up the test and avoid a large output file
// RUN: llvm-objdump -d %t2 -start-address=1048578 -stop-address=1048586 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s
// RUN: llvm-objdump -d %t2 -start-address=16777224 -stop-address=16777254 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s
-// RUN: llvm-objdump -d %t2 -start-address=17825818 -stop-address=17825828 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK3 %s
+// RUN: llvm-objdump -d %t2 -start-address=17825812 -stop-address=17825826 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK3 %s
// In this test case a branch that is in range and does not need its range
// extended can be pushed out of range by another Thunk, necessitating another
// pass
@@ -64,19 +64,15 @@ arm_target:
// CHECK2-NEXT: 100000c: c0 f2 00 1c movt r12, #256
// CHECK2-NEXT: 1000010: 60 47 bx r12
// CHECK2: __Thumbv7ABSLongThunk_target:
-// CHECK2-NEXT: 1000012: 40 f2 1b 0c movw r12, #27
-// CHECK2-NEXT: 1000016: c0 f2 10 1c movt r12, #272
-// CHECK2-NEXT: 100001a: 60 47 bx r12
+// CHECK2-NEXT: 1000012: ff f0 ff bf b.w #1048574 <target>
// CHECK2: __Thumbv7ABSLongThunk_target2:
-// CHECK2-NEXT: 100001c: 40 f2 13 0c movw r12, #19
-// CHECK2-NEXT: 1000020: c0 f2 10 0c movt r12, #16
-// CHECK2-NEXT: 1000024: 60 47 bx r12
+// CHECK2-NEXT: 1000016: ff f4 fc 97 b.w #-15728648 <target2>
.section .text.17, "ax", %progbits
// Just enough space so that bl target is in range if no extension thunks are
// generated.
- .space 0x100000 - 12
+ .space 0x100000 - 6
.section .text.18, "ax", %progbits
.thumb
@@ -90,7 +86,7 @@ target:
nop
bx lr
// CHECK3: target:
-// CHECK3-NEXT: 110001a: ff f6 ff ff bl #-1048578
-// CHECK3-NEXT: 110001e: 00 bf nop
-// CHECK3-NEXT: 1100020: 00 bf nop
-// CHECK3-NEXT: 1100022: 70 47 bx lr
+// CHECK3-NEXT: 1100014: ff f6 ff ff bl #-1048578
+// CHECK3-NEXT: 1100018: 00 bf nop
+// CHECK3-NEXT: 110001a: 00 bf nop
+// CHECK3-NEXT: 110001c: 70 47 bx lr
OpenPOWER on IntegriCloud