release/23.x: [lld][WebAssembly] Fix a number of issues with --cooperative-multithreading - #217096
release/23.x: [lld][WebAssembly] Fix a number of issues with --cooperative-multithreading#217096alexcrichton wants to merge 4 commits into
--cooperative-multithreading#217096Conversation
…lvm#208263) This commit is a change to `wasm-ld`'s behavior when the `--cooperative-threading` flag is passed to the linker. The change here is to by default work as if `--export-table` was passed as well. This is required conventionally on this target because the table is where function pointers are read from in the component model `thread.new-indirect` intrinsic. If the table is not exported then there's no way to turn the core module into a component so it's effectively required. This behavior only applies to when the table isn't otherwise imported, for example in shared libraries. The other motivation behind this change is that it'll avoid the need to manually specify `-Wl,--export-table` when compiling for the `wasm32-wasip3` target. This additionally avoids the need for the Clang driver to figure out if flags like `--import-table` were otherwise passed. Basically it seemed best to put this in `wasm-ld` itself to avoid as little juggling of pieces as necessary. cc WebAssembly/wasi-libc#808
…llvm#206831) With `--gc-sections` (the default), `wasm-ld` garbage-collects functions that are only reachable through `__wasm_get_tls_base` / `__wasm_set_tls_base` in the cooperative-threading (libcall thread-context) configuration. This produces a linked module that is invalid or behaves incorrectly: the relocation inside `__wasm_set_tls_base` is left dangling / mis-resolved, so callers trap at runtime (e.g. `validation error: ... values remaining on stack at end of block`, or a call to an unrelated function). In cooperative-threading mode (`--cooperative-threading`, added in llvm#200855), per-task thread context is accessed through libcalls rather than wasm globals. `wasm-ld` synthesizes `__wasm_init_tls` / `__wasm_init_memory`, which invoke `__wasm_get_tls_base` and `__wasm_set_tls_base` via **raw `call` instructions that carry no relocations**. To keep those accessors in the output, the linker marks them live with `Symbol::markLive()`. ## Error and Repro ```bash Error: failed to compile: wasm[0]::function[16]::__wasm_set_tls_base Caused by: 0: WebAssembly translation error 1: Invalid input WebAssembly code at offset 778: type mismatch: values remaining on stack at end of block ``` import was dropped and __wasm_set_tls_base was rewritten from ```wat (func $__wasm_set_tls_base (param i32) local.get 0 call $__wasm_component_model_builtin_context_set_1) ;; correct ``` to ```wat (func $__wasm_set_tls_base (param i32) local.get 0 call $__wasm_component_model_builtin_context_get_0) ;; wrong: get_0 is () -> i32 ``` Minimal linker-only repro (no runtime needed) is: ```bash wasm-ld --cooperative-threading tls.o libc.a # context-set-1 dropped, set_tls_base calls get_0 wasm-ld --cooperative-threading --no-gc-sections tls.o libc.a # correct ``` ## Root cause `Symbol::markLive()` sets the live flag (and the chunk's live bit) but does not push the defining chunk onto the mark queue. The mark phase only follows relocations of chunks that were enqueued via `MarkLive::enqueue()`. As a result the accessors' own relocations are never traversed. This is the same situation already handled for constructors reached through the relocation-less `__wasm_call_ctors`, which `MarkLive::run()` enqueues explicitly. ## Fix In `MarkLive::run()`, enqueue the defining chunks of `__wasm_get_tls_base` and `__wasm_set_tls_base` before `mark()`, so their relocations are followed. ```cpp for (Symbol *sym : {static_cast<Symbol *>(ctx.sym.getTLSBase), static_cast<Symbol *>(ctx.sym.setTLSBase)}) if (sym) if (InputChunk *c = sym->getChunk()) enqueue(c); ``` The symbols are only set in the libcall-thread-context configuration and are null otherwise, so the loop is a no-op for all other builds. ## Testing Adds `lld/test/wasm/cooperative-threading-gc.s`, which links with `--cooperative-threading --gc-sections` and checks (via `obj2yaml`) that the import called by `__wasm_set_tls_base` survives GC. Without this change the test drops the import and rewrites `__wasm_set_tls_base` to call an unrelated function; with it the import is retained and the call is correct. ```sh ninja check-lld-wasm ``` ## Note Human-in-the-loop with claude opus 4.8. I iterated with this patch and got to a working component running with a wasi-sdk fork.
This commit fixes a few issues that have surfaced in `wasm-ld`'s handling of `--cooperative-threading` with `-shared`. Two primary issues fixed are: * The `__wasm_init_memory` function was not valid as it referenced nonexistent locals. This was fixed by adjusting how locals are declared to make this a bit more flexible. * Combining data segments for PIC without extended-const is generalized to only operate on active data segments and is now orthogonal to threading. With coop threads there's a mixture of passive/active segments (TLS is passive, other data is active) and the active segments still need combining while TLS stays passive. The latter fix ended up touching a few more areas. The first is that `.tdata` sections are now sorted just before `.bss`, the end section, rather than first. This is done to ensure that active segments when combined can indeed start at a relative address of 0 (as required without extended-const). This change resulted in a number of adjustments for tests as the data is now sorted differently. Additionally relocations in TLS segments needed adjusting since the previous implementation implicitly only worked if `.tdata` is first.
This commit updates how `wasm-ld` initializes the `__init_tls_base` global during module instantiation. Previously this global was left entirely unmodified meaning that it was always 0. This change updates the `__wasm_init_memory` function to set this global dynamically in PIC mode based on the TLS address calculation, or in non-PIC mode the generation of `__wasm_init_memory` correctly sets it to the desired TLS address. cc WebAssembly/wasi-libc#819
|
cc @sbc100 |
|
@llvm/pr-subscribers-lld @llvm/pr-subscribers-lld-wasm Author: Alex Crichton (alexcrichton) ChangesThis PR is a combined backport of four separate fixes to the handling of the
My hope is to get this merged for the LLVM 23 release next week to ensure that various LLVM toolchains can all get the fixes at the same time, notably the Rust toolchain and wasi-sdk. These are all fixes which landed after the original I'll note that procedurally I'm doing a manual PR here and I'm not certain if this is the best way to do this, so please let me know if there's a different procedure to follow. Patch is 37.98 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/217096.diff 14 Files Affected:
diff --git a/lld/test/wasm/compress-relocs.s b/lld/test/wasm/compress-relocs.s
index 37f1b3b170ff7..e872b941416af 100644
--- a/lld/test/wasm/compress-relocs.s
+++ b/lld/test/wasm/compress-relocs.s
@@ -47,16 +47,16 @@ test_memory_and_indirect_call_relocs:
end_function
# CHECK: test_memory_and_indirect_call_relocs
-# CHECK: 41 90 80 84 80 00 i32.const 65552
+# CHECK: 41 80 80 84 80 00 i32.const 65536
# CHECK: 11 80 80 80 80 00 80 80 80 80 00 call_indirect 0
-# CHECK: 28 02 94 80 84 80 00 i32.load 65556
+# CHECK: 28 02 84 80 84 80 00 i32.load 65540
# CHECK: 11 81 80 80 80 00 80 80 80 80 00 call_indirect 1
# CHECK: 41 81 80 80 80 00 i32.const 1
# CHECK: 11 80 80 80 80 00 80 80 80 80 00 call_indirect 0
# COMPRESS: test_memory_and_indirect_call_relocs
-# COMPRESS: 41 90 80 04 i32.const 65552
+# COMPRESS: 41 80 80 04 i32.const 65536
# COMPRESS: 11 00 00 call_indirect 0
-# COMPRESS: 28 02 94 80 04 i32.load 65556
+# COMPRESS: 28 02 84 80 04 i32.load 65540
# COMPRESS: 11 01 00 call_indirect 1
# COMPRESS: 41 01 i32.const 1
# COMPRESS: 11 00 00 call_indirect 0
@@ -91,11 +91,11 @@ test_relative_relocs:
end_function
# CHECK: test_relative_relocs
-# CHECK: 41 90 80 84 80 00 i32.const 65552
+# CHECK: 41 80 80 84 80 00 i32.const 65536
# CHECK: 41 81 80 80 80 00 i32.const 1
# CHECK: 41 83 80 80 80 00 i32.const 3
# COMPRESS: test_relative_relocs
-# COMPRESS: 41 90 80 04 i32.const 65552
+# COMPRESS: 41 80 80 04 i32.const 65536
# COMPRESS: 41 01 i32.const 1
# COMPRESS: 41 03 i32.const 3
diff --git a/lld/test/wasm/compress-relocs64.s b/lld/test/wasm/compress-relocs64.s
index f3ff646cc3b1c..2dd18d604df41 100644
--- a/lld/test/wasm/compress-relocs64.s
+++ b/lld/test/wasm/compress-relocs64.s
@@ -36,12 +36,12 @@ test_memory_and_indirect_call_relocs:
end_function
# CHECK: test_memory_and_indirect_call_relocs
-# CHECK: 42 90 80 84 80 80 80 80 80 80 00 i64.const 65552
-# CHECK: 29 03 98 80 84 80 80 80 80 80 80 00 i64.load 65560
+# CHECK: 42 80 80 84 80 80 80 80 80 80 00 i64.const 65536
+# CHECK: 29 03 88 80 84 80 80 80 80 80 80 00 i64.load 65544
# CHECK: 42 81 80 80 80 80 80 80 80 80 00 i64.const 1
# COMPRESS: test_memory_and_indirect_call_relocs
-# COMPRESS: 42 90 80 04 i64.const 65552
-# COMPRESS: 29 03 98 80 04 i64.load 65560
+# COMPRESS: 42 80 80 04 i64.const 65536
+# COMPRESS: 29 03 88 80 04 i64.load 65544
# COMPRESS: 42 01 i64.const 1
.globl test_relative_relocs
@@ -56,11 +56,11 @@ test_relative_relocs:
end_function
# CHECK: test_relative_relocs
-# CHECK: 42 90 80 84 80 80 80 80 80 80 00 i64.const 65552
+# CHECK: 42 80 80 84 80 80 80 80 80 80 00 i64.const 65536
# CHECK: 42 81 80 80 80 80 80 80 80 80 00 i64.const 1
# CHECK: 42 83 80 80 80 80 80 80 80 80 00 i64.const 3
# COMPRESS: test_relative_relocs
-# COMPRESS: 42 90 80 04 i64.const 65552
+# COMPRESS: 42 80 80 04 i64.const 65536
# COMPRESS: 42 01 i64.const 1
# COMPRESS: 42 03 i64.const 3
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/test/wasm/cooperative-threading.s b/lld/test/wasm/cooperative-threading.s
index 8b0f7eb1c256f..af484b5e403d9 100644
--- a/lld/test/wasm/cooperative-threading.s
+++ b/lld/test/wasm/cooperative-threading.s
@@ -2,7 +2,7 @@
# thread-context globals (__init_stack_pointer, __init_tls_base, etc.) and
# works without --shared-memory and atomics.
-# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s
+# RUN: llvm-mc -mattr=+call-indirect-overlong -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s
# RUN: wasm-ld --cooperative-threading -no-gc-sections -o %t.wasm %t.o
# RUN: obj2yaml %t.wasm | FileCheck %s
# RUN: llvm-objdump -d --no-print-imm-hex --no-show-raw-insn %t.wasm | FileCheck %s --check-prefix=DIS
@@ -11,12 +11,22 @@
# RUN: not wasm-ld --cooperative-threading --shared-memory %t.o -o %t2.wasm 2>&1 | FileCheck %s --check-prefix=INCOMPAT
# INCOMPAT: --cooperative-threading is incompatible with --shared-memory
+.globl __indirect_function_table
+.tabletype __indirect_function_table, funcref
+
.globl __wasm_get_tls_base
__wasm_get_tls_base:
.functype __wasm_get_tls_base () -> (i32)
i32.const 0
end_function
+.globl do_call_indirect
+do_call_indirect:
+ .functype do_call_indirect () -> ()
+ i32.const 1
+ call_indirect __indirect_function_table, () -> ()
+ end_function
+
.globl _start
_start:
.functype _start () -> (i32)
@@ -57,6 +67,13 @@ foo:
.int32 0
.size foo, 4
+.section .rodata.baz,"",@
+.globl baz
+.p2align 2
+baz:
+ .int32 1
+ .size baz, 4
+
.section .custom_section.target_features,"",@
.int8 2
.int8 43
@@ -66,28 +83,68 @@ foo:
.int8 7
.ascii "atomics"
+# CHECK: - Type: TABLE
+# CHECK-NEXT: Tables:
+# CHECK-NEXT: - Index: 0
+# CHECK-NEXT: ElemType: FUNCREF
+
# Memory must NOT be marked as shared.
# CHECK: - Type: MEMORY
# CHECK-NEXT: Memories:
# 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.
+# Ensure __init_stack_pointer, __init_tls_base, and __tls_size are all correct.
+# CHECK: - Type: GLOBAL
+# CHECK-NEXT: Globals:
+# CHECK-NEXT: - Index: 0
+# CHECK-NEXT: Type: I32
+# CHECK-NEXT: Mutable: false
+# CHECK-NEXT: InitExpr:
+# CHECK-NEXT: Opcode: I32_CONST
+# CHECK-NEXT: Value: 65536
+# CHECK-NEXT: - Index: 1
+# CHECK-NEXT: Type: I32
+# CHECK-NEXT: Mutable: true
+# CHECK-NEXT: InitExpr:
+# CHECK-NEXT: Opcode: I32_CONST
+# CHECK-NEXT: Value: 65544
+# CHECK-NEXT: - Index: 2
+# CHECK-NEXT: Type: I32
+# CHECK-NEXT: Mutable: false
+# CHECK-NEXT: InitExpr:
+# CHECK-NEXT: Opcode: I32_CONST
+# CHECK-NEXT: Value: 8
+
+# The function table is exported by default.
+# CHECK: - Type: EXPORT
+# CHECK: - Name: __indirect_function_table
+# CHECK-NEXT: Kind: TABLE
+# CHECK-NEXT: Index: 0
+
+# Only TLS needs a passive data segment; .rodata and .data stay active and
+# .bss gets no segment at all since memory is only instantiated once and
+# starts zeroed. The TLS segment is sorted last.
# CHECK: - Type: DATACOUNT
-# CHECK-NEXT: Count: 2
+# CHECK-NEXT: Count: 3
# CHECK: - Type: DATA{{$}}
# CHECK-NEXT: Segments:
-# CHECK-NEXT: - SectionOffset: 3
-# CHECK-NEXT: InitFlags: 1
-# CHECK-NEXT: Content: '0100000002000000'
-# CHECK-NEXT: - SectionOffset: 18
+# CHECK-NEXT: - SectionOffset: 8
# CHECK-NEXT: InitFlags: 0
# CHECK-NEXT: Offset:
# CHECK-NEXT: Opcode: I32_CONST
-# CHECK-NEXT: Value: {{[0-9]+}}
+# CHECK-NEXT: Value: 65536
+# CHECK-NEXT: Content: '01000000'
+# CHECK-NEXT: - SectionOffset: 19
+# CHECK-NEXT: InitFlags: 0
+# CHECK-NEXT: Offset:
+# CHECK-NEXT: Opcode: I32_CONST
+# CHECK-NEXT: Value: 65540
# CHECK-NEXT: Content: 2A000000
+# CHECK-NEXT: - SectionOffset: 25
+# CHECK-NEXT: InitFlags: 1
+# CHECK-NEXT: Content: '0100000002000000'
# CHECK-NEXT: - Type: CUSTOM
# Globals should use the libcall ABI naming, not the global ABI.
@@ -102,9 +159,14 @@ foo:
# CHECK-NEXT: Name: __tls_align
# DIS-LABEL: <__wasm_init_memory>:
-# DIS: memory.init 0, 0
-# DIS-NOT: memory.fill
-# DIS-NOT: memory.init
+# DIS-EMPTY:
+# DIS-NEXT: i32.const 65544
+# DIS-NEXT: i32.const 65544
+# DIS-NEXT: call 0
+# DIS-NEXT: i32.const 0
+# DIS-NEXT: i32.const 8
+# DIS-NEXT: memory.init 2, 0
+# DIS-NEXT: end
# DIS-LABEL: <_start>:
# DIS-EMPTY:
@@ -118,3 +180,103 @@ foo:
# DIS-NEXT: i32.load 0
# DIS-NEXT: i32.add
# DIS-NEXT: end
+
+# When the table is imported instead there is no need to also export it.
+# RUN: wasm-ld --cooperative-threading --import-table -no-gc-sections -o %t3.wasm %t.o
+# RUN: obj2yaml %t3.wasm | FileCheck %s --check-prefix=IMPORT-TABLE
+
+# IMPORT-TABLE: - Type: IMPORT
+# IMPORT-TABLE: - Module: env
+# IMPORT-TABLE-NEXT: Field: __indirect_function_table
+# IMPORT-TABLE-NEXT: Kind: TABLE
+# IMPORT-TABLE-NOT: Kind: TABLE
+
+# Test --cooperative-threading combined with PIC output.
+# RUN: wasm-ld -shared --cooperative-threading -no-gc-sections -o %t.so %t.o
+# RUN: obj2yaml %t.so | FileCheck %s --check-prefix=PIC
+# RUN: llvm-objdump --disassemble-symbols=__wasm_init_memory --no-show-raw-insn --no-leading-addr %t.so | FileCheck %s --check-prefix=PIC-DIS
+
+# The stack pointer is imported under the libcall ABI name and
+# __wasm_set_tls_base is imported for TLS initialization.
+# PIC: - Type: IMPORT
+# PIC: Field: __init_stack_pointer
+# PIC-NEXT: Kind: GLOBAL
+# PIC-NEXT: GlobalType: I32
+# PIC-NEXT: GlobalMutable: false
+# PIC: Field: __memory_base
+# PIC: Field: __table_base
+# PIC: Field: __wasm_set_tls_base
+# PIC-NEXT: Kind: FUNCTION
+
+# The PIC `__init_tls_base` global (global 3) is mutable and initialized ot
+# 0 since its final value is calculated once `__memory_base` is provided.
+# PIC: - Type: GLOBAL
+# PIC-NEXT: Globals:
+# PIC-NEXT: - Index: 3
+# PIC-NEXT: Type: I32
+# PIC-NEXT: Mutable: true
+# PIC-NEXT: InitExpr:
+# PIC-NEXT: Opcode: I32_CONST
+# PIC-NEXT: Value: 0
+# PIC-NEXT: - Index: 4
+# PIC-NEXT: Type: I32
+# PIC-NEXT: Mutable: false
+# PIC-NEXT: InitExpr:
+# PIC-NEXT: Opcode: I32_CONST
+# PIC-NEXT: Value: 8
+
+# In PIC mode the active .rodata and .data segments are combined into a single
+# active segment at __memory_base; the TLS segment remains passive.
+# PIC: - Type: DATACOUNT
+# PIC-NEXT: Count: 2
+# PIC: - Type: DATA{{$}}
+# PIC-NEXT: Segments:
+# PIC-NEXT: - SectionOffset: 6
+# PIC-NEXT: InitFlags: 0
+# PIC-NEXT: Offset:
+# PIC-NEXT: Opcode: GLOBAL_GET
+# PIC-NEXT: Index: {{[0-9]+}}
+# PIC-NEXT: Content: 010000002A000000
+# PIC-NEXT: - SectionOffset: {{[0-9]+}}
+# PIC-NEXT: InitFlags: 1
+# PIC-NEXT: Content: '0100000002000000'
+# PIC-NEXT: - Type: CUSTOM
+
+# PIC: GlobalNames:
+# PIC-NEXT: - Index: 0
+# PIC-NEXT: Name: __init_stack_pointer
+# PIC-NEXT: - Index: 1
+# PIC-NEXT: Name: __memory_base
+# PIC-NEXT: - Index: 2
+# PIC-NEXT: Name: __table_base
+# PIC-NEXT: - Index: 3
+# PIC-NEXT: Name: __init_tls_base
+# PIC-NEXT: - Index: 4
+# PIC-NEXT: Name: __tls_size
+# PIC-NEXT: - Index: 5
+# PIC-NEXT: Name: __tls_align
+
+# Memory initialization in PIC mode has a few responsibilities: it calculates
+# the TLS address and puts it in a local, stores it into the __init_tls_base
+# global, `__wasm_set_tls_base` is called, TLS is initialized, and then finally
+# BSS is zero'd out.
+# PIC-DIS: <__wasm_init_memory>:
+# PIC-DIS-NEXT: .local i32
+# PIC-DIS-NEXT: i32.const 8
+# PIC-DIS-NEXT: global.get 1
+# PIC-DIS-NEXT: i32.add
+# PIC-DIS-NEXT: local.tee 0
+# PIC-DIS-NEXT: local.get 0
+# PIC-DIS-NEXT: global.set 3
+# PIC-DIS-NEXT: call {{[0-9]+}}
+# PIC-DIS-NEXT: local.get 0
+# PIC-DIS-NEXT: i32.const 0
+# PIC-DIS-NEXT: i32.const 8
+# PIC-DIS-NEXT: memory.init 1, 0
+# PIC-DIS-NEXT: i32.const 16
+# PIC-DIS-NEXT: global.get {{[0-9]+}}
+# PIC-DIS-NEXT: i32.add
+# PIC-DIS-NEXT: i32.const 0
+# PIC-DIS-NEXT: i32.const 4
+# PIC-DIS-NEXT: memory.fill 0
+# PIC-DIS-NEXT: end
diff --git a/lld/test/wasm/data-segments.ll b/lld/test/wasm/data-segments.ll
index 7a18fd5efb655..5073e9c4cc8d1 100644
--- a/lld/test/wasm/data-segments.ll
+++ b/lld/test/wasm/data-segments.ll
@@ -93,7 +93,7 @@
; ACTIVE-PIC-NEXT: Offset:
; ACTIVE-PIC-NEXT: Opcode: GLOBAL_GET
; ACTIVE-PIC-NEXT: Index: 1
-; ACTIVE-PIC-NEXT: Content: 63000000636F6E7374616E74000000002B00000068656C6C6F00676F6F646279650000002A000000
+; ACTIVE-PIC-NEXT: Content: 636F6E7374616E74000000002B00000068656C6C6F00676F6F646279650000002A00000063000000
; PASSIVE-LABEL: - Type: START
; PASSIVE-NEXT: StartFunction: 2
@@ -114,13 +114,13 @@
; PASSIVE-NEXT: Segments:
; PASSIVE-NEXT: - SectionOffset: 3
; PASSIVE-NEXT: InitFlags: 1
-; PASSIVE-NEXT: Content: '63000000'
-; PASSIVE-NEXT: - SectionOffset: 9
-; PASSIVE-NEXT: InitFlags: 1
; PASSIVE-NEXT: Content: 636F6E7374616E74000000002B
-; PASSIVE-NEXT: - SectionOffset: 24
+; PASSIVE-NEXT: - SectionOffset: 18
; PASSIVE-NEXT: InitFlags: 1
; PASSIVE-NEXT: Content: 68656C6C6F00676F6F646279650000002A000000
+; PASSIVE-NEXT: - SectionOffset: 40
+; PASSIVE-NEXT: InitFlags: 1
+; PASSIVE-NEXT: Content: '63000000'
; PASSIVE-NEXT: - Type: CUSTOM
; PASSIVE-NEXT: Name: name
; PASSIVE-NEXT: FunctionNames:
@@ -153,13 +153,13 @@
; PASSIVE-PIC-NEXT: Segments:
; PASSIVE-PIC-NEXT: - SectionOffset: 3
; PASSIVE-PIC-NEXT: InitFlags: 1
-; PASSIVE-PIC-NEXT: Content: '63000000'
-; PASSIVE-PIC-NEXT: - SectionOffset: 9
-; PASSIVE-PIC-NEXT: InitFlags: 1
; PASSIVE-PIC-NEXT: Content: 636F6E7374616E74000000002B
-; PASSIVE-PIC-NEXT: - SectionOffset: 24
+; PASSIVE-PIC-NEXT: - SectionOffset: 18
; PASSIVE-PIC-NEXT: InitFlags: 1
; PASSIVE-PIC-NEXT: Content: 68656C6C6F00676F6F646279650000002A000000
+; PASSIVE-PIC-NEXT: - SectionOffset: 40
+; PASSIVE-PIC-NEXT: InitFlags: 1
+; PASSIVE-PIC-NEXT: Content: '63000000'
; PASSIVE-PIC-NEXT: - Type: CUSTOM
; PASSIVE-PIC-NEXT: Name: name
; PASSIVE-PIC-NEXT: FunctionNames:
@@ -212,34 +212,34 @@
; DIS-NEXT: end
; NOPIC-DIS-NEXT: [[PTR]].const 65536
-; NOPIC-DIS-NEXT: [[PTR]].const 65536
-; NOPIC-DIS-NEXT: global.set 1
; PIC-DIS-NEXT: [[PTR]].const 0
; PIC-DIS-NEXT: global.get 1
; PIC-DIS-NEXT: [[PTR]].add
-; PIC-DIS-NEXT: local.tee 1
-; PIC-DIS-NEXT: global.set {{\d*}}
-; PIC-DIS-NEXT: local.get 1
+
; DIS-NEXT: i32.const 0
-; DIS-NEXT: i32.const 4
-; DIS-NEXT: memory.init 0, 0
+; DIS-NEXT: i32.const 13
+; DIS-NEXT: memory.init 0, 0
-; NOPIC-DIS-NEXT: [[PTR]].const 65540
-; PIC-DIS-NEXT: [[PTR]].const 4
+; NOPIC-DIS-NEXT: [[PTR]].const 65552
+; PIC-DIS-NEXT: [[PTR]].const 16
; PIC-DIS-NEXT: global.get 1
; PIC-DIS-NEXT: [[PTR]].add
; DIS-NEXT: i32.const 0
-; DIS-NEXT: i32.const 13
+; DIS-NEXT: i32.const 20
; DIS-NEXT: memory.init 1, 0
-; NOPIC-DIS-NEXT: [[PTR]].const 65556
-; PIC-DIS-NEXT: [[PTR]].const 20
+; NOPIC-DIS-NEXT: [[PTR]].const 65572
+; NOPIC-DIS-NEXT: [[PTR]].const 65572
+; NOPIC-DIS-NEXT: global.set 1
+; PIC-DIS-NEXT: [[PTR]].const 36
; PIC-DIS-NEXT: global.get 1
; PIC-DIS-NEXT: [[PTR]].add
-
+; PIC-DIS-NEXT: local.tee 1
+; PIC-DIS-NEXT: global.set {{\d*}}
+; PIC-DIS-NEXT: local.get 1
; DIS-NEXT: i32.const 0
-; DIS-NEXT: i32.const 20
+; DIS-NEXT: i32.const 4
; DIS-NEXT: memory.init 2, 0
; NOPIC-DIS-NEXT: [[PTR]].const 65576
; PIC-DIS-NEXT: [[PTR]].const 40
@@ -272,6 +272,6 @@
; DIS-NEXT: memory.atomic.wait32 0
; DIS-NEXT: drop
; DIS-NEXT: end
+; DIS-NEXT: data.drop 0
; DIS-NEXT: data.drop 1
-; DIS-NEXT: data.drop 2
; DIS-NEXT: end
diff --git a/lld/test/wasm/runtime-relocations-himem.s b/lld/test/wasm/runtime-relocations-himem.s
index 2d39a204c7904..2026e62a5af86 100644
--- a/lld/test/wasm/runtime-relocations-himem.s
+++ b/lld/test/wasm/runtime-relocations-himem.s
@@ -47,14 +47,14 @@ data_sym:
# CHECK: <__wasm_apply_data_relocs>:
# CHECK-EMPTY:
-# CHECK-NEXT: i32.const -2147483636
+# CHECK-NEXT: i32.const -2147483644
# CHECK-NEXT: global.get 0
# CHECK-NEXT: i32.store 0
# CHECK-NEXT: end
# CHECK: <__wasm_apply_tls_relocs>:
# CHECK-EMPTY:
-# CHECK-NEXT: i32.const -2147483644
+# CHECK-NEXT: i32.const -2147483636
# CHECK-NEXT: global.get 0
# CHECK-NE...
[truncated]
|
|
As the maintainer of wasm-ld I would not be opposed to this late backport, if making such an exception is even possible. My rationale that not only are these change isolated the Wasm backend, they are almost completely limited to the behaviousd of the new |
|
Reviewing the change I think we can take it, but it needs a review first. @sbc100 can you review/approve the change if you would like it included on the release branch? |
|
Should be good to land now? |
This PR is a combined backport of four separate fixes to the handling of the
wasm-ld's--cooperative-threadingflag, introduced in #200855. These fixes are needed to get this flag working for a new WASIp3 target that colleagues and I have been working on. The PRs here are:--cooperative-threading#208263My hope is to get this merged for the LLVM 23 release next week to ensure that various LLVM toolchains can all get the fixes at the same time, notably the Rust toolchain and wasi-sdk. These are all fixes which landed after the original
release/23.xbranch point but are intended to be minor fixes for--cooperative-threading.I'll note that procedurally I'm doing a manual PR here and I'm not certain if this is the best way to do this, so please let me know if there's a different procedure to follow.