diff options
Diffstat (limited to 'js/src/wasm/cranelift/baldrapi.h')
-rw-r--r-- | js/src/wasm/cranelift/baldrapi.h | 283 |
1 files changed, 283 insertions, 0 deletions
diff --git a/js/src/wasm/cranelift/baldrapi.h b/js/src/wasm/cranelift/baldrapi.h new file mode 100644 index 0000000000..58a999785b --- /dev/null +++ b/js/src/wasm/cranelift/baldrapi.h @@ -0,0 +1,283 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * + * Copyright 2018 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// This is an ADT-style C API to the WebAssembly per-function compilation state, +// allowing Rust to access constant metadata and produce output. +// +// This file is input to Rust's bindgen, so as to create primitive APIs for the +// Cranelift pipeline to access compilation metadata. The actual Rust API then +// wraps these primitive APIs. See src/bindings/mod.rs. +// +// This file can be included in SpiderMonkey's C++ code, where all the prefixes +// must be obeyed. The purpose of the prefixes is to avoid type confusion. See +// js/src/wasm/WasmCraneliftCompile.cpp. + +#ifndef wasm_cranelift_baldrapi_h +#define wasm_cranelift_baldrapi_h + +// DO NOT INCLUDE SPIDERMONKEY HEADER FILES INTO THIS FILE. +#include <inttypes.h> +#include <stdbool.h> +#include <stddef.h> + +#include "wasm/WasmConstants.h" + +// wasm/*.{cpp,h}, class and struct types that are opaque to us here +namespace js { +namespace wasm { +// wasm/WasmGenerator.h +struct FuncCompileInput; +// wasm/WasmTypes.h +class GlobalDesc; +class FuncType; +class TypeIdDesc; +struct TableDesc; +// wasm/WasmValidate.h +struct ModuleEnvironment; +} // namespace wasm +} // namespace js + +// This struct contains all the information that can be computed once for the +// entire process and then should never change. It contains a mix of CPU +// feature detection flags, and static information the C++ compile has access +// to, but which can't be automatically provided to Rust. + +struct CraneliftStaticEnvironment { + bool has_sse2; + bool has_sse3; + bool has_sse41; + bool has_sse42; + bool has_popcnt; + bool has_avx; + bool has_bmi1; + bool has_bmi2; + bool has_lzcnt; + bool platform_is_windows; + bool ref_types_enabled; + bool threads_enabled; + bool v128_enabled; + size_t static_memory_bound; + size_t memory_guard_size; + size_t memory_base_tls_offset; + size_t instance_tls_offset; + size_t interrupt_tls_offset; + size_t cx_tls_offset; + size_t realm_cx_offset; + size_t realm_tls_offset; + size_t realm_func_import_tls_offset; + size_t size_of_wasm_frame; + + // Not bindgen'd because it's inlined. + inline CraneliftStaticEnvironment(); +}; + +// This structure proxies the C++ ModuleEnvironment and the information it +// contains. + +struct CraneliftModuleEnvironment { + // This is a pointer and not a reference to work-around a bug in bindgen. + const js::wasm::ModuleEnvironment* env; + uint32_t min_memory_length; + + // Not bindgen'd because it's inlined. + explicit inline CraneliftModuleEnvironment( + const js::wasm::ModuleEnvironment& env); +}; + +struct BD_Stackmaps; + +// Data for a single wasm function to be compiled by Cranelift. +// This information is all from the corresponding `js::wasm::FuncCompileInput` +// struct, but formatted in a Rust-friendly way. + +struct CraneliftFuncCompileInput { + const uint8_t* bytecode; + size_t bytecode_size; + uint32_t index; + uint32_t offset_in_module; + + // The stackmaps sink to use when compiling this function. + BD_Stackmaps* stackmaps; + + // Not bindgen'd because it's inlined. + explicit inline CraneliftFuncCompileInput(const js::wasm::FuncCompileInput&); +}; + +// A single entry in all the metadata array provided after the compilation of a +// single wasm function. The meaning of the field extra depends on the enum +// value. +// +// XXX should we use a union for this instead? bindgen seems to be able to +// handle them, with a lot of unsafe'ing. + +struct CraneliftMetadataEntry { + enum Which { DirectCall, IndirectCall, Trap, SymbolicAccess } which; + uint32_t code_offset; + uint32_t module_bytecode_offset; + size_t extra; +}; + +// The result of a single function compilation, containing the machine code +// generated by Cranelift, as well as some useful metadata to generate the +// prologue/epilogue etc. + +struct CraneliftCompiledFunc { + size_t num_metadata; + const CraneliftMetadataEntry* metadatas; + + size_t frame_pushed; + bool contains_calls; + + // The compiled code comprises machine code, relocatable jump tables, and + // copyable read-only data, concatenated without padding. The "...Size" + // members give the sizes of the individual sections. The code starts at + // offsets 0; the other offsets can be derived from the sizes. + const uint8_t* code; + size_t code_size; + size_t jumptables_size; + size_t rodata_size; + size_t total_size; + + // Relocation information for instructions that reference into the jump tables + // and read-only data segments. The relocation information is + // machine-specific. + size_t num_rodata_relocs; + const uint32_t* rodata_relocs; +}; + +// Possible constant values for initializing globals. + +struct BD_ConstantValue { + js::wasm::TypeCode t; + union { + int32_t i32; + int64_t i64; + float f32; + double f64; + void* r; + uint8_t v128[16]; // Little-endian + } u; +}; + +struct BD_ValType { + uint32_t packed; +}; + +// A subset of the wasm SymbolicAddress enum. This is converted to wasm using +// ToSymbolicAddress in WasmCraneliftCompile. + +enum class BD_SymbolicAddress : uint32_t { + MemoryGrow = 0, + MemorySize, + MemoryCopy, + MemoryCopyShared, + DataDrop, + MemoryFill, + MemoryFillShared, + MemoryInit, + TableSize, + TableGrow, + TableGet, + TableSet, + TableCopy, + TableFill, + TableInit, + ElemDrop, + RefFunc, + FloorF32, + FloorF64, + CeilF32, + CeilF64, + NearestF32, + NearestF64, + TruncF32, + TruncF64, + PreBarrier, + PostBarrier, + WaitI32, + WaitI64, + Wake, + Limit +}; + +extern "C" { +js::wasm::TypeCode env_unpack(BD_ValType type); + +size_t env_num_tables(const CraneliftModuleEnvironment* env); +size_t env_num_globals(const CraneliftModuleEnvironment* env); +size_t env_num_types(const CraneliftModuleEnvironment* env); +size_t env_num_funcs(const CraneliftModuleEnvironment* env); +size_t env_num_elems(const CraneliftModuleEnvironment* env); +size_t env_num_datas(const CraneliftModuleEnvironment* env); +js::wasm::TypeCode env_elem_typecode(const CraneliftModuleEnvironment* env, + uint32_t index); +bool env_is_func_valid_for_ref(const CraneliftModuleEnvironment* env, + uint32_t index); +/// Returns the maximum memory size as an uint32, or UINT32_MAX if not defined. +uint32_t env_max_memory(const CraneliftModuleEnvironment* env); + +bool env_uses_shared_memory(const CraneliftModuleEnvironment* env); +bool env_has_memory(const CraneliftModuleEnvironment* env); +const js::wasm::FuncType* env_type(const CraneliftModuleEnvironment* env, + size_t typeIndex); +const js::wasm::FuncType* env_func_sig(const CraneliftModuleEnvironment* env, + size_t funcIndex); +const js::wasm::TypeIdDesc* env_func_sig_id( + const CraneliftModuleEnvironment* env, size_t funcIndex); +size_t env_func_sig_index(const CraneliftModuleEnvironment* env, + size_t funcIndex); +size_t env_func_import_tls_offset(const CraneliftModuleEnvironment* env, + size_t funcIndex); +bool env_func_is_import(const CraneliftModuleEnvironment* env, + size_t funcIndex); +const js::wasm::FuncType* env_signature(const CraneliftModuleEnvironment* env, + size_t sigIndex); +const js::wasm::TypeIdDesc* env_signature_id( + const CraneliftModuleEnvironment* env, size_t sigIndex); +const js::wasm::TableDesc* env_table(const CraneliftModuleEnvironment* env, + size_t tableIndex); +const js::wasm::GlobalDesc* env_global(const CraneliftModuleEnvironment* env, + size_t globalIndex); + +bool global_isConstant(const js::wasm::GlobalDesc*); +bool global_isIndirect(const js::wasm::GlobalDesc*); +BD_ConstantValue global_constantValue(const js::wasm::GlobalDesc*); +js::wasm::TypeCode global_type(const js::wasm::GlobalDesc*); +size_t global_tlsOffset(const js::wasm::GlobalDesc*); + +size_t table_tlsOffset(const js::wasm::TableDesc*); +uint32_t table_initialLimit(const js::wasm::TableDesc*); +// Returns the maximum limit as an uint32, or UINT32_MAX if not defined. +uint32_t table_maximumLimit(const js::wasm::TableDesc*); +js::wasm::TypeCode table_elementTypeCode(const js::wasm::TableDesc*); + +size_t funcType_numArgs(const js::wasm::FuncType*); +const BD_ValType* funcType_args(const js::wasm::FuncType*); +size_t funcType_numResults(const js::wasm::FuncType*); +const BD_ValType* funcType_results(const js::wasm::FuncType*); + +js::wasm::TypeIdDescKind funcType_idKind(const js::wasm::TypeIdDesc*); +size_t funcType_idImmediate(const js::wasm::TypeIdDesc*); +size_t funcType_idTlsOffset(const js::wasm::TypeIdDesc*); + +void stackmaps_add(BD_Stackmaps* sink, const uint32_t* bitMap, + size_t mappedWords, size_t argsSize, size_t codeOffset); + +} // extern "C" + +#endif // wasm_cranelift_baldrapi_h |