Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 10 additions & 16 deletions src/bin/wasmtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,15 @@ use docopt::Docopt;
use failure::{bail, Error, ResultExt};
use pretty_env_logger;
use serde::Deserialize;
use std::cell::RefCell;
use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs::File;
use std::path::Component;
use std::path::{Path, PathBuf};
use std::process::exit;
use std::rc::Rc;
use wabt;
use wasi_common::preopen_dir;
use wasmtime_api::{Config, Engine, Instance, Module, Store};
use wasmtime_api::{Config, Engine, HostRef, Instance, Module, Store};
use wasmtime_environ::cache_config;
use wasmtime_interface_types::ModuleData;
use wasmtime_jit::Features;
Expand Down Expand Up @@ -258,8 +256,8 @@ fn rmain() -> Result<(), Error> {
}

let config = Config::new(settings::Flags::new(flag_builder), features, debug_info);
let engine = Rc::new(RefCell::new(Engine::new(config)));
let store = Rc::new(RefCell::new(Store::new(engine)));
let engine = HostRef::new(Engine::new(config));
let store = HostRef::new(Store::new(engine));

let mut module_registry = HashMap::new();

Expand Down Expand Up @@ -308,14 +306,14 @@ fn rmain() -> Result<(), Error> {
}

fn instantiate_module(
store: Rc<RefCell<Store>>,
store: HostRef<Store>,
module_registry: &HashMap<String, (Instance, HashMap<String, usize>)>,
path: &Path,
) -> Result<(Rc<RefCell<Instance>>, Rc<RefCell<Module>>, Vec<u8>), Error> {
) -> Result<(HostRef<Instance>, HostRef<Module>, Vec<u8>), Error> {
// Read the wasm module binary.
let data = read_wasm(path.to_path_buf())?;

let module = Rc::new(RefCell::new(Module::new(store.clone(), &data)?));
let module = HostRef::new(Module::new(store.clone(), &data)?);

// Resolve import using module_registry.
let imports = module
Expand All @@ -341,17 +339,13 @@ fn instantiate_module(
})
.collect::<Result<Vec<_>, _>>()?;

let instance = Rc::new(RefCell::new(Instance::new(
store.clone(),
module.clone(),
&imports,
)?));
let instance = HostRef::new(Instance::new(store.clone(), module.clone(), &imports)?);

Ok((instance, module, data))
}

fn handle_module(
store: Rc<RefCell<Store>>,
store: HostRef<Store>,
module_registry: &HashMap<String, (Instance, HashMap<String, usize>)>,
args: &Args,
path: &Path,
Expand All @@ -368,8 +362,8 @@ fn handle_module(
}

fn invoke_export(
store: Rc<RefCell<Store>>,
instance: Rc<RefCell<Instance>>,
store: HostRef<Store>,
instance: HostRef<Instance>,
data: &ModuleData,
name: &str,
args: &Args,
Expand Down
12 changes: 5 additions & 7 deletions wasmtime-api/examples/gcd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,18 @@
//! invoking its exported function.

use failure::{format_err, Error};
use std::cell::RefCell;
use std::fs::read;
use std::rc::Rc;
use wasmtime_api::*;

fn main() -> Result<(), Error> {
let wasm = read("examples/gcd.wasm")?;

// Instantiate engine and store.
let engine = Rc::new(RefCell::new(Engine::default()));
let store = Rc::new(RefCell::new(Store::new(engine)));
let engine = HostRef::new(Engine::default());
let store = HostRef::new(Store::new(engine));

// Load a module.
let module = Rc::new(RefCell::new(Module::new(store.clone(), &wasm)?));
let module = HostRef::new(Module::new(store.clone(), &wasm)?);

// Find index of the `gcd` export.
let gcd_index = module
Expand All @@ -28,12 +26,12 @@ fn main() -> Result<(), Error> {
.0;

// Instantiate the module.
let instance = Rc::new(RefCell::new(Instance::new(store.clone(), module, &[])?));
let instance = HostRef::new(Instance::new(store.clone(), module, &[])?);

// Invoke `gcd` export
let gcd = instance.borrow().exports()[gcd_index]
.borrow()
.func()
.expect("gcd")
.clone();
let result = gcd
.borrow()
Expand Down
72 changes: 72 additions & 0 deletions wasmtime-api/examples/hello.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//! Translation of hello example

use failure::{bail, format_err, Error};
use std::cell::Ref;
use std::fs::read;
use std::rc::Rc;
use wasmtime_api::*;

struct HelloCallback;

impl Callable for HelloCallback {
fn call(&self, _params: &[Val], _results: &mut [Val]) -> Result<(), HostRef<Trap>> {
println!("Calling back...");
println!("> Hello World!");
Ok(())
}
}

fn main() -> Result<(), Error> {
// Initialize.
println!("Initializing...");
let engine = HostRef::new(Engine::new(Config::default()));
let store = HostRef::new(Store::new(engine));

// Load binary.
println!("Loading binary...");
let binary = read("examples/hello.wasm")?;

// Compile.
println!("Compiling module...");
let module = HostRef::new(
Module::new(store.clone(), &binary)
.map_err(|_| format_err!("> Error compiling module!"))?,
);

// Create external print functions.
println!("Creating callback...");
let hello_type = FuncType::new(Box::new([]), Box::new([]));
let hello_func = HostRef::new(Func::new(store.clone(), hello_type, Rc::new(HelloCallback)));

// Instantiate.
println!("Instantiating module...");
let imports = vec![hello_func.into()];
let instance = HostRef::new(
Instance::new(store.clone(), module, imports.as_slice())
.map_err(|_| format_err!("> Error instantiating module!"))?,
);

// Extract export.
println!("Extracting export...");
let exports = Ref::map(instance.borrow(), |instance| instance.exports());
if exports.len() == 0 {
bail!("> Error accessing exports!");
}
let run_func = exports[0]
.func()
.ok_or_else(|| format_err!("> Error accessing exports!"))?;

// Call.
println!("Calling export...");
if let Err(_) = run_func.borrow().call(&[]) {
bail!("> Error calling function!");
}

// Shut down.
println!("Shutting down...");
drop(store);

// All done.
println!("Done.");
Ok(())
}
Binary file added wasmtime-api/examples/hello.wasm
Binary file not shown.
4 changes: 4 additions & 0 deletions wasmtime-api/examples/hello.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(module
(func $hello (import "" "hello"))
(func (export "run") (call $hello))
)
160 changes: 160 additions & 0 deletions wasmtime-api/examples/memory.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
//! Translation of the memory example

use failure::{bail, format_err, Error};
use std::cell::Ref;
use std::fs::read;
use wasmtime_api::*;

fn get_export_memory(exports: &[Extern], i: usize) -> Result<HostRef<Memory>, Error> {
if exports.len() <= i {
bail!("> Error accessing memory export {}!", i);
}
Ok(exports[i]
.memory()
.ok_or_else(|| format_err!("> Error accessing memory export {}!", i))?
.clone())
}

fn get_export_func(exports: &[Extern], i: usize) -> Result<HostRef<Func>, Error> {
if exports.len() <= i {
bail!("> Error accessing function export {}!", i);
}
Ok(exports[i]
.func()
.ok_or_else(|| format_err!("> Error accessing function export {}!", i))?
.clone())
}

macro_rules! check {
($actual:expr, $expected:expr) => {
if $actual != $expected {
bail!("> Error on result, expected {}, got {}", $expected, $actual);
}
};
}

macro_rules! check_ok {
($func:expr, $($p:expr),*) => {
if let Err(_) = $func.borrow().call(&[$($p.into()),*]) {
bail!("> Error on result, expected return");
}
}
}

macro_rules! check_trap {
($func:expr, $($p:expr),*) => {
if let Ok(_) = $func.borrow().call(&[$($p.into()),*]) {
bail!("> Error on result, expected trap");
}
}
}

macro_rules! call {
($func:expr, $($p:expr),*) => {
match $func.borrow().call(&[$($p.into()),*]) {
Ok(result) => {
let result: i32 = result[0].clone().into();
result
}
Err(_) => { bail!("> Error on result, expected return"); }
}
}
}

fn main() -> Result<(), Error> {
// Initialize.
println!("Initializing...");
let engine = HostRef::new(Engine::new(Config::default()));
let store = HostRef::new(Store::new(engine));

// Load binary.
println!("Loading binary...");
let binary = read("examples/memory.wasm")?;

// Compile.
println!("Compiling module...");
let module = HostRef::new(
Module::new(store.clone(), &binary)
.map_err(|_| format_err!("> Error compiling module!"))?,
);

// Instantiate.
println!("Instantiating module...");
let instance = HostRef::new(
Instance::new(store.clone(), module, &[])
.map_err(|_| format_err!("> Error instantiating module!"))?,
);

// Extract export.
println!("Extracting export...");
let exports = Ref::map(instance.borrow(), |instance| instance.exports());
if exports.len() == 0 {
bail!("> Error accessing exports!");
}
let memory = get_export_memory(&exports, 0)?;
let size_func = get_export_func(&exports, 1)?;
let load_func = get_export_func(&exports, 2)?;
let store_func = get_export_func(&exports, 3)?;

// Try cloning.
check!(memory.clone().ptr_eq(&memory), true);

// Check initial memory.
println!("Checking memory...");
check!(memory.borrow().size(), 2u32);
check!(memory.borrow().data_size(), 0x20000usize);
check!(unsafe { memory.borrow().data()[0] }, 0);
check!(unsafe { memory.borrow().data()[0x1000] }, 1);
check!(unsafe { memory.borrow().data()[0x1003] }, 4);

check!(call!(size_func,), 2);
check!(call!(load_func, 0), 0);
check!(call!(load_func, 0x1000), 1);
check!(call!(load_func, 0x1003), 4);
check!(call!(load_func, 0x1ffff), 0);
check_trap!(load_func, 0x20000);

// Mutate memory.
println!("Mutating memory...");
unsafe {
memory.borrow_mut().data()[0x1003] = 5;
}

check_ok!(store_func, 0x1002, 6);
check_trap!(store_func, 0x20000, 0);

check!(unsafe { memory.borrow().data()[0x1002] }, 6);
check!(unsafe { memory.borrow().data()[0x1003] }, 5);
check!(call!(load_func, 0x1002), 6);
check!(call!(load_func, 0x1003), 5);

// Grow memory.
println!("Growing memory...");
check!(memory.borrow_mut().grow(1), true);
check!(memory.borrow().size(), 3u32);
check!(memory.borrow().data_size(), 0x30000usize);

check!(call!(load_func, 0x20000), 0);
check_ok!(store_func, 0x20000, 0);
check_trap!(load_func, 0x30000);
check_trap!(store_func, 0x30000, 0);

check!(memory.borrow_mut().grow(1), false);
check!(memory.borrow_mut().grow(0), true);

// Create stand-alone memory.
// TODO(wasm+): Once Wasm allows multiple memories, turn this into import.
println!("Creating stand-alone memory...");
let memorytype = MemoryType::new(Limits::new(5, 5));
let mut memory2 = Memory::new(store.clone(), memorytype);
check!(memory2.size(), 5u32);
check!(memory2.grow(1), false);
check!(memory2.grow(0), true);

// Shut down.
println!("Shutting down...");
drop(store);

println!("Done.");
Ok(())
}
Binary file added wasmtime-api/examples/memory.wasm
Binary file not shown.
11 changes: 11 additions & 0 deletions wasmtime-api/examples/memory.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
(module
(memory (export "memory") 2 3)

(func (export "size") (result i32) (memory.size))
(func (export "load") (param i32) (result i32) (i32.load8_s (local.get 0)))
(func (export "store") (param i32 i32)
(i32.store8 (local.get 0) (local.get 1))
)

(data (i32.const 0x1000) "\01\02\03\04")
)
Loading