/* -*- 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 #include #include #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