From 49a907da2526134d6c0349e4bb9ede4402a54b4a Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Thu, 23 Feb 2023 19:16:08 -0800 Subject: [PATCH] Working interpreter --- src/interp.rs | 84 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 68 insertions(+), 16 deletions(-) diff --git a/src/interp.rs b/src/interp.rs index bbf90f9..c4070cf 100644 --- a/src/interp.rs +++ b/src/interp.rs @@ -121,12 +121,9 @@ impl InterpContext { multivalue[0] }) .collect::>(); - let idx = match args[0] { - ConstVal::I32(x) => x, - _ => panic!(), - }; - let func = self.tables[table_index].elements[idx as usize]; - self.call(module, func, &args[1..])? + let idx = args.last().unwrap().as_u32().unwrap() as usize; + let func = self.tables[table_index].elements[idx]; + self.call(module, func, &args[..args.len() - 1])? } &ValueDef::Operator(ref op, ref args, _) => { let args = args @@ -167,10 +164,7 @@ impl InterpContext { } => { let cond = body.resolve_alias(cond); let cond = frame.values.get(&cond).unwrap(); - let cond = match cond[0] { - ConstVal::I32(x) => x != 0, - _ => unreachable!(), - }; + let cond = cond[0].as_u32().unwrap() != 0; if cond { frame.apply_target(body, if_true); } else { @@ -184,10 +178,7 @@ impl InterpContext { } => { let value = body.resolve_alias(value); let value = frame.values.get(&value).unwrap(); - let value = match value[0] { - ConstVal::I32(x) => x, - _ => unreachable!(), - } as usize; + let value = value[0].as_u32().unwrap() as usize; if value < targets.len() { frame.apply_target(body, &targets[value]); } else { @@ -209,8 +200,60 @@ impl InterpContext { } } - fn call_import(&mut self, name: &str, _args: &[ConstVal]) -> Option> { - todo!("call_import: {}", name); + fn call_import(&mut self, name: &str, args: &[ConstVal]) -> Option> { + let mem = &mut self.memories[Memory::from(0)]; + match name { + "__wasi_fd_prestat_get" => { + Some(smallvec![ConstVal::I32(8)]) // BADF + } + "__wasi_args_sizes_get" => { + let p_argc = args[0].as_u32().unwrap(); + let p_argv_size = args[1].as_u32().unwrap(); + write_u32(mem, p_argc, 0); + write_u32(mem, p_argv_size, 0); + Some(smallvec![ConstVal::I32(0)]) + } + "__wasi_args_get" => Some(smallvec![ConstVal::I32(0)]), + "__wasi_fd_fdstat_get" => { + let fd = args[0].as_u32().unwrap(); + let p_fdstat_t = args[1].as_u32().unwrap(); + if fd == 1 { + write_u32(mem, p_fdstat_t + 0, 2); // filetype = CHAR + write_u32(mem, p_fdstat_t + 4, 0); // flags = 0 + write_u32(mem, p_fdstat_t + 8, 0x40); // rights_base = WRITE + write_u32(mem, p_fdstat_t + 12, 0); // rights_inheriting = 0 + Some(smallvec![ConstVal::I32(0)]) + } else { + None + } + } + "__wasi_fd_write" => { + let fd = args[0].as_u32().unwrap(); + let p_iovs = args[1].as_u32().unwrap(); + let iovs_len = args[2].as_u32().unwrap(); + let p_nwritten = args[3].as_u32().unwrap(); + if fd == 1 { + let mut written = 0; + for i in 0..iovs_len { + let iov_entry = p_iovs + 8 * i; + let base = read_u32(mem, iov_entry) as usize; + let len = read_u32(mem, iov_entry + 4) as usize; + let data = &mem.data[base..(base + len)]; + print!("{}", std::str::from_utf8(data).unwrap()); + written += len; + } + write_u32(mem, p_nwritten, written as u32); + Some(smallvec![ConstVal::I32(0)]) + } else { + None + } + } + "__wasi_proc_exit" => { + eprintln!("WASI exit: {:?}", args[0]); + None + } + _ => panic!("Unknown import: {} with args: {:?}", name, args), + } } } @@ -267,6 +310,15 @@ pub enum ConstVal { None, } +impl ConstVal { + pub fn as_u32(self) -> Option { + match self { + Self::I32(x) => Some(x), + _ => None, + } + } +} + pub fn const_eval( op: &Operator, vals: &[ConstVal],