|
| 1 | +diff --git a/lld/test/wasm/cooperative-threading.s b/lld/test/wasm/cooperative-threading.s |
| 2 | +index 8b0f7eb1c256f..a4afb01dc2264 100644 |
| 3 | +--- a/lld/test/wasm/cooperative-threading.s |
| 4 | ++++ b/lld/test/wasm/cooperative-threading.s |
| 5 | +@@ -2,7 +2,7 @@ |
| 6 | + # thread-context globals (__init_stack_pointer, __init_tls_base, etc.) and |
| 7 | + # works without --shared-memory and atomics. |
| 8 | + |
| 9 | +-# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s |
| 10 | ++# RUN: llvm-mc -mattr=+call-indirect-overlong -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s |
| 11 | + # RUN: wasm-ld --cooperative-threading -no-gc-sections -o %t.wasm %t.o |
| 12 | + # RUN: obj2yaml %t.wasm | FileCheck %s |
| 13 | + # RUN: llvm-objdump -d --no-print-imm-hex --no-show-raw-insn %t.wasm | FileCheck %s --check-prefix=DIS |
| 14 | +@@ -11,12 +11,22 @@ |
| 15 | + # RUN: not wasm-ld --cooperative-threading --shared-memory %t.o -o %t2.wasm 2>&1 | FileCheck %s --check-prefix=INCOMPAT |
| 16 | + # INCOMPAT: --cooperative-threading is incompatible with --shared-memory |
| 17 | + |
| 18 | ++.globl __indirect_function_table |
| 19 | ++.tabletype __indirect_function_table, funcref |
| 20 | ++ |
| 21 | + .globl __wasm_get_tls_base |
| 22 | + __wasm_get_tls_base: |
| 23 | + .functype __wasm_get_tls_base () -> (i32) |
| 24 | + i32.const 0 |
| 25 | + end_function |
| 26 | + |
| 27 | ++.globl do_call_indirect |
| 28 | ++do_call_indirect: |
| 29 | ++ .functype do_call_indirect () -> () |
| 30 | ++ i32.const 1 |
| 31 | ++ call_indirect __indirect_function_table, () -> () |
| 32 | ++ end_function |
| 33 | ++ |
| 34 | + .globl _start |
| 35 | + _start: |
| 36 | + .functype _start () -> (i32) |
| 37 | +@@ -66,12 +76,23 @@ foo: |
| 38 | + .int8 7 |
| 39 | + .ascii "atomics" |
| 40 | + |
| 41 | ++# CHECK: - Type: TABLE |
| 42 | ++# CHECK-NEXT: Tables: |
| 43 | ++# CHECK-NEXT: - Index: 0 |
| 44 | ++# CHECK-NEXT: ElemType: FUNCREF |
| 45 | ++ |
| 46 | + # Memory must NOT be marked as shared. |
| 47 | + # CHECK: - Type: MEMORY |
| 48 | + # CHECK-NEXT: Memories: |
| 49 | + # CHECK-NEXT: - Minimum: 0x2 |
| 50 | + # CHECK-NOT: Shared |
| 51 | + |
| 52 | ++# The function table is exported by default. |
| 53 | ++# CHECK: - Type: EXPORT |
| 54 | ++# CHECK: - Name: __indirect_function_table |
| 55 | ++# CHECK-NEXT: Kind: TABLE |
| 56 | ++# CHECK-NEXT: Index: 0 |
| 57 | ++ |
| 58 | + # Only TLS needs a passive data segment; .data stays active and .bss gets no |
| 59 | + # segment at all since memory is only instantiated once and starts zeroed. |
| 60 | + # CHECK: - Type: DATACOUNT |
| 61 | +@@ -118,3 +139,14 @@ foo: |
| 62 | + # DIS-NEXT: i32.load 0 |
| 63 | + # DIS-NEXT: i32.add |
| 64 | + # DIS-NEXT: end |
| 65 | ++ |
| 66 | ++# When the table is imported instead there is no need to also export it. |
| 67 | ++# RUN: wasm-ld --cooperative-threading --import-table -no-gc-sections -o %t3.wasm %t.o |
| 68 | ++# RUN: obj2yaml %t3.wasm | FileCheck %s --check-prefix=IMPORT-TABLE |
| 69 | ++ |
| 70 | ++# When the table is imported instead there is no need to also export it. |
| 71 | ++# IMPORT-TABLE: - Type: IMPORT |
| 72 | ++# IMPORT-TABLE: - Module: env |
| 73 | ++# IMPORT-TABLE-NEXT: Field: __indirect_function_table |
| 74 | ++# IMPORT-TABLE-NEXT: Kind: TABLE |
| 75 | ++# IMPORT-TABLE-NOT: Kind: TABLE |
| 76 | +diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp |
| 77 | +index 9a2e3a82a9279..c213d7ca0b0f3 100644 |
| 78 | +--- a/lld/wasm/Driver.cpp |
| 79 | ++++ b/lld/wasm/Driver.cpp |
| 80 | +@@ -759,6 +759,14 @@ static void setConfigs() { |
| 81 | + if (ctx.arg.sharedMemory) |
| 82 | + error("--cooperative-threading is incompatible with --shared-memory"); |
| 83 | + ctx.arg.libcallThreadContext = true; |
| 84 | ++ |
| 85 | ++ // Cooperative threading requires the table is either imported or exported |
| 86 | ++ // or otherwise there's no way for embedders to read spawned functions from |
| 87 | ++ // the table. If we've gotten this far and the table isn't otherwise |
| 88 | ++ // imported (e.g in `isPic` mode) then export the table instead to ensure |
| 89 | ++ // that it's visible to the outside world. |
| 90 | ++ if (!ctx.arg.importTable) |
| 91 | ++ ctx.arg.exportTable = true; |
| 92 | + } |
| 93 | + } |
| 94 | + |
0 commit comments