-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Add APIs to lookup values in Linker
#1480
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,5 @@ | ||
| use crate::spectest::link_spectest; | ||
| use anyhow::{anyhow, bail, Context as _, Result}; | ||
| use std::collections::HashMap; | ||
| use std::path::Path; | ||
| use std::str; | ||
| use wasmtime::*; | ||
|
|
@@ -28,8 +27,9 @@ pub struct WastContext { | |
| /// Wast files have a concept of a "current" module, which is the most | ||
| /// recently defined. | ||
| current: Option<Instance>, | ||
|
|
||
| instances: HashMap<String, Instance>, | ||
|
sunfishcode marked this conversation as resolved.
|
||
| // FIXME(#1479) this is only needed to retain correct trap information after | ||
| // we've dropped previous `Instance` values. | ||
| modules: Vec<Module>, | ||
| linker: Linker, | ||
| store: Store, | ||
| } | ||
|
|
@@ -58,28 +58,36 @@ impl WastContext { | |
| linker.allow_shadowing(true); | ||
| Self { | ||
| current: None, | ||
| instances: HashMap::new(), | ||
| linker, | ||
| store, | ||
| modules: Vec::new(), | ||
| } | ||
| } | ||
|
|
||
| fn get_instance(&self, instance_name: Option<&str>) -> Result<Instance> { | ||
| match instance_name { | ||
| Some(name) => self | ||
| .instances | ||
| .get(name) | ||
| .cloned() | ||
| .ok_or_else(|| anyhow!("failed to find instance named `{}`", name)), | ||
| fn get_export(&self, module: Option<&str>, name: &str) -> Result<&Extern> { | ||
| match module { | ||
| Some(module) => { | ||
| let mut items = self.linker.get_by_name(module, name); | ||
| let ret = items | ||
| .next() | ||
| .ok_or_else(|| anyhow!("no item named `{}` in `{}`", name, module))?; | ||
| if items.next().is_some() { | ||
| bail!("too many items named `{}` in `{}`", name, module); | ||
| } | ||
| return Ok(ret); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we factor this out into a method on |
||
| } | ||
| None => self | ||
| .current | ||
| .clone() | ||
| .ok_or_else(|| anyhow!("no previous instance found")), | ||
| .as_ref() | ||
| .ok_or_else(|| anyhow!("no previous instance found"))? | ||
| .get_export(name) | ||
| .ok_or_else(|| anyhow!("no item named `{}` found", name)), | ||
| } | ||
| } | ||
|
|
||
| fn instantiate(&self, module: &[u8]) -> Result<Outcome<Instance>> { | ||
| fn instantiate(&mut self, module: &[u8]) -> Result<Outcome<Instance>> { | ||
| let module = Module::new(&self.store, module)?; | ||
| self.modules.push(module.clone()); | ||
| let instance = match self.linker.instantiate(&module) { | ||
| Ok(i) => i, | ||
| Err(e) => return e.downcast::<Trap>().map(Outcome::Trap), | ||
|
|
@@ -125,7 +133,6 @@ impl WastContext { | |
| Outcome::Trap(e) => bail!("instantiation failed with: {}", e.message()), | ||
| }; | ||
| if let Some(name) = instance_name { | ||
| self.instances.insert(name.to_string(), instance.clone()); | ||
| self.linker.instance(name, &instance)?; | ||
| } | ||
| self.current = Some(instance); | ||
|
|
@@ -134,9 +141,26 @@ impl WastContext { | |
|
|
||
| /// Register an instance to make it available for performing actions. | ||
| fn register(&mut self, name: Option<&str>, as_name: &str) -> Result<()> { | ||
| let instance = self.get_instance(name)?.clone(); | ||
| self.linker.instance(as_name, &instance)?; | ||
| self.instances.insert(as_name.to_string(), instance); | ||
| match name { | ||
| Some(name) => { | ||
| let items = self | ||
| .linker | ||
| .iter() | ||
| .filter(|(module, _, _)| *module == name) | ||
| .map(|(_, name, item)| (name.to_string(), item.clone())) | ||
| .collect::<Vec<_>>(); | ||
| for (name, item) in items { | ||
| self.linker.define(as_name, &name, item)?; | ||
| } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we factor out this logic too, with something like |
||
| } | ||
| None => { | ||
| let current = self | ||
| .current | ||
| .as_ref() | ||
| .ok_or(anyhow!("no previous instance"))?; | ||
| self.linker.instance(as_name, current)?; | ||
| } | ||
| } | ||
| Ok(()) | ||
| } | ||
|
|
||
|
|
@@ -147,10 +171,9 @@ impl WastContext { | |
| field: &str, | ||
| args: &[Val], | ||
| ) -> Result<Outcome> { | ||
| let instance = self.get_instance(instance_name.as_ref().map(|x| &**x))?; | ||
| let func = instance | ||
| .get_export(field) | ||
| .and_then(|e| e.func()) | ||
| let func = self | ||
| .get_export(instance_name, field)? | ||
| .func() | ||
| .ok_or_else(|| anyhow!("no function named `{}`", field))?; | ||
| Ok(match func.call(args) { | ||
| Ok(result) => Outcome::Ok(result.into()), | ||
|
|
@@ -160,10 +183,9 @@ impl WastContext { | |
|
|
||
| /// Get the value of an exported global from an instance. | ||
| fn get(&mut self, instance_name: Option<&str>, field: &str) -> Result<Outcome> { | ||
| let instance = self.get_instance(instance_name.as_ref().map(|x| &**x))?; | ||
| let global = instance | ||
| .get_export(field) | ||
| .and_then(|e| e.global()) | ||
| let global = self | ||
| .get_export(instance_name, field)? | ||
| .global() | ||
| .ok_or_else(|| anyhow!("no global named `{}`", field))?; | ||
| Ok(Outcome::Ok(vec![global.get()])) | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.