Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
neri committed Jun 22, 2024
1 parent 1ca807c commit dda9c39
Show file tree
Hide file tree
Showing 9 changed files with 138 additions and 89 deletions.
7 changes: 7 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"rust-analyzer.linkedProjects": [
"./Cargo.toml",
"./example/cli/Cargo.toml",
"./example/hello/Cargo.toml",
]
}
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
cargo-features = ["edition2024"]

[package]
authors = ["Nerry <[email protected]>"]
edition = "2021"
edition = "2024"
name = "wami"
version = "0.1.0"

Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ trait Hello {
}
```


## License

MIT License
Expand Down
4 changes: 3 additions & 1 deletion example/cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
cargo-features = ["edition2024"]

[package]
authors = ["Nerry <[email protected]>"]
edition = "2021"
edition = "2024"
name = "cli"
version = "0.1.0"

Expand Down
5 changes: 4 additions & 1 deletion example/hello/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
cargo-features = ["edition2024"]


[package]
authors = ["Nerry <[email protected]>"]
edition = "2021"
edition = "2024"
name = "hello"
version = "0.1.0"

Expand Down
14 changes: 12 additions & 2 deletions lib/wami_macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ macro_rules! unexpected_token {

/// A Macro to automatically generate WebAssembly import resolver from `impl`
///
/// - parameter: module name (default name is "env")
/// Valid forms are:
///
/// * `#[wasm_env]`
/// * `#[wasm_env(ident)]` - *ident*: module name, default name is `env`
#[proc_macro_attribute]
pub fn wasm_env(attr: TokenStream, input: TokenStream) -> TokenStream {
// println!("INPUT: {:?}", input.to_string());
Expand Down Expand Up @@ -179,7 +182,14 @@ let {} = {{
input_
}

/// A Macro to automatically generate WebAssembly exports from `trait`
/// A Macro to automatically generate WebAssembly exports from `trait`.
///
/// The `trait` defined by this macro is automatically implemented in `instance.exports()` with a slightly modified function signature.
/// For example, the signature of the function `fn main()` is converted to `fn main(&self) -> WasmResult<()>`.
///
/// Valid forms are:
///
/// * `#[wasm_exports]`
#[proc_macro_attribute]
pub fn wasm_exports(_attr: TokenStream, input: TokenStream) -> TokenStream {
// println!("INPUT: {:?}", input.to_string());
Expand Down
140 changes: 70 additions & 70 deletions src/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,76 +4,6 @@ use crate::*;
use core::mem::transmute;
use core::sync::atomic::{AtomicU32, AtomicU64, Ordering};

pub trait WasmGlobalProp<T>
where
T: Copy,
{
fn get(&self) -> Result<T, WasmRuntimeErrorKind>;
}

pub trait WasmGlobalPropMut<T>: WasmGlobalProp<T>
where
T: Copy,
{
fn set(&self, value: T) -> Result<(), WasmRuntimeErrorKind>;
}

pub struct WasmGlobalFixedValue<T> {
value: T,
}

impl<T> WasmGlobalFixedValue<T> {
#[inline]
pub const fn new(value: T) -> Self {
Self { value }
}
}

impl<T: Copy> WasmGlobalProp<T> for WasmGlobalFixedValue<T> {
#[inline]
fn get(&self) -> Result<T, WasmRuntimeErrorKind> {
Ok(self.value)
}
}

macro_rules! decl_wasm_global_atomics {
($class_name:ident, $val_type:ident, $atomic_type:ident) => {
pub struct $class_name {
value: $atomic_type,
}

impl $class_name {
#[inline]
pub const fn new(value: $val_type) -> Self {
Self {
value: $atomic_type::new(unsafe { transmute(value) }),
}
}
}

impl WasmGlobalProp<$val_type> for $class_name {
#[inline]
fn get(&self) -> Result<$val_type, WasmRuntimeErrorKind> {
Ok(unsafe { transmute(self.value.load(Ordering::Relaxed)) })
}
}

impl WasmGlobalPropMut<$val_type> for $class_name {
#[inline]
fn set(&self, value: $val_type) -> Result<(), WasmRuntimeErrorKind> {
self.value
.store(unsafe { transmute(value) }, Ordering::SeqCst);
Ok(())
}
}
};
}

decl_wasm_global_atomics!(WasmGlobalI32, i32, AtomicU32);
decl_wasm_global_atomics!(WasmGlobalI64, i64, AtomicU64);
decl_wasm_global_atomics!(WasmGlobalF32, f32, AtomicU32);
decl_wasm_global_atomics!(WasmGlobalF64, f64, AtomicU64);

/// WebAssembly global variable
pub enum WasmGlobal {
I32(Box<dyn WasmGlobalProp<i32>>),
Expand Down Expand Up @@ -155,6 +85,20 @@ impl WasmGlobal {
}
}

pub trait WasmGlobalProp<T>
where
T: Copy,
{
fn get(&self) -> Result<T, WasmRuntimeErrorKind>;
}

pub trait WasmGlobalPropMut<T>: WasmGlobalProp<T>
where
T: Copy,
{
fn set(&self, value: T) -> Result<(), WasmRuntimeErrorKind>;
}

pub trait Get<T> {
fn get(&self) -> Result<T, WasmRuntimeErrorKind>;
}
Expand Down Expand Up @@ -190,3 +134,59 @@ impl_get_set!(i32, I32, I32Mut);
impl_get_set!(i64, I64, I64Mut);
impl_get_set!(f32, F32, F32Mut);
impl_get_set!(f64, F64, F64Mut);

pub struct WasmGlobalFixedValue<T> {
value: T,
}

impl<T> WasmGlobalFixedValue<T> {
#[inline]
pub const fn new(value: T) -> Self {
Self { value }
}
}

impl<T: Copy> WasmGlobalProp<T> for WasmGlobalFixedValue<T> {
#[inline]
fn get(&self) -> Result<T, WasmRuntimeErrorKind> {
Ok(self.value)
}
}

macro_rules! decl_wasm_global_atomics {
($class_name:ident, $val_type:ident, $atomic_type:ident) => {
pub struct $class_name {
value: $atomic_type,
}

impl $class_name {
#[inline]
pub const fn new(value: $val_type) -> Self {
Self {
value: $atomic_type::new(unsafe { transmute(value) }),
}
}
}

impl WasmGlobalProp<$val_type> for $class_name {
#[inline]
fn get(&self) -> Result<$val_type, WasmRuntimeErrorKind> {
Ok(unsafe { transmute(self.value.load(Ordering::Relaxed)) })
}
}

impl WasmGlobalPropMut<$val_type> for $class_name {
#[inline]
fn set(&self, value: $val_type) -> Result<(), WasmRuntimeErrorKind> {
self.value
.store(unsafe { transmute(value) }, Ordering::SeqCst);
Ok(())
}
}
};
}

decl_wasm_global_atomics!(WasmGlobalI32, i32, AtomicU32);
decl_wasm_global_atomics!(WasmGlobalI64, i64, AtomicU64);
decl_wasm_global_atomics!(WasmGlobalF32, f32, AtomicU32);
decl_wasm_global_atomics!(WasmGlobalF64, f64, AtomicU64);
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! WebAssembly Interpreter
#![cfg_attr(not(test), no_std)]
#![deny(unsafe_op_in_unsafe_fn)]
//
#![feature(float_minimum_maximum)]
#![feature(negative_impls)]
Expand Down Expand Up @@ -31,6 +30,7 @@ mod tests;

pub mod prelude {
pub use crate::cg::intr::WasmRuntimeError;
pub use crate::global::*;
pub use crate::memory::{WasmMemory, WasmPtr, WasmPtrMut};
pub use crate::{
WasmArgs, WasmCompileError, WasmCompileErrorKind, WasmDynResult, WasmEnv, WasmExports,
Expand Down
50 changes: 38 additions & 12 deletions src/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,9 @@ impl WasmModule {
WasmSectionId::Export => module.parse_sec_export(section)?,
WasmSectionId::Start => module.parse_sec_start(section)?,
WasmSectionId::Element => module.parse_sec_elem(section)?,
WasmSectionId::DataCount => module.parse_sec_data_count(section)?,
WasmSectionId::Code => module.parse_sec_code(section)?,
WasmSectionId::Data => module.parse_sec_data(section)?,
WasmSectionId::DataCount => module.parse_sec_data_count(section)?,
};
}

Expand All @@ -231,12 +231,12 @@ impl WasmModule {
pub fn instantiate<Env: WasmEnv>(mut self, env: &Env) -> Result<WasmInstance, Box<dyn Error>> {
let mut func_idx = 0;
for import in &self.imports {
match import.desc {
match &import.desc {
WasmImportDescriptor::Function(type_index) => {
match env.resolve_import_func(
&import.mod_name,
&import.name,
self.type_by_index(type_index),
self.type_by_index(*type_index),
) {
WasmImportFuncResult::Ok(dyn_func) => {
self.functions[func_idx].resolve(dyn_func)?;
Expand All @@ -250,9 +250,12 @@ impl WasmModule {
}
func_idx += 1;
}
WasmImportDescriptor::Memory(_) => {
WasmImportDescriptor::Memory(_limit) => {
// TODO: import memory
}
WasmImportDescriptor::Global(_global) => {
// TODO: import global
}
}
}
Ok(WasmInstance::new(self))
Expand All @@ -272,7 +275,7 @@ impl WasmModule {
fn parse_sec_import(&mut self, mut section: WasmSection) -> Result<(), WasmCompileErrorKind> {
let n_items: usize = section.reader.read()?;
for _ in 0..n_items {
let import = WasmImport::from_reader(&mut section.reader)?;
let import = WasmImport::new(self, &mut section.reader)?;
match import.desc {
WasmImportDescriptor::Function(type_index) => {
let index = self.functions.len();
Expand All @@ -290,6 +293,9 @@ impl WasmModule {
// TODO: import memory
self.memories.push(WasmMemory::new(memtype)?);
}
WasmImportDescriptor::Global(_global) => {
//
}
}
self.imports.push(import);
}
Expand Down Expand Up @@ -630,6 +636,7 @@ impl ImportExportKind {
match *desc {
WasmImportDescriptor::Function(_) => Self::Function,
WasmImportDescriptor::Memory(_) => Self::Memory,
WasmImportDescriptor::Global(_) => Self::Global,
}
}

Expand Down Expand Up @@ -1364,7 +1371,7 @@ impl fmt::Display for WasmType {
/// WebAssembly import object
///
/// It appears as the second section (`0x02`) in the WebAssembly binary.
#[derive(Debug, Clone)]
#[derive(Debug)]
pub struct WasmImport {
mod_name: String,
name: String,
Expand All @@ -1373,10 +1380,13 @@ pub struct WasmImport {

impl WasmImport {
#[inline]
fn from_reader(reader: &mut Leb128Reader) -> Result<Self, WasmCompileErrorKind> {
fn new(
module: &mut WasmModule,
reader: &mut Leb128Reader,
) -> Result<Self, WasmCompileErrorKind> {
let mod_name = reader.get_string()?;
let name = reader.get_string()?;
let desc = WasmImportDescriptor::from_reader(reader)?;
let desc = WasmImportDescriptor::new(module, reader)?;

Ok(Self {
mod_name,
Expand All @@ -1386,17 +1396,20 @@ impl WasmImport {
}
}

#[derive(Debug, Copy, Clone)]
#[derive(Debug, Clone, Copy)]
pub enum WasmImportDescriptor {
Function(WasmTypeIndex),
// Table(_),
Memory(WasmLimit),
// Global(_),
Global(GlobalVarIndex),
}

impl WasmImportDescriptor {
#[inline]
fn from_reader(mut reader: &mut Leb128Reader) -> Result<Self, WasmCompileErrorKind> {
fn new(
module: &mut WasmModule,
mut reader: &mut Leb128Reader,
) -> Result<Self, WasmCompileErrorKind> {
let import_type = reader.read_byte()?;
match import_type {
0 => reader
Expand All @@ -1405,7 +1418,20 @@ impl WasmImportDescriptor {
.map_err(|v| v.into()),
// 1 => reader.read().map(|v| Self::Table(v)),
2 => WasmLimit::from_reader(&mut reader, true).map(|v| Self::Memory(v)),
// 3 => reader.read().map(|v| Self::Global(v)),
3 => {
let val_type = reader
.read()
.map_err(|v| v.into())
.and_then(|v| WasmValType::from_i64(v))?;
let is_mutable = reader.read_byte()? == 1;
let value = WasmValue::default_for(val_type);
let global = WasmGlobal::new(value, is_mutable);
module.globals.push(global);

Ok(Self::Global(unsafe {
GlobalVarIndex::new(module.globals.len() as u32)
}))
}
_ => Err(WasmCompileErrorKind::UnexpectedToken),
}
}
Expand Down

0 comments on commit dda9c39

Please sign in to comment.