Index: lld/trunk/ELF/Thunks.cpp =================================================================== --- lld/trunk/ELF/Thunks.cpp +++ lld/trunk/ELF/Thunks.cpp @@ -64,46 +64,99 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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(); Index: lld/trunk/test/ELF/Inputs/arm-long-thunk-converge.lds =================================================================== --- lld/trunk/test/ELF/Inputs/arm-long-thunk-converge.lds +++ lld/trunk/test/ELF/Inputs/arm-long-thunk-converge.lds @@ -0,0 +1,4 @@ +SECTIONS { + .foo : { *(.foo) } + .bar 0x2000000 : { *(.bar) } +} Index: lld/trunk/test/ELF/Inputs/far-long-arm-abs.s =================================================================== --- lld/trunk/test/ELF/Inputs/far-long-arm-abs.s +++ lld/trunk/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 Index: lld/trunk/test/ELF/arm-branch-rangethunk.s =================================================================== --- lld/trunk/test/ELF/arm-branch-rangethunk.s +++ lld/trunk/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 @@ 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 Index: lld/trunk/test/ELF/arm-long-thunk-converge.s =================================================================== --- lld/trunk/test/ELF/arm-long-thunk-converge.s +++ lld/trunk/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 Index: lld/trunk/test/ELF/arm-thumb-condbranch-thunk.s =================================================================== --- lld/trunk/test/ELF/arm-thumb-condbranch-thunk.s +++ lld/trunk/test/ELF/arm-thumb-condbranch-thunk.s @@ -38,13 +38,9 @@ // 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 // 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 FUNCTION 01 // tfunc02 is within range of tfunc02 beq.w tfunc02 @@ -61,7 +57,7 @@ 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 @@ 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 FUNCTION 10 // We can't reach any Thunk Section, create a new one beq.w tfunc03 @@ -101,17 +95,13 @@ 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 // 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 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> Index: lld/trunk/test/ELF/arm-thumb-range-thunk-os.s =================================================================== --- lld/trunk/test/ELF/arm-thumb-range-thunk-os.s +++ lld/trunk/test/ELF/arm-thumb-range-thunk-os.s @@ -60,7 +60,7 @@ 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 @@ 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 // 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 // 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 FUNCTION 15 // tfunc00 and tfunc01 are < 16Mb away, expect no range extension thunks bl tfunc00 @@ -106,8 +100,8 @@ // 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 @@ // 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 // 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 FUNCTION 30 FUNCTION 31 FUNCTION 32 @@ -148,7 +138,7 @@ // 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 @@ // 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 Index: lld/trunk/test/ELF/arm-thumb-thunk-empty-pass.s =================================================================== --- lld/trunk/test/ELF/arm-thumb-thunk-empty-pass.s +++ lld/trunk/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 @@ // 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 Index: lld/trunk/test/ELF/arm-thunk-largesection.s =================================================================== --- lld/trunk/test/ELF/arm-thunk-largesection.s +++ lld/trunk/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 @@ // 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 @@ .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 Index: lld/trunk/test/ELF/arm-thunk-linkerscript-large.s =================================================================== --- lld/trunk/test/ELF/arm-thunk-linkerscript-large.s +++ lld/trunk/test/ELF/arm-thunk-linkerscript-large.s @@ -79,9 +79,7 @@ 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 FUNCTIONL 10 FUNCTIONL 11 FUNCTIONL 12 Index: lld/trunk/test/ELF/arm-thunk-linkerscript-sort.s =================================================================== --- lld/trunk/test/ELF/arm-thunk-linkerscript-sort.s +++ lld/trunk/test/ELF/arm-thunk-linkerscript-sort.s @@ -41,9 +41,7 @@ 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 FUNCTION 14 FUNCTION 13 FUNCTION 12 Index: lld/trunk/test/ELF/arm-thunk-multipass.s =================================================================== --- lld/trunk/test/ELF/arm-thunk-multipass.s +++ lld/trunk/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 @@ // 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 // 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 .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 @@ 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