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