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 triple = "wasm32-unknown-unknown" 7 8; ERROR: LLVM ERROR: only -ftls-model=local-exec is supported for now on non-Emscripten OSes: variable tls 9 10; CHECK-LABEL: address_of_tls: 11; CHECK-NEXT: .functype address_of_tls () -> (i32) 12define i32 @address_of_tls() { 13 ; TLS-DAG: global.get __tls_base 14 ; TLS-DAG: i32.const tls@TLSREL 15 ; TLS-NEXT: i32.add 16 ; TLS-NEXT: return 17 18 ; NO-TLS-NEXT: i32.const tls 19 ; NO-TLS-NEXT: return 20 ret i32 ptrtoint(i32* @tls to i32) 21} 22 23; CHECK-LABEL: address_of_tls_external: 24; CHECK-NEXT: .functype address_of_tls_external () -> (i32) 25define i32 @address_of_tls_external() { 26 ; TLS-DAG: global.get tls_external@GOT@TLS 27 ; TLS-NEXT: return 28 29 ; NO-TLS-NEXT: i32.const tls_external 30 ; NO-TLS-NEXT: return 31 ret i32 ptrtoint(i32* @tls_external to i32) 32} 33 34; CHECK-LABEL: ptr_to_tls: 35; CHECK-NEXT: .functype ptr_to_tls () -> (i32) 36define i32* @ptr_to_tls() { 37 ; TLS-DAG: global.get __tls_base 38 ; TLS-DAG: i32.const tls@TLSREL 39 ; TLS-NEXT: i32.add 40 ; TLS-NEXT: return 41 42 ; NO-TLS-NEXT: i32.const tls 43 ; NO-TLS-NEXT: return 44 ret i32* @tls 45} 46 47; CHECK-LABEL: ptr_to_tls_external: 48; CHECK-NEXT: .functype ptr_to_tls_external () -> (i32) 49define i32* @ptr_to_tls_external() { 50 ; TLS-DAG: global.get tls_external@GOT@TLS 51 ; TLS-NEXT: return 52 53 ; NO-TLS-NEXT: i32.const tls_external 54 ; NO-TLS-NEXT: return 55 ret i32* @tls_external 56} 57 58; CHECK-LABEL: tls_load: 59; CHECK-NEXT: .functype tls_load () -> (i32) 60define i32 @tls_load() { 61 ; TLS-DAG: global.get __tls_base 62 ; TLS-DAG: i32.const tls@TLSREL 63 ; TLS-NEXT: i32.add 64 ; TLS-NEXT: i32.load 0 65 ; TLS-NEXT: return 66 67 ; NO-TLS-NEXT: i32.const 0 68 ; NO-TLS-NEXT: i32.load tls 69 ; NO-TLS-NEXT: return 70 %tmp = load i32, i32* @tls, align 4 71 ret i32 %tmp 72} 73 74; CHECK-LABEL: tls_load_external: 75; CHECK-NEXT: .functype tls_load_external () -> (i32) 76define i32 @tls_load_external() { 77 ; TLS-DAG: global.get tls_external@GOT@TLS 78 ; TLS-NEXT: i32.load 0 79 ; TLS-NEXT: return 80 81 ; NO-TLS-NEXT: i32.const 0 82 ; NO-TLS-NEXT: i32.load tls_external 83 ; NO-TLS-NEXT: return 84 %tmp = load i32, i32* @tls_external, align 4 85 ret i32 %tmp 86} 87 88; CHECK-LABEL: tls_store: 89; CHECK-NEXT: .functype tls_store (i32) -> () 90define void @tls_store(i32 %x) { 91 ; TLS-DAG: global.get __tls_base 92 ; TLS-DAG: i32.const tls@TLSREL 93 ; TLS-NEXT: i32.add 94 ; TLS-NEXT: i32.store 0 95 ; TLS-NEXT: return 96 97 ; NO-TLS-NEXT: i32.const 0 98 ; NO-TLS-NEXT: i32.store tls 99 ; NO-TLS-NEXT: return 100 store i32 %x, i32* @tls, align 4 101 ret void 102} 103 104; CHECK-LABEL: tls_store_external: 105; CHECK-NEXT: .functype tls_store_external (i32) -> () 106define void @tls_store_external(i32 %x) { 107 ; TLS-DAG: global.get tls_external@GOT@TLS 108 ; TLS-NEXT: i32.store 0 109 ; TLS-NEXT: return 110 111 ; NO-TLS-NEXT: i32.const 0 112 ; NO-TLS-NEXT: i32.store tls_external 113 ; NO-TLS-NEXT: return 114 store i32 %x, i32* @tls_external, align 4 115 ret void 116} 117 118; CHECK-LABEL: tls_size: 119; CHECK-NEXT: .functype tls_size () -> (i32) 120define i32 @tls_size() { 121; CHECK-NEXT: global.get __tls_size 122; CHECK-NEXT: return 123 %1 = call i32 @llvm.wasm.tls.size.i32() 124 ret i32 %1 125} 126 127; CHECK-LABEL: tls_align: 128; CHECK-NEXT: .functype tls_align () -> (i32) 129define i32 @tls_align() { 130; CHECK-NEXT: global.get __tls_align 131; CHECK-NEXT: return 132 %1 = call i32 @llvm.wasm.tls.align.i32() 133 ret i32 %1 134} 135 136; CHECK-LABEL: tls_base: 137; CHECK-NEXT: .functype tls_base () -> (i32) 138define i8* @tls_base() { 139; CHECK-NEXT: global.get __tls_base 140; CHECK-NEXT: return 141 %1 = call i8* @llvm.wasm.tls.base() 142 ret i8* %1 143} 144 145; CHECK-LABEL: tls_base_write: 146; CHECK-NEXT: .functype tls_base_write (i32) -> () 147define void @tls_base_write(i8** %output) { 148; CHECK-NEXT: global.get __tls_base 149; CHECK-NEXT: i32.store 0 150; CHECK-NEXT: return 151 %1 = call i8* @llvm.wasm.tls.base() 152 store i8* %1, i8** %output 153 ret void 154} 155 156; CHECK: .type tls,@object 157; TLS-NEXT: .section .tbss.tls,"T",@ 158; NO-TLS-NEXT: .section .bss.tls,"",@ 159; CHECK-NEXT: .p2align 2 160; CHECK-NEXT: tls: 161; CHECK-NEXT: .int32 0 162@tls = internal thread_local global i32 0 163 164@tls_external = external thread_local global i32, align 4 165 166declare i32 @llvm.wasm.tls.size.i32() 167declare i32 @llvm.wasm.tls.align.i32() 168declare i8* @llvm.wasm.tls.base() 169