Separate out barebones WASI impl
This commit is contained in:
parent
49a907da25
commit
c01e07977a
|
@ -7,6 +7,8 @@ use smallvec::{smallvec, SmallVec};
|
|||
|
||||
use std::collections::HashMap;
|
||||
|
||||
mod wasi;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct InterpContext {
|
||||
memories: PerEntity<Memory, InterpMemory>,
|
||||
|
@ -201,59 +203,10 @@ impl InterpContext {
|
|||
}
|
||||
|
||||
fn call_import(&mut self, name: &str, args: &[ConstVal]) -> Option<SmallVec<[ConstVal; 2]>> {
|
||||
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),
|
||||
if let Some(ret) = wasi::call_wasi(&mut self.memories[Memory::from(0)], name, args) {
|
||||
return Some(ret);
|
||||
}
|
||||
panic!("Unknown import: {} with args: {:?}", name, args);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -888,45 +841,45 @@ pub fn const_eval(
|
|||
}
|
||||
}
|
||||
|
||||
fn read_u8(mem: &InterpMemory, addr: u32) -> u8 {
|
||||
pub(crate) fn read_u8(mem: &InterpMemory, addr: u32) -> u8 {
|
||||
let addr = addr as usize;
|
||||
mem.data[addr]
|
||||
}
|
||||
|
||||
fn read_u16(mem: &InterpMemory, addr: u32) -> u16 {
|
||||
pub(crate) fn read_u16(mem: &InterpMemory, addr: u32) -> u16 {
|
||||
use std::convert::TryInto;
|
||||
let addr = addr as usize;
|
||||
u16::from_le_bytes(mem.data[addr..(addr + 2)].try_into().unwrap())
|
||||
}
|
||||
|
||||
fn read_u32(mem: &InterpMemory, addr: u32) -> u32 {
|
||||
pub(crate) fn read_u32(mem: &InterpMemory, addr: u32) -> u32 {
|
||||
use std::convert::TryInto;
|
||||
let addr = addr as usize;
|
||||
u32::from_le_bytes(mem.data[addr..(addr + 4)].try_into().unwrap())
|
||||
}
|
||||
|
||||
fn read_u64(mem: &InterpMemory, addr: u32) -> u64 {
|
||||
pub(crate) fn read_u64(mem: &InterpMemory, addr: u32) -> u64 {
|
||||
use std::convert::TryInto;
|
||||
let addr = addr as usize;
|
||||
u64::from_le_bytes(mem.data[addr..(addr + 8)].try_into().unwrap())
|
||||
}
|
||||
|
||||
fn write_u8(mem: &mut InterpMemory, addr: u32, data: u8) {
|
||||
pub(crate) fn write_u8(mem: &mut InterpMemory, addr: u32, data: u8) {
|
||||
let addr = addr as usize;
|
||||
mem.data[addr] = data;
|
||||
}
|
||||
|
||||
fn write_u16(mem: &mut InterpMemory, addr: u32, data: u16) {
|
||||
pub(crate) fn write_u16(mem: &mut InterpMemory, addr: u32, data: u16) {
|
||||
let addr = addr as usize;
|
||||
mem.data[addr..(addr + 2)].copy_from_slice(&data.to_le_bytes()[..]);
|
||||
}
|
||||
|
||||
fn write_u32(mem: &mut InterpMemory, addr: u32, data: u32) {
|
||||
pub(crate) fn write_u32(mem: &mut InterpMemory, addr: u32, data: u32) {
|
||||
let addr = addr as usize;
|
||||
mem.data[addr..(addr + 4)].copy_from_slice(&data.to_le_bytes()[..]);
|
||||
}
|
||||
|
||||
fn write_u64(mem: &mut InterpMemory, addr: u32, data: u64) {
|
||||
pub(crate) fn write_u64(mem: &mut InterpMemory, addr: u32, data: u64) {
|
||||
let addr = addr as usize;
|
||||
mem.data[addr..(addr + 8)].copy_from_slice(&data.to_le_bytes()[..]);
|
||||
}
|
||||
|
|
63
src/interp/wasi.rs
Normal file
63
src/interp/wasi.rs
Normal file
|
@ -0,0 +1,63 @@
|
|||
//! Very basic WASI implementation for interpreter: sufficient to let stdout work.
|
||||
|
||||
use crate::interp::{read_u32, write_u32, ConstVal, InterpMemory};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
|
||||
pub fn call_wasi(
|
||||
mem: &mut InterpMemory,
|
||||
name: &str,
|
||||
args: &[ConstVal],
|
||||
) -> Option<SmallVec<[ConstVal; 2]>> {
|
||||
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
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue