1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
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
|