diff --git a/cranelift/wasm/src/code_translator.rs b/cranelift/wasm/src/code_translator.rs index 26c7e5d8f8..4baa7847b4 100644 --- a/cranelift/wasm/src/code_translator.rs +++ b/cranelift/wasm/src/code_translator.rs @@ -1039,12 +1039,10 @@ pub fn translate_operator( Operator::F32Le | Operator::F64Le => { translate_fcmp(FloatCC::LessThanOrEqual, builder, state) } - Operator::RefNull { ty: _ } => state.push1(builder.ins().null(environ.reference_type())), + Operator::RefNull { ty } => state.push1(environ.translate_ref_null(builder.cursor(), *ty)?), Operator::RefIsNull { ty: _ } => { - let arg = state.pop1(); - let val = builder.ins().is_null(arg); - let val_int = builder.ins().bint(I32, val); - state.push1(val_int); + let value = state.pop1(); + state.push1(environ.translate_ref_is_null(builder.cursor(), value)?); } Operator::RefFunc { function_index } => { state.push1(environ.translate_ref_func(builder.cursor(), *function_index)?); diff --git a/cranelift/wasm/src/environ/dummy.rs b/cranelift/wasm/src/environ/dummy.rs index 2c4280e4a9..ca58b77158 100644 --- a/cranelift/wasm/src/environ/dummy.rs +++ b/cranelift/wasm/src/environ/dummy.rs @@ -197,6 +197,14 @@ impl<'dummy_environment> DummyFuncEnvironment<'dummy_environment> { )); sig } + + fn reference_type(&self) -> ir::Type { + match self.pointer_type() { + ir::types::I32 => ir::types::R32, + ir::types::I64 => ir::types::R64, + _ => panic!("unsupported pointer type"), + } + } } impl<'dummy_environment> TargetEnvironment for DummyFuncEnvironment<'dummy_environment> { diff --git a/cranelift/wasm/src/environ/spec.rs b/cranelift/wasm/src/environ/spec.rs index 98ca1c7095..8e85d49dfe 100644 --- a/cranelift/wasm/src/environ/spec.rs +++ b/cranelift/wasm/src/environ/spec.rs @@ -133,10 +133,15 @@ pub trait TargetEnvironment { self.target_config().pointer_bytes() } - /// Get the Cranelift reference type to use for native references. + /// Get the Cranelift reference type to use for the given Wasm reference + /// type. /// - /// This returns `R64` for 64-bit architectures and `R32` for 32-bit architectures. - fn reference_type(&self) -> ir::Type { + /// By default, this returns `R64` for 64-bit architectures and `R32` for + /// 32-bit architectures. If you override this, then you should also + /// override `FuncEnvironment::{translate_ref_null, translate_ref_is_null}` + /// as well. + fn reference_type(&self, ty: WasmType) -> ir::Type { + let _ = ty; match self.pointer_type() { ir::types::I32 => ir::types::R32, ir::types::I64 => ir::types::R64, @@ -419,6 +424,37 @@ pub trait FuncEnvironment: TargetEnvironment { /// Translate a `elem.drop` WebAssembly instruction. fn translate_elem_drop(&mut self, pos: FuncCursor, seg_index: u32) -> WasmResult<()>; + /// Translate a `ref.null T` WebAssembly instruction. + /// + /// By default, translates into a null reference type. + /// + /// Override this if you don't use Cranelift reference types for all Wasm + /// reference types (e.g. you use a raw pointer for `funcref`s) or if the + /// null sentinel is not a null reference type pointer for your type. If you + /// override this method, then you should also override + /// `translate_ref_is_null` as well. + fn translate_ref_null(&mut self, mut pos: FuncCursor, ty: WasmType) -> WasmResult { + let _ = ty; + Ok(pos.ins().null(self.reference_type(ty))) + } + + /// Translate a `ref.is_null` WebAssembly instruction. + /// + /// By default, assumes that `value` is a Cranelift reference type, and that + /// a null Cranelift reference type is the null value for all Wasm reference + /// types. + /// + /// If you override this method, you probably also want to override + /// `translate_ref_null` as well. + fn translate_ref_is_null( + &mut self, + mut pos: FuncCursor, + value: ir::Value, + ) -> WasmResult { + let is_null = pos.ins().is_null(value); + Ok(pos.ins().bint(ir::types::I32, is_null)) + } + /// Translate a `ref.func` WebAssembly instruction. fn translate_ref_func(&mut self, pos: FuncCursor, func_index: u32) -> WasmResult; diff --git a/cranelift/wasm/src/func_translator.rs b/cranelift/wasm/src/func_translator.rs index c446dd9488..601996d6df 100644 --- a/cranelift/wasm/src/func_translator.rs +++ b/cranelift/wasm/src/func_translator.rs @@ -196,8 +196,7 @@ fn declare_locals( let constant_handle = builder.func.dfg.constants.insert([0; 16].to_vec().into()); builder.ins().vconst(ir::types::I8X16, constant_handle) } - ExternRef => builder.ins().null(environ.reference_type()), - FuncRef => builder.ins().null(environ.reference_type()), + ExternRef | FuncRef => environ.translate_ref_null(builder.cursor(), wasm_type)?, ty => return Err(wasm_unsupported!("unsupported local type {:?}", ty)), }; diff --git a/cranelift/wasm/src/translation_utils.rs b/cranelift/wasm/src/translation_utils.rs index 19b05f760c..2b2a7af68f 100644 --- a/cranelift/wasm/src/translation_utils.rs +++ b/cranelift/wasm/src/translation_utils.rs @@ -143,7 +143,7 @@ pub fn type_to_type( wasmparser::Type::F32 => Ok(ir::types::F32), wasmparser::Type::F64 => Ok(ir::types::F64), wasmparser::Type::V128 => Ok(ir::types::I8X16), - wasmparser::Type::ExternRef | wasmparser::Type::FuncRef => Ok(environ.reference_type()), + wasmparser::Type::ExternRef | wasmparser::Type::FuncRef => Ok(environ.reference_type(ty)), ty => Err(wasm_unsupported!("type_to_type: wasm type {:?}", ty)), } } @@ -160,7 +160,7 @@ pub fn tabletype_to_type( wasmparser::Type::F32 => Ok(Some(ir::types::F32)), wasmparser::Type::F64 => Ok(Some(ir::types::F64)), wasmparser::Type::V128 => Ok(Some(ir::types::I8X16)), - wasmparser::Type::ExternRef => Ok(Some(environ.reference_type())), + wasmparser::Type::ExternRef => Ok(Some(environ.reference_type(ty))), wasmparser::Type::FuncRef => Ok(None), ty => Err(wasm_unsupported!( "tabletype_to_type: table wasm type {:?}", @@ -216,7 +216,7 @@ pub fn block_with_params( builder.append_block_param(block, ir::types::F64); } wasmparser::Type::ExternRef | wasmparser::Type::FuncRef => { - builder.append_block_param(block, environ.reference_type()); + builder.append_block_param(block, environ.reference_type(*ty)); } wasmparser::Type::V128 => { builder.append_block_param(block, ir::types::I8X16);