diff --git a/crates/cranelift/src/func_environ.rs b/crates/cranelift/src/func_environ.rs index 10d20e63b170..1e47b8c70de4 100644 --- a/crates/cranelift/src/func_environ.rs +++ b/crates/cranelift/src/func_environ.rs @@ -5584,6 +5584,15 @@ impl FuncEnvironment<'_> { ) } + pub fn continuation_arguments_from_interned( + &self, + index: ModuleInternedTypeIndex, + ) -> &[WasmValType] { + self.types[self.types[index].unwrap_cont().unwrap_module_type_index()] + .unwrap_func() + .params() + } + pub fn continuation_arguments(&self, index: TypeIndex) -> &[WasmValType] { let idx = self.module.types[index].unwrap_module_type_index(); self.types[self.types[idx].unwrap_cont().unwrap_module_type_index()] diff --git a/crates/cranelift/src/translate/code_translator.rs b/crates/cranelift/src/translate/code_translator.rs index 7de3ab3b4d62..6e1b49cb7070 100644 --- a/crates/cranelift/src/translate/code_translator.rs +++ b/crates/cranelift/src/translate/code_translator.rs @@ -3335,10 +3335,10 @@ pub fn translate_operator( WasmHeapType::ConcreteCont(index) => { let mti = index .as_module_type_index() - .expect("Only supporting module type indices on switch for now"); + .expect("expected module-local type index"); environ - .continuation_arguments(TypeIndex::from_u32(mti.as_u32())) + .continuation_arguments_from_interned(mti) .iter() .map(|ty| crate::value_type(environ.isa(), *ty)) .collect() diff --git a/tests/misc_testsuite/stack-switching/switch-type-index-conflation.wast b/tests/misc_testsuite/stack-switching/switch-type-index-conflation.wast new file mode 100644 index 000000000000..e5ae9747b7b6 --- /dev/null +++ b/tests/misc_testsuite/stack-switching/switch-type-index-conflation.wast @@ -0,0 +1,35 @@ +;;! bulk_memory = true +;;! function_references = true +;;! stack_switching = true + +;; Regression test for buggy module-local type index to declared type +;; index conversion. +(module + ;; These two function types canonicalize to the same module-interned type. + ;; As a result, subsequent TypeIndex and ModuleInternedTypeIndex values do + ;; not have the same numeric value. + (type $duplicate (func)) + (type $ft0 (func)) + + (type $ct0 (cont $ft0)) + + (type $ft1 (func (param (ref $ct0)))) + (type $ct1 (cont $ft1)) + + (tag $t) + + (func $f + (cont.new $ct1 (ref.func $g)) + (switch $ct1 $t)) + (elem declare func $f) + + (func $g (type $ft1)) + (elem declare func $g) + + (func (export "entry") (result i32) + (cont.new $ct0 (ref.func $f)) + (resume $ct0 (on $t switch)) + (i32.const 0)) +) + +(assert_return (invoke "entry") (i32.const 0))