1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 03:02:36 +01:00
llvm-mirror/include/llvm/IR/IntrinsicsWebAssembly.td

351 lines
14 KiB
TableGen
Raw Normal View History

//===- IntrinsicsWebAssembly.td - Defines wasm intrinsics --*- tablegen -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file defines all of the WebAssembly-specific intrinsics.
///
//===----------------------------------------------------------------------===//
let TargetPrefix = "wasm" in { // All intrinsics start with "llvm.wasm.".
// Query the current memory size, and increase the current memory size.
// 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>],
[]>;
//===----------------------------------------------------------------------===//
// 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]>;
//===----------------------------------------------------------------------===//
// 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]>;
//===----------------------------------------------------------------------===//
// Exception handling intrinsics
//===----------------------------------------------------------------------===//
// throw / rethrow
// The immediate argument is an index to a tag, which is 0 for C++.
def int_wasm_throw : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty],
[Throws, IntrNoReturn, ImmArg<ArgIndex<0>>]>;
def int_wasm_rethrow : Intrinsic<[], [], [Throws, IntrNoReturn]>;
// Since wasm does not use landingpad instructions, these instructions return
// exception pointer and selector values until we lower them in WasmEHPrepare.
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],
[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>>]>;
// 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.
def int_wasm_landingpad_index: Intrinsic<[], [llvm_token_ty, llvm_i32_ty],
[IntrNoMem, ImmArg<ArgIndex<1>>]>;
// Returns LSDA address of the current function.
def int_wasm_lsda : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>;
//===----------------------------------------------------------------------===//
// Atomic intrinsics
//===----------------------------------------------------------------------===//
// wait / notify
def int_wasm_memory_atomic_wait32 :
Intrinsic<[llvm_i32_ty],
[LLVMPointerType<llvm_i32_ty>, llvm_i32_ty, llvm_i64_ty],
[IntrInaccessibleMemOrArgMemOnly, ReadOnly<ArgIndex<0>>,
NoCapture<ArgIndex<0>>, IntrHasSideEffects],
"", [SDNPMemOperand]>;
def int_wasm_memory_atomic_wait64 :
Intrinsic<[llvm_i32_ty],
[LLVMPointerType<llvm_i64_ty>, llvm_i64_ty, llvm_i64_ty],
[IntrInaccessibleMemOrArgMemOnly, ReadOnly<ArgIndex<0>>,
NoCapture<ArgIndex<0>>, IntrHasSideEffects],
"", [SDNPMemOperand]>;
def int_wasm_memory_atomic_notify:
Intrinsic<[llvm_i32_ty], [LLVMPointerType<llvm_i32_ty>, llvm_i32_ty],
[IntrInaccessibleMemOnly, NoCapture<ArgIndex<0>>,
IntrHasSideEffects],
"", [SDNPMemOperand]>;
//===----------------------------------------------------------------------===//
// SIMD intrinsics
//===----------------------------------------------------------------------===//
def int_wasm_swizzle :
Intrinsic<[llvm_v16i8_ty],
[llvm_v16i8_ty, llvm_v16i8_ty],
[IntrNoMem, IntrSpeculatable]>;
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]>;
def int_wasm_sub_saturate_signed :
Intrinsic<[llvm_anyvector_ty],
[LLVMMatchType<0>, LLVMMatchType<0>],
[IntrNoMem, IntrSpeculatable]>;
def int_wasm_sub_saturate_unsigned :
Intrinsic<[llvm_anyvector_ty],
[LLVMMatchType<0>, LLVMMatchType<0>],
[IntrNoMem, IntrSpeculatable]>;
def int_wasm_avgr_unsigned :
Intrinsic<[llvm_anyvector_ty],
[LLVMMatchType<0>, LLVMMatchType<0>],
[IntrNoMem, IntrSpeculatable]>;
def int_wasm_bitselect :
Intrinsic<[llvm_anyvector_ty],
[LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>],
[IntrNoMem, IntrSpeculatable]>;
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]>;
def int_wasm_bitmask :
Intrinsic<[llvm_i32_ty],
[llvm_anyvector_ty],
[IntrNoMem, IntrSpeculatable]>;
def int_wasm_qfma :
Intrinsic<[llvm_anyvector_ty],
[LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>],
[IntrNoMem, IntrSpeculatable]>;
def int_wasm_qfms :
Intrinsic<[llvm_anyvector_ty],
[LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>],
[IntrNoMem, IntrSpeculatable]>;
def int_wasm_dot :
Intrinsic<[llvm_v4i32_ty],
[llvm_v8i16_ty, llvm_v8i16_ty],
[IntrNoMem, IntrSpeculatable]>;
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]>;
// TODO: Replace these intrinsics with normal ISel patterns once i32x4 to i64x2
// widening is merged to the proposal.
def int_wasm_widen_low_signed :
Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem, IntrSpeculatable]>;
def int_wasm_widen_high_signed :
Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem, IntrSpeculatable]>;
def int_wasm_widen_low_unsigned :
Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem, IntrSpeculatable]>;
def int_wasm_widen_high_unsigned :
Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem, IntrSpeculatable]>;
def int_wasm_q15mulr_saturate_signed :
Intrinsic<[llvm_v8i16_ty],
[llvm_v8i16_ty, llvm_v8i16_ty],
[IntrNoMem, IntrSpeculatable]>;
// TODO: Replace these intrinsics with normal ISel patterns
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>],
[IntrNoMem, IntrSpeculatable]>;
// TODO: Replace these instrinsics with normal ISel patterns once the
// rounding instructions are merged to the proposal
// (https://github.com/WebAssembly/simd/pull/232).
def int_wasm_ceil :
Intrinsic<[llvm_anyvector_ty],
[LLVMMatchType<0>],
[IntrNoMem, IntrSpeculatable]>;
def int_wasm_floor :
Intrinsic<[llvm_anyvector_ty],
[LLVMMatchType<0>],
[IntrNoMem, IntrSpeculatable]>;
def int_wasm_trunc :
Intrinsic<[llvm_anyvector_ty],
[LLVMMatchType<0>],
[IntrNoMem, IntrSpeculatable]>;
def int_wasm_nearest :
Intrinsic<[llvm_anyvector_ty],
[LLVMMatchType<0>],
[IntrNoMem, IntrSpeculatable]>;
// 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]>;
// 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]>;
// 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]>;
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>],
[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>],
[IntrNoMem, IntrSpeculatable]>;
def int_wasm_signselect :
Intrinsic<[llvm_anyvector_ty],
[LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>],
[IntrNoMem, IntrSpeculatable]>;
// TODO: Remove this intrinsic and the associated builtin if i64x2.eq gets
// merged to the proposal.
def int_wasm_eq :
Intrinsic<[llvm_v2i64_ty],
[llvm_v2i64_ty, llvm_v2i64_ty],
[IntrNoMem, IntrSpeculatable]>;
// TODO: Remove this after experiments have been run. Use the target-agnostic
// int_prefetch if this becomes specified at some point.
def int_wasm_prefetch_t :
Intrinsic<[], [llvm_ptr_ty],
[IntrInaccessibleMemOrArgMemOnly, IntrWillReturn,
ReadOnly<ArgIndex<0>>, NoCapture<ArgIndex<0>>],
"", [SDNPMemOperand]>;
def int_wasm_prefetch_nt :
Intrinsic<[], [llvm_ptr_ty],
[IntrInaccessibleMemOrArgMemOnly, IntrWillReturn,
ReadOnly<ArgIndex<0>>, NoCapture<ArgIndex<0>>],
"", [SDNPMemOperand]>;
[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]>;
def int_wasm_tls_align :
Intrinsic<[llvm_anyint_ty],
[],
[IntrNoMem, IntrSpeculatable]>;
def int_wasm_tls_base :
Intrinsic<[llvm_ptr_ty],
[],
[IntrReadMem]>;
} // TargetPrefix = "wasm"