summaryrefslogtreecommitdiffstats
path: root/lld/test
diff options
context:
space:
mode:
authorGuanzhong Chen <gzchen@google.com>2019-07-16 22:00:45 +0000
committerGuanzhong Chen <gzchen@google.com>2019-07-16 22:00:45 +0000
commit42bba4b852b1a63db4043798bba7d9fcea61cbaf (patch)
tree6d17f3ede350dc96c647deda73fdbe78a44c6071 /lld/test
parent21f2858dcf3a556f01f6ae151bf7638b70f01c02 (diff)
downloadbcm5719-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')
-rw-r--r--lld/test/wasm/data-segments.ll20
-rw-r--r--lld/test/wasm/tls.ll81
2 files changed, 96 insertions, 5 deletions
diff --git a/lld/test/wasm/data-segments.ll b/lld/test/wasm/data-segments.ll
index a9a403f3c5f..944895a0d39 100644
--- a/lld/test/wasm/data-segments.ll
+++ b/lld/test/wasm/data-segments.ll
@@ -4,11 +4,11 @@
; atomics => active segments (TODO: error)
; RUN: wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 %t.atomics.o -o %t.atomics.wasm
-; RUN: obj2yaml %t.atomics.wasm | FileCheck %s --check-prefix ACTIVE
+; RUN: obj2yaml %t.atomics.wasm | FileCheck %s --check-prefixes ACTIVE,ACTIVE-TLS
; atomics, active segments => active segments
; RUN: wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 --active-segments %t.atomics.o -o %t.atomics.active.wasm
-; RUN: obj2yaml %t.atomics.active.wasm | FileCheck %s --check-prefix ACTIVE
+; RUN: obj2yaml %t.atomics.active.wasm | FileCheck %s --check-prefixes ACTIVE,ACTIVE-TLS
; atomics, passive segments => error
; RUN: not wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 --passive-segments %t.atomics.o -o %t.atomics.passive.wasm 2>&1 | FileCheck %s --check-prefix ERROR
@@ -27,15 +27,15 @@
; atomics, bulk memory => active segments (TODO: passive)
; RUN: wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 %t.atomics.bulk-mem.o -o %t.atomics.bulk-mem.wasm
-; RUN: obj2yaml %t.atomics.bulk-mem.wasm | FileCheck %s --check-prefix ACTIVE
+; RUN: obj2yaml %t.atomics.bulk-mem.wasm | FileCheck %s --check-prefixes ACTIVE,ACTIVE-TLS
; atomics, bulk memory, active segments => active segments
; RUN: wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 --active-segments %t.atomics.bulk-mem.o -o %t.atomics.bulk-mem.active.wasm
-; RUN: obj2yaml %t.atomics.bulk-mem.active.wasm | FileCheck %s --check-prefix ACTIVE
+; RUN: obj2yaml %t.atomics.bulk-mem.active.wasm | FileCheck %s --check-prefixes ACTIVE,ACTIVE-TLS
; atomics, bulk memory, passive segments => passive segments
; RUN: wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 --passive-segments %t.atomics.bulk-mem.o -o %t.atomics.bulk-mem.passive.wasm
-; RUN: obj2yaml %t.atomics.bulk-mem.passive.wasm | FileCheck %s --check-prefix PASSIVE
+; RUN: obj2yaml %t.atomics.bulk-mem.passive.wasm | FileCheck %s --check-prefixes PASSIVE,PASSIVE-TLS
target triple = "wasm32-unknown-unknown"
@@ -54,6 +54,9 @@ target triple = "wasm32-unknown-unknown"
; ACTIVE-NEXT: - Index: 0
; ACTIVE-NEXT: Locals: []
; ACTIVE-NEXT: Body: 0B
+; ACTIVE-TLS-NEXT: - Index: 1
+; ACTIVE-TLS-NEXT: Locals: []
+; ACTIVE-TLS-NEXT: Body: 0B
; ACTIVE-NEXT: - Type: DATA
; ACTIVE-NEXT: Segments:
; ACTIVE-NEXT: - SectionOffset: 7
@@ -80,6 +83,8 @@ target triple = "wasm32-unknown-unknown"
; ACTIVE-NEXT: FunctionNames:
; ACTIVE-NEXT: - Index: 0
; ACTIVE-NEXT: Name: __wasm_call_ctors
+; ACTIVE-TLS-NEXT: - Index: 1
+; ACTIVE-TLS-NEXT: Name: __wasm_init_tls
; PASSIVE-LABEL: - Type: CODE
; PASSIVE-NEXT: Functions:
@@ -89,6 +94,9 @@ target triple = "wasm32-unknown-unknown"
; PASSIVE-NEXT: - Index: 1
; PASSIVE-NEXT: Locals: []
; PASSIVE-NEXT: Body: 41800841004114FC080000FC090041940841004190CE00FC080100FC090141A4D6004100410DFC080200FC09020B
+; PASSIVE-TLS-NEXT: - Index: 2
+; PASSIVE-TLS-NEXT: Locals: []
+; PASSIVE-TLS-NEXT: Body: 0B
; PASSIVE-NEXT: - Type: DATA
; PASSIVE-NEXT: Segments:
; PASSIVE-NEXT: - SectionOffset: 3
@@ -108,3 +116,5 @@ target triple = "wasm32-unknown-unknown"
; PASSIVE-NEXT: Name: __wasm_call_ctors
; PASSIVE-NEXT: - Index: 1
; PASSIVE-NEXT: Name: __wasm_init_memory
+; PASSIVE-TLS-NEXT: - Index: 2
+; PASSIVE-TLS-NEXT: Name: __wasm_init_tls
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
OpenPOWER on IntegriCloud