2015-07-09 22:57:38 +02:00
|
|
|
//===- IntrinsicsWebAssembly.td - Defines wasm intrinsics --*- tablegen -*-===//
|
|
|
|
//
|
2019-01-19 09:50:56 +01:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2015-07-09 22:57:38 +02:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
///
|
|
|
|
/// \file
|
2018-05-01 17:54:18 +02:00
|
|
|
/// This file defines all of the WebAssembly-specific intrinsics.
|
2015-07-09 22:57:38 +02:00
|
|
|
///
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
let TargetPrefix = "wasm" in { // All intrinsics start with "llvm.wasm.".
|
2015-08-13 02:26:04 +02:00
|
|
|
|
2018-01-23 18:02:02 +01:00
|
|
|
// Query the current memory size, and increase the current memory size.
|
2018-06-01 00:35:25 +02:00
|
|
|
// Note that memory.size is not IntrNoMem because it must be sequenced with
|
|
|
|
// respect to memory.grow calls.
|
|
|
|
def int_wasm_memory_size : Intrinsic<[llvm_anyint_ty],
|
|
|
|
[llvm_i32_ty],
|
|
|
|
[IntrReadMem]>;
|
|
|
|
def int_wasm_memory_grow : Intrinsic<[llvm_anyint_ty],
|
|
|
|
[llvm_i32_ty, LLVMMatchType<0>],
|
|
|
|
[]>;
|
|
|
|
|
2019-10-15 03:11:51 +02:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Trapping float-to-int conversions
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
def int_wasm_trunc_signed : Intrinsic<[llvm_anyint_ty],
|
|
|
|
[llvm_anyfloat_ty],
|
|
|
|
[IntrNoMem]>;
|
|
|
|
def int_wasm_trunc_unsigned : Intrinsic<[llvm_anyint_ty],
|
|
|
|
[llvm_anyfloat_ty],
|
|
|
|
[IntrNoMem]>;
|
|
|
|
|
2018-10-11 02:01:25 +02:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Saturating float-to-int conversions
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
def int_wasm_trunc_saturate_signed : Intrinsic<[llvm_anyint_ty],
|
|
|
|
[llvm_anyfloat_ty],
|
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
|
|
|
def int_wasm_trunc_saturate_unsigned : Intrinsic<[llvm_anyint_ty],
|
|
|
|
[llvm_anyfloat_ty],
|
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
|
|
|
|
2018-03-08 04:47:52 +01:00
|
|
|
//===----------------------------------------------------------------------===//
|
2017-06-30 02:43:15 +02:00
|
|
|
// Exception handling intrinsics
|
2018-03-08 04:47:52 +01:00
|
|
|
//===----------------------------------------------------------------------===//
|
2017-06-30 02:43:15 +02:00
|
|
|
|
2018-03-08 04:47:52 +01:00
|
|
|
// throw / rethrow
|
2020-12-26 01:14:35 +01:00
|
|
|
// The immediate argument is an index to a tag, which is 0 for C++.
|
2018-03-08 04:47:52 +01:00
|
|
|
def int_wasm_throw : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty],
|
2020-05-27 21:58:07 +02:00
|
|
|
[Throws, IntrNoReturn, ImmArg<ArgIndex<0>>]>;
|
2020-12-26 01:14:35 +01:00
|
|
|
def int_wasm_rethrow : Intrinsic<[], [], [Throws, IntrNoReturn]>;
|
2018-03-28 01:37:07 +02:00
|
|
|
|
|
|
|
// Since wasm does not use landingpad instructions, these instructions return
|
|
|
|
// exception pointer and selector values until we lower them in WasmEHPrepare.
|
2018-06-01 00:02:34 +02:00
|
|
|
def int_wasm_get_exception : Intrinsic<[llvm_ptr_ty], [llvm_token_ty],
|
|
|
|
[IntrHasSideEffects]>;
|
|
|
|
def int_wasm_get_ehselector : Intrinsic<[llvm_i32_ty], [llvm_token_ty],
|
2018-03-28 01:37:07 +02:00
|
|
|
[IntrHasSideEffects]>;
|
[WebAssembly] Update WasmEHPrepare for the new spec
Clang generates `wasm.get.exception` and `wasm.get.ehselector`
intrinsics, which respectively return a caught exception value (a
pointer to some C++ exception struct) and a selector (an integer value
that tells which C++ `catch` clause the current exception matches, or
does not match any).
WasmEHPrepare is a pass that does some IR-level preparation before
instruction selection. Previously one of things we did in this pass was
to convert `wasm.get.exception` intrinsic calls to
`wasm.extract.exception` intrinsics. Their semantics were the same
except `wasm.extract.exception` did not have a token argument. We
maintained these two separate intrinsics with the same semantics because
instruction selection couldn't handle token arguments. This
`wasm.extract.exception` intrinsic was later converted to
`extract_exception` instruction in instruction selection, which was a
pseudo instruction to implement `br_on_exn`. Because `br_on_exn` pushed
an extracted value onto the value stack after the `end` instruction of a
`block`, but LLVM does not have a way of modeling that kind of behavior,
so this pseudo instruction was used to pull an extracted value out of
thin air, like this:
```
block $l0
...
br_on_exn $cpp_exception $l0
...
end
extract_exception ;; pushes values onto the stack
```
In the new spec, we don't need this pseudo instruction anymore because
`catch` itself returns a value and we don't have `br_on_exn` anymore. In
the spec `catch` returns multiple values (like `br_on_exn`), but here we
assume it only returns a single i32, which is sufficient to support C++.
So this renames `wasm.get.exception` intrinsic to `wasm.catch`. Because
this CL does not yet contain instruction selection for `wasm.catch`
intrinsic, all `RUN` lines in exception.ll, eh-lsda.ll, and
cfg-stackify-eh.ll, and a single `RUN` line in wasm-eh.cpp (which is an
end-to-end test from C++ source to assembly) fail. So this CL
temporarily disables those `RUN` lines, and for those test files without
any valid remaining `RUN` lines, adds a dummy `RUN` line to make them
pass. These tests will be reenabled in later CLs.
Reviewed By: dschuff, tlively
Differential Revision: https://reviews.llvm.org/D94039
2020-12-26 03:38:59 +01:00
|
|
|
|
|
|
|
// wasm.catch returns the pointer to the exception object caught by wasm 'catch'
|
|
|
|
// instruction. This returns a single pointer, which is sufficient for C++
|
|
|
|
// support. The immediate argument is an index to for a tag, which is 0 for C++.
|
|
|
|
def int_wasm_catch : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty],
|
|
|
|
[IntrHasSideEffects, ImmArg<ArgIndex<0>>]>;
|
2018-06-01 00:02:34 +02:00
|
|
|
|
|
|
|
// WebAssembly EH must maintain the landingpads in the order assigned to them
|
|
|
|
// by WasmEHPrepare pass to generate landingpad table in EHStreamer. This is
|
|
|
|
// used in order to give them the indices in WasmEHPrepare.
|
Reland "[WebAssembly] LSDA info generation"
Summary:
This adds support for LSDA (exception table) generation for wasm EH.
Wasm EH mostly follows the structure of Itanium-style exception tables,
with one exception: a call site table entry in wasm EH corresponds to
not a call site but a landing pad.
In wasm EH, the VM is responsible for stack unwinding. After an
exception occurs and the stack is unwound, the control flow is
transferred to wasm 'catch' instruction by the VM, after which the
personality function is called from the compiler-generated code. (Refer
to WasmEHPrepare pass for more information on this part.)
This patch:
- Changes wasm.landingpad.index intrinsic to take a token argument, to
make this 1:1 match with a catchpad instruction
- Stores landingpad index info and catch type info MachineFunction in
before instruction selection
- Lowers wasm.lsda intrinsic to an MCSymbol pointing to the start of an
exception table
- Adds WasmException class with overridden methods for table generation
- Adds support for LSDA section in Wasm object writer
Reviewers: dschuff, sbc100, rnk
Subscribers: mgorny, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D52748
llvm-svn: 345345
2018-10-26 01:55:10 +02:00
|
|
|
def int_wasm_landingpad_index: Intrinsic<[], [llvm_token_ty, llvm_i32_ty],
|
2020-05-27 21:58:07 +02:00
|
|
|
[IntrNoMem, ImmArg<ArgIndex<1>>]>;
|
2018-06-01 00:02:34 +02:00
|
|
|
|
|
|
|
// Returns LSDA address of the current function.
|
|
|
|
def int_wasm_lsda : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>;
|
2018-08-02 23:44:24 +02:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Atomic intrinsics
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
// wait / notify
|
2020-11-13 13:24:47 +01:00
|
|
|
def int_wasm_memory_atomic_wait32 :
|
2018-08-02 23:44:24 +02:00
|
|
|
Intrinsic<[llvm_i32_ty],
|
|
|
|
[LLVMPointerType<llvm_i32_ty>, llvm_i32_ty, llvm_i64_ty],
|
2020-11-13 13:24:47 +01:00
|
|
|
[IntrInaccessibleMemOrArgMemOnly, ReadOnly<ArgIndex<0>>,
|
|
|
|
NoCapture<ArgIndex<0>>, IntrHasSideEffects],
|
|
|
|
"", [SDNPMemOperand]>;
|
|
|
|
def int_wasm_memory_atomic_wait64 :
|
2018-08-02 23:44:24 +02:00
|
|
|
Intrinsic<[llvm_i32_ty],
|
|
|
|
[LLVMPointerType<llvm_i64_ty>, llvm_i64_ty, llvm_i64_ty],
|
2020-11-13 13:24:47 +01:00
|
|
|
[IntrInaccessibleMemOrArgMemOnly, ReadOnly<ArgIndex<0>>,
|
|
|
|
NoCapture<ArgIndex<0>>, IntrHasSideEffects],
|
|
|
|
"", [SDNPMemOperand]>;
|
|
|
|
def int_wasm_memory_atomic_notify:
|
2018-08-21 01:49:29 +02:00
|
|
|
Intrinsic<[llvm_i32_ty], [LLVMPointerType<llvm_i32_ty>, llvm_i32_ty],
|
2020-11-13 13:24:47 +01:00
|
|
|
[IntrInaccessibleMemOnly, NoCapture<ArgIndex<0>>,
|
|
|
|
IntrHasSideEffects],
|
|
|
|
"", [SDNPMemOperand]>;
|
2018-08-02 23:44:24 +02:00
|
|
|
|
2018-10-03 02:19:39 +02:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// SIMD intrinsics
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2019-10-09 19:45:47 +02:00
|
|
|
def int_wasm_swizzle :
|
|
|
|
Intrinsic<[llvm_v16i8_ty],
|
|
|
|
[llvm_v16i8_ty, llvm_v16i8_ty],
|
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
2020-05-11 18:55:43 +02:00
|
|
|
def int_wasm_shuffle :
|
|
|
|
Intrinsic<[llvm_v16i8_ty],
|
|
|
|
[llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, llvm_i32_ty,
|
|
|
|
llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty,
|
|
|
|
llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty,
|
|
|
|
llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
|
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
2021-03-18 19:21:24 +01:00
|
|
|
def int_wasm_sub_sat_signed :
|
2018-10-05 02:45:20 +02:00
|
|
|
Intrinsic<[llvm_anyvector_ty],
|
|
|
|
[LLVMMatchType<0>, LLVMMatchType<0>],
|
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
2021-03-18 19:21:24 +01:00
|
|
|
def int_wasm_sub_sat_unsigned :
|
2018-10-05 02:45:20 +02:00
|
|
|
Intrinsic<[llvm_anyvector_ty],
|
|
|
|
[LLVMMatchType<0>, LLVMMatchType<0>],
|
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
2019-12-18 06:53:46 +01:00
|
|
|
def int_wasm_avgr_unsigned :
|
|
|
|
Intrinsic<[llvm_anyvector_ty],
|
|
|
|
[LLVMMatchType<0>, LLVMMatchType<0>],
|
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
2018-10-04 01:02:23 +02:00
|
|
|
def int_wasm_bitselect :
|
|
|
|
Intrinsic<[llvm_anyvector_ty],
|
|
|
|
[LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>],
|
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
2018-10-03 02:19:39 +02:00
|
|
|
def int_wasm_anytrue :
|
|
|
|
Intrinsic<[llvm_i32_ty],
|
|
|
|
[llvm_anyvector_ty],
|
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
|
|
|
def int_wasm_alltrue :
|
|
|
|
Intrinsic<[llvm_i32_ty],
|
|
|
|
[llvm_anyvector_ty],
|
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
2020-03-19 01:10:00 +01:00
|
|
|
def int_wasm_bitmask :
|
|
|
|
Intrinsic<[llvm_i32_ty],
|
|
|
|
[llvm_anyvector_ty],
|
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
2019-11-01 02:28:02 +01:00
|
|
|
def int_wasm_dot :
|
|
|
|
Intrinsic<[llvm_v4i32_ty],
|
|
|
|
[llvm_v8i16_ty, llvm_v8i16_ty],
|
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
2020-10-30 23:44:04 +01:00
|
|
|
|
2019-09-14 00:54:41 +02:00
|
|
|
def int_wasm_narrow_signed :
|
|
|
|
Intrinsic<[llvm_anyvector_ty],
|
|
|
|
[llvm_anyvector_ty, LLVMMatchType<1>],
|
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
|
|
|
def int_wasm_narrow_unsigned :
|
|
|
|
Intrinsic<[llvm_anyvector_ty],
|
|
|
|
[llvm_anyvector_ty, LLVMMatchType<1>],
|
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
2020-10-30 23:44:04 +01:00
|
|
|
|
2021-03-18 19:21:24 +01:00
|
|
|
def int_wasm_q15mulr_sat_signed :
|
2020-10-09 23:17:53 +02:00
|
|
|
Intrinsic<[llvm_v8i16_ty],
|
|
|
|
[llvm_v8i16_ty, llvm_v8i16_ty],
|
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
2019-09-14 00:54:41 +02:00
|
|
|
|
2020-06-09 19:14:14 +02:00
|
|
|
// TODO: Replace these intrinsics with normal ISel patterns
|
2020-05-12 18:39:01 +02:00
|
|
|
def int_wasm_pmin :
|
|
|
|
Intrinsic<[llvm_anyvector_ty],
|
|
|
|
[LLVMMatchType<0>, LLVMMatchType<0>],
|
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
|
|
|
def int_wasm_pmax :
|
|
|
|
Intrinsic<[llvm_anyvector_ty],
|
|
|
|
[LLVMMatchType<0>, LLVMMatchType<0>],
|
2020-06-09 19:14:14 +02:00
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
|
|
|
|
2020-08-03 22:54:00 +02:00
|
|
|
// TODO: Replace these intrinsic with normal ISel patterns once the
|
|
|
|
// load_zero instructions are merged to the proposal.
|
|
|
|
def int_wasm_load32_zero :
|
|
|
|
Intrinsic<[llvm_v4i32_ty],
|
|
|
|
[LLVMPointerType<llvm_i32_ty>],
|
|
|
|
[IntrReadMem, IntrArgMemOnly],
|
|
|
|
"", [SDNPMemOperand]>;
|
|
|
|
|
|
|
|
def int_wasm_load64_zero :
|
|
|
|
Intrinsic<[llvm_v2i64_ty],
|
|
|
|
[LLVMPointerType<llvm_i64_ty>],
|
|
|
|
[IntrReadMem, IntrArgMemOnly],
|
|
|
|
"", [SDNPMemOperand]>;
|
|
|
|
|
2020-10-15 21:32:34 +02:00
|
|
|
// These intrinsics do not mark their lane index arguments as immediate because
|
|
|
|
// that changes the corresponding SDNode from ISD::Constant to
|
|
|
|
// ISD::TargetConstant, which would require extra complications in the ISel
|
|
|
|
// tablegen patterns. TODO: Replace these intrinsic with normal ISel patterns
|
|
|
|
// once the load_lane instructions are merged to the proposal.
|
|
|
|
def int_wasm_load8_lane :
|
|
|
|
Intrinsic<[llvm_v16i8_ty],
|
|
|
|
[LLVMPointerType<llvm_i8_ty>, llvm_v16i8_ty, llvm_i32_ty],
|
|
|
|
[IntrReadMem, IntrArgMemOnly],
|
|
|
|
"", [SDNPMemOperand]>;
|
|
|
|
def int_wasm_load16_lane :
|
|
|
|
Intrinsic<[llvm_v8i16_ty],
|
|
|
|
[LLVMPointerType<llvm_i16_ty>, llvm_v8i16_ty, llvm_i32_ty],
|
|
|
|
[IntrReadMem, IntrArgMemOnly],
|
|
|
|
"", [SDNPMemOperand]>;
|
|
|
|
def int_wasm_load32_lane :
|
|
|
|
Intrinsic<[llvm_v4i32_ty],
|
|
|
|
[LLVMPointerType<llvm_i32_ty>, llvm_v4i32_ty, llvm_i32_ty],
|
|
|
|
[IntrReadMem, IntrArgMemOnly],
|
|
|
|
"", [SDNPMemOperand]>;
|
|
|
|
def int_wasm_load64_lane :
|
|
|
|
Intrinsic<[llvm_v2i64_ty],
|
|
|
|
[LLVMPointerType<llvm_i64_ty>, llvm_v2i64_ty, llvm_i32_ty],
|
|
|
|
[IntrReadMem, IntrArgMemOnly],
|
|
|
|
"", [SDNPMemOperand]>;
|
|
|
|
def int_wasm_store8_lane :
|
|
|
|
Intrinsic<[],
|
|
|
|
[LLVMPointerType<llvm_i8_ty>, llvm_v16i8_ty, llvm_i32_ty],
|
|
|
|
[IntrWriteMem, IntrArgMemOnly],
|
|
|
|
"", [SDNPMemOperand]>;
|
|
|
|
def int_wasm_store16_lane :
|
|
|
|
Intrinsic<[],
|
|
|
|
[LLVMPointerType<llvm_i16_ty>, llvm_v8i16_ty, llvm_i32_ty],
|
|
|
|
[IntrWriteMem, IntrArgMemOnly],
|
|
|
|
"", [SDNPMemOperand]>;
|
|
|
|
def int_wasm_store32_lane :
|
|
|
|
Intrinsic<[],
|
|
|
|
[LLVMPointerType<llvm_i32_ty>, llvm_v4i32_ty, llvm_i32_ty],
|
|
|
|
[IntrWriteMem, IntrArgMemOnly],
|
|
|
|
"", [SDNPMemOperand]>;
|
|
|
|
def int_wasm_store64_lane :
|
|
|
|
Intrinsic<[],
|
|
|
|
[LLVMPointerType<llvm_i64_ty>, llvm_v2i64_ty, llvm_i32_ty],
|
|
|
|
[IntrWriteMem, IntrArgMemOnly],
|
|
|
|
"", [SDNPMemOperand]>;
|
|
|
|
|
2020-10-15 23:18:22 +02:00
|
|
|
// TODO: Replace this intrinsic with normal ISel patterns once popcnt is merged
|
|
|
|
// to the proposal.
|
|
|
|
def int_wasm_popcnt :
|
|
|
|
Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem, IntrSpeculatable]>;
|
|
|
|
|
2020-10-28 17:38:59 +01:00
|
|
|
def int_wasm_extmul_low_signed :
|
|
|
|
Intrinsic<[llvm_anyvector_ty],
|
|
|
|
[LLVMSubdivide2VectorType<0>, LLVMSubdivide2VectorType<0>],
|
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
|
|
|
def int_wasm_extmul_high_signed :
|
|
|
|
Intrinsic<[llvm_anyvector_ty],
|
|
|
|
[LLVMSubdivide2VectorType<0>, LLVMSubdivide2VectorType<0>],
|
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
|
|
|
def int_wasm_extmul_low_unsigned :
|
|
|
|
Intrinsic<[llvm_anyvector_ty],
|
|
|
|
[LLVMSubdivide2VectorType<0>, LLVMSubdivide2VectorType<0>],
|
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
|
|
|
def int_wasm_extmul_high_unsigned :
|
|
|
|
Intrinsic<[llvm_anyvector_ty],
|
|
|
|
[LLVMSubdivide2VectorType<0>, LLVMSubdivide2VectorType<0>],
|
2020-12-28 23:11:14 +01:00
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
|
|
|
|
|
|
|
def int_wasm_extadd_pairwise_signed :
|
|
|
|
Intrinsic<[llvm_anyvector_ty],
|
|
|
|
[LLVMSubdivide2VectorType<0>],
|
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
|
|
|
def int_wasm_extadd_pairwise_unsigned :
|
|
|
|
Intrinsic<[llvm_anyvector_ty],
|
|
|
|
[LLVMSubdivide2VectorType<0>],
|
2020-10-28 17:38:59 +01:00
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
|
|
|
|
2021-01-20 20:28:06 +01:00
|
|
|
// TODO: Remove these if possible if they are merged to the spec.
|
|
|
|
def int_wasm_demote_zero :
|
|
|
|
Intrinsic<[llvm_v4f32_ty], [llvm_v2f64_ty],
|
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
|
|
|
def int_wasm_promote_low :
|
|
|
|
Intrinsic<[llvm_v2f64_ty], [llvm_v4f32_ty],
|
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
|
|
|
|
[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
2019-07-17 00:00:45 +02:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Thread-local storage intrinsics
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
def int_wasm_tls_size :
|
|
|
|
Intrinsic<[llvm_anyint_ty],
|
|
|
|
[],
|
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
|
|
|
|
[WebAssembly] Compute and export TLS block alignment
Summary:
Add immutable WASM global `__tls_align` which stores the alignment
requirements of the TLS segment.
Add `__builtin_wasm_tls_align()` intrinsic to get this alignment in Clang.
The expected usage has now changed to:
__wasm_init_tls(memalign(__builtin_wasm_tls_align(),
__builtin_wasm_tls_size()));
Reviewers: tlively, aheejin, sbc100, sunfish, alexcrichton
Reviewed By: tlively
Subscribers: dschuff, jgravelle-google, hiraditya, cfe-commits, llvm-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D65028
llvm-svn: 366624
2019-07-20 01:34:16 +02:00
|
|
|
def int_wasm_tls_align :
|
|
|
|
Intrinsic<[llvm_anyint_ty],
|
|
|
|
[],
|
|
|
|
[IntrNoMem, IntrSpeculatable]>;
|
|
|
|
|
2019-07-18 19:53:22 +02:00
|
|
|
def int_wasm_tls_base :
|
|
|
|
Intrinsic<[llvm_ptr_ty],
|
|
|
|
[],
|
|
|
|
[IntrReadMem]>;
|
|
|
|
|
2018-10-03 02:19:39 +02:00
|
|
|
} // TargetPrefix = "wasm"
|