[lld] r353158 - Merging r352929:

Hans Wennborg via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 5 03:19:42 PST 2019


Author: hans
Date: Tue Feb  5 03:19:42 2019
New Revision: 353158

URL: http://llvm.org/viewvc/llvm-project?rev=353158&view=rev
Log:
Merging r352929:
------------------------------------------------------------------------
r352929 | mstorsjo | 2019-02-01 23:08:09 +0100 (Fri, 01 Feb 2019) | 11 lines

[COFF] Create range extension thunks for ARM64

On ARM64, this is normally necessary only after a module exceeds
128 MB in size (while the limit for thumb is 16 MB). For conditional
branches, the range limit is only 1 MB though (the same as for thumb),
and for the tbz instruction, the range is only 32 KB, which allows for
a test much smaller than the full 128 MB.

This fixes PR40467.

Differential Revision: https://reviews.llvm.org/D57575
------------------------------------------------------------------------

Added:
    lld/branches/release_80/test/COFF/arm64-thunks.s
      - copied unchanged from r352929, lld/trunk/test/COFF/arm64-thunks.s
Removed:
    lld/branches/release_80/test/COFF/arm64-branch-range.test
Modified:
    lld/branches/release_80/   (props changed)
    lld/branches/release_80/COFF/Chunks.cpp
    lld/branches/release_80/COFF/Chunks.h
    lld/branches/release_80/COFF/Writer.cpp

Propchange: lld/branches/release_80/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Feb  5 03:19:42 2019
@@ -1 +1 @@
-/lld/trunk:351326,351335,351898-351899,352068,352082,352257,352302,352407,352413,352435,352459,352482,352606,352928
+/lld/trunk:351326,351335,351898-351899,352068,352082,352257,352302,352407,352413,352435,352459,352482,352606,352928-352929

Modified: lld/branches/release_80/COFF/Chunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/branches/release_80/COFF/Chunks.cpp?rev=353158&r1=353157&r2=353158&view=diff
==============================================================================
--- lld/branches/release_80/COFF/Chunks.cpp (original)
+++ lld/branches/release_80/COFF/Chunks.cpp Tue Feb  5 03:19:42 2019
@@ -669,18 +669,38 @@ const uint8_t ArmThunk[] = {
     0xe7, 0x44,             // L1: add  pc, ip
 };
 
-size_t RangeExtensionThunk::getSize() const {
+size_t RangeExtensionThunkARM::getSize() const {
   assert(Config->Machine == ARMNT);
   return sizeof(ArmThunk);
 }
 
-void RangeExtensionThunk::writeTo(uint8_t *Buf) const {
+void RangeExtensionThunkARM::writeTo(uint8_t *Buf) const {
   assert(Config->Machine == ARMNT);
   uint64_t Offset = Target->getRVA() - RVA - 12;
   memcpy(Buf + OutputSectionOff, ArmThunk, sizeof(ArmThunk));
   applyMOV32T(Buf + OutputSectionOff, uint32_t(Offset));
 }
 
+// A position independent ARM64 adrp+add thunk, with a maximum range of
+// +/- 4 GB, which is enough for any PE-COFF.
+const uint8_t Arm64Thunk[] = {
+    0x10, 0x00, 0x00, 0x90, // adrp x16, Dest
+    0x10, 0x02, 0x00, 0x91, // add  x16, x16, :lo12:Dest
+    0x00, 0x02, 0x1f, 0xd6, // br   x16
+};
+
+size_t RangeExtensionThunkARM64::getSize() const {
+  assert(Config->Machine == ARM64);
+  return sizeof(Arm64Thunk);
+}
+
+void RangeExtensionThunkARM64::writeTo(uint8_t *Buf) const {
+  assert(Config->Machine == ARM64);
+  memcpy(Buf + OutputSectionOff, Arm64Thunk, sizeof(Arm64Thunk));
+  applyArm64Addr(Buf + OutputSectionOff + 0, Target->getRVA(), RVA, 12);
+  applyArm64Imm(Buf + OutputSectionOff + 4, Target->getRVA() & 0xfff, 0);
+}
+
 void LocalImportChunk::getBaserels(std::vector<Baserel> *Res) {
   Res->emplace_back(getRVA());
 }

Modified: lld/branches/release_80/COFF/Chunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/branches/release_80/COFF/Chunks.h?rev=353158&r1=353157&r2=353158&view=diff
==============================================================================
--- lld/branches/release_80/COFF/Chunks.h (original)
+++ lld/branches/release_80/COFF/Chunks.h Tue Feb  5 03:19:42 2019
@@ -355,9 +355,18 @@ private:
   Defined *ImpSymbol;
 };
 
-class RangeExtensionThunk : public Chunk {
+class RangeExtensionThunkARM : public Chunk {
 public:
-  explicit RangeExtensionThunk(Defined *T) : Target(T) {}
+  explicit RangeExtensionThunkARM(Defined *T) : Target(T) {}
+  size_t getSize() const override;
+  void writeTo(uint8_t *Buf) const override;
+
+  Defined *Target;
+};
+
+class RangeExtensionThunkARM64 : public Chunk {
+public:
+  explicit RangeExtensionThunkARM64(Defined *T) : Target(T) {}
   size_t getSize() const override;
   void writeTo(uint8_t *Buf) const override;
 

Modified: lld/branches/release_80/COFF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/branches/release_80/COFF/Writer.cpp?rev=353158&r1=353157&r2=353158&view=diff
==============================================================================
--- lld/branches/release_80/COFF/Writer.cpp (original)
+++ lld/branches/release_80/COFF/Writer.cpp Tue Feb  5 03:19:42 2019
@@ -306,16 +306,31 @@ void OutputSection::writeHeaderTo(uint8_
 // Check whether the target address S is in range from a relocation
 // of type RelType at address P.
 static bool isInRange(uint16_t RelType, uint64_t S, uint64_t P, int Margin) {
-  assert(Config->Machine == ARMNT);
-  int64_t Diff = AbsoluteDifference(S, P + 4) + Margin;
-  switch (RelType) {
-  case IMAGE_REL_ARM_BRANCH20T:
-    return isInt<21>(Diff);
-  case IMAGE_REL_ARM_BRANCH24T:
-  case IMAGE_REL_ARM_BLX23T:
-    return isInt<25>(Diff);
-  default:
-    return true;
+  if (Config->Machine == ARMNT) {
+    int64_t Diff = AbsoluteDifference(S, P + 4) + Margin;
+    switch (RelType) {
+    case IMAGE_REL_ARM_BRANCH20T:
+      return isInt<21>(Diff);
+    case IMAGE_REL_ARM_BRANCH24T:
+    case IMAGE_REL_ARM_BLX23T:
+      return isInt<25>(Diff);
+    default:
+      return true;
+    }
+  } else if (Config->Machine == ARM64) {
+    int64_t Diff = AbsoluteDifference(S, P) + Margin;
+    switch (RelType) {
+    case IMAGE_REL_ARM64_BRANCH26:
+      return isInt<28>(Diff);
+    case IMAGE_REL_ARM64_BRANCH19:
+      return isInt<21>(Diff);
+    case IMAGE_REL_ARM64_BRANCH14:
+      return isInt<16>(Diff);
+    default:
+      return true;
+    }
+  } else {
+    llvm_unreachable("Unexpected architecture");
   }
 }
 
@@ -327,7 +342,17 @@ getThunk(DenseMap<uint64_t, Defined *> &
   Defined *&LastThunk = LastThunks[Target->getRVA()];
   if (LastThunk && isInRange(Type, LastThunk->getRVA(), P, Margin))
     return {LastThunk, false};
-  RangeExtensionThunk *C = make<RangeExtensionThunk>(Target);
+  Chunk *C;
+  switch (Config->Machine) {
+  case ARMNT:
+    C = make<RangeExtensionThunkARM>(Target);
+    break;
+  case ARM64:
+    C = make<RangeExtensionThunkARM64>(Target);
+    break;
+  default:
+    llvm_unreachable("Unexpected architecture");
+  }
   Defined *D = make<DefinedSynthetic>("", C);
   LastThunk = D;
   return {D, true};
@@ -429,7 +454,7 @@ static bool verifyRanges(const std::vect
 // Assign addresses and add thunks if necessary.
 void Writer::finalizeAddresses() {
   assignAddresses();
-  if (Config->Machine != ARMNT)
+  if (Config->Machine != ARMNT && Config->Machine != ARM64)
     return;
 
   size_t OrigNumChunks = 0;

Removed: lld/branches/release_80/test/COFF/arm64-branch-range.test
URL: http://llvm.org/viewvc/llvm-project/lld/branches/release_80/test/COFF/arm64-branch-range.test?rev=353157&view=auto
==============================================================================
--- lld/branches/release_80/test/COFF/arm64-branch-range.test (original)
+++ lld/branches/release_80/test/COFF/arm64-branch-range.test (removed)
@@ -1,16 +0,0 @@
-// REQUIRES: aarch64
-
-// RUN: echo -e '.globl _start\n _start:\n bl too_far26\n' > %t.main26.s
-// RUN: echo -e '.globl _start\n _start:\n b.ne too_far19\n' > %t.main19.s
-// RUN: echo -e '.globl _start\n _start:\n tbz x0, #0, too_far14\n' > %t.main14.s
-
-// RUN: llvm-mc -filetype=obj -triple=aarch64-windows %t.main26.s -o %t.main26.obj
-// RUN: llvm-mc -filetype=obj -triple=aarch64-windows %t.main19.s -o %t.main19.obj
-// RUN: llvm-mc -filetype=obj -triple=aarch64-windows %t.main14.s -o %t.main14.obj
-// RUN: llvm-mc -filetype=obj -triple=aarch64-windows %S/Inputs/far-arm64-abs.s -o %t.far.obj
-
-// RUN: not lld-link -base:0x10000 -entry:_start -subsystem:console %t.main26.obj %t.far.obj -out:%t.exe 2>&1 | FileCheck %s
-// RUN: not lld-link -base:0x10000 -entry:_start -subsystem:console %t.main19.obj %t.far.obj -out:%t.exe 2>&1 | FileCheck %s
-// RUN: not lld-link -base:0x10000 -entry:_start -subsystem:console %t.main14.obj %t.far.obj -out:%t.exe 2>&1 | FileCheck %s
-
-// CHECK: relocation out of range




More information about the llvm-commits mailing list