1use std::collections::HashMap;
2use std::sync::Arc;
3use std::sync::Mutex;
4
5#[macro_export]
6macro_rules! body {
7 ($( $v:expr ),*) => {{
8 let mut body = vec![];
9 $(
10 body.extend_from_slice(&$v);
11 )*
12 body.push(ast::Value::new(ast::Instr::end));
13 ast::Value::new(body)
14 }};
15}
16
17#[macro_export]
18macro_rules! make_type {
19 {} => {
20 ast::Type {
21 params: vec![],
22 results: vec![],
23 }
24 };
25
26 {($( $arg:ident ),*) -> ()} => {{
27 use ast::NumType::*;
28
29 let mut t = ast::Type {
30 params: vec![],
31 results: vec![],
32 };
33 $(
34 t.params.push(ast::ValueType::NumType($arg));
35 )*;
36
37 t
38 }};
39
40 {($( $arg:ident ),*) -> $res:ident} => {{
41 use ast::NumType::*;
42
43 let mut t = ast::Type {
44 params: vec![],
45 results: vec![ast::ValueType::NumType($res)],
46 };
47 $(
48 t.params.push(ast::ValueType::NumType($arg));
49 )*;
50
51 t
52 }};
53}
54pub use body;
55pub use make_type;
56
57#[macro_export]
58macro_rules! make_value {
59 ($v:expr) => {
60 Arc::new(Mutex::new(ast::Value::new($v)))
61 };
62}
63pub use make_value;
64
65#[derive(Debug, PartialEq, Clone)]
66pub struct Value<T> {
67 pub value: T,
68 pub start_offset: usize,
69 pub end_offset: usize,
70}
71impl<T> Value<T> {
72 pub fn new(value: T) -> Self {
73 Self {
74 start_offset: 0,
75 end_offset: 0,
76 value,
77 }
78 }
79}
80
81pub type MutableValue<T> = Arc<Mutex<Value<T>>>;
82
83#[derive(Debug, Clone)]
84pub struct Memory {
85 pub min: Value<u32>,
86 pub max: Option<u32>,
87}
88
89#[derive(Debug, Clone)]
90pub struct Code {
91 pub size: Value<u32>,
92 pub locals: Vec<CodeLocal>,
93 pub body: MutableValue<Vec<Value<Instr>>>,
94}
95
96#[derive(Debug, Clone)]
97pub struct CodeLocal {
98 pub count: u32,
99 pub value_type: ValueType,
100}
101
102#[derive(Debug, PartialEq, Clone)]
103pub enum ValueType {
104 NumType(NumType),
105 }
108
109#[derive(Debug, PartialEq, Clone)]
110pub enum NumType {
111 I32,
112 I64,
113 F32,
114 F64,
115}
116
117#[derive(Debug, Clone)]
118pub enum Reftype {
119 Func,
120 Extern,
121}
122
123#[derive(Debug, Clone)]
124pub struct Limits {
125 pub min: u32,
126 pub max: Option<u32>,
127}
128
129#[derive(Debug, Clone)]
130pub struct Table {
131 pub reftype: Reftype,
132 pub limits: Limits,
133}
134
135#[derive(Debug, Clone)]
136pub struct DataSegment {
137 pub offset: Option<Value<Vec<Value<Instr>>>>,
138 pub bytes: Vec<u8>,
139 pub mode: DataSegmentMode,
140}
141
142#[derive(Debug, Clone, PartialEq)]
143pub enum DataSegmentMode {
144 Passive,
145 Active,
146}
147
148impl DataSegment {
149 pub fn compute_offset(&self) -> i64 {
150 let expr = &self.offset.as_ref().unwrap().value;
151 for instr in expr {
152 if let Instr::i32_const(v) = instr.value {
153 return v;
154 }
155 }
156
157 unreachable!("malformed data expression: {:?}", expr)
158 }
159}
160
161#[derive(Debug, PartialEq, Clone)]
162pub enum BlockType {
163 Empty,
164 ValueType(ValueType),
165 Typeidx(u32),
166}
167
168#[derive(Debug, Clone)]
169pub enum Instr {
170 unreachable,
171 nop,
172
173 call(MutableValue<u32>),
174 call_indirect(u32, u32),
175
176 drop,
177 select,
178
179 local_get(u32),
180 local_set(u32),
181 local_tee(u32),
182 global_get(u32),
183 global_set(u32),
184 table_get(u32),
185 table_set(u32),
186
187 i32_load(MutableValue<u32>, u32),
188 i64_load(MutableValue<u32>, u32),
189 f32_load(MutableValue<u32>, u32),
190 f64_load(MutableValue<u32>, u32),
191 i32_load8_s(MutableValue<u32>, u32),
192 i32_load8_u(MutableValue<u32>, u32),
193 i32_load16_s(MutableValue<u32>, u32),
194 i32_load16_u(MutableValue<u32>, u32),
195 i64_load8_s(MutableValue<u32>, u32),
196 i64_load8_u(MutableValue<u32>, u32),
197 i64_load16_s(MutableValue<u32>, u32),
198 i64_load16_u(MutableValue<u32>, u32),
199 i64_load32_s(MutableValue<u32>, u32),
200 i64_load32_u(MutableValue<u32>, u32),
201
202 i32_store(MutableValue<u32>, u32),
203 i64_store(MutableValue<u32>, u32),
204 f32_store(MutableValue<u32>, u32),
205 f64_store(MutableValue<u32>, u32),
206 i32_store8(MutableValue<u32>, u32),
207 i32_store16(MutableValue<u32>, u32),
208 i64_store8(MutableValue<u32>, u32),
209 i64_store16(MutableValue<u32>, u32),
210 i64_store32(MutableValue<u32>, u32),
211
212 memory_size(u8),
213 memory_grow(u8),
214 memory_copy(u8, u8),
215 memory_fill(u8),
216
217 br(u32),
218 br_if(u32),
219 br_table(Vec<u32>, u32),
220 else_end,
221 end,
222 Return,
223 Block(BlockType, MutableValue<Vec<Value<Instr>>>),
224 Loop(BlockType, MutableValue<Vec<Value<Instr>>>),
225 If(BlockType, MutableValue<Vec<Value<Instr>>>),
226
227 i32_const(i64),
228 i64_const(i64),
229 f32_const(f32),
230 f64_const(f64),
231 i32_eqz,
232 i32_eq,
233 i32_ne,
234 i32_lt_s,
235 i32_lt_u,
236 i32_gt_s,
237 i32_gt_u,
238 i32_le_s,
239 i32_le_u,
240 i32_ge_s,
241 i32_ge_u,
242
243 i64_eqz,
244 i64_eq,
245 i64_ne,
246 i64_lt_s,
247 i64_lt_u,
248 i64_gt_s,
249 i64_gt_u,
250 i64_le_s,
251 i64_le_u,
252 i64_ge_s,
253 i64_ge_u,
254
255 f32_eq,
256 f32_ne,
257 f32_lt,
258 f32_gt,
259 f32_le,
260 f32_ge,
261
262 f64_eq,
263 f64_ne,
264 f64_lt,
265 f64_gt,
266 f64_le,
267 f64_ge,
268
269 i32_clz,
270 i32_ctz,
271 i32_popcnt,
272 i32_add,
273 i32_sub,
274 i32_mul,
275 i32_div_s,
276 i32_div_u,
277 i32_rem_s,
278 i32_rem_u,
279 i32_and,
280 i32_or,
281 i32_xor,
282 i32_shl,
283 i32_shr_s,
284 i32_shr_u,
285 i32_rotl,
286 i32_rotr,
287
288 i64_clz,
289 i64_ctz,
290 i64_popcnt,
291 i64_add,
292 i64_sub,
293 i64_mul,
294 i64_div_s,
295 i64_div_u,
296 i64_rem_s,
297 i64_rem_u,
298 i64_and,
299 i64_or,
300 i64_xor,
301 i64_shl,
302 i64_shr_s,
303 i64_shr_u,
304 i64_rotl,
305 i64_rotr,
306
307 f32_abs,
308 f32_neg,
309 f32_ceil,
310 f32_floor,
311 f32_trunc,
312 f32_nearest,
313 f32_sqrt,
314 f32_add,
315 f32_sub,
316 f32_mul,
317 f32_div,
318 f32_min,
319 f32_max,
320 f32_copysign,
321
322 f64_abs,
323 f64_neg,
324 f64_ceil,
325 f64_floor,
326 f64_trunc,
327 f64_nearest,
328 f64_sqrt,
329 f64_add,
330 f64_sub,
331 f64_mul,
332 f64_div,
333 f64_min,
334 f64_max,
335 f64_copysign,
336
337 i32_wrap_i64,
338 i32_trunc_f32_s,
339 i32_trunc_f32_u,
340 i32_trunc_f64_s,
341 i32_trunc_f64_u,
342 i32_trunc_sat_f32_s,
343 i32_trunc_sat_f32_u,
344 i32_trunc_sat_f64_s,
345 i32_trunc_sat_f64_u,
346 i64_extend_i32_s,
347 i64_extend_i32_u,
348 i64_trunc_f32_s,
349 i64_trunc_f32_u,
350 i64_trunc_f64_s,
351 i64_trunc_f64_u,
352 i64_trunc_sat_f32_s,
353 i64_trunc_sat_f32_u,
354 i64_trunc_sat_f64_s,
355 i64_trunc_sat_f64_u,
356 f32_convert_i32_s,
357 f32_convert_i32_u,
358 f32_convert_i64_s,
359 f32_convert_i64_u,
360 f32_demote_f64,
361 f64_convert_i32_s,
362 f64_convert_i32_u,
363 f64_convert_i64_s,
364 f64_convert_i64_u,
365 f64_promote_f32,
366
367 i32_reinterpret_f32,
368 i64_reinterpret_f64,
369 f32_reinterpret_i32,
370 f64_reinterpret_i64,
371
372 i32_extend8_s,
373 i32_extend16_s,
374 i64_extend8_s,
375 i64_extend16_s,
376 i64_extend32_s,
377}
378
379pub type Expr = Value<Vec<Value<Instr>>>;
380
381#[derive(Debug, Clone)]
382pub enum Section {
383 Memory((Value<u32>, Vec<Memory>)),
385 Data((Value<u32>, Arc<Mutex<Vec<DataSegment>>>)),
386 Code((Value<u32>, MutableValue<Vec<Code>>)),
387 Type((Value<u32>, Arc<Mutex<Vec<Type>>>)),
388 Func((Value<u32>, Arc<Mutex<Vec<u32>>>)),
389 Import((Value<u32>, Arc<Mutex<Vec<Import>>>)),
390 Table((Value<u32>, Arc<Mutex<Vec<Table>>>)),
391 Export((Value<u32>, Arc<Mutex<Vec<Export>>>)),
392 Element((Value<u32>, Arc<Mutex<Vec<Element>>>)),
393 Custom((Value<u32>, Arc<Mutex<CustomSection>>)),
394 Global((Value<u32>, Arc<Mutex<Vec<Global>>>)),
395 Unknown((u8, u32, Vec<u8>)),
397}
398
399impl Value<Section> {
400 pub fn pos(&self) -> usize {
401 use Section::*;
402
403 match self.value {
404 Type(_) => 1,
405 Import(_) => 2,
406 Func(_) => 3,
407 Table(_) => 4,
408 Memory(_) => 5,
409 Global(_) => 6,
410 Export(_) => 7,
411 Element(_) => 9,
413 Code(_) => 10,
414 Data(_) => 11,
415 Custom(_) | Unknown(_) => 99,
416 }
417 }
418}
419
420#[derive(Debug, Clone)]
421pub enum CustomSection {
422 Unknown(String, Vec<u8>),
423 Name(DebugNames),
424 CoredumpCore(wasm_coredump_types::ProcessInfo),
425 CoredumpCoreStack(wasm_coredump_types::CoreStack),
426 BuildId(Vec<u8>),
427}
428
429#[derive(Debug)]
430pub struct Module {
431 pub sections: Arc<Mutex<Vec<Value<Section>>>>,
432}
433
434#[derive(Debug, Clone)]
435pub struct Type {
436 pub params: Vec<ValueType>,
437 pub results: Vec<ValueType>,
438}
439
440#[derive(Debug, Clone)]
441pub struct Import {
442 pub module: String,
443 pub name: String,
444 pub import_type: ImportType,
445}
446
447#[derive(Debug, Clone)]
448pub enum ImportType {
449 Func(u32),
450 Table(Table),
451 Memory(Memory),
452 Global(GlobalType),
453}
454
455#[derive(Debug, Clone)]
456pub struct Export {
457 pub name: String,
458 pub descr: ExportDescr,
459}
460
461#[derive(Debug, Clone)]
462pub enum ExportDescr {
463 Func(Arc<Mutex<u32>>),
464 Table(Arc<Mutex<u32>>),
465 Mem(Arc<Mutex<u32>>),
466 Global(Arc<Mutex<u32>>),
467}
468
469#[derive(Debug, Clone)]
470pub enum Element {
471 FuncActive(Expr, Arc<Mutex<Vec<u32>>>),
472}
473
474#[derive(Debug, Clone)]
475pub struct Global {
476 pub global_type: GlobalType,
477 pub expr: Expr,
478}
479
480impl Global {
481 pub fn compute_value(&self) -> i64 {
482 let expr = &self.expr.value;
483 if !self.global_type.mutable {
484 for instr in expr {
485 if let Instr::i32_const(v) = instr.value {
486 return v;
487 }
488 }
489 }
490
491 unreachable!("unsupported global expression: {:?}", expr)
492 }
493}
494
495#[derive(Debug, Clone)]
496pub struct GlobalType {
497 pub valtype: ValueType,
498 pub mutable: bool,
499}
500
501#[derive(Debug, Clone)]
502pub struct DebugNames {
503 pub module: Option<String>,
504 pub func_names: Option<Arc<Mutex<HashMap<u32, String>>>>,
505 pub func_local_names: Option<HashMap<u32, HashMap<u32, String>>>,
506 pub global_names: Arc<Mutex<HashMap<u32, String>>>,
507}