1; RUN: not --crash llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory 2>&1 | FileCheck %s --check-prefix=ERROR
2; RUN: not --crash llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory -fast-isel 2>&1 | FileCheck %s --check-prefix=ERROR
3; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory --mtriple wasm32-unknown-emscripten | FileCheck %s --check-prefixes=CHECK,TLS
4; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory --mtriple wasm32-unknown-emscripten -fast-isel | FileCheck %s --check-prefixes=CHECK,TLS
5; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=-bulk-memory | FileCheck %s --check-prefixes=CHECK,NO-TLS
6target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
7target triple = "wasm32-unknown-unknown"
8
9; ERROR: LLVM ERROR: only -ftls-model=local-exec is supported for now on non-Emscripten OSes: variable tls
10
11; CHECK-LABEL: address_of_tls:
12; CHECK-NEXT: .functype  address_of_tls () -> (i32)
13define i32 @address_of_tls() {
14  ; TLS-DAG: global.get __tls_base
15  ; TLS-DAG: i32.const tls@TLSREL
16  ; TLS-NEXT: i32.add
17  ; TLS-NEXT: return
18
19  ; NO-TLS-NEXT: i32.const tls
20  ; NO-TLS-NEXT: return
21  ret i32 ptrtoint(i32* @tls to i32)
22}
23
24; CHECK-LABEL: ptr_to_tls:
25; CHECK-NEXT: .functype ptr_to_tls () -> (i32)
26define i32* @ptr_to_tls() {
27  ; TLS-DAG: global.get __tls_base
28  ; TLS-DAG: i32.const tls@TLSREL
29  ; TLS-NEXT: i32.add
30  ; TLS-NEXT: return
31
32  ; NO-TLS-NEXT: i32.const tls
33  ; NO-TLS-NEXT: return
34  ret i32* @tls
35}
36
37; CHECK-LABEL: tls_load:
38; CHECK-NEXT: .functype tls_load () -> (i32)
39define i32 @tls_load() {
40  ; TLS-DAG: global.get __tls_base
41  ; TLS-DAG: i32.const tls@TLSREL
42  ; TLS-NEXT: i32.add
43  ; TLS-NEXT: i32.load 0
44  ; TLS-NEXT: return
45
46  ; NO-TLS-NEXT: i32.const 0
47  ; NO-TLS-NEXT: i32.load tls
48  ; NO-TLS-NEXT: return
49  %tmp = load i32, i32* @tls, align 4
50  ret i32 %tmp
51}
52
53; CHECK-LABEL: tls_store:
54; CHECK-NEXT: .functype tls_store (i32) -> ()
55define void @tls_store(i32 %x) {
56  ; TLS-DAG: global.get __tls_base
57  ; TLS-DAG: i32.const tls@TLSREL
58  ; TLS-NEXT: i32.add
59  ; TLS-NEXT: i32.store 0
60  ; TLS-NEXT: return
61
62  ; NO-TLS-NEXT: i32.const 0
63  ; NO-TLS-NEXT: i32.store tls
64  ; NO-TLS-NEXT: return
65  store i32 %x, i32* @tls, align 4
66  ret void
67}
68
69; CHECK-LABEL: tls_size:
70; CHECK-NEXT: .functype tls_size () -> (i32)
71define i32 @tls_size() {
72; CHECK-NEXT: global.get __tls_size
73; CHECK-NEXT: return
74  %1 = call i32 @llvm.wasm.tls.size.i32()
75  ret i32 %1
76}
77
78; CHECK-LABEL: tls_align:
79; CHECK-NEXT: .functype tls_align () -> (i32)
80define i32 @tls_align() {
81; CHECK-NEXT: global.get __tls_align
82; CHECK-NEXT: return
83  %1 = call i32 @llvm.wasm.tls.align.i32()
84  ret i32 %1
85}
86
87; CHECK-LABEL: tls_base:
88; CHECK-NEXT: .functype tls_base () -> (i32)
89define i8* @tls_base() {
90; CHECK-NEXT: global.get __tls_base
91; CHECK-NEXT: return
92  %1 = call i8* @llvm.wasm.tls.base()
93  ret i8* %1
94}
95
96; CHECK-LABEL: tls_base_write:
97; CHECK-NEXT: .functype tls_base_write (i32) -> ()
98define void @tls_base_write(i8** %output) {
99; CHECK-NEXT: global.get __tls_base
100; CHECK-NEXT: i32.store 0
101; CHECK-NEXT: return
102  %1 = call i8* @llvm.wasm.tls.base()
103  store i8* %1, i8** %output
104  ret void
105}
106
107; CHECK: .type tls,@object
108; TLS-NEXT: .section .tbss.tls,"",@
109; NO-TLS-NEXT: .section .bss.tls,"",@
110; CHECK-NEXT: .p2align 2
111; CHECK-NEXT: tls:
112; CHECK-NEXT: .int32 0
113@tls = internal thread_local global i32 0
114
115declare i32 @llvm.wasm.tls.size.i32()
116declare i32 @llvm.wasm.tls.align.i32()
117declare i8* @llvm.wasm.tls.base()
118