wasmtime: Option to return default values for unknown imports (#6010)

Similar to the `--trap-unknown-imports` option, which defines unknown function
imports with functions that trap when called, this new
`--default-values-unknown-imports` option defines unknown function imports with
a function that returns the default values for the result types (either zero or
null depending on the value type).
This commit is contained in:
Nick Fitzgerald
2023-03-13 14:39:30 -07:00
committed by GitHub
parent e2a6fe99c2
commit 90c9bec225
3 changed files with 102 additions and 1 deletions

View File

@@ -3,7 +3,7 @@ use crate::instance::InstancePre;
use crate::store::StoreOpaque;
use crate::{
AsContext, AsContextMut, Caller, Engine, Extern, ExternType, Func, FuncType, ImportType,
Instance, IntoFunc, Module, StoreContextMut, Val, ValRaw,
Instance, IntoFunc, Module, StoreContextMut, Val, ValRaw, ValType,
};
use anyhow::{bail, Context, Result};
use log::warn;
@@ -289,6 +289,62 @@ impl<T> Linker<T> {
Ok(())
}
/// Implement any function imports of the [`Module`] with a function that
/// ignores its arguments and returns default values.
///
/// Default values are either zero or null, depending on the value type.
///
/// This method can be used to allow unknown imports from command modules.
///
/// # Example
///
/// ```
/// # use wasmtime::*;
/// # fn main() -> anyhow::Result<()> {
/// # let engine = Engine::default();
/// # let module = Module::new(&engine, "(module (import \"unknown\" \"import\" (func)))")?;
/// # let mut store = Store::new(&engine, ());
/// let mut linker = Linker::new(&engine);
/// linker.define_unknown_imports_as_default_values(&module)?;
/// linker.instantiate(&mut store, &module)?;
/// # Ok(())
/// # }
/// ```
#[cfg(compiler)]
#[cfg_attr(nightlydoc, doc(cfg(feature = "cranelift")))] // see build.rs
pub fn define_unknown_imports_as_default_values(
&mut self,
module: &Module,
) -> anyhow::Result<()> {
for import in module.imports() {
if let Err(import_err) = self._get_by_import(&import) {
if let ExternType::Func(func_ty) = import_err.ty() {
let result_tys: Vec<_> = func_ty.results().collect();
self.func_new(
import.module(),
import.name(),
func_ty,
move |_caller, _args, results| {
for (result, ty) in results.iter_mut().zip(&result_tys) {
*result = match ty {
ValType::I32 => Val::I32(0),
ValType::I64 => Val::I64(0),
ValType::F32 => Val::F32(0.0_f32.to_bits()),
ValType::F64 => Val::F64(0.0_f64.to_bits()),
ValType::V128 => Val::V128(0),
ValType::FuncRef => Val::FuncRef(None),
ValType::ExternRef => Val::ExternRef(None),
};
}
Ok(())
},
)?;
}
}
}
Ok(())
}
/// Defines a new item in this [`Linker`].
///
/// This method will add a new definition, by name, to this instance of