Working interpreter

This commit is contained in:
Chris Fallin 2023-02-23 19:16:08 -08:00
parent 58c89bbbb6
commit 49a907da25

View file

@ -121,12 +121,9 @@ impl InterpContext {
multivalue[0] multivalue[0]
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let idx = match args[0] { let idx = args.last().unwrap().as_u32().unwrap() as usize;
ConstVal::I32(x) => x, let func = self.tables[table_index].elements[idx];
_ => panic!(), self.call(module, func, &args[..args.len() - 1])?
};
let func = self.tables[table_index].elements[idx as usize];
self.call(module, func, &args[1..])?
} }
&ValueDef::Operator(ref op, ref args, _) => { &ValueDef::Operator(ref op, ref args, _) => {
let args = args let args = args
@ -167,10 +164,7 @@ impl InterpContext {
} => { } => {
let cond = body.resolve_alias(cond); let cond = body.resolve_alias(cond);
let cond = frame.values.get(&cond).unwrap(); let cond = frame.values.get(&cond).unwrap();
let cond = match cond[0] { let cond = cond[0].as_u32().unwrap() != 0;
ConstVal::I32(x) => x != 0,
_ => unreachable!(),
};
if cond { if cond {
frame.apply_target(body, if_true); frame.apply_target(body, if_true);
} else { } else {
@ -184,10 +178,7 @@ impl InterpContext {
} => { } => {
let value = body.resolve_alias(value); let value = body.resolve_alias(value);
let value = frame.values.get(&value).unwrap(); let value = frame.values.get(&value).unwrap();
let value = match value[0] { let value = value[0].as_u32().unwrap() as usize;
ConstVal::I32(x) => x,
_ => unreachable!(),
} as usize;
if value < targets.len() { if value < targets.len() {
frame.apply_target(body, &targets[value]); frame.apply_target(body, &targets[value]);
} else { } else {
@ -209,8 +200,60 @@ impl InterpContext {
} }
} }
fn call_import(&mut self, name: &str, _args: &[ConstVal]) -> Option<SmallVec<[ConstVal; 2]>> { fn call_import(&mut self, name: &str, args: &[ConstVal]) -> Option<SmallVec<[ConstVal; 2]>> {
todo!("call_import: {}", name); 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, None,
} }
impl ConstVal {
pub fn as_u32(self) -> Option<u32> {
match self {
Self::I32(x) => Some(x),
_ => None,
}
}
}
pub fn const_eval( pub fn const_eval(
op: &Operator, op: &Operator,
vals: &[ConstVal], vals: &[ConstVal],