1use crate::entity::{EntityRef, PerEntity};
4use crate::ir::*;
5use crate::ops::Operator;
6use smallvec::{smallvec, SmallVec};
7
8use std::collections::HashMap;
9
10const MAX_PAGES: usize = 2048; pub struct InterpContext {
18 pub memories: PerEntity<Memory, InterpMemory>,
20 pub tables: PerEntity<Table, InterpTable>,
22 pub globals: PerEntity<Global, ConstVal>,
24 pub fuel: u64,
26}
27
28#[derive(Debug, Clone, Default, PartialEq, Eq)]
30pub struct InterpMemory {
31 pub data: Vec<u8>,
32 pub max_pages: usize,
33}
34
35#[derive(Debug, Clone, Default, PartialEq, Eq)]
37pub struct InterpTable {
38 pub elements: Vec<Func>,
39}
40
41#[derive(Debug, Clone, Default)]
43pub struct InterpStackFrame {
44 func: Func,
45 cur_block: Block,
46 values: HashMap<Value, SmallVec<[ConstVal; 2]>>,
47}
48
49#[derive(Clone, Debug)]
51pub enum InterpResult {
52 Ok(MultiVal),
54 Trap(Func, Block, u32),
56 OutOfFuel,
58}
59
60#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
62pub enum ConstVal {
63 I32(u32),
64 I64(u64),
65 F32(u32),
66 F64(u64),
67 #[default]
68 None,
69}
70
71type MultiVal = SmallVec<[ConstVal; 2]>;
73
74impl InterpResult {
75 pub fn ok(self) -> anyhow::Result<MultiVal> {
78 match self {
79 InterpResult::Ok(vals) => Ok(vals),
80 other => anyhow::bail!("Bad InterpResult: {:?}", other),
81 }
82 }
83}
84
85impl InterpContext {
86 pub fn new(module: &Module<'_>) -> anyhow::Result<Self> {
88 let mut memories = PerEntity::default();
89 for (memory, data) in module.memories.entries() {
90 let mut interp_mem = InterpMemory {
91 data: vec![0; data.initial_pages * WASM_PAGE],
92 max_pages: data.maximum_pages.unwrap_or(MAX_PAGES),
93 };
94 for segment in &data.segments {
95 let end = match segment.offset.checked_add(segment.data.len()) {
96 Some(end) => end,
97 None => anyhow::bail!("Data segment offset + length overflows"),
98 };
99 if end > interp_mem.data.len() {
100 anyhow::bail!("Data segment out of bounds");
101 }
102 interp_mem.data[segment.offset..end].copy_from_slice(&segment.data[..]);
103 }
104 memories[memory] = interp_mem;
105 }
106
107 let mut tables = PerEntity::default();
108 for (table, data) in module.tables.entries() {
109 let interp_table = InterpTable {
110 elements: data.func_elements.clone().unwrap_or(vec![]),
111 };
112 tables[table] = interp_table;
113 }
114
115 let mut globals = PerEntity::default();
116 for (global, data) in module.globals.entries() {
117 globals[global] = match data.ty {
118 Type::I32 => ConstVal::I32(data.value.unwrap_or(0) as u32),
119 Type::I64 => ConstVal::I64(data.value.unwrap_or(0)),
120 Type::F32 => ConstVal::F32(data.value.unwrap_or(0) as u32),
121 Type::F64 => ConstVal::F64(data.value.unwrap_or(0)),
122 _ => unimplemented!(),
123 };
124 }
125
126 Ok(InterpContext {
127 memories,
128 tables,
129 globals,
130 fuel: u64::MAX,
131 })
132 }
133
134 pub fn call(&mut self, module: &Module<'_>, func: Func, args: &[ConstVal]) -> InterpResult {
137 let body = match &module.funcs[func] {
138 FuncDecl::Lazy(..) => panic!("Un-expanded function"),
139 FuncDecl::Compiled(..) => panic!("Already-compiled function"),
140 FuncDecl::Import(..) => {
141 let import = &module.imports[func.index()];
142 assert_eq!(import.kind, ImportKind::Func(func));
143 return self.call_import(&import.name[..], args);
144 }
145 FuncDecl::Body(_, _, body) => body,
146 FuncDecl::None => panic!("FuncDecl::None in call()"),
147 };
148
149 log::trace!(
150 "Interp: entering func {}:\n{}\n",
151 func,
152 body.display_verbose("| ", Some(module))
153 );
154 log::trace!("args: {:?}", args);
155
156 let mut frame = InterpStackFrame {
157 func,
158 cur_block: body.entry,
159 values: HashMap::new(),
160 };
161
162 for (&arg, &(_, blockparam)) in args.iter().zip(body.blocks[body.entry].params.iter()) {
163 log::trace!("Entry block param {} gets arg value {:?}", blockparam, arg);
164 frame.values.insert(blockparam, smallvec![arg]);
165 }
166
167 loop {
168 self.fuel -= 1;
169 if self.fuel == 0 {
170 return InterpResult::OutOfFuel;
171 }
172
173 log::trace!("Interpreting block {}", frame.cur_block);
174 for (inst_idx, &inst) in body.blocks[frame.cur_block].insts.iter().enumerate() {
175 log::trace!("Evaluating inst {}", inst);
176 let result = match &body.values[inst] {
177 &ValueDef::Alias(_) => smallvec![],
178 &ValueDef::PickOutput(val, idx, _) => {
179 let val = body.resolve_alias(val);
180 smallvec![frame.values.get(&val).unwrap()[idx as usize]]
181 }
182 &ValueDef::Operator(Operator::Call { function_index }, args, _) => {
183 let args = body.arg_pool[args]
184 .iter()
185 .map(|&arg| {
186 let arg = body.resolve_alias(arg);
187 let multivalue = frame.values.get(&arg).unwrap();
188 assert_eq!(multivalue.len(), 1);
189 multivalue[0]
190 })
191 .collect::<Vec<_>>();
192 let result = self.call(module, function_index, &args[..]);
193 match result {
194 InterpResult::Ok(vals) => vals,
195 _ => return result,
196 }
197 }
198 &ValueDef::Operator(Operator::CallIndirect { table_index, .. }, args, _) => {
199 let args = body.arg_pool[args]
200 .iter()
201 .map(|&arg| {
202 let arg = body.resolve_alias(arg);
203 let multivalue = frame.values.get(&arg).unwrap();
204 assert_eq!(multivalue.len(), 1);
205 multivalue[0]
206 })
207 .collect::<Vec<_>>();
208 let idx = args.last().unwrap().as_u32().unwrap() as usize;
209 let func = self.tables[table_index].elements[idx];
210 let result = self.call(module, func, &args[..args.len() - 1]);
211 match result {
212 InterpResult::Ok(vals) => vals,
213 _ => return result,
214 }
215 }
216 &ValueDef::Operator(ref op, args, _) => {
217 let args = body.arg_pool[args]
218 .iter()
219 .map(|&arg| {
220 let arg = body.resolve_alias(arg);
221 let multivalue = frame
222 .values
223 .get(&arg)
224 .ok_or_else(|| format!("Unset SSA value: {}", arg))
225 .unwrap();
226 assert_eq!(multivalue.len(), 1);
227 multivalue[0]
228 })
229 .collect::<Vec<_>>();
230 let result = match const_eval(op, &args[..], Some(self)) {
231 Some(result) => result,
232 None => {
233 log::trace!("const_eval failed on {:?} args {:?}", op, args);
234 return InterpResult::Trap(
235 frame.func,
236 frame.cur_block,
237 inst_idx as u32,
238 );
239 }
240 };
241 smallvec![result]
242 }
243 &ValueDef::None | &ValueDef::Placeholder(..) | &ValueDef::BlockParam(..) => {
244 unreachable!();
245 }
246 };
247
248 log::trace!("Inst {} gets result {:?}", inst, result);
249 frame.values.insert(inst, result);
250 }
251
252 match &body.blocks[frame.cur_block].terminator {
253 &Terminator::None => {
254 return InterpResult::Trap(frame.func, frame.cur_block, u32::MAX)
255 }
256 &Terminator::Unreachable => {
257 return InterpResult::Trap(frame.func, frame.cur_block, u32::MAX)
258 }
259 &Terminator::Br { ref target } => {
260 frame.apply_target(body, target);
261 }
262 &Terminator::CondBr {
263 cond,
264 ref if_true,
265 ref if_false,
266 } => {
267 let cond = body.resolve_alias(cond);
268 let cond = frame.values.get(&cond).unwrap();
269 let cond = cond[0].as_u32().unwrap() != 0;
270 if cond {
271 frame.apply_target(body, if_true);
272 } else {
273 frame.apply_target(body, if_false);
274 }
275 }
276 &Terminator::Select {
277 value,
278 ref targets,
279 ref default,
280 } => {
281 let value = body.resolve_alias(value);
282 let value = frame.values.get(&value).unwrap();
283 let value = value[0].as_u32().unwrap() as usize;
284 if value < targets.len() {
285 frame.apply_target(body, &targets[value]);
286 } else {
287 frame.apply_target(body, default);
288 }
289 }
290 &Terminator::Return { ref values } => {
291 let values = values
292 .iter()
293 .map(|&value| {
294 let value = body.resolve_alias(value);
295 frame.values.get(&value).unwrap()[0]
296 })
297 .collect();
298 log::trace!("returning from {}: {:?}", func, values);
299 return InterpResult::Ok(values);
300 }
301 }
302 }
303 }
304
305 fn call_import(&mut self, name: &str, args: &[ConstVal]) -> InterpResult {
306 panic!("Unknown import: {} with args: {:?}", name, args);
307 }
308}
309
310impl InterpStackFrame {
311 fn apply_target(&mut self, body: &FunctionBody, target: &BlockTarget) {
312 let args = target
314 .args
315 .iter()
316 .map(|&arg| {
317 let arg = body.resolve_alias(arg);
318 self.values.get(&arg).unwrap().clone()
319 })
320 .collect::<Vec<_>>();
321 log::trace!("taking target {:?} with args {:?}", target, args);
322 for (arg, &(_, param)) in args
324 .into_iter()
325 .zip(body.blocks[target.block].params.iter())
326 {
327 log::trace!("setting blockparam {} to {:?}", param, arg);
328 self.values.insert(param, arg);
329 }
330 self.cur_block = target.block;
332 }
333}
334
335impl ConstVal {
336 pub fn as_u32(self) -> Option<u32> {
337 match self {
338 Self::I32(x) => Some(x),
339 _ => None,
340 }
341 }
342
343 pub fn meet(a: Option<ConstVal>, b: Option<ConstVal>) -> Option<ConstVal> {
344 match (a, b) {
345 (None, None) => None,
346 (Some(a), None) | (None, Some(a)) => Some(a),
347 (Some(a), Some(b)) if a == b => Some(a),
348 _ => Some(ConstVal::None),
349 }
350 }
351}
352
353pub fn const_eval(
356 op: &Operator,
357 vals: &[ConstVal],
358 ctx: Option<&mut InterpContext>,
359) -> Option<ConstVal> {
360 match (op, vals) {
361 (Operator::I32Const { value }, []) => Some(ConstVal::I32(*value)),
362 (Operator::I64Const { value }, []) => Some(ConstVal::I64(*value)),
363 (Operator::F32Const { value }, []) => Some(ConstVal::F32(*value)),
364 (Operator::F64Const { value }, []) => Some(ConstVal::F64(*value)),
365 (Operator::I32Eqz, [ConstVal::I32(a)]) => Some(ConstVal::I32(if *a == 0 { 1 } else { 0 })),
366 (Operator::I32Eq, [ConstVal::I32(a), ConstVal::I32(b)]) => {
367 Some(ConstVal::I32(if a == b { 1 } else { 0 }))
368 }
369 (Operator::I32Ne, [ConstVal::I32(a), ConstVal::I32(b)]) => {
370 Some(ConstVal::I32(if a != b { 1 } else { 0 }))
371 }
372 (Operator::I32LtS, [ConstVal::I32(a), ConstVal::I32(b)]) => {
373 Some(ConstVal::I32(if (*a as i32) < (*b as i32) { 1 } else { 0 }))
374 }
375 (Operator::I32LtU, [ConstVal::I32(a), ConstVal::I32(b)]) => {
376 Some(ConstVal::I32(if a < b { 1 } else { 0 }))
377 }
378 (Operator::I32GtS, [ConstVal::I32(a), ConstVal::I32(b)]) => {
379 Some(ConstVal::I32(if (*a as i32) > (*b as i32) { 1 } else { 0 }))
380 }
381 (Operator::I32GtU, [ConstVal::I32(a), ConstVal::I32(b)]) => {
382 Some(ConstVal::I32(if a > b { 1 } else { 0 }))
383 }
384 (Operator::I32LeS, [ConstVal::I32(a), ConstVal::I32(b)]) => {
385 Some(ConstVal::I32(if (*a as i32) <= (*b as i32) {
386 1
387 } else {
388 0
389 }))
390 }
391 (Operator::I32LeU, [ConstVal::I32(a), ConstVal::I32(b)]) => {
392 Some(ConstVal::I32(if a <= b { 1 } else { 0 }))
393 }
394 (Operator::I32GeS, [ConstVal::I32(a), ConstVal::I32(b)]) => {
395 Some(ConstVal::I32(if (*a as i32) >= (*b as i32) {
396 1
397 } else {
398 0
399 }))
400 }
401 (Operator::I32GeU, [ConstVal::I32(a), ConstVal::I32(b)]) => {
402 Some(ConstVal::I32(if a >= b { 1 } else { 0 }))
403 }
404 (Operator::I64Eqz, [ConstVal::I64(a)]) => Some(ConstVal::I32(if *a == 0 { 1 } else { 0 })),
405 (Operator::I64Eq, [ConstVal::I64(a), ConstVal::I64(b)]) => {
406 Some(ConstVal::I32(if a == b { 1 } else { 0 }))
407 }
408 (Operator::I64Ne, [ConstVal::I64(a), ConstVal::I64(b)]) => {
409 Some(ConstVal::I32(if a != b { 1 } else { 0 }))
410 }
411 (Operator::I64LtS, [ConstVal::I64(a), ConstVal::I64(b)]) => {
412 Some(ConstVal::I32(if (*a as i64) < (*b as i64) { 1 } else { 0 }))
413 }
414 (Operator::I64LtU, [ConstVal::I64(a), ConstVal::I64(b)]) => {
415 Some(ConstVal::I32(if a < b { 1 } else { 0 }))
416 }
417 (Operator::I64GtS, [ConstVal::I64(a), ConstVal::I64(b)]) => {
418 Some(ConstVal::I32(if (*a as i64) > (*b as i64) { 1 } else { 0 }))
419 }
420 (Operator::I64GtU, [ConstVal::I64(a), ConstVal::I64(b)]) => {
421 Some(ConstVal::I32(if a > b { 1 } else { 0 }))
422 }
423 (Operator::I64LeS, [ConstVal::I64(a), ConstVal::I64(b)]) => {
424 Some(ConstVal::I32(if (*a as i64) <= (*b as i64) {
425 1
426 } else {
427 0
428 }))
429 }
430 (Operator::I64LeU, [ConstVal::I64(a), ConstVal::I64(b)]) => {
431 Some(ConstVal::I32(if a <= b { 1 } else { 0 }))
432 }
433 (Operator::I64GeS, [ConstVal::I64(a), ConstVal::I64(b)]) => {
434 Some(ConstVal::I32(if (*a as i64) >= (*b as i64) {
435 1
436 } else {
437 0
438 }))
439 }
440 (Operator::I64GeU, [ConstVal::I64(a), ConstVal::I64(b)]) => {
441 Some(ConstVal::I32(if a >= b { 1 } else { 0 }))
442 }
443
444 (Operator::F32Eq, [ConstVal::F32(a), ConstVal::F32(b)]) => {
445 Some(ConstVal::I32(if f32::from_bits(*a) == f32::from_bits(*b) {
446 1
447 } else {
448 0
449 }))
450 }
451 (Operator::F32Ne, [ConstVal::F32(a), ConstVal::F32(b)]) => {
452 Some(ConstVal::I32(if f32::from_bits(*a) != f32::from_bits(*b) {
453 1
454 } else {
455 0
456 }))
457 }
458 (Operator::F32Lt, [ConstVal::F32(a), ConstVal::F32(b)]) => {
459 Some(ConstVal::I32(if f32::from_bits(*a) < f32::from_bits(*b) {
460 1
461 } else {
462 0
463 }))
464 }
465 (Operator::F32Gt, [ConstVal::F32(a), ConstVal::F32(b)]) => {
466 Some(ConstVal::I32(if f32::from_bits(*a) > f32::from_bits(*b) {
467 1
468 } else {
469 0
470 }))
471 }
472 (Operator::F32Le, [ConstVal::F32(a), ConstVal::F32(b)]) => {
473 Some(ConstVal::I32(if f32::from_bits(*a) <= f32::from_bits(*b) {
474 1
475 } else {
476 0
477 }))
478 }
479 (Operator::F32Ge, [ConstVal::F32(a), ConstVal::F32(b)]) => {
480 Some(ConstVal::I32(if f32::from_bits(*a) >= f32::from_bits(*b) {
481 1
482 } else {
483 0
484 }))
485 }
486
487 (Operator::F64Eq, [ConstVal::F64(a), ConstVal::F64(b)]) => {
488 Some(ConstVal::I32(if f64::from_bits(*a) == f64::from_bits(*b) {
489 1
490 } else {
491 0
492 }))
493 }
494 (Operator::F64Ne, [ConstVal::F64(a), ConstVal::F64(b)]) => {
495 Some(ConstVal::I32(if f64::from_bits(*a) != f64::from_bits(*b) {
496 1
497 } else {
498 0
499 }))
500 }
501 (Operator::F64Lt, [ConstVal::F64(a), ConstVal::F64(b)]) => {
502 Some(ConstVal::I32(if f64::from_bits(*a) < f64::from_bits(*b) {
503 1
504 } else {
505 0
506 }))
507 }
508 (Operator::F64Gt, [ConstVal::F64(a), ConstVal::F64(b)]) => {
509 Some(ConstVal::I32(if f64::from_bits(*a) > f64::from_bits(*b) {
510 1
511 } else {
512 0
513 }))
514 }
515 (Operator::F64Le, [ConstVal::F64(a), ConstVal::F64(b)]) => {
516 Some(ConstVal::I32(if f64::from_bits(*a) <= f64::from_bits(*b) {
517 1
518 } else {
519 0
520 }))
521 }
522 (Operator::F64Ge, [ConstVal::F64(a), ConstVal::F64(b)]) => {
523 Some(ConstVal::I32(if f64::from_bits(*a) >= f64::from_bits(*b) {
524 1
525 } else {
526 0
527 }))
528 }
529
530 (Operator::I32Clz, [ConstVal::I32(x)]) => Some(ConstVal::I32(x.leading_zeros())),
531 (Operator::I32Ctz, [ConstVal::I32(x)]) => Some(ConstVal::I32(x.trailing_zeros())),
532 (Operator::I32Popcnt, [ConstVal::I32(x)]) => Some(ConstVal::I32(x.count_ones())),
533
534 (Operator::I32Add, [ConstVal::I32(a), ConstVal::I32(b)]) => {
535 Some(ConstVal::I32(a.wrapping_add(*b)))
536 }
537 (Operator::I32Sub, [ConstVal::I32(a), ConstVal::I32(b)]) => {
538 Some(ConstVal::I32(a.wrapping_sub(*b)))
539 }
540 (Operator::I32Mul, [ConstVal::I32(a), ConstVal::I32(b)]) => {
541 Some(ConstVal::I32(a.wrapping_mul(*b)))
542 }
543 (Operator::I32DivU, [ConstVal::I32(a), ConstVal::I32(b)]) => {
544 Some(ConstVal::I32(a.checked_div(*b)?))
545 }
546 (Operator::I32DivS, [ConstVal::I32(a), ConstVal::I32(b)]) => {
547 Some(ConstVal::I32((*a as i32).checked_div(*b as i32)? as u32))
548 }
549 (Operator::I32RemU, [ConstVal::I32(a), ConstVal::I32(b)]) => {
550 Some(ConstVal::I32(a.checked_rem(*b)?))
551 }
552 (Operator::I32RemS, [ConstVal::I32(a), ConstVal::I32(b)]) => {
553 Some(ConstVal::I32((*a as i32).checked_rem(*b as i32)? as u32))
554 }
555 (Operator::I32And, [ConstVal::I32(a), ConstVal::I32(b)]) => Some(ConstVal::I32(a & b)),
556 (Operator::I32Or, [ConstVal::I32(a), ConstVal::I32(b)]) => Some(ConstVal::I32(a | b)),
557 (Operator::I32Xor, [ConstVal::I32(a), ConstVal::I32(b)]) => Some(ConstVal::I32(a ^ b)),
558 (Operator::I32Shl, [ConstVal::I32(a), ConstVal::I32(b)]) => {
559 Some(ConstVal::I32(a.wrapping_shl(*b)))
560 }
561 (Operator::I32ShrS, [ConstVal::I32(a), ConstVal::I32(b)]) => {
562 Some(ConstVal::I32((*a as i32).wrapping_shr(*b) as u32))
563 }
564 (Operator::I32ShrU, [ConstVal::I32(a), ConstVal::I32(b)]) => {
565 Some(ConstVal::I32(a.wrapping_shr(*b)))
566 }
567 (Operator::I32Rotl, [ConstVal::I32(a), ConstVal::I32(b)]) => {
568 Some(ConstVal::I32(a.rotate_left(*b & 0x1f)))
569 }
570 (Operator::I32Rotr, [ConstVal::I32(a), ConstVal::I32(b)]) => {
571 Some(ConstVal::I32(a.rotate_right(*b & 0x1f)))
572 }
573
574 (Operator::I64Clz, [ConstVal::I64(x)]) => Some(ConstVal::I64(x.leading_zeros() as u64)),
575 (Operator::I64Ctz, [ConstVal::I64(x)]) => Some(ConstVal::I64(x.trailing_zeros() as u64)),
576 (Operator::I64Popcnt, [ConstVal::I64(x)]) => Some(ConstVal::I64(x.count_ones() as u64)),
577
578 (Operator::I64Add, [ConstVal::I64(a), ConstVal::I64(b)]) => {
579 Some(ConstVal::I64(a.wrapping_add(*b)))
580 }
581 (Operator::I64Sub, [ConstVal::I64(a), ConstVal::I64(b)]) => {
582 Some(ConstVal::I64(a.wrapping_sub(*b)))
583 }
584 (Operator::I64Mul, [ConstVal::I64(a), ConstVal::I64(b)]) => {
585 Some(ConstVal::I64(a.wrapping_mul(*b)))
586 }
587 (Operator::I64DivU, [ConstVal::I64(a), ConstVal::I64(b)]) => {
588 Some(ConstVal::I64(a.checked_div(*b)?))
589 }
590 (Operator::I64DivS, [ConstVal::I64(a), ConstVal::I64(b)]) => {
591 Some(ConstVal::I64((*a as i64).checked_div(*b as i64)? as u64))
592 }
593 (Operator::I64RemU, [ConstVal::I64(a), ConstVal::I64(b)]) => {
594 Some(ConstVal::I64(a.checked_rem(*b)?))
595 }
596 (Operator::I64RemS, [ConstVal::I64(a), ConstVal::I64(b)]) => {
597 Some(ConstVal::I64((*a as i64).checked_rem(*b as i64)? as u64))
598 }
599 (Operator::I64And, [ConstVal::I64(a), ConstVal::I64(b)]) => Some(ConstVal::I64(a & b)),
600 (Operator::I64Or, [ConstVal::I64(a), ConstVal::I64(b)]) => Some(ConstVal::I64(a | b)),
601 (Operator::I64Xor, [ConstVal::I64(a), ConstVal::I64(b)]) => Some(ConstVal::I64(a ^ b)),
602 (Operator::I64Shl, [ConstVal::I64(a), ConstVal::I64(b)]) => {
603 Some(ConstVal::I64(a.wrapping_shl(*b as u32)))
604 }
605 (Operator::I64ShrS, [ConstVal::I64(a), ConstVal::I64(b)]) => {
606 Some(ConstVal::I64((*a as i64).wrapping_shr(*b as u32) as u64))
607 }
608 (Operator::I64ShrU, [ConstVal::I64(a), ConstVal::I64(b)]) => {
609 Some(ConstVal::I64(a.wrapping_shr(*b as u32)))
610 }
611 (Operator::I64Rotl, [ConstVal::I64(a), ConstVal::I64(b)]) => {
612 Some(ConstVal::I64(a.rotate_left((*b as u32) & 0x3f)))
613 }
614 (Operator::I64Rotr, [ConstVal::I64(a), ConstVal::I64(b)]) => {
615 Some(ConstVal::I64(a.rotate_right((*b as u32) & 0x3f)))
616 }
617
618 (Operator::F32Abs, [ConstVal::F32(a)]) => {
619 Some(ConstVal::F32(f32::from_bits(*a).abs().to_bits()))
620 }
621 (Operator::F32Neg, [ConstVal::F32(a)]) => {
622 Some(ConstVal::F32((-f32::from_bits(*a)).to_bits()))
623 }
624 (Operator::F32Ceil, [ConstVal::F32(a)]) => {
625 Some(ConstVal::F32(f32::from_bits(*a).ceil().to_bits()))
626 }
627 (Operator::F32Floor, [ConstVal::F32(a)]) => {
628 Some(ConstVal::F32(f32::from_bits(*a).floor().to_bits()))
629 }
630 (Operator::F32Trunc, [ConstVal::F32(a)]) => {
631 Some(ConstVal::F32(f32::from_bits(*a).trunc().to_bits()))
632 }
633 (Operator::F32Nearest, [ConstVal::F32(a)]) => Some(ConstVal::F32(
634 f32::from_bits(*a).round_ties_even().to_bits(),
635 )),
636 (Operator::F32Sqrt, [ConstVal::F32(a)]) => {
637 Some(ConstVal::F32(f32::from_bits(*a).sqrt().to_bits()))
638 }
639 (Operator::F32Add, [ConstVal::F32(a), ConstVal::F32(b)]) => Some(ConstVal::F32(
640 (f32::from_bits(*a) + f32::from_bits(*b)).to_bits(),
641 )),
642 (Operator::F32Sub, [ConstVal::F32(a), ConstVal::F32(b)]) => Some(ConstVal::F32(
643 (f32::from_bits(*a) - f32::from_bits(*b)).to_bits(),
644 )),
645 (Operator::F32Mul, [ConstVal::F32(a), ConstVal::F32(b)]) => Some(ConstVal::F32(
646 (f32::from_bits(*a) * f32::from_bits(*b)).to_bits(),
647 )),
648 (Operator::F32Div, [ConstVal::F32(a), ConstVal::F32(b)]) => Some(ConstVal::F32(
649 (f32::from_bits(*a) / f32::from_bits(*b)).to_bits(),
650 )),
651 (Operator::F32Min, [ConstVal::F32(a), ConstVal::F32(b)]) => Some(ConstVal::F32(
652 f32_min(f32::from_bits(*a), f32::from_bits(*b)).to_bits(),
653 )),
654 (Operator::F32Max, [ConstVal::F32(a), ConstVal::F32(b)]) => Some(ConstVal::F32(
655 f32_max(f32::from_bits(*a), f32::from_bits(*b)).to_bits(),
656 )),
657 (Operator::F32Copysign, [ConstVal::F32(a), ConstVal::F32(b)]) => Some(ConstVal::F32(
658 f32::copysign(f32::from_bits(*a), f32::from_bits(*b)).to_bits(),
659 )),
660
661 (Operator::F64Abs, [ConstVal::F64(a)]) => {
662 Some(ConstVal::F64(f64::from_bits(*a).abs().to_bits()))
663 }
664 (Operator::F64Neg, [ConstVal::F64(a)]) => {
665 Some(ConstVal::F64((-f64::from_bits(*a)).to_bits()))
666 }
667 (Operator::F64Ceil, [ConstVal::F64(a)]) => {
668 Some(ConstVal::F64(f64::from_bits(*a).ceil().to_bits()))
669 }
670 (Operator::F64Floor, [ConstVal::F64(a)]) => {
671 Some(ConstVal::F64(f64::from_bits(*a).floor().to_bits()))
672 }
673 (Operator::F64Trunc, [ConstVal::F64(a)]) => {
674 Some(ConstVal::F64(f64::from_bits(*a).trunc().to_bits()))
675 }
676 (Operator::F64Nearest, [ConstVal::F64(a)]) => Some(ConstVal::F64(
677 f64::from_bits(*a).round_ties_even().to_bits(),
678 )),
679 (Operator::F64Sqrt, [ConstVal::F64(a)]) => {
680 Some(ConstVal::F64(f64::from_bits(*a).sqrt().to_bits()))
681 }
682 (Operator::F64Add, [ConstVal::F64(a), ConstVal::F64(b)]) => Some(ConstVal::F64(
683 (f64::from_bits(*a) + f64::from_bits(*b)).to_bits(),
684 )),
685 (Operator::F64Sub, [ConstVal::F64(a), ConstVal::F64(b)]) => Some(ConstVal::F64(
686 (f64::from_bits(*a) - f64::from_bits(*b)).to_bits(),
687 )),
688 (Operator::F64Mul, [ConstVal::F64(a), ConstVal::F64(b)]) => Some(ConstVal::F64(
689 (f64::from_bits(*a) * f64::from_bits(*b)).to_bits(),
690 )),
691 (Operator::F64Div, [ConstVal::F64(a), ConstVal::F64(b)]) => Some(ConstVal::F64(
692 (f64::from_bits(*a) / f64::from_bits(*b)).to_bits(),
693 )),
694 (Operator::F64Min, [ConstVal::F64(a), ConstVal::F64(b)]) => Some(ConstVal::F64(
695 f64_min(f64::from_bits(*a), f64::from_bits(*b)).to_bits(),
696 )),
697 (Operator::F64Max, [ConstVal::F64(a), ConstVal::F64(b)]) => Some(ConstVal::F64(
698 f64_max(f64::from_bits(*a), f64::from_bits(*b)).to_bits(),
699 )),
700 (Operator::F64Copysign, [ConstVal::F64(a), ConstVal::F64(b)]) => Some(ConstVal::F64(
701 f64::copysign(f64::from_bits(*a), f64::from_bits(*b)).to_bits(),
702 )),
703
704 (Operator::I32WrapI64, [ConstVal::I64(a)]) => Some(ConstVal::I32(*a as u32)),
705
706 (Operator::I32TruncF32S, [ConstVal::F32(a)]) => {
707 let a = f32::from_bits(*a);
708 if a >= (i32::MIN as f32) && a <= (i32::MAX as f32) {
709 Some(ConstVal::I32(a as i32 as u32))
710 } else {
711 None
712 }
713 }
714 (Operator::I32TruncF32U, [ConstVal::F32(a)]) => {
715 let a = f32::from_bits(*a);
716 if a >= 0.0 && a <= (u32::MAX as f32) {
717 Some(ConstVal::I32(a as u32))
718 } else {
719 None
720 }
721 }
722 (Operator::I32TruncF64S, [ConstVal::F64(a)]) => {
723 let a = f64::from_bits(*a);
724 if a >= (i32::MIN as f64) && a <= (i32::MAX as f64) {
725 Some(ConstVal::I32(a as i32 as u32))
726 } else {
727 None
728 }
729 }
730 (Operator::I32TruncF64U, [ConstVal::F64(a)]) => {
731 let a = f64::from_bits(*a);
732 if a >= 0.0 && a <= (u32::MAX as f64) {
733 Some(ConstVal::I32(a as u32))
734 } else {
735 None
736 }
737 }
738
739 (Operator::I64TruncF32S, [ConstVal::F32(a)]) => {
740 let a = f32::from_bits(*a);
741 if a >= (i64::MIN as f32) && a <= (i64::MAX as f32) {
742 Some(ConstVal::I64(a as i64 as u64))
743 } else {
744 None
745 }
746 }
747 (Operator::I64TruncF32U, [ConstVal::F32(a)]) => {
748 let a = f32::from_bits(*a);
749 if a >= 0.0 && a <= (u64::MAX as f32) {
750 Some(ConstVal::I64(a as u64))
751 } else {
752 None
753 }
754 }
755 (Operator::I64TruncF64S, [ConstVal::F64(a)]) => {
756 let a = f64::from_bits(*a);
757 if a >= (i64::MIN as f64) && a <= (i64::MAX as f64) {
758 Some(ConstVal::I64(a as i64 as u64))
759 } else {
760 None
761 }
762 }
763 (Operator::I64TruncF64U, [ConstVal::F64(a)]) => {
764 let a = f64::from_bits(*a);
765 if a >= 0.0 && a <= (u64::MAX as f64) {
766 Some(ConstVal::I64(a as u64))
767 } else {
768 None
769 }
770 }
771
772 (Operator::I32TruncSatF32S, [ConstVal::F32(a)]) => {
773 let a = f32::from_bits(*a);
774 Some(ConstVal::I32(if a.is_nan() {
775 0
776 } else {
777 a.min(i32::MAX as f32).max(i32::MIN as f32) as i32 as u32
778 }))
779 }
780 (Operator::I32TruncSatF32U, [ConstVal::F32(a)]) => {
781 let a = f32::from_bits(*a);
782 Some(ConstVal::I32(if a.is_nan() {
783 0
784 } else {
785 a.min(u32::MAX as f32).max(0.0) as u32
786 }))
787 }
788 (Operator::I32TruncSatF64S, [ConstVal::F64(a)]) => {
789 let a = f64::from_bits(*a);
790 Some(ConstVal::I32(if a.is_nan() {
791 0
792 } else {
793 a.min(i32::MAX as f64).max(i32::MIN as f64) as i32 as u32
794 }))
795 }
796 (Operator::I32TruncSatF64U, [ConstVal::F64(a)]) => {
797 let a = f64::from_bits(*a);
798 Some(ConstVal::I32(if a.is_nan() {
799 0
800 } else {
801 a.min(u32::MAX as f64).max(0.0) as u32
802 }))
803 }
804
805 (Operator::I64TruncSatF32S, [ConstVal::F32(a)]) => {
806 let a = f32::from_bits(*a);
807 Some(ConstVal::I64(if a.is_nan() {
808 0
809 } else {
810 a.min(i64::MAX as f32).max(i64::MIN as f32) as i64 as u64
811 }))
812 }
813 (Operator::I64TruncSatF32U, [ConstVal::F32(a)]) => {
814 let a = f32::from_bits(*a);
815 Some(ConstVal::I64(if a.is_nan() {
816 0
817 } else {
818 a.min(u64::MAX as f32).max(0.0) as u64
819 }))
820 }
821 (Operator::I64TruncSatF64S, [ConstVal::F64(a)]) => {
822 let a = f64::from_bits(*a);
823 Some(ConstVal::I64(if a.is_nan() {
824 0
825 } else {
826 a.min(i64::MAX as f64).max(i64::MIN as f64) as i64 as u64
827 }))
828 }
829 (Operator::I64TruncSatF64U, [ConstVal::F64(a)]) => {
830 let a = f64::from_bits(*a);
831 Some(ConstVal::I64(if a.is_nan() {
832 0
833 } else {
834 a.min(u64::MAX as f64).max(0.0) as u64
835 }))
836 }
837
838 (Operator::F32ConvertI32S, [ConstVal::I32(a)]) => {
839 Some(ConstVal::F32((*a as i32 as f32).to_bits()))
840 }
841 (Operator::F32ConvertI32U, [ConstVal::I32(a)]) => {
842 Some(ConstVal::F32((*a as f32).to_bits()))
843 }
844 (Operator::F32ConvertI64S, [ConstVal::I64(a)]) => {
845 Some(ConstVal::F32((*a as i64 as f32).to_bits()))
846 }
847 (Operator::F32ConvertI64U, [ConstVal::I64(a)]) => {
848 Some(ConstVal::F32((*a as f32).to_bits()))
849 }
850
851 (Operator::F64ConvertI32S, [ConstVal::I32(a)]) => {
852 Some(ConstVal::F64((*a as i32 as f64).to_bits()))
853 }
854 (Operator::F64ConvertI32U, [ConstVal::I32(a)]) => {
855 Some(ConstVal::F64((*a as f64).to_bits()))
856 }
857 (Operator::F64ConvertI64S, [ConstVal::I64(a)]) => {
858 Some(ConstVal::F64((*a as i64 as f64).to_bits()))
859 }
860 (Operator::F64ConvertI64U, [ConstVal::I64(a)]) => {
861 Some(ConstVal::F64((*a as f64).to_bits()))
862 }
863
864 (Operator::F32DemoteF64, [ConstVal::F64(a)]) => {
865 Some(ConstVal::F32((f64::from_bits(*a) as f32).to_bits()))
866 }
867 (Operator::F64PromoteF32, [ConstVal::F32(a)]) => {
868 Some(ConstVal::F64((f32::from_bits(*a) as f64).to_bits()))
869 }
870
871 (Operator::F32ReinterpretI32, [ConstVal::I32(a)]) => Some(ConstVal::F32(*a)),
872 (Operator::F64ReinterpretI64, [ConstVal::I64(a)]) => Some(ConstVal::F64(*a)),
873 (Operator::I32ReinterpretF32, [ConstVal::F32(a)]) => Some(ConstVal::I32(*a)),
874 (Operator::I64ReinterpretF64, [ConstVal::F64(a)]) => Some(ConstVal::I64(*a)),
875
876 (Operator::I32Extend8S, [ConstVal::I32(a)]) => Some(ConstVal::I32(*a as i8 as i32 as u32)),
877 (Operator::I32Extend16S, [ConstVal::I32(a)]) => {
878 Some(ConstVal::I32(*a as i16 as i32 as u32))
879 }
880 (Operator::I64Extend8S, [ConstVal::I64(a)]) => Some(ConstVal::I64(*a as i8 as i64 as u64)),
881 (Operator::I64Extend16S, [ConstVal::I64(a)]) => {
882 Some(ConstVal::I64(*a as i16 as i64 as u64))
883 }
884 (Operator::I64Extend32S, [ConstVal::I64(a)]) => {
885 Some(ConstVal::I64(*a as i32 as i64 as u64))
886 }
887 (Operator::I64ExtendI32S, [ConstVal::I32(a)]) => {
888 Some(ConstVal::I64(*a as i32 as i64 as u64))
889 }
890 (Operator::I64ExtendI32U, [ConstVal::I32(a)]) => Some(ConstVal::I64(*a as u64)),
891
892 (Operator::Select, [x, y, ConstVal::I32(k)]) => Some(if *k != 0 { *x } else { *y }),
893 (Operator::TypedSelect { .. }, [x, y, ConstVal::I32(k)]) => {
894 Some(if *k != 0 { *x } else { *y })
895 }
896
897 (Operator::GlobalGet { global_index }, []) => {
898 ctx.map(|global| global.globals[*global_index])
899 }
900 (Operator::GlobalSet { global_index }, [x]) => ctx.map(|global| {
901 global.globals[*global_index] = *x;
902 ConstVal::None
903 }),
904
905 (Operator::TableGet { .. }, _)
906 | (Operator::TableSet { .. }, _)
907 | (Operator::TableGrow { .. }, _) => None,
908
909 (Operator::TableSize { table_index }, []) => {
910 ctx.map(|global| ConstVal::I32(global.tables[*table_index].elements.len() as u32))
911 }
912
913 (Operator::MemorySize { mem }, []) => {
914 ctx.map(|global| ConstVal::I32((global.memories[*mem].data.len() / WASM_PAGE) as u32))
915 }
916
917 (Operator::MemoryGrow { mem }, [ConstVal::I32(amount)]) => ctx.and_then(|global| {
918 let cur_pages = global.memories[*mem].data.len() / WASM_PAGE;
919 let new_pages = cur_pages + (*amount as usize);
920 if new_pages > global.memories[*mem].max_pages || new_pages > MAX_PAGES {
921 None
922 } else {
923 global.memories[*mem].data.resize(new_pages * WASM_PAGE, 0);
924 Some(ConstVal::I32(cur_pages as u32))
925 }
926 }),
927
928 (Operator::Nop, []) => Some(ConstVal::None),
929 (Operator::Unreachable, []) => None,
930
931 (Operator::I32Load { memory }, [ConstVal::I32(addr)]) => ctx.and_then(|global| {
932 let addr = addr.checked_add(memory.offset)?;
933 if addr.checked_add(4)? > global.memories[memory.memory].data.len() as u32 {
934 return None;
935 }
936 Some(ConstVal::I32(read_u32(
937 &global.memories[memory.memory],
938 addr,
939 )))
940 }),
941 (Operator::I64Load { memory }, [ConstVal::I32(addr)]) => ctx.and_then(|global| {
942 let addr = addr.checked_add(memory.offset)?;
943 if addr.checked_add(8)? > global.memories[memory.memory].data.len() as u32 {
944 return None;
945 }
946 Some(ConstVal::I64(read_u64(
947 &global.memories[memory.memory],
948 addr,
949 )))
950 }),
951 (Operator::F32Load { memory }, [ConstVal::I32(addr)]) => ctx.and_then(|global| {
952 let addr = addr.checked_add(memory.offset)?;
953 if addr.checked_add(4)? > global.memories[memory.memory].data.len() as u32 {
954 return None;
955 }
956 Some(ConstVal::F32(read_u32(
957 &global.memories[memory.memory],
958 addr,
959 )))
960 }),
961 (Operator::F64Load { memory }, [ConstVal::I32(addr)]) => ctx.and_then(|global| {
962 let addr = addr.checked_add(memory.offset)?;
963 if addr.checked_add(8)? > global.memories[memory.memory].data.len() as u32 {
964 return None;
965 }
966 Some(ConstVal::F64(read_u64(
967 &global.memories[memory.memory],
968 addr,
969 )))
970 }),
971 (Operator::I32Load8S { memory }, [ConstVal::I32(addr)]) => ctx.and_then(|global| {
972 let addr = addr.checked_add(memory.offset)?;
973 if addr.checked_add(1)? > global.memories[memory.memory].data.len() as u32 {
974 return None;
975 }
976 Some(ConstVal::I32(
977 read_u8(&global.memories[memory.memory], addr) as i8 as i32 as u32,
978 ))
979 }),
980 (Operator::I32Load8U { memory }, [ConstVal::I32(addr)]) => ctx.and_then(|global| {
981 let addr = addr.checked_add(memory.offset)?;
982 if addr.checked_add(4)? > global.memories[memory.memory].data.len() as u32 {
983 return None;
984 }
985 Some(ConstVal::I32(
986 read_u8(&global.memories[memory.memory], addr) as u32,
987 ))
988 }),
989 (Operator::I32Load16S { memory }, [ConstVal::I32(addr)]) => ctx.and_then(|global| {
990 let addr = addr.checked_add(memory.offset)?;
991 if addr.checked_add(2)? > global.memories[memory.memory].data.len() as u32 {
992 return None;
993 }
994 Some(ConstVal::I32(
995 read_u16(&global.memories[memory.memory], addr) as i16 as i32 as u32,
996 ))
997 }),
998 (Operator::I32Load16U { memory }, [ConstVal::I32(addr)]) => ctx.and_then(|global| {
999 let addr = addr.checked_add(memory.offset)?;
1000 if addr.checked_add(2)? > global.memories[memory.memory].data.len() as u32 {
1001 return None;
1002 }
1003 Some(ConstVal::I32(
1004 read_u16(&global.memories[memory.memory], addr) as u32,
1005 ))
1006 }),
1007 (Operator::I64Load8S { memory }, [ConstVal::I32(addr)]) => ctx.and_then(|global| {
1008 let addr = addr.checked_add(memory.offset)?;
1009 if addr.checked_add(1)? > global.memories[memory.memory].data.len() as u32 {
1010 return None;
1011 }
1012 Some(ConstVal::I64(
1013 read_u8(&global.memories[memory.memory], addr) as i8 as i64 as u64,
1014 ))
1015 }),
1016 (Operator::I64Load8U { memory }, [ConstVal::I32(addr)]) => ctx.and_then(|global| {
1017 let addr = addr.checked_add(memory.offset)?;
1018 if addr.checked_add(1)? > global.memories[memory.memory].data.len() as u32 {
1019 return None;
1020 }
1021 Some(ConstVal::I64(
1022 read_u8(&global.memories[memory.memory], addr) as u64,
1023 ))
1024 }),
1025 (Operator::I64Load16S { memory }, [ConstVal::I32(addr)]) => ctx.and_then(|global| {
1026 let addr = addr.checked_add(memory.offset)?;
1027 if addr.checked_add(2)? > global.memories[memory.memory].data.len() as u32 {
1028 return None;
1029 }
1030 Some(ConstVal::I64(
1031 read_u16(&global.memories[memory.memory], addr) as i16 as i64 as u64,
1032 ))
1033 }),
1034 (Operator::I64Load16U { memory }, [ConstVal::I32(addr)]) => ctx.and_then(|global| {
1035 let addr = addr.checked_add(memory.offset)?;
1036 if addr.checked_add(2)? > global.memories[memory.memory].data.len() as u32 {
1037 return None;
1038 }
1039 Some(ConstVal::I64(
1040 read_u16(&global.memories[memory.memory], addr) as u64,
1041 ))
1042 }),
1043 (Operator::I64Load32S { memory }, [ConstVal::I32(addr)]) => ctx.and_then(|global| {
1044 let addr = addr.checked_add(memory.offset)?;
1045 if addr.checked_add(4)? > global.memories[memory.memory].data.len() as u32 {
1046 return None;
1047 }
1048 Some(ConstVal::I64(
1049 read_u32(&global.memories[memory.memory], addr) as i32 as i64 as u64,
1050 ))
1051 }),
1052 (Operator::I64Load32U { memory }, [ConstVal::I32(addr)]) => ctx.and_then(|global| {
1053 let addr = addr.checked_add(memory.offset)?;
1054 if addr.checked_add(4)? > global.memories[memory.memory].data.len() as u32 {
1055 return None;
1056 }
1057 Some(ConstVal::I64(
1058 read_u32(&global.memories[memory.memory], addr) as u64,
1059 ))
1060 }),
1061 (Operator::I32Store { memory }, [ConstVal::I32(addr), ConstVal::I32(data)]) => ctx
1062 .and_then(|global| {
1063 let addr = addr.checked_add(memory.offset)?;
1064 if addr.checked_add(4)? > global.memories[memory.memory].data.len() as u32 {
1065 return None;
1066 }
1067 write_u32(&mut global.memories[memory.memory], addr, *data);
1068 Some(ConstVal::None)
1069 }),
1070 (Operator::I64Store { memory }, [ConstVal::I32(addr), ConstVal::I64(data)]) => ctx
1071 .and_then(|global| {
1072 let addr = addr.checked_add(memory.offset)?;
1073 if addr.checked_add(8)? > global.memories[memory.memory].data.len() as u32 {
1074 return None;
1075 }
1076 write_u64(&mut global.memories[memory.memory], addr, *data);
1077 Some(ConstVal::None)
1078 }),
1079 (Operator::I32Store8 { memory }, [ConstVal::I32(addr), ConstVal::I32(data)]) => ctx
1080 .and_then(|global| {
1081 let addr = addr.checked_add(memory.offset)?;
1082 if addr.checked_add(1)? > global.memories[memory.memory].data.len() as u32 {
1083 return None;
1084 }
1085 write_u8(&mut global.memories[memory.memory], addr, *data as u8);
1086 Some(ConstVal::None)
1087 }),
1088 (Operator::I32Store16 { memory }, [ConstVal::I32(addr), ConstVal::I32(data)]) => ctx
1089 .and_then(|global| {
1090 let addr = addr.checked_add(memory.offset)?;
1091 if addr.checked_add(2)? > global.memories[memory.memory].data.len() as u32 {
1092 return None;
1093 }
1094 write_u16(&mut global.memories[memory.memory], addr, *data as u16);
1095 Some(ConstVal::None)
1096 }),
1097 (Operator::I64Store8 { memory }, [ConstVal::I32(addr), ConstVal::I64(data)]) => ctx
1098 .and_then(|global| {
1099 let addr = addr.checked_add(memory.offset)?;
1100 if addr.checked_add(1)? > global.memories[memory.memory].data.len() as u32 {
1101 return None;
1102 }
1103 write_u8(&mut global.memories[memory.memory], addr, *data as u8);
1104 Some(ConstVal::None)
1105 }),
1106 (Operator::I64Store16 { memory }, [ConstVal::I32(addr), ConstVal::I64(data)]) => ctx
1107 .and_then(|global| {
1108 let addr = addr.checked_add(memory.offset)?;
1109 if addr.checked_add(2)? > global.memories[memory.memory].data.len() as u32 {
1110 return None;
1111 }
1112 write_u16(&mut global.memories[memory.memory], addr, *data as u16);
1113 Some(ConstVal::None)
1114 }),
1115 (Operator::I64Store32 { memory }, [ConstVal::I32(addr), ConstVal::I64(data)]) => ctx
1116 .and_then(|global| {
1117 let addr = addr.checked_add(memory.offset)?;
1118 if addr.checked_add(4)? > global.memories[memory.memory].data.len() as u32 {
1119 return None;
1120 }
1121 write_u32(&mut global.memories[memory.memory], addr, *data as u32);
1122 Some(ConstVal::None)
1123 }),
1124 (Operator::F32Store { memory }, [ConstVal::I32(addr), ConstVal::F32(data)]) => ctx
1125 .and_then(|global| {
1126 let addr = addr.checked_add(memory.offset)?;
1127 if addr.checked_add(4)? > global.memories[memory.memory].data.len() as u32 {
1128 return None;
1129 }
1130 write_u32(&mut global.memories[memory.memory], addr, *data);
1131 Some(ConstVal::None)
1132 }),
1133 (Operator::F64Store { memory }, [ConstVal::I32(addr), ConstVal::F64(data)]) => ctx
1134 .and_then(|global| {
1135 let addr = addr.checked_add(memory.offset)?;
1136 if addr.checked_add(8)? > global.memories[memory.memory].data.len() as u32 {
1137 return None;
1138 }
1139 write_u64(&mut global.memories[memory.memory], addr, *data);
1140 Some(ConstVal::None)
1141 }),
1142 (_, args) if args.iter().any(|&arg| arg == ConstVal::None) => None,
1143 _ => None,
1144 }
1145}
1146
1147pub(crate) fn read_u8(mem: &InterpMemory, addr: u32) -> u8 {
1148 let addr = addr as usize;
1149 mem.data[addr]
1150}
1151
1152pub(crate) fn read_u16(mem: &InterpMemory, addr: u32) -> u16 {
1153 use std::convert::TryInto;
1154 let addr = addr as usize;
1155 u16::from_le_bytes(mem.data[addr..(addr + 2)].try_into().unwrap())
1156}
1157
1158pub(crate) fn read_u32(mem: &InterpMemory, addr: u32) -> u32 {
1159 use std::convert::TryInto;
1160 let addr = addr as usize;
1161 u32::from_le_bytes(mem.data[addr..(addr + 4)].try_into().unwrap())
1162}
1163
1164pub(crate) fn read_u64(mem: &InterpMemory, addr: u32) -> u64 {
1165 use std::convert::TryInto;
1166 let addr = addr as usize;
1167 u64::from_le_bytes(mem.data[addr..(addr + 8)].try_into().unwrap())
1168}
1169
1170pub(crate) fn write_u8(mem: &mut InterpMemory, addr: u32, data: u8) {
1171 let addr = addr as usize;
1172 mem.data[addr] = data;
1173}
1174
1175pub(crate) fn write_u16(mem: &mut InterpMemory, addr: u32, data: u16) {
1176 let addr = addr as usize;
1177 mem.data[addr..(addr + 2)].copy_from_slice(&data.to_le_bytes()[..]);
1178}
1179
1180pub(crate) fn write_u32(mem: &mut InterpMemory, addr: u32, data: u32) {
1181 let addr = addr as usize;
1182 mem.data[addr..(addr + 4)].copy_from_slice(&data.to_le_bytes()[..]);
1183}
1184
1185pub(crate) fn write_u64(mem: &mut InterpMemory, addr: u32, data: u64) {
1186 let addr = addr as usize;
1187 mem.data[addr..(addr + 8)].copy_from_slice(&data.to_le_bytes()[..]);
1188}
1189
1190fn f32_min(a: f32, b: f32) -> f32 {
1195 if a < b {
1196 a
1197 } else if a > b {
1198 b
1199 } else if a == b {
1200 if a.is_sign_negative() && b.is_sign_positive() {
1201 a
1202 } else {
1203 b
1204 }
1205 } else {
1206 f32::NAN
1207 }
1208}
1209fn f32_max(a: f32, b: f32) -> f32 {
1210 if a < b {
1211 b
1212 } else if a > b {
1213 a
1214 } else if a == b {
1215 if a.is_sign_positive() && b.is_sign_negative() {
1216 a
1217 } else {
1218 b
1219 }
1220 } else {
1221 f32::NAN
1222 }
1223}
1224fn f64_min(a: f64, b: f64) -> f64 {
1225 if a < b {
1226 a
1227 } else if a > b {
1228 b
1229 } else if a == b {
1230 if a.is_sign_negative() && b.is_sign_positive() {
1231 a
1232 } else {
1233 b
1234 }
1235 } else {
1236 f64::NAN
1237 }
1238}
1239fn f64_max(a: f64, b: f64) -> f64 {
1240 if a < b {
1241 b
1242 } else if a > b {
1243 a
1244 } else if a == b {
1245 if a.is_sign_positive() && b.is_sign_negative() {
1246 a
1247 } else {
1248 b
1249 }
1250 } else {
1251 f64::NAN
1252 }
1253}