From c3ff0754d4f2a28a7438a90319b062fa407ce143 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 17 Jul 2020 12:05:42 -0500 Subject: [PATCH] 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. --- crates/wasmtime/src/runtime.rs | 6 ++++++ crates/wasmtime/src/trampoline/func.rs | 5 ++++- tests/all/func.rs | 15 +++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/crates/wasmtime/src/runtime.rs b/crates/wasmtime/src/runtime.rs index cbba86eafa..94eea934c9 100644 --- a/crates/wasmtime/src/runtime.rs +++ b/crates/wasmtime/src/runtime.rs @@ -609,6 +609,12 @@ impl Config { .finish(settings::Flags::new(self.flags.clone())) } + pub(crate) fn target_isa_with_reference_types(&self) -> Box { + 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) diff --git a/crates/wasmtime/src/trampoline/func.rs b/crates/wasmtime/src/trampoline/func.rs index a8fe766cca..2ba739da5c 100644 --- a/crates/wasmtime/src/trampoline/func.rs +++ b/crates/wasmtime/src/trampoline/func.rs @@ -206,7 +206,10 @@ pub fn create_handle_with_function( func: Box 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); diff --git a/tests/all/func.rs b/tests/all/func.rs index 76019e70b5..ddce6b1e68 100644 --- a/tests/all/func.rs +++ b/tests/all/func.rs @@ -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::new( + &store, + FuncType::new( + Box::new([ValType::FuncRef, ValType::ExternRef]), + Box::new([ValType::FuncRef, ValType::ExternRef]), + ), + |_, _, _| Ok(()), + ); + Ok(()) +}