Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
neri committed Sep 22, 2024
1 parent 2ec7298 commit 3478105
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 55 deletions.
4 changes: 2 additions & 2 deletions lib/wami_macro/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ version = "0.1.0"
proc-macro = true

[dependencies]
syn = {version = "2.0.72", features = ["full", "extra-traits","printing"]}
quote = {version = "1.0.36"}
syn = {version = "2.0.77", features = ["full", "extra-traits","printing"]}
quote = {version = "1.0.37"}
30 changes: 28 additions & 2 deletions lib/wami_macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,9 +254,9 @@ pub fn wasm_exports(_attr: TokenStream, input: TokenStream) -> TokenStream {
output_impl.push(format!("let args = [{}];", push_args.join(",")));
output_impl.push(format!(
"self.instance().exports().get({:?})
.ok_or(WasmRuntimeErrorKind::NoMethod.into())
.ok_or(WasmRuntimeErrorKind::NoMethod({:?}.to_owned()).into())
.and_then(|v| v.invoke(&args))",
func_name
func_name, func_name,
));
match result_type {
Some(ref result_type) => output_impl.push(format!(
Expand Down Expand Up @@ -360,6 +360,13 @@ impl ParsedType {
Some(path)
}
syn::Type::Reference(reference) => {
if options.allow_intrinsics {
if let Some(intrinsics) =
IntrinsicType::from_ref(reference.elem.as_ref(), options)
{
return Some(ParsedType::IntrinsicType(intrinsics));
}
}
if options.allow_reference {
Self::new(
reference.elem.as_ref(),
Expand Down Expand Up @@ -625,6 +632,25 @@ impl IntrinsicType {
}
}

pub fn from_ref(ty: &syn::Type, options: ParseOption) -> Option<Self> {
// For some reason it is not always possible to get the content of the `span` in the usual way
let _ = options;
match ty {
syn::Type::Path(type_path) => {
let mut segments = type_path.path.segments.iter();
let Some(first_elem) = segments.next() else {
return None;
};
match first_elem.ident.to_string().as_str() {
"WasmInstance" => Some(Self::WasmInstance),
"str" => Some(Self::Str),
_ => None,
}
}
_ => None,
}
}

pub fn to_string(&self) -> Cow<'static, str> {
match self {
Self::WasmInstance => Cow::Borrowed("&WasmInstance"),
Expand Down
87 changes: 70 additions & 17 deletions src/cg/intr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::memory::WasmMemory;
use crate::stack::*;
use crate::wasm::*;
use crate::*;
use alloc::format;
use core::error::Error;
use core::iter;
use core::mem::{size_of, transmute};
Expand All @@ -19,6 +20,14 @@ const INITIAL_VALUE_STACK_SIZE: usize = 512;
pub struct WasmInterpreter<'a> {
instance: &'a WasmInstance,
func_index: usize,
stack_trace: Vec<StackTraceEntry>,
}

#[derive(Debug, Clone)]
pub struct StackTraceEntry {
pub func: u32,
pub position: u32,
pub name: Option<String>,
}

impl<'a> WasmInterpreter<'a> {
Expand All @@ -27,6 +36,7 @@ impl<'a> WasmInterpreter<'a> {
Self {
instance,
func_index: 0,
stack_trace: Vec::new(),
}
}
}
Expand All @@ -52,13 +62,24 @@ impl WasmInterpreter<'_> {
.unwrap_or(0)
+ ex_position.position();

let mut stack_trace = self.stack_trace.clone();
for item in stack_trace.iter_mut() {
item.name = self
.instance
.module()
.names()
.and_then(|v| v.func_by_index(item.func as usize))
.map(|v| v.to_owned());
}

Box::new(WasmRuntimeError {
kind,
file_position,
function: self.func_index,
function_name,
position: ex_position.position(),
mnemonic,
stack_trace,
})
}

Expand Down Expand Up @@ -269,7 +290,7 @@ impl WasmInterpreter<'_> {
let index =
unsafe { value_stack.get(code.base_stack_level()).get_i32() as usize };
let func = self.instance.module().elem_get(index).ok_or(self.error(
WasmRuntimeErrorKind::NoMethod,
WasmRuntimeErrorKind::NoMethod(format!("$elem({index})")),
opcode,
ex_position,
))?;
Expand Down Expand Up @@ -1572,6 +1593,11 @@ impl WasmInterpreter<'_> {
locals
};

self.stack_trace.push(StackTraceEntry {
func: self.func_index as u32,
position: ex_position.position() as u32,
name: None,
});
self._interpret(
target.index(),
code_block,
Expand All @@ -1584,6 +1610,7 @@ impl WasmInterpreter<'_> {
let var = value_stack.get_mut(stack_under);
*var = WasmUnionValue::from(result);
}
self.stack_trace.pop();
self.func_index = current_function;
Ok(())
})
Expand Down Expand Up @@ -1612,9 +1639,11 @@ impl WasmInterpreter<'_> {
}
})
}
WasmFunctionContent::Unresolved => {
Err(self.error(WasmRuntimeErrorKind::NoMethod, opcode, ex_position))
}
WasmFunctionContent::Unresolved => Err(self.error(
WasmRuntimeErrorKind::NoMethod(format!("$func({})", target.index())),
opcode,
ex_position,
)),
}
}
}
Expand Down Expand Up @@ -1662,7 +1691,10 @@ impl WasmInvocation for WasmRunnable<'_> {
let code_block = match function.content() {
WasmFunctionContent::CodeBlock(v) => Ok(v),
WasmFunctionContent::Dynamic(_) => Err(WasmRuntimeErrorKind::InvalidParameter),
WasmFunctionContent::Unresolved => Err(WasmRuntimeErrorKind::NoMethod),
WasmFunctionContent::Unresolved => Err(WasmRuntimeErrorKind::NoMethod(format!(
"$func({})",
function.index()
))),
}?;

let mut locals =
Expand Down Expand Up @@ -1699,6 +1731,7 @@ pub struct WasmRuntimeError {
function_name: Option<String>,
position: usize,
mnemonic: WasmMnemonic,
stack_trace: Vec<StackTraceEntry>,
}

impl WasmRuntimeError {
Expand Down Expand Up @@ -1762,6 +1795,7 @@ impl From<WasmRuntimeErrorKind> for Box<dyn Error> {
function_name: None,
position: 0,
mnemonic: WasmMnemonic::Unreachable,
stack_trace: Vec::new(),
})
}
}
Expand All @@ -1770,20 +1804,39 @@ impl fmt::Display for WasmRuntimeError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mnemonic = self.mnemonic();
write!(f, "{:?} at", self.kind())?;
if let Some(function_name) = self.function_name() {
write!(
f,
" {}(${}):{}",
function_name,
self.function(),
self.position(),
)?;
} else {
write!(f, " ${}:{}", self.function(), self.position(),)?;
write!(f, "{:?}", self.kind())?;

// In wasm, positon is never zero.
if self.position() > 0 {
write!(f, "\n at")?;
if let Some(function_name) = self.function_name() {
write!(
f,
" {}(${}):{}",
function_name,
self.function(),
self.position(),
)?;
} else {
write!(f, " ${}:{}", self.function(), self.position(),)?;
}
}
if self.file_position() > 0 {
write!(f, ", 0x{:x}: {:?}", self.file_position(), mnemonic)?;
}

if self.stack_trace.len() > 0 {
writeln!(f, "")?;
for item in self.stack_trace.iter().rev() {
if let Some(name) = item.name.as_ref() {
writeln!(f, " at {}(${}):{}", name, item.func, item.position)?;
} else {
writeln!(f, " at {}:{}", item.func, item.position)?;
}
}
}

write!(f, ", 0x{:x}: {:?}", self.file_position(), mnemonic)
Ok(())
}
}

Expand Down
46 changes: 19 additions & 27 deletions src/stack.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
//! Stack structure for the Webassembly Runtime
use crate::*;
use core::cell::UnsafeCell;
use core::mem::align_of;
use core::mem::size_of;
use core::mem::{self, align_of, size_of};
use core::slice;

/// Fixed size stack
Expand Down Expand Up @@ -38,12 +37,7 @@ impl<T> FixedStack<'_, T> {
}
}

impl<T: Sized> FixedStack<'_, T> {
#[inline]
pub fn remove_all(&mut self) {
while self.pop().is_some() {}
}

impl<T: Copy + Sized> FixedStack<'_, T> {
#[inline]
pub fn last(&self) -> Option<&T> {
if self.stack_pointer > 0 {
Expand Down Expand Up @@ -89,20 +83,20 @@ impl<T: Sized> FixedStack<'_, T> {
}
}

impl<T: Sized + Clone> FixedStack<'_, T> {
#[track_caller]
pub fn resize(&mut self, new_size: usize, new_value: T) {
if new_size < self.slice.len() {
if self.stack_pointer < new_size {
let _ = new_value;
todo!();
}
self.stack_pointer = new_size;
} else {
todo!()
}
}
}
// impl<T: Sized + Clone> FixedStack<'_, T> {
// #[track_caller]
// pub fn resize(&mut self, new_size: usize, new_value: T) {
// if new_size < self.slice.len() {
// if self.stack_pointer < new_size {
// let _ = new_value;
// todo!();
// }
// self.stack_pointer = new_size;
// } else {
// todo!()
// }
// }
// }

/// Shared Stack
pub struct StackHeap {
Expand Down Expand Up @@ -134,17 +128,15 @@ impl StackHeap {
{
let Self { vec, stack_pointer } = self;

let vec = unsafe { vec.get().replace(Vec::new()) };
let vec = UnsafeCell::new(unsafe { vec.get().read() });

let mut child = Self {
vec: UnsafeCell::new(vec),
vec,
stack_pointer: *stack_pointer,
};
let r = f(&mut child);

unsafe {
self.vec.get().replace(child.vec.into_inner());
}
mem::forget(child.vec);

r
}
Expand Down
6 changes: 3 additions & 3 deletions src/tests.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::cg::intr::WasmInterpreter;
use crate::cg::WasmCodeBlock;
use crate::cg::intr::WasmInterpreter;
use crate::opcode::WasmMnemonic;
use crate::prelude::*;
use crate::{leb128::*, WasmSectionId};
use crate::{WasmSectionId, leb128::*};
use core::f64::consts::PI;
use num_traits::Zero;
use std::assert_matches::assert_matches;
Expand Down Expand Up @@ -1297,7 +1297,7 @@ fn call_indirect_test() {
.unwrap_err()
.downcast()
.unwrap();
assert_matches!(err.kind(), WasmRuntimeErrorKind::NoMethod);
assert_matches!(err.kind(), WasmRuntimeErrorKind::NoMethod(_));
}
}

Expand Down
8 changes: 4 additions & 4 deletions src/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,7 @@ impl WasmModule {
}

#[inline]
pub fn custom_sections<'a>(&'a self, section_name: &str) -> Option<&Box<[u8]>> {
pub fn custom_sections(&self, section_name: &str) -> Option<&Box<[u8]>> {
self.custom_sections.get(section_name)
}

Expand Down Expand Up @@ -602,7 +602,7 @@ impl WasmModule {
}
}
}
Err(WasmRuntimeErrorKind::NoMethod)
Err(WasmRuntimeErrorKind::NoMethod(name.to_owned()))
}

#[inline]
Expand Down Expand Up @@ -1733,7 +1733,7 @@ pub enum WasmLinkError {

impl fmt::Display for WasmLinkError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self)
write!(f, "LinkError: {:?}", self)
}
}

Expand All @@ -1756,7 +1756,7 @@ pub enum WasmRuntimeErrorKind {
/// (unrecoverable) Memory Boundary Errors
OutOfBounds,
/// (unrecoverable) The specified function cannot be found.
NoMethod,
NoMethod(String),
/// (unrecoverable) Devide by zero
DivideByZero,
/// (unrecoverable) The type of call instructions do not match.
Expand Down
Binary file modified test/tester.wasm
Binary file not shown.

0 comments on commit 3478105

Please sign in to comment.