wasm_core/
executor.rs

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) // (fn_id, expected, actual)
35}
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), // (module, field)
67    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        //let debug_print = rt.debug_print_hook;
124
125        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                /*if let Some(f) = debug_print {
141                    f(text);
142                }*/
143                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        // FIXME: Hardcoded limit for now (prevent overflow etc.)
216        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        // Overflow?
224        if after_inc <= self.data.len() {
225            return Value::I32(-1);
226        }
227
228        // Check for the limit
229        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        //panic!("After inc: {}", after_inc);
239
240        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        // Now we've switched the current function to the new one.
411        // Initialize the new frame now.
412
413        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        // Initialize the new locals.
429        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        // FIXME: Handle initial call gracefully
449        {
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            // Fetch the current instruction and move to the next one.
475            if ip >= current_func.body.opcodes.len() {
476                return Err(ExecuteError::OpcodeIndexOutOfBound);
477            }
478            let op = &current_func.body.opcodes[ip];
479            ip += 1;
480
481            /*if let Some(f) = debug_print {
482                f(format!("{:?}", op).as_str());
483            }*/
484
485            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                    // "Push" IP so that we can restore it after the call is done.
501                    frame.ip = Some(ip);
502
503                    // Reset IP.
504                    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                    // Push the newly-created frame.
510                    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                    // Push the newly-created frame.
559                    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                    // Pop the current frame.
593                    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                    // There should be exactly n_rets operands now.
607                    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                    // self.frames.len() > initial_stack_depth >= 0 always hold here.
624
625                    // Restore IP.
626                    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                    // Pop in reverse order.
1100                    // (dest, src, n_bytes)
1101                    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]; // copy_from_slice ?
1115                    }
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}