Fix a panic with Func::new and reference types (#2039)
Currently `Func::new` will panic if one of the arguments of the function is a reference type and the `Store` doesn't have reference types enabled. This happens because cranelift isn't configure to enable stack maps but the register allocators expects them to exist when reference types are seen. The fix here is to always enable reference types in cranelift for our trampoline generation and `Func::new`. This should hopefully ensure that trampolines are generated correctly and they'll just not be able to get hooked up to an `Instance` because validation will prevent reference types from being used elsewhere.
This commit is contained in:
@@ -609,6 +609,12 @@ impl Config {
|
||||
.finish(settings::Flags::new(self.flags.clone()))
|
||||
}
|
||||
|
||||
pub(crate) fn target_isa_with_reference_types(&self) -> Box<dyn TargetIsa> {
|
||||
let mut flags = self.flags.clone();
|
||||
flags.set("enable_safepoints", "true").unwrap();
|
||||
self.isa_flags.clone().finish(settings::Flags::new(flags))
|
||||
}
|
||||
|
||||
pub(crate) fn validator(&self) -> Validator {
|
||||
let mut ret = Validator::new();
|
||||
ret.wasm_threads(self.wasm_threads)
|
||||
|
||||
@@ -206,7 +206,10 @@ pub fn create_handle_with_function(
|
||||
func: Box<dyn Fn(*mut VMContext, *mut u128) -> Result<(), Trap>>,
|
||||
store: &Store,
|
||||
) -> Result<(StoreInstanceHandle, VMTrampoline)> {
|
||||
let isa = store.engine().config().target_isa();
|
||||
// Note that we specifically enable reference types here in our ISA because
|
||||
// `Func::new` is intended to be infallible, but our signature may use
|
||||
// reference types which requires safepoints.
|
||||
let isa = store.engine().config().target_isa_with_reference_types();
|
||||
|
||||
let pointer_type = isa.pointer_type();
|
||||
let sig = ft.get_wasmtime_signature(pointer_type);
|
||||
|
||||
@@ -507,3 +507,18 @@ fn pass_cross_store_arg() -> anyhow::Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn externref_signature_no_reference_types() -> anyhow::Result<()> {
|
||||
let store = Store::default();
|
||||
Func::wrap(&store, |_: Option<Func>| {});
|
||||
Func::new(
|
||||
&store,
|
||||
FuncType::new(
|
||||
Box::new([ValType::FuncRef, ValType::ExternRef]),
|
||||
Box::new([ValType::FuncRef, ValType::ExternRef]),
|
||||
),
|
||||
|_, _, _| Ok(()),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user