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