Some refactoring for tracepoints
This commit is contained in:
parent
5c48a0a3ea
commit
20ea31c9dd
|
@ -62,6 +62,7 @@ impl Trees {
|
|||
&ValueDef::BlockParam(..)
|
||||
| &ValueDef::Alias(..)
|
||||
| &ValueDef::Placeholder(..)
|
||||
| &ValueDef::Trace(..)
|
||||
| &ValueDef::None => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,7 +104,7 @@ fn main() -> Result<()> {
|
|||
let mut ctx = InterpContext::new(&module);
|
||||
debug!("Calling start function");
|
||||
if let Some(start) = module.start_func {
|
||||
ctx.call(&module, start, &[]).unwrap();
|
||||
ctx.call(&module, start, &[]).ok().unwrap();
|
||||
}
|
||||
// Find a function called `_start`, if any.
|
||||
if let Some(waffle::Export {
|
||||
|
@ -113,7 +113,7 @@ fn main() -> Result<()> {
|
|||
}) = module.exports.iter().find(|e| &e.name == "_start")
|
||||
{
|
||||
debug!("Calling _start");
|
||||
ctx.call(&module, *func, &[]).unwrap();
|
||||
ctx.call(&module, *func, &[]).ok().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,25 @@ pub struct InterpContext {
|
|||
memories: PerEntity<Memory, InterpMemory>,
|
||||
tables: PerEntity<Table, InterpTable>,
|
||||
globals: PerEntity<Global, ConstVal>,
|
||||
trace_log: Vec<(usize, Vec<ConstVal>)>,
|
||||
}
|
||||
|
||||
type MultiVal = SmallVec<[ConstVal; 2]>;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum InterpResult {
|
||||
Ok(MultiVal),
|
||||
Exit,
|
||||
Trap,
|
||||
}
|
||||
|
||||
impl InterpResult {
|
||||
pub fn ok(self) -> anyhow::Result<MultiVal> {
|
||||
match self {
|
||||
InterpResult::Ok(vals) => Ok(vals),
|
||||
other => anyhow::bail!("Bad InterpResult: {:?}", other),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InterpContext {
|
||||
|
@ -54,15 +73,11 @@ impl InterpContext {
|
|||
memories,
|
||||
tables,
|
||||
globals,
|
||||
trace_log: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn call(
|
||||
&mut self,
|
||||
module: &Module<'_>,
|
||||
func: Func,
|
||||
args: &[ConstVal],
|
||||
) -> Option<SmallVec<[ConstVal; 2]>> {
|
||||
pub fn call(&mut self, module: &Module<'_>, func: Func, args: &[ConstVal]) -> InterpResult {
|
||||
let body = match &module.funcs[func] {
|
||||
FuncDecl::Lazy(..) => panic!("Un-expanded function"),
|
||||
FuncDecl::Import(..) => {
|
||||
|
@ -111,7 +126,11 @@ impl InterpContext {
|
|||
multivalue[0]
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
self.call(module, function_index, &args[..])?
|
||||
let result = self.call(module, function_index, &args[..]);
|
||||
match result {
|
||||
InterpResult::Ok(vals) => vals,
|
||||
_ => return result,
|
||||
}
|
||||
}
|
||||
&ValueDef::Operator(
|
||||
Operator::CallIndirect { table_index, .. },
|
||||
|
@ -129,7 +148,11 @@ impl InterpContext {
|
|||
.collect::<Vec<_>>();
|
||||
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])?
|
||||
let result = self.call(module, func, &args[..args.len() - 1]);
|
||||
match result {
|
||||
InterpResult::Ok(vals) => vals,
|
||||
_ => return result,
|
||||
}
|
||||
}
|
||||
&ValueDef::Operator(ref op, ref args, _) => {
|
||||
let args = args
|
||||
|
@ -149,11 +172,28 @@ impl InterpContext {
|
|||
Some(result) => result,
|
||||
None => {
|
||||
log::trace!("const_eval failed on {:?} args {:?}", op, args);
|
||||
return None;
|
||||
return InterpResult::Trap;
|
||||
}
|
||||
};
|
||||
smallvec![result]
|
||||
}
|
||||
&ValueDef::Trace(id, ref args) => {
|
||||
let args = args
|
||||
.iter()
|
||||
.map(|&arg| {
|
||||
let arg = body.resolve_alias(arg);
|
||||
let multivalue = frame
|
||||
.values
|
||||
.get(&arg)
|
||||
.ok_or_else(|| format!("Unset SSA value: {}", arg))
|
||||
.unwrap();
|
||||
assert_eq!(multivalue.len(), 1);
|
||||
multivalue[0]
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
self.trace_log.push((id, args));
|
||||
smallvec![]
|
||||
}
|
||||
&ValueDef::None | &ValueDef::Placeholder(..) | &ValueDef::BlockParam(..) => {
|
||||
unreachable!();
|
||||
}
|
||||
|
@ -165,7 +205,7 @@ impl InterpContext {
|
|||
|
||||
match &body.blocks[frame.cur_block].terminator {
|
||||
&Terminator::None => unreachable!(),
|
||||
&Terminator::Unreachable => return None,
|
||||
&Terminator::Unreachable => return InterpResult::Trap,
|
||||
&Terminator::Br { ref target } => {
|
||||
frame.apply_target(body, target);
|
||||
}
|
||||
|
@ -206,15 +246,15 @@ impl InterpContext {
|
|||
})
|
||||
.collect();
|
||||
log::trace!("returning from {}: {:?}", func, values);
|
||||
return Some(values);
|
||||
return InterpResult::Ok(values);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn call_import(&mut self, name: &str, args: &[ConstVal]) -> Option<SmallVec<[ConstVal; 2]>> {
|
||||
fn call_import(&mut self, name: &str, args: &[ConstVal]) -> InterpResult {
|
||||
if let Some(ret) = wasi::call_wasi(&mut self.memories[Memory::from(0)], name, args) {
|
||||
return Some(ret);
|
||||
return ret;
|
||||
}
|
||||
panic!("Unknown import: {} with args: {:?}", name, args);
|
||||
}
|
||||
|
|
|
@ -1,32 +1,28 @@
|
|||
//! Very basic WASI implementation for interpreter: sufficient to let stdout work.
|
||||
|
||||
use crate::interp::{read_u32, write_u32, ConstVal, InterpMemory};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use crate::interp::{read_u32, write_u32, ConstVal, InterpMemory, InterpResult};
|
||||
use smallvec::smallvec;
|
||||
|
||||
pub fn call_wasi(
|
||||
mem: &mut InterpMemory,
|
||||
name: &str,
|
||||
args: &[ConstVal],
|
||||
) -> Option<SmallVec<[ConstVal; 2]>> {
|
||||
pub fn call_wasi(mem: &mut InterpMemory, name: &str, args: &[ConstVal]) -> Option<InterpResult> {
|
||||
match name {
|
||||
"fd_prestat_get" => {
|
||||
Some(smallvec![ConstVal::I32(8)]) // BADF
|
||||
Some(InterpResult::Ok(smallvec![ConstVal::I32(8)])) // BADF
|
||||
}
|
||||
"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)])
|
||||
Some(InterpResult::Ok(smallvec![ConstVal::I32(0)]))
|
||||
}
|
||||
"environ_sizes_get" => {
|
||||
let p_environ_count = args[0].as_u32().unwrap();
|
||||
let p_environ_buf_size = args[0].as_u32().unwrap();
|
||||
write_u32(mem, p_environ_count, 0);
|
||||
write_u32(mem, p_environ_buf_size, 0);
|
||||
Some(smallvec![ConstVal::I32(0)])
|
||||
Some(InterpResult::Ok(smallvec![ConstVal::I32(0)]))
|
||||
}
|
||||
"args_get" => Some(smallvec![ConstVal::I32(0)]),
|
||||
"args_get" => Some(InterpResult::Ok(smallvec![ConstVal::I32(0)])),
|
||||
"fd_fdstat_get" => {
|
||||
let fd = args[0].as_u32().unwrap();
|
||||
let p_fdstat_t = args[1].as_u32().unwrap();
|
||||
|
@ -35,7 +31,7 @@ pub fn call_wasi(
|
|||
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)])
|
||||
Some(InterpResult::Ok(smallvec![ConstVal::I32(0)]))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -56,24 +52,24 @@ pub fn call_wasi(
|
|||
written += len;
|
||||
}
|
||||
write_u32(mem, p_nwritten, written as u32);
|
||||
Some(smallvec![ConstVal::I32(0)])
|
||||
Some(InterpResult::Ok(smallvec![ConstVal::I32(0)]))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
"proc_exit" => {
|
||||
eprintln!("WASI exit: {:?}", args[0]);
|
||||
None
|
||||
Some(InterpResult::Exit)
|
||||
}
|
||||
"clock_time_get" => {
|
||||
let p_time = args[2].as_u32().unwrap();
|
||||
write_u32(mem, p_time, 0);
|
||||
Some(smallvec![ConstVal::I32(0)])
|
||||
Some(InterpResult::Ok(smallvec![ConstVal::I32(0)]))
|
||||
}
|
||||
"clock_res_get" => {
|
||||
let p_res = args[1].as_u32().unwrap();
|
||||
write_u32(mem, p_res, 1);
|
||||
Some(smallvec![ConstVal::I32(0)])
|
||||
Some(InterpResult::Ok(smallvec![ConstVal::I32(0)]))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ pub enum ValueDef {
|
|||
PickOutput(Value, usize, Type),
|
||||
Alias(Value),
|
||||
Placeholder(Type),
|
||||
Trace(usize, Vec<Value>),
|
||||
#[default]
|
||||
None,
|
||||
}
|
||||
|
@ -20,6 +21,7 @@ impl ValueDef {
|
|||
&ValueDef::Operator(_, _, ref tys) if tys.len() == 1 => Some(tys[0]),
|
||||
&ValueDef::PickOutput(_, _, ty) => Some(ty),
|
||||
&ValueDef::Placeholder(ty) => Some(ty),
|
||||
&ValueDef::Trace(_, _) => None,
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +47,11 @@ impl ValueDef {
|
|||
&ValueDef::PickOutput(from, ..) => f(from),
|
||||
&ValueDef::Alias(value) => f(value),
|
||||
&ValueDef::Placeholder(_) => {}
|
||||
&ValueDef::Trace(_, ref args) => {
|
||||
for &arg in args {
|
||||
f(arg);
|
||||
}
|
||||
}
|
||||
&ValueDef::None => panic!(),
|
||||
}
|
||||
}
|
||||
|
@ -60,6 +67,11 @@ impl ValueDef {
|
|||
&mut ValueDef::PickOutput(ref mut from, ..) => f(from),
|
||||
&mut ValueDef::Alias(ref mut value) => f(value),
|
||||
&mut ValueDef::Placeholder(_) => {}
|
||||
&mut ValueDef::Trace(_, ref mut args) => {
|
||||
for arg in args {
|
||||
f(arg);
|
||||
}
|
||||
}
|
||||
&mut ValueDef::None => panic!(),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue