Skip to content

Commit

Permalink
Add convenience methods to instance for getting specific extern types.
Browse files Browse the repository at this point in the history
  • Loading branch information
sunfishcode committed Apr 18, 2020
1 parent d1e639f commit 186573c
Show file tree
Hide file tree
Showing 18 changed files with 64 additions and 74 deletions.
2 changes: 1 addition & 1 deletion crates/api/src/externals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,7 @@ impl Memory {
/// let store = Store::default();
/// let module = Module::new(&store, "(module (memory (export \"mem\") 1))")?;
/// let instance = Instance::new(&module, &[])?;
/// let memory = instance.get_export("mem").unwrap().into_memory().unwrap();
/// let memory = instance.get_memory("mem").unwrap();
/// let ty = memory.ty();
/// assert_eq!(ty.limits().min(), 1);
/// # Ok(())
Expand Down
35 changes: 34 additions & 1 deletion crates/api/src/instance.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::externals::{Export, Extern};
use crate::externals::{Export, Extern, Global, Memory, Table};
use crate::func::Func;
use crate::module::Module;
use crate::runtime::{Config, Store};
use crate::trap::Trap;
Expand Down Expand Up @@ -188,6 +189,38 @@ impl Instance {
))
}

/// Looks up an exported [`Func`] value by name.
///
/// Returns `None` if there was no export named `name`, or if there was but
/// it wasn't a function.
pub fn get_func(&self, name: &str) -> Option<Func> {
self.get_export(name)?.into_func()
}

/// Looks up an exported [`Table`] value by name.
///
/// Returns `None` if there was no export named `name`, or if there was but
/// it wasn't a table.
pub fn get_table(&self, name: &str) -> Option<Table> {
self.get_export(name)?.into_table()
}

/// Looks up an exported [`Memory`] value by name.
///
/// Returns `None` if there was no export named `name`, or if there was but
/// it wasn't a memory.
pub fn get_memory(&self, name: &str) -> Option<Memory> {
self.get_export(name)?.into_memory()
}

/// Looks up an exported [`Global`] value by name.
///
/// Returns `None` if there was no export named `name`, or if there was but
/// it wasn't a global.
pub fn get_global(&self, name: &str) -> Option<Global> {
self.get_export(name)?.into_global()
}

#[doc(hidden)]
pub fn handle(&self) -> &InstanceHandle {
&self.instance_handle
Expand Down
8 changes: 3 additions & 5 deletions crates/fuzzing/src/oracles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,13 +185,11 @@ pub fn differential_execution(
// infinite loop when calling another export.
init_hang_limit(&instance);

let f = match instance
let f = instance
.get_export(&name)
.expect("instance should have export from module")
{
Extern::Func(f) => f.clone(),
_ => panic!("export should be a function"),
};
.into_func()
.expect("export should be a function");

let ty = f.ty();
let params = match dummy::dummy_values(ty.params()) {
Expand Down
17 changes: 5 additions & 12 deletions crates/test-programs/tests/wasm_tests/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,11 @@ pub fn instantiate(
let imports = module
.imports()
.map(|i| {
let field_name = i.name();
if let Some(export) = snapshot1.get_export(field_name) {
let field_name = i.name;
if let Some(export) = snapshot1.get_export(&field_name) {
Ok(export.clone().into())
} else {
bail!(
"import {} was not found in module {}",
field_name,
i.module(),
)
bail!("import {} was not found in module {}", field_name, i.module,)
}
})
.collect::<Result<Vec<_>, _>>()?;
Expand All @@ -70,13 +66,10 @@ pub fn instantiate(
bin_name,
))?;

let export = instance
instance
.get_export("_start")
.context("expected a _start export")?
.clone();

export
.func()
.into_func()
.context("expected export to be a func")?
.call(&[])?;

Expand Down
2 changes: 1 addition & 1 deletion docs/wasm-wat.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ let wat = r#"
"#;
let module = Module::new(&store, wat)?;
let instance = Instance::new(&module, &[])?;
let add = instance.get_export("add").and_then(|f| f.into_func()).unwrap();
let add = instance.get_func("add").unwrap();
let add = add.get2::<i32, i32, i32>()?;
println!("1 + 2 = {}", add(1, 2)?);
# Ok(())
Expand Down
3 changes: 1 addition & 2 deletions examples/fib-debug/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ fn main() -> Result<()> {

// Invoke `fib` export
let fib = instance
.get_export("fib")
.and_then(|e| e.into_func())
.get_func("fib")
.ok_or(anyhow::format_err!("failed to find `fib` function export"))?
.get1::<i32, i32>()?;
println!("fib(6) = {}", fib(6)?);
Expand Down
3 changes: 1 addition & 2 deletions examples/gcd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ fn main() -> Result<()> {

// Invoke `gcd` export
let gcd = instance
.get_export("gcd")
.and_then(|e| e.into_func())
.get_func("gcd")
.ok_or(anyhow::format_err!("failed to find `gcd` function export"))?
.get2::<i32, i32, i32>()?;

Expand Down
3 changes: 1 addition & 2 deletions examples/hello.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ fn main() -> Result<()> {
// Next we poke around a bit to extract the `run` function from the module.
println!("Extracting export...");
let run = instance
.get_export("run")
.and_then(|e| e.into_func())
.get_func("run")
.ok_or(anyhow::format_err!("failed to find `run` function export"))?
.get0::<()>()?;

Expand Down
5 changes: 1 addition & 4 deletions examples/linking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,7 @@ fn main() -> Result<()> {

// And with that we can perform the final link and the execute the module.
let linking1 = linker.instantiate(&linking1)?;
let run = linking1
.get_export("run")
.and_then(|e| e.into_func())
.unwrap();
let run = linking1.get_func("run").unwrap();
let run = run.get0::<()>()?;
run()?;
Ok(())
Expand Down
12 changes: 4 additions & 8 deletions examples/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,18 @@ fn main() -> Result<()> {

// Load up our exports from the instance
let memory = instance
.get_export("memory")
.and_then(|e| e.into_memory())
.get_memory("memory")
.ok_or(anyhow::format_err!("failed to find `memory` export"))?;
let size = instance
.get_export("size")
.and_then(|e| e.into_func())
.get_func("size")
.ok_or(anyhow::format_err!("failed to find `size` export"))?
.get0::<i32>()?;
let load = instance
.get_export("load")
.and_then(|e| e.into_func())
.get_func("load")
.ok_or(anyhow::format_err!("failed to find `load` export"))?
.get1::<i32, i32>()?;
let store = instance
.get_export("store")
.and_then(|e| e.into_func())
.get_func("store")
.ok_or(anyhow::format_err!("failed to find `store` export"))?
.get2::<i32, i32, ()>()?;

Expand Down
6 changes: 2 additions & 4 deletions examples/multi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ fn main() -> Result<()> {
// Extract exports.
println!("Extracting export...");
let g = instance
.get_export("g")
.and_then(|e| e.into_func())
.get_func("g")
.ok_or(format_err!("failed to find export `g`"))?;

// Call `$g`.
Expand All @@ -60,8 +59,7 @@ fn main() -> Result<()> {
// Call `$round_trip_many`.
println!("Calling export \"round_trip_many\"...");
let round_trip_many = instance
.get_export("round_trip_many")
.and_then(|e| e.into_func())
.get_func("round_trip_many")
.ok_or(format_err!("failed to find export `round_trip_many`"))?;
let args = vec![
Val::I64(0),
Expand Down
5 changes: 1 addition & 4 deletions examples/wasi/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,7 @@ fn main() -> Result<()> {
// Instance our module with the imports we've created, then we can run the
// standard wasi `_start` function.
let instance = Instance::new(&module, &imports)?;
let start = instance
.get_export("_start")
.and_then(|e| e.into_func())
.unwrap();
let start = instance.get_func("_start").unwrap();
let start = start.get0::<()>()?;
start()?;
Ok(())
Expand Down
13 changes: 2 additions & 11 deletions tests/all/custom_signal_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,13 @@ mod tests {
"#;

fn invoke_export(instance: &Instance, func_name: &str) -> Result<Box<[Val]>> {
let ret = instance
.get_export(func_name)
.unwrap()
.into_func()
.unwrap()
.call(&[])?;
let ret = instance.get_func(func_name).unwrap().call(&[])?;
Ok(ret)
}

// Locate "memory" export, get base address and size and set memory protection to PROT_NONE
fn set_up_memory(instance: &Instance) -> (*mut u8, usize) {
let mem_export = instance
.get_export("memory")
.unwrap()
.into_memory()
.unwrap();
let mem_export = instance.get_memory("memory").unwrap();
let base = mem_export.data_ptr();
let length = mem_export.data_size();

Expand Down
6 changes: 3 additions & 3 deletions tests/all/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,14 +269,14 @@ fn get_from_module() -> anyhow::Result<()> {
"#,
)?;
let instance = Instance::new(&module, &[])?;
let f0 = instance.get_export("f0").unwrap().into_func().unwrap();
let f0 = instance.get_func("f0").unwrap();
assert!(f0.get0::<()>().is_ok());
assert!(f0.get0::<i32>().is_err());
let f1 = instance.get_export("f1").unwrap().into_func().unwrap();
let f1 = instance.get_func("f1").unwrap();
assert!(f1.get0::<()>().is_err());
assert!(f1.get1::<i32, ()>().is_ok());
assert!(f1.get1::<i32, f32>().is_err());
let f2 = instance.get_export("f2").unwrap().into_func().unwrap();
let f2 = instance.get_func("f2").unwrap();
assert!(f2.get0::<()>().is_err());
assert!(f2.get0::<i32>().is_ok());
assert!(f2.get1::<i32, ()>().is_err());
Expand Down
2 changes: 1 addition & 1 deletion tests/all/import_indexes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ fn same_import_names_still_distinct() -> anyhow::Result<()> {
];
let instance = Instance::new(&module, &imports)?;

let func = instance.get_export("foo").unwrap().into_func().unwrap();
let func = instance.get_func("foo").unwrap();
let results = func.call(&[])?;
assert_eq!(results.len(), 1);
match results[0] {
Expand Down
4 changes: 1 addition & 3 deletions tests/all/invoke_func_via_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ fn test_invoke_func_via_table() -> Result<()> {
let instance = Instance::new(&module, &[]).context("> Error instantiating module!")?;

let f = instance
.get_export("table")
.unwrap()
.into_table()
.get_table("table")
.unwrap()
.get(0)
.unwrap()
Expand Down
2 changes: 1 addition & 1 deletion tests/all/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ fn interposition() -> Result<()> {
)?;
}
let instance = linker.instantiate(&module)?;
let func = instance.get_export("export").unwrap().into_func().unwrap();
let func = instance.get_func("export").unwrap();
let func = func.get0::<i32>()?;
assert_eq!(func()?, 112);
Ok(())
Expand Down
10 changes: 1 addition & 9 deletions tests/all/memory_creator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,15 +169,7 @@ mod not_for_windows {

assert_eq!(*mem_creator.num_created_memories.lock().unwrap(), 2);

assert_eq!(
instance2
.get_export("memory")
.unwrap()
.into_memory()
.unwrap()
.size(),
2
);
assert_eq!(instance2.get_memory("memory").unwrap().size(), 2);

// we take the lock outside the assert, so it won't get poisoned on assert failure
let tot_pages = *mem_creator.num_total_pages.lock().unwrap();
Expand Down

0 comments on commit 186573c

Please sign in to comment.