Skip to content
This repository was archived by the owner on Oct 3, 2025. It is now read-only.

Commit 9f1bc8d

Browse files
feat: replace RefNull with new FuncRef and ExternRef structs
Signed-off-by: Henry Gressmann <[email protected]>
1 parent 0202878 commit 9f1bc8d

File tree

14 files changed

+192
-108
lines changed

14 files changed

+192
-108
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414
### Changed
1515

1616
- **Breaking:**: New backwards-incompatible version of the twasm format (upgraded `rkyv` to 0.8.0)
17+
- **Breaking:**: `RefNull` has been removed and replaced with new `FuncRef` and `ExternRef` structs
1718
- Increased MSRV to 1.83.0
1819

1920
### Fixed

Cargo.lock

Lines changed: 33 additions & 26 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/parser/src/conversion.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,12 @@ pub(crate) fn process_const_operators(ops: OperatorsReader<'_>) -> Result<ConstI
251251
assert!(matches!(ops[ops.len() - 1], wasmparser::Operator::End));
252252

253253
match &ops[ops.len() - 2] {
254-
wasmparser::Operator::RefNull { hty } => Ok(ConstInstruction::RefNull(convert_heaptype(*hty))),
255-
wasmparser::Operator::RefFunc { function_index } => Ok(ConstInstruction::RefFunc(*function_index)),
254+
wasmparser::Operator::RefNull { hty } => match convert_heaptype(*hty) {
255+
ValType::RefFunc => Ok(ConstInstruction::RefFunc(None)),
256+
ValType::RefExtern => Ok(ConstInstruction::RefExtern(None)),
257+
_ => unimplemented!("Unsupported heap type: {:?}", hty),
258+
},
259+
wasmparser::Operator::RefFunc { function_index } => Ok(ConstInstruction::RefFunc(Some(*function_index))),
256260
wasmparser::Operator::I32Const { value } => Ok(ConstInstruction::I32Const(*value)),
257261
wasmparser::Operator::I64Const { value } => Ok(ConstInstruction::I64Const(*value)),
258262
wasmparser::Operator::F32Const { value } => Ok(ConstInstruction::F32Const(f32::from_bits(value.bits()))),

crates/parser/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ impl Parser {
6565
memory64: true,
6666
custom_page_sizes: true,
6767

68+
extended_const: false,
6869
wide_arithmetic: false,
6970
gc_types: true,
7071
stack_switching: false,
@@ -73,7 +74,6 @@ impl Parser {
7374
component_model_values: false,
7475
component_model_more_flags: false,
7576
exceptions: false,
76-
extended_const: false,
7777
gc: false,
7878
memory_control: false,
7979
relaxed_simd: false,

crates/tinywasm/src/func.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::interpreter::stack::{CallFrame, Stack};
22
use crate::{log, unlikely, Function};
33
use crate::{Error, FuncContext, Result, Store};
44
use alloc::{boxed::Box, format, string::String, string::ToString, vec, vec::Vec};
5-
use tinywasm_types::{FuncType, ModuleInstanceAddr, ValType, WasmValue};
5+
use tinywasm_types::{ExternRef, FuncRef, FuncType, ModuleInstanceAddr, ValType, WasmValue};
66

77
#[derive(Debug)]
88
/// A function handle
@@ -219,6 +219,18 @@ impl ToValType for f64 {
219219
}
220220
}
221221

222+
impl ToValType for FuncRef {
223+
fn to_val_type() -> ValType {
224+
ValType::RefFunc
225+
}
226+
}
227+
228+
impl ToValType for ExternRef {
229+
fn to_val_type() -> ValType {
230+
ValType::RefExtern
231+
}
232+
}
233+
222234
macro_rules! impl_val_types_from_tuple {
223235
($($t:ident),+) => {
224236
impl<$($t),+> ValTypesFromTuple for ($($t,)+)
@@ -251,11 +263,15 @@ impl_from_wasm_value_tuple_single!(i32);
251263
impl_from_wasm_value_tuple_single!(i64);
252264
impl_from_wasm_value_tuple_single!(f32);
253265
impl_from_wasm_value_tuple_single!(f64);
266+
impl_from_wasm_value_tuple_single!(FuncRef);
267+
impl_from_wasm_value_tuple_single!(ExternRef);
254268

255269
impl_into_wasm_value_tuple_single!(i32);
256270
impl_into_wasm_value_tuple_single!(i64);
257271
impl_into_wasm_value_tuple_single!(f32);
258272
impl_into_wasm_value_tuple_single!(f64);
273+
impl_into_wasm_value_tuple_single!(FuncRef);
274+
impl_into_wasm_value_tuple_single!(ExternRef);
259275

260276
impl_val_types_from_tuple!(T1);
261277
impl_val_types_from_tuple!(T1, T2);

crates/tinywasm/src/interpreter/stack/value_stack.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use alloc::vec::Vec;
2-
use tinywasm_types::{ValType, ValueCounts, ValueCountsSmall, WasmValue};
2+
use tinywasm_types::{ExternRef, FuncRef, ValType, ValueCounts, ValueCountsSmall, WasmValue};
33

44
use crate::{interpreter::*, Result};
55

@@ -173,14 +173,8 @@ impl ValueStack {
173173
ValType::V128 => WasmValue::V128(self.pop()),
174174
ValType::F32 => WasmValue::F32(self.pop()),
175175
ValType::F64 => WasmValue::F64(self.pop()),
176-
ValType::RefExtern => match self.pop() {
177-
Some(v) => WasmValue::RefExtern(v),
178-
None => WasmValue::RefNull(ValType::RefExtern),
179-
},
180-
ValType::RefFunc => match self.pop() {
181-
Some(v) => WasmValue::RefFunc(v),
182-
None => WasmValue::RefNull(ValType::RefFunc),
183-
},
176+
ValType::RefExtern => WasmValue::RefExtern(ExternRef::new(self.pop())),
177+
ValType::RefFunc => WasmValue::RefFunc(FuncRef::new(self.pop())),
184178
}
185179
}
186180

crates/tinywasm/src/interpreter/values.rs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::Result;
2-
use tinywasm_types::{LocalAddr, ValType, WasmValue};
2+
use tinywasm_types::{ExternRef, FuncRef, LocalAddr, ValType, WasmValue};
33

44
use super::stack::{Locals, ValueStack};
55

@@ -107,14 +107,8 @@ impl TinyWasmValue {
107107
ValType::F32 => WasmValue::F32(f32::from_bits(self.unwrap_32())),
108108
ValType::F64 => WasmValue::F64(f64::from_bits(self.unwrap_64())),
109109
ValType::V128 => WasmValue::V128(self.unwrap_128()),
110-
ValType::RefExtern => match self.unwrap_ref() {
111-
Some(v) => WasmValue::RefExtern(v),
112-
None => WasmValue::RefNull(ValType::RefExtern),
113-
},
114-
ValType::RefFunc => match self.unwrap_ref() {
115-
Some(v) => WasmValue::RefFunc(v),
116-
None => WasmValue::RefNull(ValType::RefFunc),
117-
},
110+
ValType::RefExtern => WasmValue::RefExtern(ExternRef::new(self.unwrap_ref())),
111+
ValType::RefFunc => WasmValue::RefFunc(FuncRef::new(self.unwrap_ref())),
118112
}
119113
}
120114
}
@@ -127,8 +121,8 @@ impl From<&WasmValue> for TinyWasmValue {
127121
WasmValue::V128(v) => TinyWasmValue::Value128(*v),
128122
WasmValue::F32(v) => TinyWasmValue::Value32(v.to_bits()),
129123
WasmValue::F64(v) => TinyWasmValue::Value64(v.to_bits()),
130-
WasmValue::RefFunc(v) | WasmValue::RefExtern(v) => TinyWasmValue::ValueRef(Some(*v)),
131-
WasmValue::RefNull(_) => TinyWasmValue::ValueRef(None),
124+
WasmValue::RefExtern(v) => TinyWasmValue::ValueRef(v.addr()),
125+
WasmValue::RefFunc(v) => TinyWasmValue::ValueRef(v.addr()),
132126
}
133127
}
134128
}

crates/tinywasm/src/module.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ impl Module {
4747
/// Instantiate the module in the given store
4848
///
4949
/// Runs the start function if it exists
50+
///
5051
/// If you want to run the start function yourself, use `ModuleInstance::instantiate`
5152
///
5253
/// See <https://webassembly.github.io/spec/core/exec/modules.html#exec-instantiation>

crates/tinywasm/src/store/mod.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -278,12 +278,13 @@ impl Store {
278278

279279
fn elem_addr(&self, item: &ElementItem, globals: &[Addr], funcs: &[FuncAddr]) -> Result<Option<u32>> {
280280
let res = match item {
281-
ElementItem::Func(addr) | ElementItem::Expr(ConstInstruction::RefFunc(addr)) => {
281+
ElementItem::Func(addr) | ElementItem::Expr(ConstInstruction::RefFunc(Some(addr))) => {
282282
Some(funcs.get(*addr as usize).copied().ok_or_else(|| {
283283
Error::Other(format!("function {addr} not found. This should have been caught by the validator"))
284284
})?)
285285
}
286-
ElementItem::Expr(ConstInstruction::RefNull(_ty)) => None,
286+
ElementItem::Expr(ConstInstruction::RefFunc(None)) => None,
287+
ElementItem::Expr(ConstInstruction::RefExtern(None)) => None,
287288
ElementItem::Expr(ConstInstruction::GlobalGet(addr)) => {
288289
let addr = globals.get(*addr as usize).copied().ok_or_else(|| {
289290
Error::Other(format!("global {addr} not found. This should have been caught by the validator"))
@@ -450,10 +451,14 @@ impl Store {
450451
self.data.globals.get(*addr as usize).expect("global not found. This should be unreachable");
451452
global.value.get()
452453
}
453-
RefNull(t) => t.default_value().into(),
454-
RefFunc(idx) => TinyWasmValue::ValueRef(Some(*module_func_addrs.get(*idx as usize).ok_or_else(|| {
455-
Error::Other(format!("function {idx} not found. This should have been caught by the validator"))
456-
})?)),
454+
RefFunc(None) => TinyWasmValue::ValueRef(None),
455+
RefExtern(None) => TinyWasmValue::ValueRef(None),
456+
RefFunc(Some(idx)) => {
457+
TinyWasmValue::ValueRef(Some(*module_func_addrs.get(*idx as usize).ok_or_else(|| {
458+
Error::Other(format!("function {idx} not found. This should have been caught by the validator"))
459+
})?))
460+
}
461+
_ => return Err(Error::Other("unsupported const instruction".to_string())),
457462
};
458463
Ok(val)
459464
}

crates/tinywasm/src/store/table.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ impl TableInstance {
3030
let val = self.get(addr)?.addr();
3131

3232
Ok(match self.kind.element_type {
33-
ValType::RefFunc => val.map_or(WasmValue::RefNull(ValType::RefFunc), WasmValue::RefFunc),
34-
ValType::RefExtern => val.map_or(WasmValue::RefNull(ValType::RefExtern), WasmValue::RefExtern),
33+
ValType::RefFunc => WasmValue::RefFunc(FuncRef::new(val)),
34+
ValType::RefExtern => WasmValue::RefExtern(ExternRef::new(val)),
3535
_ => Err(Error::UnsupportedFeature("non-ref table".into()))?,
3636
})
3737
}
@@ -211,7 +211,7 @@ mod tests {
211211
}
212212

213213
match table_instance.get_wasm_val(1) {
214-
Ok(WasmValue::RefNull(ValType::RefFunc)) => {}
214+
Ok(WasmValue::RefFunc(f)) if f.is_null() => {}
215215
_ => panic!("get_wasm_val failed to return the correct WasmValue"),
216216
}
217217

0 commit comments

Comments
 (0)