diff options
| author | Guanzhong Chen <gzchen@google.com> | 2019-07-16 22:00:45 +0000 |
|---|---|---|
| committer | Guanzhong Chen <gzchen@google.com> | 2019-07-16 22:00:45 +0000 |
| commit | 42bba4b852b1a63db4043798bba7d9fcea61cbaf (patch) | |
| tree | 6d17f3ede350dc96c647deda73fdbe78a44c6071 /lld/test/wasm/tls.ll | |
| parent | 21f2858dcf3a556f01f6ae151bf7638b70f01c02 (diff) | |
| download | bcm5719-llvm-42bba4b852b1a63db4043798bba7d9fcea61cbaf.tar.gz bcm5719-llvm-42bba4b852b1a63db4043798bba7d9fcea61cbaf.zip | |
[WebAssembly] Implement thread-local storage (local-exec model)
Summary:
Thread local variables are placed inside a `.tdata` segment. Their symbols are
offsets from the start of the segment. The address of a thread local variable
is computed as `__tls_base` + the offset from the start of the segment.
`.tdata` segment is a passive segment and `memory.init` is used once per thread
to initialize the thread local storage.
`__tls_base` is a wasm global. Since each thread has its own wasm instance,
it is effectively thread local. Currently, `__tls_base` must be initialized
at thread startup, and so cannot be used with dynamic libraries.
`__tls_base` is to be initialized with a new linker-synthesized function,
`__wasm_init_tls`, which takes as an argument a block of memory to use as the
storage for thread locals. It then initializes the block of memory and sets
`__tls_base`. As `__wasm_init_tls` will handle the memory initialization,
the memory does not have to be zeroed.
To help allocating memory for thread-local storage, a new compiler intrinsic
is introduced: `__builtin_wasm_tls_size()`. This instrinsic function returns
the size of the thread-local storage for the current function.
The expected usage is to run something like the following upon thread startup:
__wasm_init_tls(malloc(__builtin_wasm_tls_size()));
Reviewers: tlively, aheejin, kripken, sbc100
Subscribers: dschuff, jgravelle-google, hiraditya, sunfish, jfb, cfe-commits, llvm-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D64537
llvm-svn: 366272
Diffstat (limited to 'lld/test/wasm/tls.ll')
| -rw-r--r-- | lld/test/wasm/tls.ll | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/lld/test/wasm/tls.ll b/lld/test/wasm/tls.ll new file mode 100644 index 00000000000..b570d467568 --- /dev/null +++ b/lld/test/wasm/tls.ll @@ -0,0 +1,81 @@ +; RUN: llc -mattr=+bulk-memory -filetype=obj %s -o %t.o + +target triple = "wasm32-unknown-unknown" + +@tls1 = thread_local(localexec) global i32 1, align 4 +@no_tls = global i32 0, align 4 +@tls2 = thread_local(localexec) global i32 1, align 4 + +define i32* @tls1_addr() { + ret i32* @tls1 +} + +define i32* @tls2_addr() { + ret i32* @tls2 +} + +; RUN: wasm-ld -no-gc-sections --shared-memory --max-memory=131072 --no-entry -o %t.wasm %t.o +; RUN: obj2yaml %t.wasm | FileCheck %s + +; RUN: wasm-ld -no-gc-sections --shared-memory --max-memory=131072 --no-merge-data-segments --no-entry -o %t.wasm %t.o +; RUN: obj2yaml %t.wasm | FileCheck %s + +; CHECK: - Type: GLOBAL +; CHECK-NEXT: Globals: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Type: I32 +; CHECK-NEXT: Mutable: true +; CHECK-NEXT: InitExpr: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 66576 +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Type: I32 +; CHECK-NEXT: Mutable: true +; CHECK-NEXT: InitExpr: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 0 +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: Type: I32 +; CHECK-NEXT: Mutable: false +; CHECK-NEXT: InitExpr: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 8 + + +; CHECK: - Type: CODE +; CHECK-NEXT: Functions: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Locals: [] +; CHECK-NEXT: Body: 0B +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Locals: [] +; CHECK-NEXT: Body: 20002401200041004108FC0800000B + +; Expected body of __wasm_init_tls: +; local.get 0 +; global.set 1 +; local.get 0 +; i32.const 0 +; i32.const 8 +; memory.init 0, 0 +; end + +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: Locals: [] +; CHECK-NEXT: Body: 2381808080004180808080006A0B + +; Expected body of tls1_addr: +; global.get 1 +; i32.const 0 +; i32.add +; end + +; CHECK-NEXT: - Index: 3 +; CHECK-NEXT: Locals: [] +; CHECK-NEXT: Body: 2381808080004184808080006A0B + +; Expected body of tls1_addr: +; global.get 1 +; i32.const 4 +; i32.add +; end |

