mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 15:06:09 +00:00

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
83 lines
2.3 KiB
LLVM
83 lines
2.3 KiB
LLVM
; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory | FileCheck %s --check-prefixes=CHECK,TLS
|
|
; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -mattr=+bulk-memory -fast-isel | FileCheck %s --check-prefixes=CHECK,TLS
|
|
; 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
|
|
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
|
|
target triple = "wasm32-unknown-unknown"
|
|
|
|
; CHECK-LABEL: address_of_tls:
|
|
; CHECK-NEXT: .functype address_of_tls () -> (i32)
|
|
define i32 @address_of_tls() {
|
|
; TLS-DAG: global.get __tls_base
|
|
; TLS-DAG: i32.const tls
|
|
; TLS-NEXT: i32.add
|
|
; TLS-NEXT: return
|
|
|
|
; NO-TLS-NEXT: i32.const tls
|
|
; NO-TLS-NEXT: return
|
|
ret i32 ptrtoint(i32* @tls to i32)
|
|
}
|
|
|
|
; CHECK-LABEL: ptr_to_tls:
|
|
; CHECK-NEXT: .functype ptr_to_tls () -> (i32)
|
|
define i32* @ptr_to_tls() {
|
|
; TLS-DAG: global.get __tls_base
|
|
; TLS-DAG: i32.const tls
|
|
; TLS-NEXT: i32.add
|
|
; TLS-NEXT: return
|
|
|
|
; NO-TLS-NEXT: i32.const tls
|
|
; NO-TLS-NEXT: return
|
|
ret i32* @tls
|
|
}
|
|
|
|
; CHECK-LABEL: tls_load:
|
|
; CHECK-NEXT: .functype tls_load () -> (i32)
|
|
define i32 @tls_load() {
|
|
; TLS-DAG: global.get __tls_base
|
|
; TLS-DAG: i32.const tls
|
|
; TLS-NEXT: i32.add
|
|
; TLS-NEXT: i32.load 0
|
|
; TLS-NEXT: return
|
|
|
|
; NO-TLS-NEXT: i32.const 0
|
|
; NO-TLS-NEXT: i32.load tls
|
|
; NO-TLS-NEXT: return
|
|
%tmp = load i32, i32* @tls, align 4
|
|
ret i32 %tmp
|
|
}
|
|
|
|
; CHECK-LABEL: tls_store:
|
|
; CHECK-NEXT: .functype tls_store (i32) -> ()
|
|
define void @tls_store(i32 %x) {
|
|
; TLS-DAG: global.get __tls_base
|
|
; TLS-DAG: i32.const tls
|
|
; TLS-NEXT: i32.add
|
|
; TLS-NEXT: i32.store 0
|
|
; TLS-NEXT: return
|
|
|
|
; NO-TLS-NEXT: i32.const 0
|
|
; NO-TLS-NEXT: i32.store tls
|
|
; NO-TLS-NEXT: return
|
|
store i32 %x, i32* @tls, align 4
|
|
ret void
|
|
}
|
|
|
|
; CHECK-LABEL: tls_size:
|
|
; CHECK-NEXT: .functype tls_size () -> (i32)
|
|
define i32 @tls_size() {
|
|
; CHECK-NEXT: global.get __tls_size
|
|
; CHECK-NEXT: return
|
|
%1 = call i32 @llvm.wasm.tls.size.i32()
|
|
ret i32 %1
|
|
}
|
|
|
|
; CHECK: .type tls,@object
|
|
; TLS-NEXT: .section .tbss.tls,"",@
|
|
; NO-TLS-NEXT: .section .bss.tls,"",@
|
|
; CHECK-NEXT: .p2align 2
|
|
; CHECK-NEXT: tls:
|
|
; CHECK-NEXT: .int32 0
|
|
@tls = internal thread_local(localexec) global i32 0
|
|
|
|
declare i32 @llvm.wasm.tls.size.i32()
|