[lld] r340159 - [ELF] Add support for older Arm Architectures with smaller branch range

Peter Smith via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 20 02:19:31 PDT 2018


Author: psmith
Date: Mon Aug 20 02:19:30 2018
New Revision: 340159

URL: http://llvm.org/viewvc/llvm-project?rev=340159&view=rev
Log:
[ELF] Add support for older Arm Architectures with smaller branch range

The Thumb BL and BLX instructions on older Arm Architectures such as v5 and
v6 have a constrained encoding J1 and J2 must equal 1, later Architectures
relaxed this restriction allowing J1 and J2 to be used to calculate a larger
immediate.

This patch adds support for the old encoding, it is used when the build
attributes for the input objects only contain older architectures.

Differential Revision: https://reviews.llvm.org/D50076


Added:
    lld/trunk/test/ELF/arm-bl-v6-inrange.s
Modified:
    lld/trunk/ELF/Arch/ARM.cpp
    lld/trunk/ELF/Driver.cpp
    lld/trunk/test/ELF/arm-bl-v6.s
    lld/trunk/test/ELF/arm-blx-v4t.s
    lld/trunk/test/ELF/arm-thumb-branch.s
    lld/trunk/test/ELF/arm-thumb-condbranch-thunk.s
    lld/trunk/test/ELF/arm-thumb-mix-range-thunk-os.s
    lld/trunk/test/ELF/arm-thumb-plt-range-thunk-os.s
    lld/trunk/test/ELF/arm-thumb-range-thunk-os.s
    lld/trunk/test/ELF/arm-thumb-thunk-empty-pass.s
    lld/trunk/test/ELF/arm-thunk-largesection.s
    lld/trunk/test/ELF/arm-thunk-linkerscript-large.s
    lld/trunk/test/ELF/arm-thunk-linkerscript-sort.s
    lld/trunk/test/ELF/arm-thunk-multipass.s

Modified: lld/trunk/ELF/Arch/ARM.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/ARM.cpp?rev=340159&r1=340158&r2=340159&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/ARM.cpp (original)
+++ lld/trunk/ELF/Arch/ARM.cpp Mon Aug 20 02:19:30 2018
@@ -342,7 +342,7 @@ bool ARM::inBranchRange(RelType Type, ui
     break;
   case R_ARM_THM_JUMP24:
   case R_ARM_THM_CALL:
-    Range = 0x1000000;
+    Range = Config->ARMJ1J2BranchEncoding ? 0x1000000 : 0x400000;
     InstrSize = 2;
     break;
   default:
@@ -447,11 +447,23 @@ void ARM::relocateOne(uint8_t *Loc, RelT
     }
     // Bit 12 is 0 for BLX, 1 for BL
     write16le(Loc + 2, (read16le(Loc + 2) & ~0x1000) | (Val & 1) << 12);
+    if (!Config->ARMJ1J2BranchEncoding) {
+      // Older Arm architectures do not support R_ARM_THM_JUMP24 and have
+      // different encoding rules and range due to J1 and J2 always being 1.
+      checkInt(Loc, Val, 23, Type);
+      write16le(Loc,
+                0xf000 |                     // opcode
+                    ((Val >> 12) & 0x07ff)); // imm11
+      write16le(Loc + 2,
+                (read16le(Loc + 2) & 0xd000) | // opcode
+                    0x2800 |                   // J1 == J2 == 1
+                    ((Val >> 1) & 0x07ff));    // imm11
+      break;
+    }
     // Fall through as rest of encoding is the same as B.W
     LLVM_FALLTHROUGH;
   case R_ARM_THM_JUMP24:
     // Encoding B  T4, BL T1, BLX T2: Val = S:I1:I2:imm10:imm11:0
-    // FIXME: Use of I1 and I2 require v6T2ops
     checkInt(Loc, Val, 25, Type);
     write16le(Loc,
               0xf000 |                     // opcode
@@ -542,10 +554,19 @@ int64_t ARM::getImplicitAddend(const uin
                             ((Lo & 0x07ff) << 1));  // imm11:0
   }
   case R_ARM_THM_CALL:
+    if (!Config->ARMJ1J2BranchEncoding) {
+      // Older Arm architectures do not support R_ARM_THM_JUMP24 and have
+      // different encoding rules and range due to J1 and J2 always being 1.
+      uint16_t Hi = read16le(Buf);
+      uint16_t Lo = read16le(Buf + 2);
+      return SignExtend64<22>(((Hi & 0x7ff) << 12) | // imm11
+                              ((Lo & 0x7ff) << 1));  // imm11:0
+      break;
+    }
+    LLVM_FALLTHROUGH;
   case R_ARM_THM_JUMP24: {
     // Encoding B T4, BL T1, BLX T2: A = S:I1:I2:imm10:imm11:0
     // I1 = NOT(J1 EOR S), I2 = NOT(J2 EOR S)
-    // FIXME: I1 and I2 require v6T2ops
     uint16_t Hi = read16le(Buf);
     uint16_t Lo = read16le(Buf + 2);
     return SignExtend64<24>(((Hi & 0x0400) << 14) |                    // S

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=340159&r1=340158&r2=340159&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Mon Aug 20 02:19:30 2018
@@ -1504,9 +1504,6 @@ template <class ELFT> void LinkerDriver:
     if (Config->ARMHasBlx == false)
       warn("lld uses blx instruction, no object with architecture supporting "
            "feature detected.");
-    if (Config->ARMJ1J2BranchEncoding == false)
-      warn("lld uses extended branch encoding, no object with architecture "
-           "supporting feature detected.");
     if (Config->ARMHasMovtMovw == false)
       warn("lld may use movt/movw, no object with architecture supporting "
            "feature detected.");

Added: lld/trunk/test/ELF/arm-bl-v6-inrange.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-bl-v6-inrange.s?rev=340159&view=auto
==============================================================================
--- lld/trunk/test/ELF/arm-bl-v6-inrange.s (added)
+++ lld/trunk/test/ELF/arm-bl-v6-inrange.s Mon Aug 20 02:19:30 2018
@@ -0,0 +1,47 @@
+// REQUIRES: arm
+// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv6-none-linux-gnueabi %s -o %t
+// RUN: echo "SECTIONS { \
+// RUN:          .callee1 0x100004 : { *(.callee_low) } \
+// RUN:          .caller  0x500000 : { *(.text) } \
+// RUN:          .callee2 0x900004 : { *(.callee_high) } } " > %t.script
+// RUN: ld.lld %t --script %t.script -o %t2 2>&1
+// RUN: llvm-objdump -d -triple=thumbv6-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-THUMB %s
+// RUN: llvm-objdump -d -triple=armv6-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-ARM %s
+
+// On older Arm Architectures such as v5 and v6 the Thumb BL and BLX relocation
+// uses a slightly different encoding that has a lower range. These relocations
+// are at the extreme range of what is permitted.
+ .thumb
+ .text
+ .syntax unified
+ .cpu    arm1176jzf-s
+ .globl _start
+ .type   _start,%function
+_start:
+  bl thumbfunc
+  bl armfunc
+  bx lr
+
+  .section .callee_low, "ax", %progbits
+  .globl thumbfunc
+  .type thumbfunc, %function
+thumbfunc:
+  bx lr
+// CHECK-THUMB: Disassembly of section .callee1:
+// CHECK-THUMB-NEXT: thumbfunc:
+// CHECK-THUMB-NEXT:   100004:       70 47   bx      lr
+// CHECK-THUMB-NEXT: Disassembly of section .caller:
+// CHECK-THUMB-NEXT: _start:
+// CHECK-THUMB-NEXT:   500000:       00 f4 00 f8     bl      #-4194304
+// CHECK-THUMB-NEXT:   500004:       ff f3 fe ef     blx     #4194300
+// CHECK-THUMB-NEXT:   500008:       70 47   bx      lr
+
+  .arm
+  .section .callee_high, "ax", %progbits
+  .globl armfunc
+  .type armfunc, %function
+armfunc:
+  bx lr
+// CHECK-ARM: Disassembly of section .callee2:
+// CHECK-ARM-NEXT: armfunc:
+// CHECK-ARM-NEXT:   900004:       1e ff 2f e1     bx      lr

Modified: lld/trunk/test/ELF/arm-bl-v6.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-bl-v6.s?rev=340159&r1=340158&r2=340159&view=diff
==============================================================================
--- lld/trunk/test/ELF/arm-bl-v6.s (original)
+++ lld/trunk/test/ELF/arm-bl-v6.s Mon Aug 20 02:19:30 2018
@@ -1,5 +1,5 @@
 // REQUIRES: arm
-// RUN: llvm-mc -filetype=obj -triple=arm-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv6-none-linux-gnueabi %s -o %t
 // RUN: ld.lld %t -o /dev/null 2>&1 | FileCheck %s
 
 // On Arm v6 the range of a Thumb BL instruction is only 4 megabytes as the
@@ -9,14 +9,12 @@
 // use these instructions either. At present we don't support v6 so we give a
 // warning for unsupported features.
 
-// CHECK: warning: lld uses extended branch encoding, no object with architecture supporting feature detected.
-// CHECK-NEXT: warning: lld may use movt/movw, no object with architecture supporting feature detected.
+// CHECK: warning: lld may use movt/movw, no object with architecture supporting feature detected.
 // ARM v6 supports blx so we shouldn't see the blx not supported warning.
 // CHECK-NOT: warning: lld uses blx instruction, no object with architecture supporting feature detected.
  .text
  .syntax unified
  .cpu    arm1176jzf-s
- .eabi_attribute 6, 6    @ Tag_CPU_arch
  .globl _start
  .type   _start,%function
  .balign 0x1000

Modified: lld/trunk/test/ELF/arm-blx-v4t.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-blx-v4t.s?rev=340159&r1=340158&r2=340159&view=diff
==============================================================================
--- lld/trunk/test/ELF/arm-blx-v4t.s (original)
+++ lld/trunk/test/ELF/arm-blx-v4t.s Mon Aug 20 02:19:30 2018
@@ -1,5 +1,5 @@
 // REQUIRES: arm
-// RUN: llvm-mc -filetype=obj -triple=arm-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=arm-none-linux-gnueabi %s -o %t
 // RUN: ld.lld %t -o /dev/null 2>&1 | FileCheck %s
 
 // On Arm v4t there is no blx instruction so all interworking must go via
@@ -7,13 +7,11 @@
 // features.
 
 // CHECK: warning: lld uses blx instruction, no object with architecture supporting feature detected.
-// CHECK-NEXT: warning: lld uses extended branch encoding, no object with architecture supporting feature detected.
 // CHECK-NEXT: warning: lld may use movt/movw, no object with architecture supporting feature detected.
 
  .text
  .syntax unified
  .cpu   arm7tdmi
- .eabi_attribute        6, 2    @ Tag_CPU_arch
  .arm
  .globl _start
  .type   _start,%function

Modified: lld/trunk/test/ELF/arm-thumb-branch.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-thumb-branch.s?rev=340159&r1=340158&r2=340159&view=diff
==============================================================================
--- lld/trunk/test/ELF/arm-thumb-branch.s (original)
+++ lld/trunk/test/ELF/arm-thumb-branch.s Mon Aug 20 02:19:30 2018
@@ -1,6 +1,6 @@
 // REQUIRES: arm
-// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
-// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %S/Inputs/far-arm-thumb-abs.s -o %tfar
+// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %S/Inputs/far-arm-thumb-abs.s -o %tfar
 // RUN: echo "SECTIONS { \
 // RUN:          . = 0xb4; \
 // RUN:          .callee1 : { *(.callee_low) } \

Modified: lld/trunk/test/ELF/arm-thumb-condbranch-thunk.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-thumb-condbranch-thunk.s?rev=340159&r1=340158&r2=340159&view=diff
==============================================================================
--- lld/trunk/test/ELF/arm-thumb-condbranch-thunk.s (original)
+++ lld/trunk/test/ELF/arm-thumb-condbranch-thunk.s Mon Aug 20 02:19:30 2018
@@ -1,5 +1,5 @@
 // REQUIRES: arm
-// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
 // RUN: ld.lld %t -o %t2 2>&1
 // The output file is large, most of it zeroes. We dissassemble only the
 // parts we need to speed up the test and avoid a large output file

Modified: lld/trunk/test/ELF/arm-thumb-mix-range-thunk-os.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-thumb-mix-range-thunk-os.s?rev=340159&r1=340158&r2=340159&view=diff
==============================================================================
--- lld/trunk/test/ELF/arm-thumb-mix-range-thunk-os.s (original)
+++ lld/trunk/test/ELF/arm-thumb-mix-range-thunk-os.s Mon Aug 20 02:19:30 2018
@@ -1,5 +1,5 @@
 // REQUIRES: arm
-// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
 // RUN: ld.lld %t -o %t2 2>&1
 // The output file is large, most of it zeroes. We dissassemble only the
 // parts we need to speed up the test and avoid a large output file

Modified: lld/trunk/test/ELF/arm-thumb-plt-range-thunk-os.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-thumb-plt-range-thunk-os.s?rev=340159&r1=340158&r2=340159&view=diff
==============================================================================
--- lld/trunk/test/ELF/arm-thumb-plt-range-thunk-os.s (original)
+++ lld/trunk/test/ELF/arm-thumb-plt-range-thunk-os.s Mon Aug 20 02:19:30 2018
@@ -1,5 +1,5 @@
 // REQUIRES: arm
-// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
 // RUN: ld.lld %t --shared --icf=all -o %t.so
 // The output file is large, most of it zeroes. We dissassemble only the
 // parts we need to speed up the test and avoid a large output file

Modified: lld/trunk/test/ELF/arm-thumb-range-thunk-os.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-thumb-range-thunk-os.s?rev=340159&r1=340158&r2=340159&view=diff
==============================================================================
--- lld/trunk/test/ELF/arm-thumb-range-thunk-os.s (original)
+++ lld/trunk/test/ELF/arm-thumb-range-thunk-os.s Mon Aug 20 02:19:30 2018
@@ -1,5 +1,5 @@
 // REQUIRES: arm
-// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc  -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
 // RUN: ld.lld %t -o %t2 2>&1
 // The output file is large, most of it zeroes. We dissassemble only the
 // parts we need to speed up the test and avoid a large output file

Modified: lld/trunk/test/ELF/arm-thumb-thunk-empty-pass.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-thumb-thunk-empty-pass.s?rev=340159&r1=340158&r2=340159&view=diff
==============================================================================
--- lld/trunk/test/ELF/arm-thumb-thunk-empty-pass.s (original)
+++ lld/trunk/test/ELF/arm-thumb-thunk-empty-pass.s Mon Aug 20 02:19:30 2018
@@ -1,5 +1,5 @@
 // REQUIRES: arm
-// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc -arm-add-build-attributes -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=16846856 -stop-address=16846874 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s

Modified: lld/trunk/test/ELF/arm-thunk-largesection.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-thunk-largesection.s?rev=340159&r1=340158&r2=340159&view=diff
==============================================================================
--- lld/trunk/test/ELF/arm-thunk-largesection.s (original)
+++ lld/trunk/test/ELF/arm-thunk-largesection.s Mon Aug 20 02:19:30 2018
@@ -1,5 +1,5 @@
 // REQUIRES: arm
-// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
 // 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

Modified: lld/trunk/test/ELF/arm-thunk-linkerscript-large.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-thunk-linkerscript-large.s?rev=340159&r1=340158&r2=340159&view=diff
==============================================================================
--- lld/trunk/test/ELF/arm-thunk-linkerscript-large.s (original)
+++ lld/trunk/test/ELF/arm-thunk-linkerscript-large.s Mon Aug 20 02:19:30 2018
@@ -1,5 +1,5 @@
 // REQUIRES: arm
-// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
 // RUN: echo "SECTIONS { \
 // RUN:       .text 0x100000 : { *(.text) } \
 // RUN:       .textl : { *(.text_l0*) *(.text_l1*) *(.text_l2*) *(.text_l3*) } \
@@ -21,7 +21,8 @@
 // per OutputSection basis
  .syntax unified
 
-// Define a function that we can match with .text_l* aligned on a megabyte      // boundary
+// Define a function that we can match with .text_l* aligned on a megabyte
+// boundary
  .macro FUNCTIONL suff
  .section .text_l\suff\(), "ax", %progbits
  .thumb

Modified: lld/trunk/test/ELF/arm-thunk-linkerscript-sort.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-thunk-linkerscript-sort.s?rev=340159&r1=340158&r2=340159&view=diff
==============================================================================
--- lld/trunk/test/ELF/arm-thunk-linkerscript-sort.s (original)
+++ lld/trunk/test/ELF/arm-thunk-linkerscript-sort.s Mon Aug 20 02:19:30 2018
@@ -1,5 +1,5 @@
 // REQUIRES: arm
-// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
 // RUN: echo "SECTIONS { \
 // RUN:       .text 0x100000 : { *(SORT_BY_NAME(.text.*)) } \
 // RUN:       }" > %t.script

Modified: lld/trunk/test/ELF/arm-thunk-multipass.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-thunk-multipass.s?rev=340159&r1=340158&r2=340159&view=diff
==============================================================================
--- lld/trunk/test/ELF/arm-thunk-multipass.s (original)
+++ lld/trunk/test/ELF/arm-thunk-multipass.s Mon Aug 20 02:19:30 2018
@@ -1,5 +1,5 @@
 // REQUIRES: arm
-// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
 // RUN: ld.lld %t -o %t2 2>&1
 // The output file is large, most of it zeroes. We dissassemble only the
 // parts we need to speed up the test and avoid a large output file




More information about the llvm-commits mailing list