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;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
mod wasi;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct InterpContext {
|
pub struct InterpContext {
|
||||||
memories: PerEntity<Memory, InterpMemory>,
|
memories: PerEntity<Memory, InterpMemory>,
|
||||||
|
@ -201,59 +203,10 @@ 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]>> {
|
||||||
let mem = &mut self.memories[Memory::from(0)];
|
if let Some(ret) = wasi::call_wasi(&mut self.memories[Memory::from(0)], name, args) {
|
||||||
match name {
|
return Some(ret);
|
||||||
"__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),
|
|
||||||
}
|
}
|
||||||
|
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;
|
let addr = addr as usize;
|
||||||
mem.data[addr]
|
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;
|
use std::convert::TryInto;
|
||||||
let addr = addr as usize;
|
let addr = addr as usize;
|
||||||
u16::from_le_bytes(mem.data[addr..(addr + 2)].try_into().unwrap())
|
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;
|
use std::convert::TryInto;
|
||||||
let addr = addr as usize;
|
let addr = addr as usize;
|
||||||
u32::from_le_bytes(mem.data[addr..(addr + 4)].try_into().unwrap())
|
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;
|
use std::convert::TryInto;
|
||||||
let addr = addr as usize;
|
let addr = addr as usize;
|
||||||
u64::from_le_bytes(mem.data[addr..(addr + 8)].try_into().unwrap())
|
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;
|
let addr = addr as usize;
|
||||||
mem.data[addr] = data;
|
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;
|
let addr = addr as usize;
|
||||||
mem.data[addr..(addr + 2)].copy_from_slice(&data.to_le_bytes()[..]);
|
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;
|
let addr = addr as usize;
|
||||||
mem.data[addr..(addr + 4)].copy_from_slice(&data.to_le_bytes()[..]);
|
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;
|
let addr = addr as usize;
|
||||||
mem.data[addr..(addr + 8)].copy_from_slice(&data.to_le_bytes()[..]);
|
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