From 186573c2084f0c0dc80cedef0e855576be092303 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 17 Apr 2020 17:57:22 -0700 Subject: [PATCH] Add convenience methods to instance for getting specific extern types. --- crates/api/src/externals.rs | 2 +- crates/api/src/instance.rs | 35 ++++++++++++++++++- crates/fuzzing/src/oracles.rs | 8 ++--- .../test-programs/tests/wasm_tests/runtime.rs | 17 +++------ docs/wasm-wat.md | 2 +- examples/fib-debug/main.rs | 3 +- examples/gcd.rs | 3 +- examples/hello.rs | 3 +- examples/linking.rs | 5 +-- examples/memory.rs | 12 +++---- examples/multi.rs | 6 ++-- examples/wasi/main.rs | 5 +-- tests/all/custom_signal_handler.rs | 13 ++----- tests/all/func.rs | 6 ++-- tests/all/import_indexes.rs | 2 +- tests/all/invoke_func_via_table.rs | 4 +-- tests/all/linker.rs | 2 +- tests/all/memory_creator.rs | 10 +----- 18 files changed, 64 insertions(+), 74 deletions(-) diff --git a/crates/api/src/externals.rs b/crates/api/src/externals.rs index 5b1470ed9c51..55dbe28987f5 100644 --- a/crates/api/src/externals.rs +++ b/crates/api/src/externals.rs @@ -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(()) diff --git a/crates/api/src/instance.rs b/crates/api/src/instance.rs index 2ac135a9bae9..ad49cadac398 100644 --- a/crates/api/src/instance.rs +++ b/crates/api/src/instance.rs @@ -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; @@ -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 { + 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 { + 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 { + 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 { + self.get_export(name)?.into_global() + } + #[doc(hidden)] pub fn handle(&self) -> &InstanceHandle { &self.instance_handle diff --git a/crates/fuzzing/src/oracles.rs b/crates/fuzzing/src/oracles.rs index 838f076ce736..b786714a2015 100644 --- a/crates/fuzzing/src/oracles.rs +++ b/crates/fuzzing/src/oracles.rs @@ -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()) { diff --git a/crates/test-programs/tests/wasm_tests/runtime.rs b/crates/test-programs/tests/wasm_tests/runtime.rs index fe67d4c5e812..e2bbcfc0c05c 100644 --- a/crates/test-programs/tests/wasm_tests/runtime.rs +++ b/crates/test-programs/tests/wasm_tests/runtime.rs @@ -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::, _>>()?; @@ -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(&[])?; diff --git a/docs/wasm-wat.md b/docs/wasm-wat.md index db7c23268128..0f9153771696 100644 --- a/docs/wasm-wat.md +++ b/docs/wasm-wat.md @@ -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::()?; println!("1 + 2 = {}", add(1, 2)?); # Ok(()) diff --git a/examples/fib-debug/main.rs b/examples/fib-debug/main.rs index 7028a4ed786f..ff35b8c83c10 100644 --- a/examples/fib-debug/main.rs +++ b/examples/fib-debug/main.rs @@ -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::()?; println!("fib(6) = {}", fib(6)?); diff --git a/examples/gcd.rs b/examples/gcd.rs index f9832b494e2b..067ab7b2dff8 100644 --- a/examples/gcd.rs +++ b/examples/gcd.rs @@ -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::()?; diff --git a/examples/hello.rs b/examples/hello.rs index 85d8926c31c6..00772b22eb01 100644 --- a/examples/hello.rs +++ b/examples/hello.rs @@ -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::<()>()?; diff --git a/examples/linking.rs b/examples/linking.rs index 8a0188ecb9b4..4f9548739e6c 100644 --- a/examples/linking.rs +++ b/examples/linking.rs @@ -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(()) diff --git a/examples/memory.rs b/examples/memory.rs index d60cb18a85b2..6f952dbb21b1 100644 --- a/examples/memory.rs +++ b/examples/memory.rs @@ -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::()?; 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::()?; 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::()?; diff --git a/examples/multi.rs b/examples/multi.rs index 0357c91776dc..0a5af6389913 100644 --- a/examples/multi.rs +++ b/examples/multi.rs @@ -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`. @@ -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), diff --git a/examples/wasi/main.rs b/examples/wasi/main.rs index 9ae8b8bbd5b1..66151937eca4 100644 --- a/examples/wasi/main.rs +++ b/examples/wasi/main.rs @@ -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(()) diff --git a/tests/all/custom_signal_handler.rs b/tests/all/custom_signal_handler.rs index 55287172c5cf..f40614d5fe2a 100644 --- a/tests/all/custom_signal_handler.rs +++ b/tests/all/custom_signal_handler.rs @@ -38,22 +38,13 @@ mod tests { "#; fn invoke_export(instance: &Instance, func_name: &str) -> Result> { - 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(); diff --git a/tests/all/func.rs b/tests/all/func.rs index f04f6cee5e6e..1cbb3e081406 100644 --- a/tests/all/func.rs +++ b/tests/all/func.rs @@ -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::().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::().is_ok()); assert!(f1.get1::().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::().is_ok()); assert!(f2.get1::().is_err()); diff --git a/tests/all/import_indexes.rs b/tests/all/import_indexes.rs index 86a7c3783109..d13d100a9f0f 100644 --- a/tests/all/import_indexes.rs +++ b/tests/all/import_indexes.rs @@ -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] { diff --git a/tests/all/invoke_func_via_table.rs b/tests/all/invoke_func_via_table.rs index 57a2ae51bc12..8f59fb17d8d5 100644 --- a/tests/all/invoke_func_via_table.rs +++ b/tests/all/invoke_func_via_table.rs @@ -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() diff --git a/tests/all/linker.rs b/tests/all/linker.rs index 3430aeb9c529..efca285267f0 100644 --- a/tests/all/linker.rs +++ b/tests/all/linker.rs @@ -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::()?; assert_eq!(func()?, 112); Ok(()) diff --git a/tests/all/memory_creator.rs b/tests/all/memory_creator.rs index cddb89464224..ed80cc72c95f 100644 --- a/tests/all/memory_creator.rs +++ b/tests/all/memory_creator.rs @@ -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();