[lld] [WebAssembly] Don't use passive segments for bss in coop threads (PR #208284)

Alex Crichton via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 9 09:05:54 PDT 2026


https://github.com/alexcrichton updated https://github.com/llvm/llvm-project/pull/208284

>From 2b510ac2e310575390bdc376e4f3238f7c79d759 Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex at alexcrichton.com>
Date: Wed, 8 Jul 2026 11:18:53 -0700
Subject: [PATCH] [WebAssembly] Don't use passive segments for bss in coop
 threads

This commit is an update to `wasm-ld`'s behavior with bss data segments
with `--cooperative-threading`. Previously bss segments were forced to
become passive data segments meaning that a `start` function was emitted
with a `memory.fill` that set the required region of memory to 0. This
isn't required for coop threads though because the module is only
instantiated once and the default pattern for memory is 0, so only
special treatment of TLS segments are required.
---
 lld/test/wasm/cooperative-threading.s | 35 +++++++++++++++++++++++++++
 lld/wasm/Writer.cpp                   | 11 +++------
 2 files changed, 39 insertions(+), 7 deletions(-)

diff --git a/lld/test/wasm/cooperative-threading.s b/lld/test/wasm/cooperative-threading.s
index 64e392fbc45dd..8b0f7eb1c256f 100644
--- a/lld/test/wasm/cooperative-threading.s
+++ b/lld/test/wasm/cooperative-threading.s
@@ -43,6 +43,20 @@ tls2:
   .int32  2
   .size tls2, 4
 
+.section  .data.bar,"",@
+.globl  bar
+.p2align  2
+bar:
+  .int32  42
+  .size bar, 4
+
+.section  .bss.foo,"",@
+.globl  foo
+.p2align  2
+foo:
+  .int32  0
+  .size foo, 4
+
 .section  .custom_section.target_features,"",@
   .int8 2
   .int8 43
@@ -58,6 +72,24 @@ tls2:
 # CHECK-NEXT:     - Minimum:         0x2
 # CHECK-NOT:       Shared
 
+# Only TLS needs a passive data segment; .data stays active and .bss gets no
+# segment at all since memory is only instantiated once and starts zeroed.
+# CHECK:        - Type:            DATACOUNT
+# CHECK-NEXT:     Count:           2
+
+# CHECK:        - Type:            DATA{{$}}
+# CHECK-NEXT:     Segments:
+# CHECK-NEXT:       - SectionOffset:   3
+# CHECK-NEXT:         InitFlags:       1
+# CHECK-NEXT:         Content:         '0100000002000000'
+# CHECK-NEXT:       - SectionOffset:   18
+# CHECK-NEXT:         InitFlags:       0
+# CHECK-NEXT:         Offset:
+# CHECK-NEXT:           Opcode:          I32_CONST
+# CHECK-NEXT:           Value:           {{[0-9]+}}
+# CHECK-NEXT:         Content:         2A000000
+# CHECK-NEXT:   - Type:            CUSTOM
+
 # Globals should use the libcall ABI naming, not the global ABI.
 # CHECK:      GlobalNames:
 # CHECK-NEXT:      - Index:           0
@@ -70,6 +102,9 @@ tls2:
 # CHECK-NEXT:        Name:            __tls_align
 
 # DIS-LABEL: <__wasm_init_memory>:
+# DIS:         memory.init     0, 0
+# DIS-NOT:     memory.fill
+# DIS-NOT:     memory.init
 
 # DIS-LABEL: <_start>:
 # DIS-EMPTY:
diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp
index 6ff5fbe6d9c0d..7ceff0e14413c 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -1058,14 +1058,11 @@ OutputSegment *Writer::createOutputSegment(StringRef name) {
   OutputSegment *s = make<OutputSegment>(name);
   // In the shared memory case, all data segments must be passive since they
   // will be initialized once by the main thread and then shared with other
-  // threads. In the cooperative threading case, TLS segments must be passive
-  // so they can be re-initialized per-thread via memory.init, and .bss
-  // segments are passive to avoid serializing their zero bytes into the binary;
-  // they are still present as passive segment entries and zero-filled via
-  // memory.fill in __wasm_init_memory.
+  // threads. In the cooperative threading case, TLS segments need to exist to
+  // be able to run TLS initialization on spawned threads, so that's managed
+  // here by flagging TLS as passive as well.
   bool needsPassiveInit =
-      ctx.arg.sharedMemory || (ctx.arg.cooperativeThreading &&
-                               (s->isTLS() || s->name.starts_with(".bss")));
+      ctx.arg.sharedMemory || (ctx.arg.cooperativeThreading && s->isTLS());
   if (needsPassiveInit)
     s->initFlags = WASM_DATA_SEGMENT_IS_PASSIVE;
   if (!ctx.arg.relocatable && name.starts_with(".bss"))



More information about the llvm-commits mailing list