1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * 4 * Copyright 2018 Mozilla Foundation 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 // This is an ADT-style C API to the WebAssembly per-function compilation state, 20 // allowing Rust to access constant metadata and produce output. 21 // 22 // This file is input to Rust's bindgen, so as to create primitive APIs for the 23 // Cranelift pipeline to access compilation metadata. The actual Rust API then 24 // wraps these primitive APIs. See src/bindings/mod.rs. 25 // 26 // This file can be included in SpiderMonkey's C++ code, where all the prefixes 27 // must be obeyed. The purpose of the prefixes is to avoid type confusion. See 28 // js/src/wasm/WasmCraneliftCompile.cpp. 29 30 #ifndef wasm_cranelift_baldrapi_h 31 #define wasm_cranelift_baldrapi_h 32 33 // DO NOT INCLUDE SPIDERMONKEY HEADER FILES INTO THIS FILE. 34 #include <inttypes.h> 35 #include <stdbool.h> 36 #include <stddef.h> 37 38 #include "wasm/WasmConstants.h" 39 40 // wasm/*.{cpp,h}, class and struct types that are opaque to us here 41 namespace js { 42 namespace wasm { 43 // wasm/WasmGenerator.h 44 struct FuncCompileInput; 45 // wasm/WasmTypes.h 46 class GlobalDesc; 47 class FuncType; 48 class TypeIdDesc; 49 struct TableDesc; 50 // wasm/WasmValidate.h 51 struct ModuleEnvironment; 52 } // namespace wasm 53 } // namespace js 54 55 // This struct contains all the information that can be computed once for the 56 // entire process and then should never change. It contains a mix of CPU 57 // feature detection flags, and static information the C++ compile has access 58 // to, but which can't be automatically provided to Rust. 59 60 struct CraneliftStaticEnvironment { 61 bool has_sse2; 62 bool has_sse3; 63 bool has_sse41; 64 bool has_sse42; 65 bool has_popcnt; 66 bool has_avx; 67 bool has_bmi1; 68 bool has_bmi2; 69 bool has_lzcnt; 70 bool platform_is_windows; 71 bool ref_types_enabled; 72 bool threads_enabled; 73 bool v128_enabled; 74 size_t static_memory_bound; 75 size_t memory_guard_size; 76 size_t memory_base_tls_offset; 77 size_t instance_tls_offset; 78 size_t interrupt_tls_offset; 79 size_t cx_tls_offset; 80 size_t realm_cx_offset; 81 size_t realm_tls_offset; 82 size_t realm_func_import_tls_offset; 83 size_t size_of_wasm_frame; 84 85 // Not bindgen'd because it's inlined. 86 inline CraneliftStaticEnvironment(); 87 }; 88 89 // This structure proxies the C++ ModuleEnvironment and the information it 90 // contains. 91 92 struct CraneliftModuleEnvironment { 93 // This is a pointer and not a reference to work-around a bug in bindgen. 94 const js::wasm::ModuleEnvironment* env; 95 uint32_t min_memory_length; 96 97 // Not bindgen'd because it's inlined. 98 explicit inline CraneliftModuleEnvironment( 99 const js::wasm::ModuleEnvironment& env); 100 }; 101 102 struct BD_Stackmaps; 103 104 // Data for a single wasm function to be compiled by Cranelift. 105 // This information is all from the corresponding `js::wasm::FuncCompileInput` 106 // struct, but formatted in a Rust-friendly way. 107 108 struct CraneliftFuncCompileInput { 109 const uint8_t* bytecode; 110 size_t bytecode_size; 111 uint32_t index; 112 uint32_t offset_in_module; 113 114 // The stackmaps sink to use when compiling this function. 115 BD_Stackmaps* stackmaps; 116 117 // Not bindgen'd because it's inlined. 118 explicit inline CraneliftFuncCompileInput(const js::wasm::FuncCompileInput&); 119 }; 120 121 // A single entry in all the metadata array provided after the compilation of a 122 // single wasm function. The meaning of the field extra depends on the enum 123 // value. 124 // 125 // XXX should we use a union for this instead? bindgen seems to be able to 126 // handle them, with a lot of unsafe'ing. 127 128 struct CraneliftMetadataEntry { 129 enum Which { DirectCall, IndirectCall, Trap, SymbolicAccess } which; 130 uint32_t code_offset; 131 uint32_t module_bytecode_offset; 132 size_t extra; 133 }; 134 135 // The result of a single function compilation, containing the machine code 136 // generated by Cranelift, as well as some useful metadata to generate the 137 // prologue/epilogue etc. 138 139 struct CraneliftCompiledFunc { 140 size_t num_metadata; 141 const CraneliftMetadataEntry* metadatas; 142 143 size_t frame_pushed; 144 bool contains_calls; 145 146 // The compiled code comprises machine code, relocatable jump tables, and 147 // copyable read-only data, concatenated without padding. The "...Size" 148 // members give the sizes of the individual sections. The code starts at 149 // offsets 0; the other offsets can be derived from the sizes. 150 const uint8_t* code; 151 size_t code_size; 152 size_t jumptables_size; 153 size_t rodata_size; 154 size_t total_size; 155 156 // Relocation information for instructions that reference into the jump tables 157 // and read-only data segments. The relocation information is 158 // machine-specific. 159 size_t num_rodata_relocs; 160 const uint32_t* rodata_relocs; 161 }; 162 163 // Possible constant values for initializing globals. 164 165 struct BD_ConstantValue { 166 js::wasm::TypeCode t; 167 union { 168 int32_t i32; 169 int64_t i64; 170 float f32; 171 double f64; 172 void* r; 173 uint8_t v128[16]; // Little-endian 174 } u; 175 }; 176 177 struct BD_ValType { 178 size_t packed; 179 }; 180 181 // A subset of the wasm SymbolicAddress enum. This is converted to wasm using 182 // ToSymbolicAddress in WasmCraneliftCompile. 183 184 enum class BD_SymbolicAddress : uint32_t { 185 MemoryGrow = 0, /* MemoryGrowM32 */ 186 MemorySize, /* MemorySizeM32 */ 187 MemoryCopy, /* MemoryCopyM32 */ 188 MemoryCopyShared, /* MemoryCopySharedM32 */ 189 DataDrop, 190 MemoryFill, /* MemoryFillM32 */ 191 MemoryFillShared, /* MemoryFillSharedM32 */ 192 MemoryInit, /* MemoryInitM32 */ 193 TableSize, 194 TableGrow, 195 TableGet, 196 TableSet, 197 TableCopy, 198 TableFill, 199 TableInit, 200 ElemDrop, 201 RefFunc, 202 FloorF32, 203 FloorF64, 204 CeilF32, 205 CeilF64, 206 NearestF32, 207 NearestF64, 208 TruncF32, 209 TruncF64, 210 PreBarrier, 211 PostBarrier, 212 WaitI32, /* WaitI32M32 */ 213 WaitI64, /* WaitI64M32 */ 214 Wake, /* WakeM32 */ 215 Limit 216 }; 217 218 extern "C" { 219 js::wasm::TypeCode env_unpack(BD_ValType type); 220 221 size_t env_num_tables(const CraneliftModuleEnvironment* env); 222 size_t env_num_globals(const CraneliftModuleEnvironment* env); 223 size_t env_num_types(const CraneliftModuleEnvironment* env); 224 size_t env_num_funcs(const CraneliftModuleEnvironment* env); 225 size_t env_num_elems(const CraneliftModuleEnvironment* env); 226 size_t env_num_datas(const CraneliftModuleEnvironment* env); 227 js::wasm::TypeCode env_elem_typecode(const CraneliftModuleEnvironment* env, 228 uint32_t index); 229 bool env_is_func_valid_for_ref(const CraneliftModuleEnvironment* env, 230 uint32_t index); 231 /// Returns the maximum memory size as an uint32, or UINT32_MAX if not defined. 232 uint32_t env_max_memory(const CraneliftModuleEnvironment* env); 233 234 bool env_uses_shared_memory(const CraneliftModuleEnvironment* env); 235 bool env_has_memory(const CraneliftModuleEnvironment* env); 236 const js::wasm::FuncType* env_type(const CraneliftModuleEnvironment* env, 237 size_t typeIndex); 238 const js::wasm::FuncType* env_func_sig(const CraneliftModuleEnvironment* env, 239 size_t funcIndex); 240 const js::wasm::TypeIdDesc* env_func_sig_id( 241 const CraneliftModuleEnvironment* env, size_t funcIndex); 242 size_t env_func_sig_index(const CraneliftModuleEnvironment* env, 243 size_t funcIndex); 244 size_t env_func_import_tls_offset(const CraneliftModuleEnvironment* env, 245 size_t funcIndex); 246 bool env_func_is_import(const CraneliftModuleEnvironment* env, 247 size_t funcIndex); 248 const js::wasm::FuncType* env_signature(const CraneliftModuleEnvironment* env, 249 size_t sigIndex); 250 const js::wasm::TypeIdDesc* env_signature_id( 251 const CraneliftModuleEnvironment* env, size_t sigIndex); 252 const js::wasm::TableDesc* env_table(const CraneliftModuleEnvironment* env, 253 size_t tableIndex); 254 const js::wasm::GlobalDesc* env_global(const CraneliftModuleEnvironment* env, 255 size_t globalIndex); 256 257 bool global_isConstant(const js::wasm::GlobalDesc*); 258 bool global_isMutable(const js::wasm::GlobalDesc*); 259 bool global_isIndirect(const js::wasm::GlobalDesc*); 260 BD_ConstantValue global_constantValue(const js::wasm::GlobalDesc*); 261 js::wasm::TypeCode global_type(const js::wasm::GlobalDesc*); 262 size_t global_tlsOffset(const js::wasm::GlobalDesc*); 263 264 size_t table_tlsOffset(const js::wasm::TableDesc*); 265 uint32_t table_initialLimit(const js::wasm::TableDesc*); 266 // Returns the maximum limit as an uint32, or UINT32_MAX if not defined. 267 uint32_t table_maximumLimit(const js::wasm::TableDesc*); 268 js::wasm::TypeCode table_elementTypeCode(const js::wasm::TableDesc*); 269 270 size_t funcType_numArgs(const js::wasm::FuncType*); 271 const BD_ValType* funcType_args(const js::wasm::FuncType*); 272 size_t funcType_numResults(const js::wasm::FuncType*); 273 const BD_ValType* funcType_results(const js::wasm::FuncType*); 274 275 js::wasm::TypeIdDescKind funcType_idKind(const js::wasm::TypeIdDesc*); 276 size_t funcType_idImmediate(const js::wasm::TypeIdDesc*); 277 size_t funcType_idTlsOffset(const js::wasm::TypeIdDesc*); 278 279 void stackmaps_add(BD_Stackmaps* sink, const uint32_t* bitMap, 280 size_t mappedWords, size_t argsSize, size_t codeOffset); 281 282 } // extern "C" 283 284 #endif // wasm_cranelift_baldrapi_h 285