1use module::{Module, Function, Type, Export, Table};
2use prelude::{Box, Vec, String};
3use prelude::str;
4use opcode::Opcode;
5use int_ops;
6use value::Value;
7use prelude;
8use fp_ops;
9
10const PAGE_SIZE: usize = 65536;
11
12#[derive(Debug)]
13pub enum ExecuteError {
14 Custom(String),
15 OperandStackUnderflow,
16 NotImplemented,
17 TableIndexOutOfBound,
18 TypeIdxIndexOufOfBound,
19 FunctionIndexOutOfBound,
20 OpcodeIndexOutOfBound,
21 FrameIndexOutOfBound,
22 LocalIndexOutOfBound(usize),
23 GlobalIndexOutOfBound,
24 UnreachableExecuted,
25 AddrOutOfBound(u32, u32),
26 TypeMismatch,
27 ValueTypeMismatch,
28 ReturnTypeMismatch,
29 UndefinedTableEntry,
30 FunctionNotFound,
31 ExportEntryNotFound,
32 InvalidMemoryOperation,
33 FloatingPointException,
34 IndirectCallTypeMismatch(usize, Type, Type) }
36
37impl prelude::fmt::Display for ExecuteError {
38 fn fmt(&self, f: &mut prelude::fmt::Formatter) -> Result<(), prelude::fmt::Error> {
39 <Self as prelude::fmt::Debug>::fmt(self, f)
40 }
41}
42
43pub type ExecuteResult<T> = Result<T, ExecuteError>;
44
45pub struct VirtualMachine<'a> {
46 module: &'a Module,
47 rt: RuntimeInfo,
48 frames: Vec<Frame>,
49 native_functions: Vec<NativeFunctionInfo>
50}
51
52pub struct NativeFunctionInfo {
53 pub f: NativeFunction,
54 pub typeidx: usize
55}
56
57pub trait GlobalStateProvider {
58 fn get_memory(&self) -> &[u8];
59 fn get_memory_mut(&mut self) -> &mut [u8];
60 fn resolve(&self, module: &str, field: &str) -> Option<NativeEntry>;
61}
62
63pub type NativeEntry = Box<Fn(&mut GlobalStateProvider, &[Value]) -> ExecuteResult<Option<Value>> + 'static>;
64
65pub enum NativeFunction {
66 Uninitialized(String, String), Ready(NativeEntry)
68}
69
70pub trait NativeResolver: 'static {
71 fn resolve(&self, module: &str, field: &str) -> Option<NativeEntry>;
72}
73
74#[derive(Copy, Clone, Debug)]
75pub enum Mutable {
76 Const,
77 Mut
78}
79
80pub struct RuntimeInfo {
81 pub(crate) debug_print_hook: Option<fn(s: &str)>,
82 pub(crate) mem: Memory,
83 pub(crate) globals: Vec<Value>,
84 pub(crate) resolver: Box<NativeResolver>
85}
86
87pub struct RuntimeConfig {
88 pub mem_default_size_pages: usize,
89 pub mem_max_size_pages: Option<usize>,
90 pub resolver: Box<NativeResolver>
91}
92
93impl NativeFunction {
94 pub fn invoke(&mut self, rt: &mut GlobalStateProvider, args: &[Value]) -> ExecuteResult<Option<Value>> {
95 match *self {
96 NativeFunction::Uninitialized(ref m, ref f) => {
97 let target = match rt.resolve(m.as_str(), f.as_str()) {
98 Some(v) => v,
99 None => {
100 match NativeFunction::builtin_resolve(rt, m.as_str(), f.as_str()) {
101 Some(v) => v,
102 None => return Err(ExecuteError::FunctionNotFound)
103 }
104 }
105 };
106 *self = NativeFunction::Ready(target);
107 },
108 _ => {}
109 }
110
111 if let NativeFunction::Ready(ref f) = *self {
112 f(rt, args)
113 } else {
114 Err(ExecuteError::UnreachableExecuted)
115 }
116 }
117
118 fn builtin_resolve(rt: &GlobalStateProvider, module: &str, field: &str) -> Option<NativeEntry> {
119 if module != "env" {
120 return None;
121 }
122
123 match field {
126 "__wcore_print" => Some(Box::new(move |rt, args| {
127 if args.len() != 2 {
128 return Err(ExecuteError::TypeMismatch);
129 }
130 let ptr = args[0].get_i32()? as usize;
131 let len = args[1].get_i32()? as usize;
132 let mem = rt.get_memory();
133 if ptr >= mem.len() || ptr + len < ptr || ptr + len > mem.len() {
134 return Err(ExecuteError::AddrOutOfBound(ptr as u32, len as u32));
135 }
136 let text = match str::from_utf8(&mem[ptr..ptr + len]) {
137 Ok(v) => v,
138 Err(_) => return Err(ExecuteError::Custom("Invalid UTF-8".to_string()))
139 };
140 Ok(None)
144 })),
145 _ => None
146 }
147 }
148}
149
150impl RuntimeInfo {
151 pub fn new(config: RuntimeConfig) -> RuntimeInfo {
152 RuntimeInfo {
153 debug_print_hook: None,
154 mem: Memory::new(
155 config.mem_default_size_pages * PAGE_SIZE,
156 config.mem_max_size_pages.map(|v| v * PAGE_SIZE)
157 ),
158 globals: Vec::new(),
159 resolver: config.resolver
160 }
161 }
162
163 pub fn debug_print(&self, s: &str) {
164 if let Some(hook) = self.debug_print_hook {
165 hook(s);
166 }
167 }
168
169 pub fn get_memory(&self) -> &[u8] {
170 self.mem.data.as_slice()
171 }
172
173 pub fn get_memory_mut(&mut self) -> &mut Vec<u8> {
174 &mut self.mem.data
175 }
176}
177
178impl GlobalStateProvider for RuntimeInfo {
179 fn get_memory(&self) -> &[u8] {
180 self.mem.data.as_slice()
181 }
182
183 fn get_memory_mut(&mut self) -> &mut [u8] {
184 self.mem.data.as_mut_slice()
185 }
186
187 fn resolve(&self, module: &str, field: &str) -> Option<NativeEntry> {
188 self.resolver.resolve(module, field)
189 }
190}
191
192pub struct Memory {
193 pub(crate) data: Vec<u8>,
194 max_size: Option<usize>
195}
196
197impl Memory {
198 pub fn new(default_size: usize, max_size: Option<usize>) -> Memory {
199 Memory {
200 data: vec![0; default_size],
201 max_size: max_size
202 }
203 }
204
205 pub fn current_size(&self) -> Value {
206 Value::I32((self.data.len() / PAGE_SIZE) as i32)
207 }
208
209 pub fn grow(&mut self, n_pages: i32) -> Value {
210 if n_pages <= 0 {
211 return Value::I32(-1);
212 }
213 let n_pages = n_pages as usize;
214
215 if n_pages > 16384 {
217 return Value::I32(-1);
218 }
219
220 let len_inc = n_pages * PAGE_SIZE;
221 let after_inc = self.data.len() + len_inc;
222
223 if after_inc <= self.data.len() {
225 return Value::I32(-1);
226 }
227
228 if let Some(limit) = self.max_size {
230 if after_inc > limit {
231 return Value::I32(-1);
232 }
233 }
234
235 let prev_size = self.data.len() / PAGE_SIZE;
236
237 self.data.resize(after_inc, 0);
238 Value::I32(prev_size as i32)
241 }
242}
243
244#[derive(Clone, Debug)]
245pub struct Backtrace {
246 pub frames: Vec<BtFrame>
247}
248
249#[derive(Clone, Debug)]
250pub struct BtFrame {
251 pub name: Option<String>
252}
253
254pub struct Frame {
255 func_id: usize,
256 ip: Option<usize>,
257 operands: Vec<Value>,
258 locals: Vec<Value>
259}
260
261impl Frame {
262 pub fn setup(func_id: usize, func: &Function) -> Frame {
263 Frame {
264 func_id: func_id,
265 ip: None,
266 operands: Vec::new(),
267 locals: vec![Value::default(); func.locals.len()]
268 }
269 }
270
271 pub fn setup_no_locals(func_id: usize) -> Frame {
272 Frame {
273 func_id: func_id,
274 ip: None,
275 operands: Vec::new(),
276 locals: Vec::new()
277 }
278 }
279
280 pub fn top_operand(&self) -> ExecuteResult<Value> {
281 match self.operands.last() {
282 Some(v) => Ok(*v),
283 None => Err(ExecuteError::OperandStackUnderflow)
284 }
285 }
286
287 pub fn pop_operand(&mut self) -> ExecuteResult<Value> {
288 match self.operands.pop() {
289 Some(v) => Ok(v),
290 None => Err(ExecuteError::OperandStackUnderflow)
291 }
292 }
293
294 pub fn push_operand(&mut self, operand: Value) {
295 self.operands.push(operand);
296 }
297
298 pub fn set_local(&mut self, idx: u32, val: Value) -> ExecuteResult<()> {
299 let idx = idx as usize;
300
301 if idx >= self.locals.len() {
302 Err(ExecuteError::LocalIndexOutOfBound(idx))
303 } else {
304 self.locals[idx] = val;
305 Ok(())
306 }
307 }
308
309 pub fn get_local(&mut self, idx: u32) -> ExecuteResult<Value> {
310 let idx = idx as usize;
311
312 if idx >= self.locals.len() {
313 Err(ExecuteError::LocalIndexOutOfBound(idx))
314 } else {
315 Ok(self.locals[idx])
316 }
317 }
318}
319
320impl<'a> VirtualMachine<'a> {
321 pub fn new(module: &'a Module, rt_config: RuntimeConfig) -> ExecuteResult<VirtualMachine<'a>> {
322 let mut vm = VirtualMachine {
323 module: module,
324 rt: RuntimeInfo::new(rt_config),
325 frames: Vec::new(),
326 native_functions: Vec::new()
327 };
328
329 for ds in &module.data_segments {
330 let offset = ds.offset as usize;
331 if offset >= vm.rt.mem.data.len() || offset + ds.data.len() > vm.rt.mem.data.len() {
332 return Err(ExecuteError::AddrOutOfBound(offset as u32, ds.data.len() as u32));
333 }
334 for i in 0..ds.data.len() {
335 vm.rt.mem.data[offset + i] = ds.data[i];
336 }
337 }
338
339 for g in &module.globals {
340 vm.rt.globals.push(g.value);
341 }
342
343 for n in &module.natives {
344 vm.native_functions.push(NativeFunctionInfo {
345 f: NativeFunction::Uninitialized(
346 n.module.clone(),
347 n.field.clone()
348 ),
349 typeidx: n.typeidx as usize
350 });
351 }
352
353 Ok(vm)
354 }
355
356 pub fn get_runtime_info(&self) -> &RuntimeInfo {
357 &self.rt
358 }
359
360 pub fn get_runtime_info_mut(&mut self) -> &mut RuntimeInfo {
361 &mut self.rt
362 }
363
364 pub fn lookup_exported_func(&self, name: &str) -> ExecuteResult<usize> {
365 match self.module.exports.get(name) {
366 Some(v) => match *v {
367 Export::Function(id) => Ok(id as usize)
368 },
369 None => Err(ExecuteError::FunctionNotFound)
370 }
371 }
372
373 pub fn last_function(&'a self) -> Option<&'a Function> {
374 let frame: &Frame = match self.frames.last() {
375 Some(v) => v,
376 None => return None
377 };
378 Some(&self.module.functions[frame.func_id])
379 }
380
381 pub fn backtrace(&self) -> Backtrace {
382 let mut bt_frames: Vec<BtFrame> = Vec::new();
383 for f in self.frames.iter().rev() {
384 let func_id = f.func_id;
385 let func = &self.module.functions[func_id];
386 bt_frames.push(BtFrame {
387 name: func.name.clone()
388 });
389 }
390
391 Backtrace {
392 frames: bt_frames
393 }
394 }
395
396 pub fn set_debug_print_hook(&mut self, f: fn(s: &str)) {
397 self.rt.debug_print_hook = Some(f);
398 }
399
400 fn prep_invoke(
401 module: &Module,
402 frame: &mut Frame,
403 idx: usize
404 ) -> ExecuteResult<Frame> {
405 if idx >= module.functions.len() {
406 return Err(ExecuteError::FunctionIndexOutOfBound);
407 }
408 let current_func = &module.functions[idx];
409
410 let mut new_frame = Frame::setup_no_locals(idx);
414
415 let ty = if (current_func.typeidx as usize) < module.types.len() {
416 &module.types[current_func.typeidx as usize]
417 } else {
418 return Err(ExecuteError::TypeIdxIndexOufOfBound);
419 };
420
421 let n_args = match *ty {
422 Type::Func(ref args, _) => args.len(),
423 _ => return Err(ExecuteError::TypeMismatch)
424 };
425
426 let n_locals = current_func.locals.len();
427
428 new_frame.locals = vec![Value::default(); n_args + n_locals];
430
431 for i in 0..n_args {
432 let arg_v = frame.pop_operand()?;
433 new_frame.locals[n_args - 1 - i] = arg_v;
434 }
435
436 Ok(new_frame)
437 }
438
439 pub fn execute(
440 &mut self,
441 initial_func: usize,
442 args: &[Value]
443 ) -> ExecuteResult<Option<Value>> {
444 let mut current_func: &Function = &self.module.functions[initial_func];
445 let initial_stack_depth: usize = self.frames.len();
446 let debug_print = self.rt.debug_print_hook;
447
448 {
450 if current_func.typeidx as usize >= self.module.types.len() {
451 return Err(ExecuteError::TypeIdxIndexOufOfBound);
452 }
453
454 let Type::Func(ref initial_func_args_type, _) = self.module.types[current_func.typeidx as usize];
455 if args.len() != initial_func_args_type.len() {
456 return Err(ExecuteError::TypeMismatch);
457 }
458 let mut initial_frame = Frame::setup_no_locals(initial_func);
459 initial_frame.locals = vec! [ Value::default(); args.len() + current_func.locals.len() ];
460 for i in 0..args.len() {
461 initial_frame.locals[i] = args[i];
462 }
463 self.frames.push(initial_frame);
464 }
465
466 let mut ip: usize = 0;
467
468 loop {
469 let frame: &mut Frame = match self.frames.last_mut() {
470 Some(v) => v,
471 None => return Err(ExecuteError::FrameIndexOutOfBound)
472 };
473
474 if ip >= current_func.body.opcodes.len() {
476 return Err(ExecuteError::OpcodeIndexOutOfBound);
477 }
478 let op = ¤t_func.body.opcodes[ip];
479 ip += 1;
480
481 match *op {
486 Opcode::Drop => {
487 frame.pop_operand()?;
488 },
489 Opcode::Select => {
490 let c = frame.pop_operand()?.get_i32()?;
491 let val2 = frame.pop_operand()?;
492 let val1 = frame.pop_operand()?;
493 if c != 0 {
494 frame.push_operand(val1);
495 } else {
496 frame.push_operand(val2);
497 }
498 },
499 Opcode::Call(idx) => {
500 frame.ip = Some(ip);
502
503 ip = 0;
505
506 let new_frame = Self::prep_invoke(&self.module, frame, idx as usize)?;
507 current_func = &self.module.functions[new_frame.func_id];
508
509 self.frames.push(new_frame);
511
512 },
513 Opcode::CallIndirect(typeidx) => {
514 let typeidx = typeidx as usize;
515 if self.module.tables.len() == 0 {
516 return Err(ExecuteError::TableIndexOutOfBound);
517 }
518 let table: &Table = &self.module.tables[0];
519
520 if typeidx >= self.module.types.len() {
521 return Err(ExecuteError::TypeIdxIndexOufOfBound);
522 }
523 let ft_expect = &self.module.types[typeidx];
524
525 let index = frame.pop_operand()?.get_i32()? as usize;
526 if index >= table.elements.len() {
527 return Err(ExecuteError::TableIndexOutOfBound);
528 }
529
530 let elem: u32 = if let Some(v) = table.elements[index] {
531 v
532 } else {
533 return Err(ExecuteError::UndefinedTableEntry);
534 };
535
536 if elem as usize >= self.module.functions.len() {
537 return Err(ExecuteError::FunctionIndexOutOfBound);
538 }
539
540 let actual_typeidx = self.module.functions[elem as usize].typeidx as usize;
541 if actual_typeidx >= self.module.types.len() {
542 return Err(ExecuteError::TypeIdxIndexOufOfBound);
543 }
544 if self.module.types[actual_typeidx] != *ft_expect {
545 return Err(ExecuteError::IndirectCallTypeMismatch(
546 elem as usize,
547 ft_expect.clone(),
548 self.module.types[actual_typeidx].clone()
549 ));
550 }
551
552 frame.ip = Some(ip);
553 ip = 0;
554
555 let new_frame = Self::prep_invoke(&self.module, frame, elem as usize)?;
556 current_func = &self.module.functions[new_frame.func_id];
557
558 self.frames.push(new_frame);
560 },
561 Opcode::NativeInvoke(id) => {
562 let id = id as usize;
563
564 if id >= self.native_functions.len() {
565 return Err(ExecuteError::FunctionIndexOutOfBound);
566 }
567 let f: &mut NativeFunctionInfo = &mut self.native_functions[id];
568
569 if f.typeidx >= self.module.types.len() {
570 return Err(ExecuteError::TypeIdxIndexOufOfBound);
571 }
572
573 let Type::Func(ref args, ref expected_ret) = self.module.types[f.typeidx];
574 if args.len() > frame.operands.len() {
575 return Err(ExecuteError::OperandStackUnderflow);
576 }
577 let ret = f.f.invoke(&mut self.rt, &frame.operands[frame.operands.len() - args.len()..frame.operands.len()])?;
578
579 if (expected_ret.len() != 0 && ret.is_none()) || (expected_ret.len() == 0 && ret.is_some()) {
580 return Err(ExecuteError::TypeMismatch);
581 }
582
583 for _ in 0..args.len() {
584 frame.pop_operand()?;
585 }
586
587 if let Some(v) = ret {
588 frame.push_operand(v);
589 }
590 },
591 Opcode::Return => {
592 let mut prev_frame = self.frames.pop().unwrap();
594
595 let ty = if (current_func.typeidx as usize) < self.module.types.len() {
596 &self.module.types[current_func.typeidx as usize]
597 } else {
598 return Err(ExecuteError::TypeIdxIndexOufOfBound);
599 };
600
601 let n_rets = match *ty {
602 Type::Func(_ , ref rets) => rets.len(),
603 _ => return Err(ExecuteError::TypeMismatch)
604 };
605
606 if prev_frame.operands.len() != n_rets {
608 return Err(ExecuteError::ReturnTypeMismatch);
609 }
610
611 if self.frames.len() < initial_stack_depth {
612 return Err(ExecuteError::Custom("BUG: Invalid frames".into()));
613 }
614
615 if self.frames.len() == initial_stack_depth {
616 return Ok(if n_rets == 0 {
617 None
618 } else {
619 Some(prev_frame.operands[0])
620 });
621 }
622
623 let frame: &mut Frame = self.frames.last_mut().unwrap();
627 ip = frame.ip.take().unwrap();
628
629 for op in &prev_frame.operands {
630 frame.push_operand(*op);
631 }
632
633 current_func = &self.module.functions[frame.func_id];
634 },
635 Opcode::CurrentMemory => {
636 frame.push_operand(self.rt.mem.current_size());
637 },
638 Opcode::GrowMemory => {
639 let n_pages = frame.pop_operand()?.get_i32()?;
640 frame.push_operand(self.rt.mem.grow(n_pages));
641 },
642 Opcode::Nop => {},
643 Opcode::Jmp(target) => {
644 ip = target as usize;
645 },
646 Opcode::JmpIf(target) => {
647 let v = frame.pop_operand()?.get_i32()?;
648 if v != 0 {
649 ip = target as usize;
650 }
651 },
652 Opcode::JmpEither(if_true, if_false) => {
653 let v = frame.pop_operand()?.get_i32()?;
654 if v != 0 {
655 ip = if_true as usize;
656 } else {
657 ip = if_false as usize;
658 }
659 },
660 Opcode::JmpTable(ref table, otherwise) => {
661 let v = frame.pop_operand()?.get_i32()? as usize;
662 if v < table.len() {
663 ip = table[v] as usize;
664 } else {
665 ip = otherwise as usize;
666 }
667 },
668 Opcode::SetLocal(idx) => {
669 let v = frame.pop_operand()?;
670 frame.set_local(idx, v)?;
671 },
672 Opcode::GetLocal(idx) => {
673 let v = frame.get_local(idx)?;
674 frame.push_operand(v);
675 },
676 Opcode::TeeLocal(idx) => {
677 let v = frame.top_operand()?;
678 frame.set_local(idx, v)?;
679 },
680 Opcode::GetGlobal(idx) => {
681 let idx = idx as usize;
682 if idx >= self.rt.globals.len() {
683 return Err(ExecuteError::GlobalIndexOutOfBound);
684 }
685 frame.push_operand(self.rt.globals[idx])
686 },
687 Opcode::SetGlobal(idx) => {
688 let idx = idx as usize;
689 if idx >= self.rt.globals.len() {
690 return Err(ExecuteError::GlobalIndexOutOfBound);
691 }
692 let v = frame.pop_operand()?;
693 self.rt.globals[idx] = v;
694 },
695 Opcode::Unreachable => {
696 return Err(ExecuteError::UnreachableExecuted);
697 },
698 Opcode::I32Const(v) => {
699 frame.push_operand(Value::I32(v));
700 },
701 Opcode::I32Clz => {
702 let v = frame.pop_operand()?;
703 frame.push_operand(int_ops::i32_clz(v.get_i32()?));
704 },
705 Opcode::I32Ctz => {
706 let v = frame.pop_operand()?;
707 frame.push_operand(int_ops::i32_ctz(v.get_i32()?));
708 },
709 Opcode::I32Popcnt => {
710 let v = frame.pop_operand()?;
711 frame.push_operand(int_ops::i32_popcnt(v.get_i32()?));
712 },
713 Opcode::I32Add => {
714 let c2 = frame.pop_operand()?;
715 let c1 = frame.pop_operand()?;
716 frame.push_operand(int_ops::i32_add(c1.get_i32()?, c2.get_i32()?));
717 },
718 Opcode::I32Sub => {
719 let c2 = frame.pop_operand()?;
720 let c1 = frame.pop_operand()?;
721 frame.push_operand(int_ops::i32_sub(c1.get_i32()?, c2.get_i32()?));
722 },
723 Opcode::I32Mul => {
724 let c2 = frame.pop_operand()?;
725 let c1 = frame.pop_operand()?;
726 frame.push_operand(int_ops::i32_mul(c1.get_i32()?, c2.get_i32()?));
727 },
728 Opcode::I32DivU => {
729 let c2 = frame.pop_operand()?;
730 let c1 = frame.pop_operand()?;
731 frame.push_operand(int_ops::i32_div_u(c1.get_i32()?, c2.get_i32()?));
732 },
733 Opcode::I32DivS => {
734 let c2 = frame.pop_operand()?;
735 let c1 = frame.pop_operand()?;
736 frame.push_operand(int_ops::i32_div_s(c1.get_i32()?, c2.get_i32()?));
737 },
738 Opcode::I32RemU => {
739 let c2 = frame.pop_operand()?;
740 let c1 = frame.pop_operand()?;
741 frame.push_operand(int_ops::i32_rem_u(c1.get_i32()?, c2.get_i32()?));
742 },
743 Opcode::I32RemS => {
744 let c2 = frame.pop_operand()?;
745 let c1 = frame.pop_operand()?;
746 frame.push_operand(int_ops::i32_rem_s(c1.get_i32()?, c2.get_i32()?));
747 },
748 Opcode::I32And => {
749 let c2 = frame.pop_operand()?;
750 let c1 = frame.pop_operand()?;
751 frame.push_operand(int_ops::i32_and(c1.get_i32()?, c2.get_i32()?));
752 },
753 Opcode::I32Or => {
754 let c2 = frame.pop_operand()?;
755 let c1 = frame.pop_operand()?;
756 frame.push_operand(int_ops::i32_or(c1.get_i32()?, c2.get_i32()?));
757 },
758 Opcode::I32Xor => {
759 let c2 = frame.pop_operand()?;
760 let c1 = frame.pop_operand()?;
761 frame.push_operand(int_ops::i32_xor(c1.get_i32()?, c2.get_i32()?));
762 },
763 Opcode::I32Shl => {
764 let c2 = frame.pop_operand()?;
765 let c1 = frame.pop_operand()?;
766 frame.push_operand(int_ops::i32_shl(c1.get_i32()?, c2.get_i32()?));
767 },
768 Opcode::I32ShrU => {
769 let c2 = frame.pop_operand()?;
770 let c1 = frame.pop_operand()?;
771 frame.push_operand(int_ops::i32_shr_u(c1.get_i32()?, c2.get_i32()?));
772 },
773 Opcode::I32ShrS => {
774 let c2 = frame.pop_operand()?;
775 let c1 = frame.pop_operand()?;
776 frame.push_operand(int_ops::i32_shr_s(c1.get_i32()?, c2.get_i32()?));
777 },
778 Opcode::I32Rotl => {
779 let c2 = frame.pop_operand()?;
780 let c1 = frame.pop_operand()?;
781 frame.push_operand(int_ops::i32_rotl(c1.get_i32()?, c2.get_i32()?));
782 },
783 Opcode::I32Rotr => {
784 let c2 = frame.pop_operand()?;
785 let c1 = frame.pop_operand()?;
786 frame.push_operand(int_ops::i32_rotr(c1.get_i32()?, c2.get_i32()?));
787 },
788 Opcode::I32Eqz => {
789 let v = frame.pop_operand()?;
790 frame.push_operand(int_ops::i32_eqz(v.get_i32()?));
791 },
792 Opcode::I32Eq => {
793 let c2 = frame.pop_operand()?;
794 let c1 = frame.pop_operand()?;
795 frame.push_operand(int_ops::i32_eq(c1.get_i32()?, c2.get_i32()?));
796 },
797 Opcode::I32Ne => {
798 let c2 = frame.pop_operand()?;
799 let c1 = frame.pop_operand()?;
800 frame.push_operand(int_ops::i32_ne(c1.get_i32()?, c2.get_i32()?));
801 },
802 Opcode::I32LtU => {
803 let c2 = frame.pop_operand()?;
804 let c1 = frame.pop_operand()?;
805 frame.push_operand(int_ops::i32_lt_u(c1.get_i32()?, c2.get_i32()?));
806 },
807 Opcode::I32LtS => {
808 let c2 = frame.pop_operand()?;
809 let c1 = frame.pop_operand()?;
810 frame.push_operand(int_ops::i32_lt_s(c1.get_i32()?, c2.get_i32()?));
811 },
812 Opcode::I32LeU => {
813 let c2 = frame.pop_operand()?;
814 let c1 = frame.pop_operand()?;
815 frame.push_operand(int_ops::i32_le_u(c1.get_i32()?, c2.get_i32()?));
816 },
817 Opcode::I32LeS => {
818 let c2 = frame.pop_operand()?;
819 let c1 = frame.pop_operand()?;
820 frame.push_operand(int_ops::i32_le_s(c1.get_i32()?, c2.get_i32()?));
821 },
822 Opcode::I32GtU => {
823 let c2 = frame.pop_operand()?;
824 let c1 = frame.pop_operand()?;
825 frame.push_operand(int_ops::i32_gt_u(c1.get_i32()?, c2.get_i32()?));
826 },
827 Opcode::I32GtS => {
828 let c2 = frame.pop_operand()?;
829 let c1 = frame.pop_operand()?;
830 frame.push_operand(int_ops::i32_gt_s(c1.get_i32()?, c2.get_i32()?));
831 },
832 Opcode::I32GeU => {
833 let c2 = frame.pop_operand()?;
834 let c1 = frame.pop_operand()?;
835 frame.push_operand(int_ops::i32_ge_u(c1.get_i32()?, c2.get_i32()?));
836 },
837 Opcode::I32GeS => {
838 let c2 = frame.pop_operand()?;
839 let c1 = frame.pop_operand()?;
840 frame.push_operand(int_ops::i32_ge_s(c1.get_i32()?, c2.get_i32()?));
841 },
842 Opcode::I32WrapI64 => {
843 let v = frame.pop_operand()?;
844 frame.push_operand(int_ops::i32_wrap_i64(v.get_i64()?));
845 },
846 Opcode::I32Load(ref m) => {
847 let i = frame.pop_operand()?.get_i32()? as u32;
848 let v = int_ops::i32_load_u(i, m, &mut self.rt.mem, 4)?;
849 frame.push_operand(v);
850 },
851 Opcode::I32Load8U(ref m) => {
852 let i = frame.pop_operand()?.get_i32()? as u32;
853 let v = int_ops::i32_load_u(i, m, &mut self.rt.mem, 1)?;
854 frame.push_operand(v);
855 },
856 Opcode::I32Load8S(ref m) => {
857 let i = frame.pop_operand()?.get_i32()? as u32;
858 let v = int_ops::i32_load_s(i, m, &mut self.rt.mem, 1)?;
859 frame.push_operand(v);
860 },
861 Opcode::I32Load16U(ref m) => {
862 let i = frame.pop_operand()?.get_i32()? as u32;
863 let v = int_ops::i32_load_u(i, m, &mut self.rt.mem, 2)?;
864 frame.push_operand(v);
865 },
866 Opcode::I32Load16S(ref m) => {
867 let i = frame.pop_operand()?.get_i32()? as u32;
868 let v = int_ops::i32_load_s(i, m, &mut self.rt.mem, 2)?;
869 frame.push_operand(v);
870 },
871 Opcode::I32Store(ref m) => {
872 let c = frame.pop_operand()?;
873 let i = frame.pop_operand()?.get_i32()? as u32;
874 int_ops::i32_store(i, c, m, &mut self.rt.mem, 4)?;
875 },
876 Opcode::I32Store8(ref m) => {
877 let c = frame.pop_operand()?;
878 let i = frame.pop_operand()?.get_i32()? as u32;
879 int_ops::i32_store(i, c, m, &mut self.rt.mem, 1)?;
880 },
881 Opcode::I32Store16(ref m) => {
882 let c = frame.pop_operand()?;
883 let i = frame.pop_operand()?.get_i32()? as u32;
884 int_ops::i32_store(i, c, m, &mut self.rt.mem, 2)?;
885 },
886 Opcode::I64Const(v) => {
887 frame.push_operand(Value::I64(v));
888 },
889 Opcode::I64Clz => {
890 let v = frame.pop_operand()?;
891 frame.push_operand(int_ops::i64_clz(v.get_i64()?));
892 },
893 Opcode::I64Ctz => {
894 let v = frame.pop_operand()?;
895 frame.push_operand(int_ops::i64_ctz(v.get_i64()?));
896 },
897 Opcode::I64Popcnt => {
898 let v = frame.pop_operand()?;
899 frame.push_operand(int_ops::i64_popcnt(v.get_i64()?));
900 },
901 Opcode::I64Add => {
902 let c2 = frame.pop_operand()?;
903 let c1 = frame.pop_operand()?;
904 frame.push_operand(int_ops::i64_add(c1.get_i64()?, c2.get_i64()?));
905 },
906 Opcode::I64Sub => {
907 let c2 = frame.pop_operand()?;
908 let c1 = frame.pop_operand()?;
909 frame.push_operand(int_ops::i64_sub(c1.get_i64()?, c2.get_i64()?));
910 },
911 Opcode::I64Mul => {
912 let c2 = frame.pop_operand()?;
913 let c1 = frame.pop_operand()?;
914 frame.push_operand(int_ops::i64_mul(c1.get_i64()?, c2.get_i64()?));
915 },
916 Opcode::I64DivU => {
917 let c2 = frame.pop_operand()?;
918 let c1 = frame.pop_operand()?;
919 frame.push_operand(int_ops::i64_div_u(c1.get_i64()?, c2.get_i64()?));
920 },
921 Opcode::I64DivS => {
922 let c2 = frame.pop_operand()?;
923 let c1 = frame.pop_operand()?;
924 frame.push_operand(int_ops::i64_div_s(c1.get_i64()?, c2.get_i64()?));
925 },
926 Opcode::I64RemU => {
927 let c2 = frame.pop_operand()?;
928 let c1 = frame.pop_operand()?;
929 frame.push_operand(int_ops::i64_rem_u(c1.get_i64()?, c2.get_i64()?));
930 },
931 Opcode::I64RemS => {
932 let c2 = frame.pop_operand()?;
933 let c1 = frame.pop_operand()?;
934 frame.push_operand(int_ops::i64_rem_s(c1.get_i64()?, c2.get_i64()?));
935 },
936 Opcode::I64And => {
937 let c2 = frame.pop_operand()?;
938 let c1 = frame.pop_operand()?;
939 frame.push_operand(int_ops::i64_and(c1.get_i64()?, c2.get_i64()?));
940 },
941 Opcode::I64Or => {
942 let c2 = frame.pop_operand()?;
943 let c1 = frame.pop_operand()?;
944 frame.push_operand(int_ops::i64_or(c1.get_i64()?, c2.get_i64()?));
945 },
946 Opcode::I64Xor => {
947 let c2 = frame.pop_operand()?;
948 let c1 = frame.pop_operand()?;
949 frame.push_operand(int_ops::i64_xor(c1.get_i64()?, c2.get_i64()?));
950 },
951 Opcode::I64Shl => {
952 let c2 = frame.pop_operand()?;
953 let c1 = frame.pop_operand()?;
954 frame.push_operand(int_ops::i64_shl(c1.get_i64()?, c2.get_i64()?));
955 },
956 Opcode::I64ShrU => {
957 let c2 = frame.pop_operand()?;
958 let c1 = frame.pop_operand()?;
959 frame.push_operand(int_ops::i64_shr_u(c1.get_i64()?, c2.get_i64()?));
960 },
961 Opcode::I64ShrS => {
962 let c2 = frame.pop_operand()?;
963 let c1 = frame.pop_operand()?;
964 frame.push_operand(int_ops::i64_shr_s(c1.get_i64()?, c2.get_i64()?));
965 },
966 Opcode::I64Rotl => {
967 let c2 = frame.pop_operand()?;
968 let c1 = frame.pop_operand()?;
969 frame.push_operand(int_ops::i64_rotl(c1.get_i64()?, c2.get_i64()?));
970 },
971 Opcode::I64Rotr => {
972 let c2 = frame.pop_operand()?;
973 let c1 = frame.pop_operand()?;
974 frame.push_operand(int_ops::i64_rotr(c1.get_i64()?, c2.get_i64()?));
975 },
976 Opcode::I64Eqz => {
977 let v = frame.pop_operand()?;
978 frame.push_operand(int_ops::i64_eqz(v.get_i64()?));
979 },
980 Opcode::I64Eq => {
981 let c2 = frame.pop_operand()?;
982 let c1 = frame.pop_operand()?;
983 frame.push_operand(int_ops::i64_eq(c1.get_i64()?, c2.get_i64()?));
984 },
985 Opcode::I64Ne => {
986 let c2 = frame.pop_operand()?;
987 let c1 = frame.pop_operand()?;
988 frame.push_operand(int_ops::i64_ne(c1.get_i64()?, c2.get_i64()?));
989 },
990 Opcode::I64LtU => {
991 let c2 = frame.pop_operand()?;
992 let c1 = frame.pop_operand()?;
993 frame.push_operand(int_ops::i64_lt_u(c1.get_i64()?, c2.get_i64()?));
994 },
995 Opcode::I64LtS => {
996 let c2 = frame.pop_operand()?;
997 let c1 = frame.pop_operand()?;
998 frame.push_operand(int_ops::i64_lt_s(c1.get_i64()?, c2.get_i64()?));
999 },
1000 Opcode::I64LeU => {
1001 let c2 = frame.pop_operand()?;
1002 let c1 = frame.pop_operand()?;
1003 frame.push_operand(int_ops::i64_le_u(c1.get_i64()?, c2.get_i64()?));
1004 },
1005 Opcode::I64LeS => {
1006 let c2 = frame.pop_operand()?;
1007 let c1 = frame.pop_operand()?;
1008 frame.push_operand(int_ops::i64_le_s(c1.get_i64()?, c2.get_i64()?));
1009 },
1010 Opcode::I64GtU => {
1011 let c2 = frame.pop_operand()?;
1012 let c1 = frame.pop_operand()?;
1013 frame.push_operand(int_ops::i64_gt_u(c1.get_i64()?, c2.get_i64()?));
1014 },
1015 Opcode::I64GtS => {
1016 let c2 = frame.pop_operand()?;
1017 let c1 = frame.pop_operand()?;
1018 frame.push_operand(int_ops::i64_gt_s(c1.get_i64()?, c2.get_i64()?));
1019 },
1020 Opcode::I64GeU => {
1021 let c2 = frame.pop_operand()?;
1022 let c1 = frame.pop_operand()?;
1023 frame.push_operand(int_ops::i64_ge_u(c1.get_i64()?, c2.get_i64()?));
1024 },
1025 Opcode::I64GeS => {
1026 let c2 = frame.pop_operand()?;
1027 let c1 = frame.pop_operand()?;
1028 frame.push_operand(int_ops::i64_ge_s(c1.get_i64()?, c2.get_i64()?));
1029 },
1030 Opcode::I64ExtendI32U => {
1031 let v = frame.pop_operand()?;
1032 frame.push_operand(int_ops::i64_extend_i32_u(v.get_i32()?));
1033 },
1034 Opcode::I64ExtendI32S => {
1035 let v = frame.pop_operand()?;
1036 frame.push_operand(int_ops::i64_extend_i32_s(v.get_i32()?));
1037 },
1038 Opcode::I64Load(ref m) => {
1039 let i = frame.pop_operand()?.get_i32()? as u32;
1040 let v = int_ops::i64_load_u(i, m, &mut self.rt.mem, 8)?;
1041 frame.push_operand(v);
1042 },
1043 Opcode::I64Load8U(ref m) => {
1044 let i = frame.pop_operand()?.get_i32()? as u32;
1045 let v = int_ops::i64_load_u(i, m, &mut self.rt.mem, 1)?;
1046 frame.push_operand(v);
1047 },
1048 Opcode::I64Load8S(ref m) => {
1049 let i = frame.pop_operand()?.get_i32()? as u32;
1050 let v = int_ops::i64_load_s(i, m, &mut self.rt.mem, 1)?;
1051 frame.push_operand(v);
1052 },
1053 Opcode::I64Load16U(ref m) => {
1054 let i = frame.pop_operand()?.get_i32()? as u32;
1055 let v = int_ops::i64_load_u(i, m, &mut self.rt.mem, 2)?;
1056 frame.push_operand(v);
1057 },
1058 Opcode::I64Load16S(ref m) => {
1059 let i = frame.pop_operand()?.get_i32()? as u32;
1060 let v = int_ops::i64_load_s(i, m, &mut self.rt.mem, 2)?;
1061 frame.push_operand(v);
1062 },
1063 Opcode::I64Load32U(ref m) => {
1064 let i = frame.pop_operand()?.get_i32()? as u32;
1065 let v = int_ops::i64_load_u(i, m, &mut self.rt.mem, 4)?;
1066 frame.push_operand(v);
1067 },
1068 Opcode::I64Load32S(ref m) => {
1069 let i = frame.pop_operand()?.get_i32()? as u32;
1070 let v = int_ops::i64_load_s(i, m, &mut self.rt.mem, 4)?;
1071 frame.push_operand(v);
1072 },
1073 Opcode::I64Store(ref m) => {
1074 let c = frame.pop_operand()?;
1075 let i = frame.pop_operand()?.get_i32()? as u32;
1076 int_ops::i64_store(i, c, m, &mut self.rt.mem, 8)?;
1077 },
1078 Opcode::I64Store8(ref m) => {
1079 let c = frame.pop_operand()?;
1080 let i = frame.pop_operand()?.get_i32()? as u32;
1081 int_ops::i64_store(i, c, m, &mut self.rt.mem, 1)?;
1082 },
1083 Opcode::I64Store16(ref m) => {
1084 let c = frame.pop_operand()?;
1085 let i = frame.pop_operand()?.get_i32()? as u32;
1086 int_ops::i64_store(i, c, m, &mut self.rt.mem, 2)?;
1087 },
1088 Opcode::I64Store32(ref m) => {
1089 let c = frame.pop_operand()?;
1090 let i = frame.pop_operand()?.get_i32()? as u32;
1091 int_ops::i64_store(i, c, m, &mut self.rt.mem, 4)?;
1092 },
1093 Opcode::NotImplemented(ref s) => {
1094 return Err(ExecuteError::Custom(
1095 format!("Not implemented: {}", s)
1096 ))
1097 },
1098 Opcode::Memcpy => {
1099 let n_bytes = frame.pop_operand()?.get_i32()? as usize;
1102 let src = frame.pop_operand()?.get_i32()? as usize;
1103 let dest = frame.pop_operand()?.get_i32()? as usize;
1104 let mem = self.rt.mem.data.as_mut_slice();
1105
1106 if dest + n_bytes >= mem.len() {
1107 return Err(ExecuteError::AddrOutOfBound(dest as u32, n_bytes as u32));
1108 }
1109 if src + n_bytes >= mem.len() {
1110 return Err(ExecuteError::AddrOutOfBound(src as u32, n_bytes as u32));
1111 }
1112
1113 for i in 0..n_bytes {
1114 mem[dest + i] = mem[src + i]; }
1116 },
1117 Opcode::F32Const(v) => {
1118 frame.push_operand(Value::F32(fp_ops::f32_reinterpret_i32(v as i32)));
1119 },
1120 Opcode::F64Const(v) => {
1121 frame.push_operand(Value::F64(fp_ops::f64_reinterpret_i64(v as i64)));
1122 },
1123 _ => return Err(ExecuteError::NotImplemented)
1124 }
1125 }
1126 }
1127}
1128
1129impl Module {
1130 pub fn execute(&self, rt_config: RuntimeConfig, initial_func: usize) -> ExecuteResult<Option<Value>> {
1131 let mut vm = VirtualMachine::new(self, rt_config)?;
1132 vm.execute(initial_func, &[])
1133 }
1134}