Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion cmake/wasi-sdk-toolchain.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,12 @@ ExternalProject_Add(llvm-build
USES_TERMINAL_CONFIGURE ON
USES_TERMINAL_BUILD ON
USES_TERMINAL_INSTALL ON
PATCH_COMMAND
${CMAKE_COMMAND} -E chdir .. bash -c
"git apply ${CMAKE_SOURCE_DIR}/src/llvm-pr-206831.patch || git apply ${CMAKE_SOURCE_DIR}/src/llvm-pr-206831.patch -R --check"
COMMAND
${CMAKE_COMMAND} -E chdir .. bash -c
"git apply ${CMAKE_SOURCE_DIR}/src/llvm-prs-208263-208332-208597.patch || git apply ${CMAKE_SOURCE_DIR}/src/llvm-prs-208263-208332-208597.patch -R --check"
)

add_custom_target(build ALL DEPENDS llvm-build)
Expand All @@ -269,7 +275,7 @@ install(DIRECTORY ${wasi_tmp_install}/bin ${wasi_tmp_install}/lib ${wasi_tmp_ins
# Build logic for `wasm-component-ld` installed from Rust code.
set(wasm_component_ld_root ${CMAKE_CURRENT_BINARY_DIR}/wasm-component-ld)
set(wasm_component_ld ${wasm_component_ld_root}/bin/wasm-component-ld${CMAKE_EXECUTABLE_SUFFIX})
set(wasm_component_ld_version 0.5.26)
set(wasm_component_ld_version 0.5.27)
if(RUST_TARGET)
set(rust_target_flag --target=${RUST_TARGET})
endif()
Expand Down
88 changes: 88 additions & 0 deletions src/llvm-pr-206831.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
diff --git a/lld/test/wasm/cooperative-threading-gc.s b/lld/test/wasm/cooperative-threading-gc.s
new file mode 100644
index 0000000000000..2af2460939aad
--- /dev/null
+++ b/lld/test/wasm/cooperative-threading-gc.s
@@ -0,0 +1,57 @@
+# Verify that --gc-sections preserves functions reachable only through the
+# thread-context accessors __wasm_{get,set}_tls_base. These accessors are
+# invoked by synthetic init functions (e.g. __wasm_init_tls) via `call`
+# instructions that carry no relocations, so the linker marks the accessors
+# live explicitly. Their own relocations must still be followed during GC,
+# otherwise functions they call (here modeling the cooperative-threading
+# context.set builtin) are incorrectly collected and the call is mis-resolved.
+
+# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s
+# RUN: wasm-ld --cooperative-threading --gc-sections -o %t.wasm %t.o
+# RUN: obj2yaml %t.wasm | FileCheck %s
+
+ .functype set_helper (i32) -> ()
+ .import_module set_helper, "env"
+ .import_name set_helper, "set_helper"
+
+.globl __wasm_get_tls_base
+__wasm_get_tls_base:
+ .functype __wasm_get_tls_base () -> (i32)
+ i32.const 0
+ end_function
+
+# Reachable only via the synthetic __wasm_init_tls. Its call to `set_helper`
+# must keep `set_helper` live.
+.globl __wasm_set_tls_base
+__wasm_set_tls_base:
+ .functype __wasm_set_tls_base (i32) -> ()
+ local.get 0
+ call set_helper
+ end_function
+
+.globl _start
+_start:
+ .functype _start () -> (i32)
+ call __wasm_get_tls_base
+ i32.const tls1@TLSREL
+ i32.add
+ i32.load 0
+ end_function
+
+.section .tdata.tls1,"",@
+.globl tls1
+tls1:
+ .int32 1
+ .size tls1, 4
+
+.section .custom_section.target_features,"",@
+ .int8 2
+ .int8 43
+ .int8 11
+ .ascii "bulk-memory"
+ .int8 43
+ .int8 7
+ .ascii "atomics"
+
+# The imported helper called by __wasm_set_tls_base must survive GC.
+# CHECK: Field: set_helper
diff --git a/lld/wasm/MarkLive.cpp b/lld/wasm/MarkLive.cpp
index 2b2cf19f14b30..3364be006ca24 100644
--- a/lld/wasm/MarkLive.cpp
+++ b/lld/wasm/MarkLive.cpp
@@ -126,6 +126,20 @@ void MarkLive::run() {
enqueueRetainedSegments(obj);
}

+ // `__wasm_{get,set}_tls_base` are called from synthetic init functions (e.g.
+ // `__wasm_init_tls`, `__wasm_init_memory`) via raw `call` instructions that
+ // carry no relocations, so the mark phase below cannot discover the functions
+ // they in turn call (e.g. the cooperative-threading
+ // `context.get`/`context.set` builtins). They are already marked live, but
+ // their defining chunks were never enqueued; enqueue them here so their
+ // relocations are followed. This mirrors the handling of ctor functions
+ // reached via `__wasm_call_ctors`.
+ for (Symbol *sym : {static_cast<Symbol *>(ctx.sym.getTLSBase),
+ static_cast<Symbol *>(ctx.sym.setTLSBase)})
+ if (sym)
+ if (InputChunk *c = sym->getChunk())
+ enqueue(c);
+
mark();

// If we have any non-discarded init functions, mark `__wasm_call_ctors` as
2 changes: 1 addition & 1 deletion src/llvm-project
Submodule llvm-project updated 11412 files
Loading
Loading