[llvm-branch-commits] [lld] release/23.x: [LLD][COFF] Replace ARM64EC TLS directory chunks with native chunks when available (#212845) (PR #213533)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sun Aug 2 04:53:25 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-platform-windows

Author: llvmbot

<details>
<summary>Changes</summary>

Backport e096d2f60dbc6cab991d5c02a5f7125a6dc694dc

Requested by: @<!-- -->cjacek

---
Full diff: https://github.com/llvm/llvm-project/pull/213533.diff


3 Files Affected:

- (modified) lld/COFF/Chunks.h (+2-1) 
- (modified) lld/COFF/Driver.cpp (+24-3) 
- (added) lld/test/COFF/arm64x-tls.s (+121) 


``````````diff
diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h
index fd2948fc31eb1..a0628654b94e4 100644
--- a/lld/COFF/Chunks.h
+++ b/lld/COFF/Chunks.h
@@ -394,11 +394,12 @@ class SectionChunk : public Chunk {
   // and this chunk is considered as dead.
   SectionChunk *repl;
 
+  void replace(SectionChunk *other);
+
 private:
   SectionChunk *assocChildren = nullptr;
 
   // Used for ICF (Identical COMDAT Folding)
-  void replace(SectionChunk *other);
   uint32_t eqClass[2] = {0, 0};
 
   // Relocations for this section. Size is stored below.
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 4eedefbf2ba5e..9d39aff73601b 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -2805,9 +2805,11 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   ltoCompilationDone = true;
   ctx.forEachSymtab([](SymbolTable &symtab) { symtab.compileBitcodeFiles(); });
 
-  if (Defined *d =
-          dyn_cast_or_null<Defined>(ctx.symtab.findUnderscore("_tls_used")))
-    config->gcroot.push_back(d);
+  ctx.forEachSymtab([&](SymbolTable &symtab) {
+    if (Defined *d =
+            dyn_cast_or_null<Defined>(symtab.findUnderscore("_tls_used")))
+      config->gcroot.push_back(d);
+  });
 
   // If -thinlto-index-only is given, we should create only "index
   // files" and not object files. Index file creation is already done
@@ -2837,6 +2839,25 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   if (errorCount())
     return;
 
+  if (ctx.hybridSymtab) {
+    // On ARM64X, merge tls chunks, there may be only one true _tls_start and
+    // _tls_end chunk. Additionally, both views use the same _tls_used and
+    // _tls_index.
+    auto maybeReplaceWithNative = [&](StringRef name) {
+      auto nativeSym = dyn_cast_or_null<DefinedRegular>(
+          ctx.hybridSymtab->findUnderscore(name));
+      if (!nativeSym)
+        return;
+      if (auto ecSym =
+              dyn_cast_or_null<DefinedRegular>(ctx.symtab.findUnderscore(name)))
+        nativeSym->getChunk()->replace(ecSym->getChunk());
+    };
+    maybeReplaceWithNative("_tls_used");
+    maybeReplaceWithNative("_tls_index");
+    maybeReplaceWithNative("_tls_start");
+    maybeReplaceWithNative("_tls_end");
+  }
+
   ctx.forEachActiveSymtab([](SymbolTable &symtab) {
     symtab.initializeECThunks();
     symtab.initializeLoadConfig();
diff --git a/lld/test/COFF/arm64x-tls.s b/lld/test/COFF/arm64x-tls.s
new file mode 100644
index 0000000000000..608604fab2fb3
--- /dev/null
+++ b/lld/test/COFF/arm64x-tls.s
@@ -0,0 +1,121 @@
+// REQUIRES: aarch64
+// RUN: split-file %s %t.dir && cd %t.dir
+
+// RUN: llvm-mc -filetype=obj -triple=aarch64-windows aarch64.s -o aarch64.obj
+// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows arm64ec.s -o arm64ec.obj
+// RUN: llvm-mc -filetype=obj -triple=aarch64-windows tls-aarch64.s -o tls-aarch64.obj
+// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows tls-arm64ec.s -o tls-arm64ec.obj
+// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows %S/Inputs/loadconfig-arm64ec.s -o loadconfig-arm64ec.obj
+// RUN: llvm-mc -filetype=obj -triple=aarch64-windows %S/Inputs/loadconfig-arm64.s -o loadconfig-arm64.obj
+
+// RUN: rm -f tls.lib
+// RUN: llvm-lib -machine:arm64x -out:tls.lib tls-aarch64.obj tls-arm64ec.obj loadconfig-arm64ec.obj loadconfig-arm64.obj
+// RUN: lld-link -machine:arm64x -dll -noentry aarch64.obj arm64ec.obj tls.lib -out:out.dll
+
+// Check that we're using native _tls_index and _tls_used for both views.
+
+// RUN: llvm-readobj --coff-tls-directory --hex-dump=.ec --hex-dump=.a64 out.dll | FileCheck %s
+// CHECK:      Format: COFF-ARM64X
+// CHECK-NEXT: Arch: aarch64
+// CHECK-NEXT: AddressSize: 64bit
+// CHECK-EMPTY:
+// CHECK-NEXT: Hex dump of section '.a64':
+// CHECK-NEXT: 0x180004000 00500000 04500000 00700000 01700000
+// CHECK-EMPTY:
+// CHECK-NEXT: Hex dump of section '.ec':
+// CHECK-NEXT: 0x180006000 00500000 04500000 00700000 01700000
+// CHECK-NEXT: TLSDirectory {
+// CHECK-NEXT:   StartAddressOfRawData: 0x180007000
+// CHECK-NEXT:   EndAddressOfRawData: 0x180007001
+// CHECK-NEXT:   AddressOfIndex: 0x180005000
+// CHECK-NEXT:   AddressOfCallBacks: 0x0
+// CHECK-NEXT:   SizeOfZeroFill: 0x0
+// CHECK-NEXT:   Characteristics [ (0x100000)
+// CHECK-NEXT:     IMAGE_SCN_ALIGN_1BYTES (0x100000)
+// CHECK-NEXT:   ]
+// CHECK-NEXT: }
+// CHECK-NEXT: HybridObject {
+// CHECK-NEXT:   Format: COFF-ARM64EC
+// CHECK-NEXT:   Arch: aarch64
+// CHECK-NEXT:   AddressSize: 64bit
+// CHECK-EMPTY:
+// CHECK-NEXT:   Hex dump of section '.a64':
+// CHECK-NEXT:   0x180004000 00500000 04500000 00700000 01700000
+// CHECK-EMPTY:
+// CHECK-NEXT:   Hex dump of section '.ec':
+// CHECK-NEXT:   0x180006000 00500000 04500000 00700000 01700000
+// CHECK-NEXT:   TLSDirectory {
+// CHECK-NEXT:     StartAddressOfRawData: 0x180007000
+// CHECK-NEXT:     EndAddressOfRawData: 0x180007001
+// CHECK-NEXT:     AddressOfIndex: 0x180005000
+// CHECK-NEXT:     AddressOfCallBacks: 0x0
+// CHECK-NEXT:     SizeOfZeroFill: 0x0
+// CHECK-NEXT:     Characteristics [ (0x100000)
+// CHECK-NEXT:       IMAGE_SCN_ALIGN_1BYTES (0x100000)
+// CHECK-NEXT:     ]
+// CHECK-NEXT:   }
+// CHECK-NEXT: }
+
+#--- tls-aarch64.s
+        .section .defa64,"dr",discard,_tls_index
+        .globl _tls_index
+_tls_index:
+        .long 0
+
+        .section .tls,"dr",discard,_tls_start
+        .globl _tls_start
+_tls_start:
+        .byte 0
+
+        .section .tls$ZZZ,"dr",discard,_tls_end
+        .globl _tls_end
+_tls_end:
+        .byte 0
+
+        .section .defa64,"dr",discard,_tls_used
+        .globl _tls_used
+_tls_used:
+        .xword _tls_start
+        .xword _tls_end
+        .xword _tls_index
+        .xword 0
+        .xword 0
+
+#--- aarch64.s
+        .section .a64,"dr"
+        .rva _tls_index
+        .rva _tls_used
+        .rva _tls_start
+        .rva _tls_end
+
+#--- tls-arm64ec.s
+        .section .defec,"dr",discard,_tls_index
+        .globl _tls_index
+_tls_index:
+        .long 0
+
+        .section .tls,"dr",discard,_tls_start
+        .globl _tls_start
+_tls_start:
+        .byte 0
+
+        .section .tls$ZZZ,"dr",discard,_tls_end
+        .globl _tls_end
+_tls_end:
+        .byte 0
+
+        .section .defec,"dr",discard,_tls_used
+        .globl _tls_used
+_tls_used:
+        .xword _tls_start
+        .xword _tls_end
+        .xword _tls_index
+        .xword 0
+        .xword 0
+
+#--- arm64ec.s
+        .section .ec,"dr"
+        .rva _tls_index
+        .rva _tls_used
+        .rva _tls_start
+        .rva _tls_end

``````````

</details>


https://github.com/llvm/llvm-project/pull/213533


More information about the llvm-branch-commits mailing list