summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorHenry <mail@henrygressmann.de>2026-04-16 23:29:00 +0200
committerHenry <mail@henrygressmann.de>2026-04-16 23:29:00 +0200
commit5de0533875b6f439ea9e562cba93204ec15e3ba8 (patch)
treeedd4a4ea369d9ea0dfa599e9f01b960ca28c6802 /crates
parente47089bf4c53323a22bd9d8ba4b7a8836fcb45a6 (diff)
chore: remove ref stack
Signed-off-by: Henry <mail@henrygressmann.de>
Diffstat (limited to 'crates')
-rw-r--r--crates/parser/src/conversion.rs4
-rw-r--r--crates/parser/src/optimize.rs38
-rw-r--r--crates/parser/src/visit.rs62
-rw-r--r--crates/tinywasm/src/engine.rs12
-rw-r--r--crates/tinywasm/src/interpreter/executor.rs41
-rw-r--r--crates/tinywasm/src/interpreter/stack/call_stack.rs2
-rw-r--r--crates/tinywasm/src/interpreter/stack/value_stack.rs29
-rw-r--r--crates/tinywasm/src/interpreter/values.rs86
-rw-r--r--crates/tinywasm/src/store/mod.rs16
-rw-r--r--crates/types/src/instructions.rs7
-rw-r--r--crates/types/src/lib.rs5
-rw-r--r--crates/types/src/value.rs52
12 files changed, 179 insertions, 175 deletions
diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs
index 19ce975..32f2944 100644
--- a/crates/parser/src/conversion.rs
+++ b/crates/parser/src/conversion.rs
@@ -191,8 +191,8 @@ pub(crate) fn convert_module_code(
local_counts.c128 += 1;
}
Some(wasmparser::ValType::Ref(_)) => {
- local_addr_map.push(local_counts.cref);
- local_counts.cref += 1;
+ local_addr_map.push(local_counts.c32);
+ local_counts.c32 += 1;
}
None => return Err(crate::ParseError::UnsupportedOperator("Unknown local type".to_string())),
}
diff --git a/crates/parser/src/optimize.rs b/crates/parser/src/optimize.rs
index 1369d7a..c066c29 100644
--- a/crates/parser/src/optimize.rs
+++ b/crates/parser/src/optimize.rs
@@ -21,7 +21,6 @@ fn rewrite(instructions: &mut [Instruction], self_func_addr: u32) {
Instruction::LocalCopy32(a, b) if a == b => instructions[read] = Instruction::Nop,
Instruction::LocalCopy64(a, b) if a == b => instructions[read] = Instruction::Nop,
Instruction::LocalCopy128(a, b) if a == b => instructions[read] = Instruction::Nop,
- Instruction::LocalCopyRef(a, b) if a == b => instructions[read] = Instruction::Nop,
Instruction::Call(addr) if addr == self_func_addr => instructions[read] = Instruction::CallSelf,
Instruction::ReturnCall(addr) if addr == self_func_addr => instructions[read] = Instruction::ReturnCallSelf,
Instruction::I32Add => {
@@ -154,16 +153,6 @@ fn rewrite(instructions: &mut [Instruction], self_func_addr: u32) {
instructions[read] = Instruction::Nop;
}
}
- Instruction::LocalGetRef(dst) => {
- if read > 0
- && let Instruction::LocalSetRef(src) = instructions[read - 1]
- && src == dst
- {
- instructions[read - 1] = Instruction::LocalTeeRef(src);
- instructions[read] = Instruction::Nop;
- }
- }
-
Instruction::LocalSet32(dst) => {
if read > 0 {
match instructions[read - 1] {
@@ -243,16 +232,6 @@ fn rewrite(instructions: &mut [Instruction], self_func_addr: u32) {
if src == dst { Instruction::Nop } else { Instruction::LocalCopy128(src, dst) };
}
}
- Instruction::LocalSetRef(dst) => {
- if read > 0
- && let Instruction::LocalGetRef(src) = instructions[read - 1]
- {
- instructions[read - 1] = Instruction::Nop;
- instructions[read] =
- if src == dst { Instruction::Nop } else { Instruction::LocalCopyRef(src, dst) };
- }
- }
-
Instruction::LocalTee32(dst) => {
if read > 0
&& let Instruction::LocalGet32(src) = instructions[read - 1]
@@ -289,15 +268,6 @@ fn rewrite(instructions: &mut [Instruction], self_func_addr: u32) {
instructions[read] = Instruction::Nop;
}
}
- Instruction::LocalTeeRef(dst) => {
- if read > 0
- && let Instruction::LocalGetRef(src) = instructions[read - 1]
- && src == dst
- {
- instructions[read] = Instruction::Nop;
- }
- }
-
Instruction::Drop32 => {
if read > 0
&& let Instruction::LocalTee32(local) = instructions[read - 1]
@@ -322,14 +292,6 @@ fn rewrite(instructions: &mut [Instruction], self_func_addr: u32) {
instructions[read] = Instruction::Nop;
}
}
- Instruction::DropRef => {
- if read > 0
- && let Instruction::LocalTeeRef(local) = instructions[read - 1]
- {
- instructions[read - 1] = Instruction::LocalSetRef(local);
- instructions[read] = Instruction::Nop;
- }
- }
_ => {}
}
}
diff --git a/crates/parser/src/visit.rs b/crates/parser/src/visit.rs
index 94cb4ea..e6f415b 100644
--- a/crates/parser/src/visit.rs
+++ b/crates/parser/src/visit.rs
@@ -22,7 +22,6 @@ struct StackBase {
s32: u16,
s64: u16,
s128: u16,
- sref: u16,
}
struct LoweringCtx {
@@ -214,7 +213,7 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild
wasmparser::ValType::I64 => Instruction::GlobalSet64(global_index),
wasmparser::ValType::F64 => Instruction::GlobalSet64(global_index),
wasmparser::ValType::V128 => Instruction::GlobalSet128(global_index),
- wasmparser::ValType::Ref(_) => Instruction::GlobalSetRef(global_index),
+ wasmparser::ValType::Ref(_) => Instruction::GlobalSet32(global_index),
})
}
}
@@ -227,7 +226,7 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild
wasmparser::ValType::I64 => Instruction::Drop64,
wasmparser::ValType::F64 => Instruction::Drop64,
wasmparser::ValType::V128 => Instruction::Drop128,
- wasmparser::ValType::Ref(_) => Instruction::DropRef,
+ wasmparser::ValType::Ref(_) => Instruction::Drop32,
})
}
}
@@ -257,7 +256,7 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild
self.instructions.push(Instruction::LocalGet128(resolved_idx));
}
wasmparser::ValType::Ref(_) => {
- self.instructions.push(Instruction::LocalGetRef(resolved_idx));
+ self.instructions.push(Instruction::LocalGet32(resolved_idx));
}
}
}
@@ -272,7 +271,7 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild
wasmparser::ValType::I64 => Instruction::LocalSet64(resolved_idx),
wasmparser::ValType::F64 => Instruction::LocalSet64(resolved_idx),
wasmparser::ValType::V128 => Instruction::LocalSet128(resolved_idx),
- wasmparser::ValType::Ref(_) => Instruction::LocalSetRef(resolved_idx),
+ wasmparser::ValType::Ref(_) => Instruction::LocalSet32(resolved_idx),
})
}
}
@@ -286,7 +285,7 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild
wasmparser::ValType::I64 => Instruction::LocalTee64(resolved_idx),
wasmparser::ValType::F64 => Instruction::LocalTee64(resolved_idx),
wasmparser::ValType::V128 => Instruction::LocalTee128(resolved_idx),
- wasmparser::ValType::Ref(_) => Instruction::LocalTeeRef(resolved_idx),
+ wasmparser::ValType::Ref(_) => Instruction::LocalTee32(resolved_idx),
})
}
}
@@ -457,8 +456,8 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild
}
fn visit_typed_select_multi(&mut self, tys: Vec<wasmparser::ValType>) -> Self::Output {
- let (c32, c64, c128, cref) = Self::label_keep_counts(&tys);
- self.instructions.push(Instruction::SelectMulti(tinywasm_types::ValueCounts { c32, c64, c128, cref }));
+ let (c32, c64, c128) = Self::label_keep_counts(&tys);
+ self.instructions.push(Instruction::SelectMulti(tinywasm_types::ValueCounts { c32, c64, c128 }));
}
fn visit_typed_select(&mut self, ty: wasmparser::ValType) -> Self::Output {
@@ -468,7 +467,7 @@ impl<'a, R: WasmModuleResources> wasmparser::VisitOperator<'a> for FunctionBuild
wasmparser::ValType::I64 => Instruction::Select64,
wasmparser::ValType::F64 => Instruction::Select64,
wasmparser::ValType::V128 => Instruction::Select128,
- wasmparser::ValType::Ref(_) => Instruction::SelectRef,
+ wasmparser::ValType::Ref(_) => Instruction::Select32,
});
}
@@ -595,7 +594,7 @@ impl<R: WasmModuleResources> FunctionBuilder<R> {
wasmparser::ValType::I32 | wasmparser::ValType::F32 => base.s32 += 1,
wasmparser::ValType::I64 | wasmparser::ValType::F64 => base.s64 += 1,
wasmparser::ValType::V128 => base.s128 += 1,
- wasmparser::ValType::Ref(_) => base.sref += 1,
+ wasmparser::ValType::Ref(_) => base.s32 += 1,
}
}
}
@@ -617,16 +616,8 @@ impl<R: WasmModuleResources> FunctionBuilder<R> {
Some(idx)
}
- fn emit_dropkeep(&mut self, base: StackBase, c32: u16, c64: u16, c128: u16, cref: u16) {
- if base.s32 == 0
- && c32 == 0
- && base.s64 == 0
- && c64 == 0
- && base.s128 == 0
- && c128 == 0
- && base.sref == 0
- && cref == 0
- {
+ fn emit_dropkeep(&mut self, base: StackBase, c32: u16, c64: u16, c128: u16) {
+ if base.s32 == 0 && c32 == 0 && base.s64 == 0 && c64 == 0 && base.s128 == 0 && c128 == 0 {
return;
}
@@ -635,26 +626,21 @@ impl<R: WasmModuleResources> FunctionBuilder<R> {
&& base.s64 <= u8::MAX as u16
&& c64 <= u8::MAX as u16
&& base.s128 <= u8::MAX as u16
- && c128 <= u8::MAX as u16
- && base.sref <= u8::MAX as u16
- && cref <= u8::MAX as u16;
+ && c128 <= u8::MAX as u16;
if fits_u8 {
- self.instructions.push(Instruction::DropKeepSmall {
- base32: base.s32 as u8,
+ self.instructions.push(Instruction::DropKeep {
+ base32: base.s32,
keep32: c32 as u8,
- base64: base.s64 as u8,
+ base64: base.s64,
keep64: c64 as u8,
- base128: base.s128 as u8,
+ base128: base.s128,
keep128: c128 as u8,
- base_ref: base.sref as u8,
- keep_ref: cref as u8,
});
} else {
self.instructions.push(Instruction::DropKeep32(base.s32, c32));
self.instructions.push(Instruction::DropKeep64(base.s64, c64));
self.instructions.push(Instruction::DropKeep128(base.s128, c128));
- self.instructions.push(Instruction::DropKeepRef(base.sref, cref));
}
}
@@ -673,18 +659,18 @@ impl<R: WasmModuleResources> FunctionBuilder<R> {
}
}
- fn label_keep_counts(label_types: &[wasmparser::ValType]) -> (u16, u16, u16, u16) {
- let (mut c32, mut c64, mut c128, mut cref) = (0, 0, 0, 0);
+ fn label_keep_counts(label_types: &[wasmparser::ValType]) -> (u16, u16, u16) {
+ let (mut c32, mut c64, mut c128) = (0, 0, 0);
for ty in label_types {
match ty {
wasmparser::ValType::I32 | wasmparser::ValType::F32 => c32 += 1,
wasmparser::ValType::I64 | wasmparser::ValType::F64 => c64 += 1,
wasmparser::ValType::V128 => c128 += 1,
- wasmparser::ValType::Ref(_) => cref += 1,
+ wasmparser::ValType::Ref(_) => c32 += 1,
}
}
- (c32, c64, c128, cref)
+ (c32, c64, c128)
}
fn emit_dropkeep_to_label(&mut self, label_depth: u32) {
@@ -698,9 +684,9 @@ impl<R: WasmModuleResources> FunctionBuilder<R> {
let base = self.stack_base_at_frame(label_depth as usize);
let label_types: Vec<_> = self.label_types_for_frame(frame);
- let (c32, c64, c128, cref) = Self::label_keep_counts(&label_types);
+ let (c32, c64, c128) = Self::label_keep_counts(&label_types);
- self.emit_dropkeep(base, c32, c64, c128, cref);
+ self.emit_dropkeep(base, c32, c64, c128);
}
fn label_types_for_frame(&self, frame: &wasmparser::Frame) -> Vec<wasmparser::ValType> {
@@ -746,8 +732,8 @@ impl<R: WasmModuleResources> FunctionBuilder<R> {
let base = self.stack_base_at_frame(depth as usize);
let label_types: Vec<_> = self.label_types_for_frame(frame);
- let (c32, c64, c128, cref) = Self::label_keep_counts(&label_types);
- self.emit_dropkeep(base, c32, c64, c128, cref);
+ let (c32, c64, c128) = Self::label_keep_counts(&label_types);
+ self.emit_dropkeep(base, c32, c64, c128);
let jump_ip = self.instructions.len();
self.instructions.push(Instruction::Jump(0));
diff --git a/crates/tinywasm/src/engine.rs b/crates/tinywasm/src/engine.rs
index ce84f3d..c8f05e9 100644
--- a/crates/tinywasm/src/engine.rs
+++ b/crates/tinywasm/src/engine.rs
@@ -39,8 +39,8 @@ pub enum FuelPolicy {
Weighted,
}
-/// Default size for the 32-bit value stack (i32, f32 values).
-pub const DEFAULT_VALUE_STACK_32_SIZE: usize = 32 * 1024; // 32k slots
+/// Default size for the 32-bit value stack (i32, f32, ref values).
+pub const DEFAULT_VALUE_STACK_32_SIZE: usize = 36 * 1024; // 36k slots
/// Default size for the 64-bit value stack (i64, f64 values).
pub const DEFAULT_VALUE_STACK_64_SIZE: usize = 32 * 1024; // 32k slots
@@ -48,9 +48,6 @@ pub const DEFAULT_VALUE_STACK_64_SIZE: usize = 32 * 1024; // 32k slots
/// Default size for the 128-bit value stack (v128 values).
pub const DEFAULT_VALUE_STACK_128_SIZE: usize = 4 * 1024; // 4k slots
-/// Default size for the reference value stack (funcref, externref values).
-pub const DEFAULT_VALUE_STACK_REF_SIZE: usize = 4 * 1024; // 4k slots
-
/// Default maximum size for the call stack (function frames).
pub const DEFAULT_MAX_CALL_STACK_SIZE: usize = 1024; // 1024 frames
@@ -59,14 +56,12 @@ pub const DEFAULT_MAX_CALL_STACK_SIZE: usize = 1024; // 1024 frames
#[cfg_attr(feature = "debug", derive(Debug))]
#[non_exhaustive]
pub struct Config {
- /// Size of the 32-bit value stack (i32, f32 values).
+ /// Size of the 32-bit value stack (i32, f32, ref values).
pub stack_32_size: usize,
/// Size of the 64-bit value stack (i64, f64 values).
pub stack_64_size: usize,
/// Size of the 128-bit value stack (v128 values).
pub stack_128_size: usize,
- /// Size of the reference value stack (funcref, externref values).
- pub stack_ref_size: usize,
/// Maximum size of the call stack
pub max_call_stack_size: usize,
/// Fuel accounting policy used by budgeted execution.
@@ -92,7 +87,6 @@ impl Default for Config {
stack_32_size: DEFAULT_VALUE_STACK_32_SIZE,
stack_64_size: DEFAULT_VALUE_STACK_64_SIZE,
stack_128_size: DEFAULT_VALUE_STACK_128_SIZE,
- stack_ref_size: DEFAULT_VALUE_STACK_REF_SIZE,
max_call_stack_size: DEFAULT_MAX_CALL_STACK_SIZE,
fuel_policy: FuelPolicy::default(),
}
diff --git a/crates/tinywasm/src/interpreter/executor.rs b/crates/tinywasm/src/interpreter/executor.rs
index fd7d49e..a6052a9 100644
--- a/crates/tinywasm/src/interpreter/executor.rs
+++ b/crates/tinywasm/src/interpreter/executor.rs
@@ -135,11 +135,9 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
Drop32 => self.store.stack.values.drop::<Value32>(),
Drop64 => self.store.stack.values.drop::<Value64>(),
Drop128 => self.store.stack.values.drop::<Value128>(),
- DropRef => self.store.stack.values.drop::<ValueRef>(),
Select32 => self.store.stack.values.select::<Value32>()?,
Select64 => self.store.stack.values.select::<Value64>()?,
Select128 => self.store.stack.values.select::<Value128>()?,
- SelectRef => self.store.stack.values.select::<ValueRef>()?,
SelectMulti(counts) => self.store.stack.values.select_multi(*counts),
Call(v) => { self.exec_call_direct::<false>(*v)?; continue; }
CallSelf => { self.exec_call_self::<false>()?; continue; }
@@ -150,28 +148,24 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
Jump(ip) => { self.exec_jump(*ip); continue; }
JumpIfZero(ip) => if self.exec_jump_if_zero(*ip) { continue; },
JumpIfNonZero(ip) => if self.exec_jump_if_non_zero(*ip) { continue; },
- DropKeepSmall { base32, keep32, base64, keep64, base128, keep128, base_ref, keep_ref } => {
- let mut base = self.cf.stack_base(); base.s32 += *base32 as u32; base.s64 += *base64 as u32; base.s128 += *base128 as u32; base.sref += *base_ref as u32;
- self.store.stack.values.truncate_keep_counts(base, ValueCounts { c32: *keep32 as u16, c64: *keep64 as u16, c128: *keep128 as u16, cref: *keep_ref as u16 });
+ DropKeep { base32, keep32, base64, keep64, base128, keep128 } => {
+ let mut base = self.cf.stack_base(); base.s32 += *base32 as u32; base.s64 += *base64 as u32; base.s128 += *base128 as u32;
+ self.store.stack.values.truncate_keep_counts(base, ValueCounts { c32: *keep32 as u16, c64: *keep64 as u16, c128: *keep128 as u16 });
}
DropKeep32(base, keep) => self.store.stack.values.stack_32.truncate_keep((self.cf.stack_base().s32 + *base as u32) as usize, *keep as usize),
DropKeep64(base, keep) => self.store.stack.values.stack_64.truncate_keep((self.cf.stack_base().s64 + *base as u32) as usize, *keep as usize),
DropKeep128(base, keep) => self.store.stack.values.stack_128.truncate_keep((self.cf.stack_base().s128 + *base as u32) as usize, *keep as usize),
- DropKeepRef(base, keep) => self.store.stack.values.stack_ref.truncate_keep((self.cf.stack_base().sref + *base as u32) as usize, *keep as usize),
BranchTable(default_ip, start, len) => { self.exec_branch_table(*default_ip, *start, *len); continue; }
Return => { if self.exec_return() { return Ok(Some(())); } continue; }
LocalGet32(local_index) => self.store.stack.values.push(self.store.stack.values.local_get::<Value32>(&self.cf, *local_index))?,
LocalGet64(local_index) => self.store.stack.values.push(self.store.stack.values.local_get::<Value64>(&self.cf, *local_index))?,
LocalGet128(local_index) => self.store.stack.values.push(self.store.stack.values.local_get::<Value128>(&self.cf, *local_index))?,
- LocalGetRef(local_index) => self.store.stack.values.push(self.store.stack.values.local_get::<ValueRef>(&self.cf, *local_index))?,
LocalSet32(local_index) => stack_op!(local_set_pop Value32, local_index),
LocalSet64(local_index) => stack_op!(local_set_pop Value64, local_index),
LocalSet128(local_index) => stack_op!(local_set_pop Value128, local_index),
- LocalSetRef(local_index) => stack_op!(local_set_pop ValueRef, local_index),
LocalCopy32(from, to) => self.store.stack.values.local_set(&self.cf, *to, self.store.stack.values.local_get::<Value32>(&self.cf, *from)),
LocalCopy64(from, to) => self.store.stack.values.local_set(&self.cf, *to, self.store.stack.values.local_get::<Value64>(&self.cf, *from)),
LocalCopy128(from, to) => self.store.stack.values.local_set(&self.cf, *to, self.store.stack.values.local_get::<Value128>(&self.cf, *from)),
- LocalCopyRef(from, to) => self.store.stack.values.local_set(&self.cf, *to, self.store.stack.values.local_get::<ValueRef>(&self.cf, *from)),
I32AddLocals(a, b) => self.store.stack.values.push(self.store.stack.values.local_get::<i32>(&self.cf, *a).wrapping_add(self.store.stack.values.local_get::<i32>(&self.cf, *b)))?,
I64AddLocals(a, b) => self.store.stack.values.push(self.store.stack.values.local_get::<i64>(&self.cf, *a).wrapping_add(self.store.stack.values.local_get::<i64>(&self.cf, *b)))?,
I32AddConst(c) => stack_op!(unary i32, |v| v.wrapping_add(*c)),
@@ -192,12 +186,10 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
LocalTee32(local_index) => stack_op!(local_tee Value32, local_index),
LocalTee64(local_index) => stack_op!(local_tee Value64, local_index),
LocalTee128(local_index) => stack_op!(local_tee Value128, local_index),
- LocalTeeRef(local_index) => stack_op!(local_tee ValueRef, local_index),
GlobalGet(global_index) => self.exec_global_get(*global_index)?,
- GlobalSet32(global_index) => self.exec_global_set::<Value32>(*global_index),
+ GlobalSet32(global_index) => self.exec_global_set_32(*global_index),
GlobalSet64(global_index) => self.exec_global_set::<Value64>(*global_index),
GlobalSet128(global_index) => self.exec_global_set::<Value128>(*global_index),
- GlobalSetRef(global_index) => self.exec_global_set::<ValueRef>(*global_index),
I32Const(val) => self.exec_const(*val)?,
I64Const(val) => self.exec_const(*val)?,
F32Const(val) => self.exec_const(*val)?,
@@ -302,8 +294,8 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
I64Popcnt => stack_op!(unary i64, |v| i64::from(v.count_ones())),
// Reference types
- RefFunc(func_idx) => self.exec_const::<ValueRef>(Some(self.module.resolve_func_addr(*func_idx)))?,
- RefNull(_) => self.exec_const::<ValueRef>(None)?,
+ RefFunc(func_idx) => self.exec_const(ValueRef::from_addr(Some(self.module.resolve_func_addr(*func_idx))))?,
+ RefNull(_) => self.exec_const(ValueRef::NULL)?,
RefIsNull => self.exec_ref_is_null()?,
MemorySize(addr) => self.exec_memory_size(*addr)?,
MemoryGrow(addr) => self.exec_memory_grow(*addr)?,
@@ -909,11 +901,24 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
let val = self.store.stack.values.pop::<T>().into();
self.store.state.set_global_val(self.module.resolve_global_addr(global_index), val);
}
+
+ fn exec_global_set_32(&mut self, global_index: u32) {
+ let global_addr = self.module.resolve_global_addr(global_index);
+ let raw = self.store.stack.values.pop::<Value32>();
+ let ty = self.store.state.get_global(global_addr).ty.ty;
+ let value = match ty {
+ WasmType::I32 | WasmType::F32 => TinyWasmValue::Value32(raw),
+ WasmType::RefExtern | WasmType::RefFunc => TinyWasmValue::ValueRef(ValueRef::from_raw(raw)),
+ WasmType::I64 | WasmType::F64 | WasmType::V128 => unreachable!("invalid global.set.32 target type"),
+ };
+ self.store.state.set_global_val(global_addr, value);
+ }
+
fn exec_const<T: InternalValue>(&mut self, val: T) -> Result<()> {
self.store.stack.values.push(val)
}
fn exec_ref_is_null(&mut self) -> Result<()> {
- let is_null = i32::from(self.store.stack.values.pop::<ValueRef>().is_none());
+ let is_null = i32::from(self.store.stack.values.pop::<ValueRef>().is_null());
self.store.stack.values.push::<i32>(is_null)
}
@@ -1137,7 +1142,7 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
let val = self.store.stack.values.pop::<ValueRef>();
let idx = self.store.stack.values.pop::<i32>() as u32;
let table = self.store.state.get_table_mut(self.module.resolve_table_addr(table_index));
- table.set(idx, val.into())
+ table.set(idx, val.addr().into())
}
fn exec_table_size(&mut self, table_index: u32) -> Result<()> {
let table = self.store.state.get_table(self.module.resolve_table_addr(table_index));
@@ -1194,7 +1199,7 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
let n = self.store.stack.values.pop::<i32>();
let val = self.store.stack.values.pop::<ValueRef>();
- match table.grow(n, val.into()) {
+ match table.grow(n, val.addr().into()) {
Ok(()) => self.store.stack.values.push(sz)?,
Err(_) => self.store.stack.values.push(-1_i32)?,
}
@@ -1221,7 +1226,7 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
return Ok(());
}
- table.fill(self.module.func_addrs(), i as usize, n as usize, val.into())
+ table.fill(self.module.func_addrs(), i as usize, n as usize, val.addr().into())
}
}
diff --git a/crates/tinywasm/src/interpreter/stack/call_stack.rs b/crates/tinywasm/src/interpreter/stack/call_stack.rs
index dfc71bc..fbf5ca5 100644
--- a/crates/tinywasm/src/interpreter/stack/call_stack.rs
+++ b/crates/tinywasm/src/interpreter/stack/call_stack.rs
@@ -48,7 +48,6 @@ pub(crate) struct StackBase {
pub(crate) s32: u32,
pub(crate) s64: u32,
pub(crate) s128: u32,
- pub(crate) sref: u32,
}
impl CallFrame {
@@ -67,7 +66,6 @@ impl CallFrame {
s32: self.locals_base.s32 + self.stack_offset.c32 as u32,
s64: self.locals_base.s64 + self.stack_offset.c64 as u32,
s128: self.locals_base.s128 + self.stack_offset.c128 as u32,
- sref: self.locals_base.sref + self.stack_offset.cref as u32,
}
}
diff --git a/crates/tinywasm/src/interpreter/stack/value_stack.rs b/crates/tinywasm/src/interpreter/stack/value_stack.rs
index 189282f..f59f3b6 100644
--- a/crates/tinywasm/src/interpreter/stack/value_stack.rs
+++ b/crates/tinywasm/src/interpreter/stack/value_stack.rs
@@ -4,16 +4,14 @@ use alloc::boxed::Box;
use alloc::vec::Vec;
use tinywasm_types::{ExternRef, FuncRef, LocalAddr, ValueCounts, WasmType, WasmValue};
-use crate::{Result, Trap, engine::Config, interpreter::*};
-
use super::{CallFrame, StackBase};
+use crate::{Result, Trap, engine::Config, interpreter::*};
#[cfg_attr(feature = "debug", derive(Debug))]
pub(crate) struct ValueStack {
pub(crate) stack_32: Stack<Value32>,
pub(crate) stack_64: Stack<Value64>,
pub(crate) stack_128: Stack<Value128>,
- pub(crate) stack_ref: Stack<ValueRef>,
}
#[cfg_attr(feature = "debug", derive(Debug))]
@@ -160,7 +158,6 @@ impl ValueStack {
stack_32: Stack::new(config.stack_32_size),
stack_64: Stack::new(config.stack_64_size),
stack_128: Stack::new(config.stack_128_size),
- stack_ref: Stack::new(config.stack_ref_size),
}
}
@@ -168,12 +165,11 @@ impl ValueStack {
self.stack_32.clear();
self.stack_64.clear();
self.stack_128.clear();
- self.stack_ref.clear();
}
#[inline(always)]
pub(crate) fn len(&self) -> usize {
- self.stack_32.len + self.stack_64.len + self.stack_128.len + self.stack_ref.len
+ self.stack_32.len + self.stack_64.len + self.stack_128.len
}
#[inline(always)]
@@ -213,7 +209,6 @@ impl ValueStack {
self.stack_32.select_many(counts.c32 as usize, condition);
self.stack_64.select_many(counts.c64 as usize, condition);
self.stack_128.select_many(counts.c128 as usize, condition);
- self.stack_ref.select_many(counts.cref as usize, condition);
}
pub(crate) fn pop_types<'a>(
@@ -239,13 +234,7 @@ impl ValueStack {
} else {
self.stack_128.enter_locals(params.c128 as usize, locals.c128 as usize)?
};
- let locals_baseref = if params.cref == 0 && locals.cref == 0 {
- self.stack_ref.len as u32
- } else {
- self.stack_ref.enter_locals(params.cref as usize, locals.cref as usize)?
- };
-
- Ok(StackBase { s32: locals_base32, s64: locals_base64, s128: locals_base128, sref: locals_baseref })
+ Ok(StackBase { s32: locals_base32, s64: locals_base64, s128: locals_base128 })
}
pub(crate) fn truncate_keep_counts(&mut self, base: StackBase, keep: ValueCounts) {
@@ -253,14 +242,12 @@ impl ValueStack {
self.stack_32.len = base.s32 as usize;
self.stack_64.len = base.s64 as usize;
self.stack_128.len = base.s128 as usize;
- self.stack_ref.len = base.sref as usize;
return;
}
self.stack_32.truncate_keep(base.s32 as usize, keep.c32 as usize);
self.stack_64.truncate_keep(base.s64 as usize, keep.c64 as usize);
self.stack_128.truncate_keep(base.s128 as usize, keep.c128 as usize);
- self.stack_ref.truncate_keep(base.sref as usize, keep.cref as usize);
}
#[inline]
@@ -288,7 +275,7 @@ impl ValueStack {
TinyWasmValue::Value32(v) => self.stack_32.push(v)?,
TinyWasmValue::Value64(v) => self.stack_64.push(v)?,
TinyWasmValue::Value128(v) => self.stack_128.push(v)?,
- TinyWasmValue::ValueRef(v) => self.stack_ref.push(v)?,
+ TinyWasmValue::ValueRef(v) => self.stack_32.push(v.raw())?,
}
Ok(())
}
@@ -299,8 +286,8 @@ impl ValueStack {
WasmType::I64 => WasmValue::I64(self.pop()),
WasmType::F32 => WasmValue::F32(self.pop()),
WasmType::F64 => WasmValue::F64(self.pop()),
- WasmType::RefExtern => WasmValue::RefExtern(ExternRef::new(self.pop())),
- WasmType::RefFunc => WasmValue::RefFunc(FuncRef::new(self.pop())),
+ WasmType::RefExtern => WasmValue::RefExtern(ExternRef::from_raw(self.pop::<ValueRef>().raw())),
+ WasmType::RefFunc => WasmValue::RefFunc(FuncRef::from_raw(self.pop::<ValueRef>().raw())),
WasmType::V128 => WasmValue::V128(self.pop::<Value128>().into()),
}
}
@@ -312,8 +299,8 @@ impl ValueStack {
WasmValue::I64(v) => self.stack_64.push(*v as u64)?,
WasmValue::F32(v) => self.stack_32.push(v.to_bits())?,
WasmValue::F64(v) => self.stack_64.push(v.to_bits())?,
- WasmValue::RefExtern(v) => self.stack_ref.push(v.addr())?,
- WasmValue::RefFunc(v) => self.stack_ref.push(v.addr())?,
+ WasmValue::RefExtern(v) => self.stack_32.push(v.raw())?,
+ WasmValue::RefFunc(v) => self.stack_32.push(v.raw())?,
WasmValue::V128(v) => self.stack_128.push((*v).into())?,
}
}
diff --git a/crates/tinywasm/src/interpreter/values.rs b/crates/tinywasm/src/interpreter/values.rs
index 7726e57..eae0c53 100644
--- a/crates/tinywasm/src/interpreter/values.rs
+++ b/crates/tinywasm/src/interpreter/values.rs
@@ -6,9 +6,50 @@ use tinywasm_types::{ExternRef, FuncRef, WasmType, WasmValue};
pub(crate) type Value32 = u32;
pub(crate) type Value64 = u64;
-pub(crate) type ValueRef = Option<u32>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub(crate) struct ValueRef(u32);
+
+impl Default for ValueRef {
+ fn default() -> Self {
+ Self::NULL
+ }
+}
+
+impl ValueRef {
+ pub(crate) const NULL: Self = Self(u32::MAX);
+
+ #[inline]
+ pub(crate) const fn from_raw(raw: u32) -> Self {
+ Self(raw)
+ }
+
+ #[inline]
+ pub(crate) const fn from_addr(addr: Option<u32>) -> Self {
+ match addr {
+ Some(addr) => Self(addr),
+ None => Self::NULL,
+ }
+ }
+
+ #[inline]
+ pub(crate) const fn addr(self) -> Option<u32> {
+ if self.is_null() { None } else { Some(self.0) }
+ }
+
+ #[inline]
+ pub(crate) const fn is_null(self) -> bool {
+ self.0 == Self::NULL.0
+ }
+
+ #[inline]
+ pub(crate) const fn raw(self) -> u32 {
+ self.0
+ }
+}
+
+#[allow(private_interfaces)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// A untyped WebAssembly value
pub enum TinyWasmValue {
/// A 32-bit value
@@ -47,6 +88,7 @@ impl TinyWasmValue {
}
/// Converts the value to a reference value (returns None if the value is not a reference value)
+ #[allow(private_interfaces, dead_code)]
pub fn as_ref(self) -> Option<ValueRef> {
match self {
Self::ValueRef(v) => Some(v),
@@ -61,8 +103,8 @@ impl TinyWasmValue {
(Self::Value64(v), WasmType::I64) => Some(WasmValue::I64(v as i64)),
(Self::Value32(v), WasmType::F32) => Some(WasmValue::F32(f32::from_bits(v))),
(Self::Value64(v), WasmType::F64) => Some(WasmValue::F64(f64::from_bits(v))),
- (Self::ValueRef(v), WasmType::RefExtern) => Some(WasmValue::RefExtern(ExternRef::new(v))),
- (Self::ValueRef(v), WasmType::RefFunc) => Some(WasmValue::RefFunc(FuncRef::new(v))),
+ (Self::ValueRef(v), WasmType::RefExtern) => Some(WasmValue::RefExtern(ExternRef::from_raw(v.raw()))),
+ (Self::ValueRef(v), WasmType::RefFunc) => Some(WasmValue::RefFunc(FuncRef::from_raw(v.raw()))),
(Self::Value128(v), WasmType::V128) => Some(WasmValue::V128((v).into())),
(_, WasmType::I32 | WasmType::F32) => None,
(_, WasmType::I64 | WasmType::F64) => None,
@@ -79,8 +121,8 @@ impl From<&WasmValue> for TinyWasmValue {
WasmValue::I64(v) => Self::Value64(*v as u64),
WasmValue::F32(v) => Self::Value32(v.to_bits()),
WasmValue::F64(v) => Self::Value64(v.to_bits()),
- WasmValue::RefExtern(v) => Self::ValueRef(v.addr()),
- WasmValue::RefFunc(v) => Self::ValueRef(v.addr()),
+ WasmValue::RefExtern(v) => Self::ValueRef(ValueRef::from_addr(v.addr())),
+ WasmValue::RefFunc(v) => Self::ValueRef(ValueRef::from_addr(v.addr())),
WasmValue::V128(v) => Self::Value128((*v).into()),
}
}
@@ -113,48 +155,48 @@ pub(crate) trait InternalValue: sealed::Sealed + Into<TinyWasmValue> + Copy + De
}
macro_rules! impl_internalvalue {
- ($( $variant:ident, $stack:ident, $stack_base:ident, $outer:ty, $to_internal:expr, $to_outer:expr )*) => {
+ ($( $variant:ident, $stack:ident, $stack_base:ident, $outer:ty, $to_value:expr, $to_stack:expr, $from_stack:expr )*) => {
$(
impl sealed::Sealed for $outer {}
impl From<$outer> for TinyWasmValue {
fn from(value: $outer) -> Self {
- TinyWasmValue::$variant($to_internal(value))
+ TinyWasmValue::$variant($to_value(value))
}
}
impl InternalValue for $outer {
#[inline(always)]
fn stack_push(stack: &mut ValueStack, value: Self) -> Result<()> {
- stack.$stack.push($to_internal(value))
+ stack.$stack.push($to_stack(value))
}
#[inline(always)]
fn local_get(stack: &ValueStack, frame: &CallFrame, index: LocalAddr) -> Self {
- $to_outer(*stack.$stack.get(frame.locals_base.$stack_base as usize + index as usize))
+ $from_stack(*stack.$stack.get(frame.locals_base.$stack_base as usize + index as usize))
}
#[inline(always)]
fn local_update(stack: &mut ValueStack, frame: &CallFrame, index: LocalAddr, func: impl FnOnce(&mut Self)) {
let slot = stack.$stack.get_mut(frame.locals_base.$stack_base as usize + index as usize);
- let mut value = $to_outer(*slot);
+ let mut value = $from_stack(*slot);
func(&mut value);
- *slot = $to_internal(value);
+ *slot = $to_stack(value);
}
#[inline(always)]
fn local_set(stack: &mut ValueStack, frame: &CallFrame, index: LocalAddr, value: Self) {
- stack.$stack.set(frame.locals_base.$stack_base as usize + index as usize, $to_internal(value));
+ stack.$stack.set(frame.locals_base.$stack_base as usize + index as usize, $to_stack(value));
}
#[inline(always)]
fn stack_pop(stack: &mut ValueStack) -> Self {
- $to_outer(stack.$stack.pop())
+ $from_stack(stack.$stack.pop())
}
#[inline(always)]
fn stack_peek(stack: &ValueStack) -> Self {
- $to_outer(*stack.$stack.last())
+ $from_stack(*stack.$stack.last())
}
}
)*
@@ -162,12 +204,12 @@ macro_rules! impl_internalvalue {
}
impl_internalvalue! {
- Value32, stack_32, s32, u32, |v| v, |v| v
- Value64, stack_64, s64, u64, |v| v, |v| v
- Value32, stack_32, s32, i32, |v: i32| u32::from_ne_bytes(v.to_ne_bytes()), |v: u32| i32::from_ne_bytes(v.to_ne_bytes())
- Value64, stack_64, s64, i64, |v: i64| u64::from_ne_bytes(v.to_ne_bytes()), |v: u64| i64::from_ne_bytes(v.to_ne_bytes())
- Value32, stack_32, s32, f32, f32::to_bits, f32::from_bits
- Value64, stack_64, s64, f64, f64::to_bits, f64::from_bits
- ValueRef, stack_ref, sref, ValueRef, |v| v, |v| v
- Value128, stack_128, s128, Value128, |v| v, |v| v
+ Value32, stack_32, s32, u32, |v| v, |v| v, |v| v
+ Value64, stack_64, s64, u64, |v| v, |v| v, |v| v
+ Value32, stack_32, s32, i32, |v: i32| u32::from_ne_bytes(v.to_ne_bytes()), |v: i32| u32::from_ne_bytes(v.to_ne_bytes()), |v: u32| i32::from_ne_bytes(v.to_ne_bytes())
+ Value64, stack_64, s64, i64, |v: i64| u64::from_ne_bytes(v.to_ne_bytes()), |v: i64| u64::from_ne_bytes(v.to_ne_bytes()), |v: u64| i64::from_ne_bytes(v.to_ne_bytes())
+ Value32, stack_32, s32, f32, f32::to_bits, f32::to_bits, f32::from_bits
+ Value64, stack_64, s64, f64, f64::to_bits, f64::to_bits, f64::from_bits
+ ValueRef, stack_32, s32, ValueRef, |v| v, |v: ValueRef| v.raw(), |v: u32| ValueRef(v)
+ Value128, stack_128, s128, Value128, |v| v, |v| v, |v| v
}
diff --git a/crates/tinywasm/src/store/mod.rs b/crates/tinywasm/src/store/mod.rs
index 4ba6c97..57601a4 100644
--- a/crates/tinywasm/src/store/mod.rs
+++ b/crates/tinywasm/src/store/mod.rs
@@ -4,8 +4,8 @@ use core::sync::atomic::{AtomicUsize, Ordering};
use tinywasm_types::*;
use crate::instance::ModuleInstanceInner;
-use crate::interpreter::TinyWasmValue;
use crate::interpreter::stack::Stack;
+use crate::interpreter::{TinyWasmValue, ValueRef};
use crate::{Engine, Error, ModuleInstance, Result, Trap};
mod data;
@@ -478,9 +478,9 @@ impl Store {
I64Const(i) => (*i).into(),
V128Const(i) => (*i).into(),
GlobalGet(addr) => resolve_global(*addr)?,
- RefFunc(None) => TinyWasmValue::ValueRef(None),
- RefExtern(None) => TinyWasmValue::ValueRef(None),
- RefFunc(Some(idx)) => TinyWasmValue::ValueRef(Some(resolve_func(*idx)?)),
+ RefFunc(None) => TinyWasmValue::ValueRef(ValueRef::NULL),
+ RefExtern(None) => TinyWasmValue::ValueRef(ValueRef::NULL),
+ RefFunc(Some(idx)) => TinyWasmValue::ValueRef(ValueRef::from_addr(Some(resolve_func(*idx)?))),
_ => return Err(Error::Other("unsupported const instruction".to_string())),
};
return Ok(val);
@@ -495,8 +495,10 @@ impl Store {
F64Const(f) => stack.push(TinyWasmValue::Value64(f.to_bits())),
V128Const(i) => stack.push(TinyWasmValue::Value128((*i).into())),
GlobalGet(addr) => stack.push(resolve_global(*addr)?),
- RefFunc(None) | RefExtern(None) => stack.push(TinyWasmValue::ValueRef(None)),
- RefFunc(Some(idx)) => stack.push(TinyWasmValue::ValueRef(Some(resolve_func(*idx)?))),
+ RefFunc(None) | RefExtern(None) => stack.push(TinyWasmValue::ValueRef(ValueRef::NULL)),
+ RefFunc(Some(idx)) => {
+ stack.push(TinyWasmValue::ValueRef(ValueRef::from_addr(Some(resolve_func(*idx)?))))
+ }
RefExtern(Some(_)) => {
return Err(Error::Other("ref.extern constants are not supported in init expressions".to_string()));
}
@@ -550,7 +552,7 @@ impl Store {
) -> Result<Option<u32>> {
let value = self.eval_const(const_instrs, module_global_addrs, module_func_addrs)?;
match value {
- TinyWasmValue::ValueRef(v) => Ok(v),
+ TinyWasmValue::ValueRef(v) => Ok(v.addr()),
other => Err(Error::Other(format!("expected reference const value, got {other:?}"))),
}
}
diff --git a/crates/types/src/instructions.rs b/crates/types/src/instructions.rs
index 01398b5..7db9f79 100644
--- a/crates/types/src/instructions.rs
+++ b/crates/types/src/instructions.rs
@@ -59,7 +59,7 @@ pub enum ConstInstruction {
#[cfg_attr(feature = "debug", derive(Debug))]
#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
pub enum Instruction {
- LocalCopy32(LocalAddr, LocalAddr), LocalCopy64(LocalAddr, LocalAddr), LocalCopy128(LocalAddr, LocalAddr), LocalCopyRef(LocalAddr, LocalAddr),
+ LocalCopy32(LocalAddr, LocalAddr), LocalCopy64(LocalAddr, LocalAddr), LocalCopy128(LocalAddr, LocalAddr),
I32AddLocals(LocalAddr, LocalAddr), I64AddLocals(LocalAddr, LocalAddr),
I32AddConst(i32), I64AddConst(i64),
LocalAddConst32(LocalAddr, i32), LocalAddConst64(LocalAddr, i64),
@@ -78,11 +78,10 @@ pub enum Instruction {
Jump(u32),
JumpIfZero(u32),
JumpIfNonZero(u32),
- DropKeepSmall { base32: u8, keep32: u8, base64: u8, keep64: u8, base128: u8, keep128: u8, base_ref: u8, keep_ref: u8 },
+ DropKeep { base32: u16, keep32: u8, base64: u16, keep64: u8, base128: u16, keep128: u8 },
DropKeep32(u16, u16),
DropKeep64(u16, u16),
DropKeep128(u16, u16),
- DropKeepRef(u16, u16),
BranchTable(u32, u32, u32), // (default_landing_pad_ip, branch_table_start, target_count)
Return,
Call(FuncAddr),
@@ -97,7 +96,6 @@ pub enum Instruction {
Drop32, Select32,
Drop64, Select64,
Drop128, Select128,
- DropRef, SelectRef,
SelectMulti(ValueCounts),
// > Variable Instructions
@@ -106,7 +104,6 @@ pub enum Instruction {
LocalGet32(LocalAddr), LocalSet32(LocalAddr), LocalTee32(LocalAddr), GlobalSet32(GlobalAddr),
LocalGet64(LocalAddr), LocalSet64(LocalAddr), LocalTee64(LocalAddr), GlobalSet64(GlobalAddr),
LocalGet128(LocalAddr), LocalSet128(LocalAddr), LocalTee128(LocalAddr), GlobalSet128(GlobalAddr),
- LocalGetRef(LocalAddr), LocalSetRef(LocalAddr), LocalTeeRef(LocalAddr), GlobalSetRef(GlobalAddr),
// > Memory Instructions
I32Load(MemoryArg),
diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs
index ece6086..28d52a7 100644
--- a/crates/types/src/lib.rs
+++ b/crates/types/src/lib.rs
@@ -230,13 +230,12 @@ pub struct ValueCounts {
pub c32: u16,
pub c64: u16,
pub c128: u16,
- pub cref: u16,
}
impl ValueCounts {
#[inline]
pub fn is_empty(&self) -> bool {
- self.c32 == 0 && self.c64 == 0 && self.c128 == 0 && self.cref == 0
+ self.c32 == 0 && self.c64 == 0 && self.c128 == 0
}
}
@@ -248,7 +247,7 @@ impl<'a> FromIterator<&'a WasmType> for ValueCounts {
WasmType::I32 | WasmType::F32 => counts.c32 += 1,
WasmType::I64 | WasmType::F64 => counts.c64 += 1,
WasmType::V128 => counts.c128 += 1,
- WasmType::RefExtern | WasmType::RefFunc => counts.cref += 1,
+ WasmType::RefExtern | WasmType::RefFunc => counts.c32 += 1,
}
counts
})
diff --git a/crates/types/src/value.rs b/crates/types/src/value.rs
index 462749b..20c822e 100644
--- a/crates/types/src/value.rs
+++ b/crates/types/src/value.rs
@@ -42,16 +42,18 @@ impl Debug for WasmValue {
}
}
+const NULL_REF: u32 = u32::MAX;
+
#[derive(Clone, Copy, PartialEq, Eq)]
-pub struct ExternRef(Option<ExternAddr>);
+pub struct ExternRef(u32);
#[derive(Clone, Copy, PartialEq, Eq)]
-pub struct FuncRef(Option<FuncAddr>);
+pub struct FuncRef(u32);
#[cfg(feature = "debug")]
impl Debug for ExternRef {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
- match self.0 {
+ match self.addr() {
Some(addr) => write!(f, "extern({addr:?})"),
None => write!(f, "extern(null)"),
}
@@ -61,7 +63,7 @@ impl Debug for ExternRef {
#[cfg(feature = "debug")]
impl Debug for FuncRef {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
- match self.0 {
+ match self.addr() {
Some(addr) => write!(f, "func({addr:?})"),
None => write!(f, "func(null)"),
}
@@ -72,24 +74,39 @@ impl FuncRef {
#[inline]
/// Create a new [`FuncRef`] from a [`FuncAddr`].
pub const fn new(addr: Option<FuncAddr>) -> Self {
- Self(addr)
+ match addr {
+ Some(addr) => Self(addr),
+ None => Self::null(),
+ }
}
#[inline]
/// Create a null [`FuncRef`].
pub const fn null() -> Self {
- Self(None)
+ Self(NULL_REF)
}
#[inline]
/// Check if the [`FuncRef`] is null.
pub const fn is_null(&self) -> bool {
- self.0.is_none()
+ self.0 == NULL_REF
}
#[inline]
/// Get the [`FuncAddr`] from the [`FuncRef`].
pub const fn addr(&self) -> Option<FuncAddr> {
+ if self.is_null() { None } else { Some(self.0) }
+ }
+
+ #[inline]
+ #[doc(hidden)]
+ pub const fn from_raw(raw: u32) -> Self {
+ Self(raw)
+ }
+
+ #[inline]
+ #[doc(hidden)]
+ pub const fn raw(&self) -> u32 {
self.0
}
}
@@ -99,24 +116,39 @@ impl ExternRef {
/// Create a new [`ExternRef`] from an [`ExternAddr`].
/// Should only be used by the runtime.
pub const fn new(addr: Option<ExternAddr>) -> Self {
- Self(addr)
+ match addr {
+ Some(addr) => Self(addr),
+ None => Self::null(),
+ }
}
/// Create a null [`ExternRef`].
#[inline]
pub const fn null() -> Self {
- Self(None)
+ Self(NULL_REF)
}
/// Check if the [`ExternRef`] is null.
#[inline]
pub const fn is_null(&self) -> bool {
- self.0.is_none()
+ self.0 == NULL_REF
}
/// Get the [`ExternAddr`] from the [`ExternRef`].
#[inline]
pub const fn addr(&self) -> Option<ExternAddr> {
+ if self.is_null() { None } else { Some(self.0) }
+ }
+
+ #[inline]
+ #[doc(hidden)]
+ pub const fn from_raw(raw: u32) -> Self {
+ Self(raw)
+ }
+
+ #[inline]
+ #[doc(hidden)]
+ pub const fn raw(&self) -> u32 {
self.0
}
}