diff --git a/src/runner.rs b/src/runner.rs index 7e171c3..faba091 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -10,8 +10,8 @@ use module::ModuleRef; use memory::MemoryRef; use func::{FuncRef, FuncInstance, FuncInstanceInternal}; use value::{ - RuntimeValue, FromRuntimeValue, WrapInto, TryTruncateInto, ExtendInto, - ArithmeticOps, Integer, Float, LittleEndianConvert, TransmuteInto, + ArithmeticOps, ExtendInto, Float, FromRuntimeValueInternal, Integer, LittleEndianConvert, + RuntimeValue, RuntimeValueInternal, TransmuteInto, TryTruncateInto, WrapInto, }; use host::Externals; use common::{DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX}; @@ -78,14 +78,13 @@ pub struct Interpreter { impl Interpreter { pub fn new(func: &FuncRef, args: &[RuntimeValue]) -> Result { let mut value_stack = ValueStack::with_limit(DEFAULT_VALUE_STACK_LIMIT); - for arg in args { - value_stack - .push(*arg) - .map_err( - // There is not enough space for pushing initial arguments. - // Weird, but bail out anyway. - |_| Trap::from(TrapKind::StackOverflow) - )?; + for &arg in args { + let arg = arg.into(); + value_stack.push(arg).map_err( + // There is not enough space for pushing initial arguments. + // Weird, but bail out anyway. + |_| Trap::from(TrapKind::StackOverflow), + )?; } let mut call_stack = Vec::new(); @@ -113,9 +112,9 @@ impl Interpreter { self.state = InterpreterState::Started; self.run_interpreter_loop(externals)?; - let opt_return_value = self.return_type.map(|_vt| { - self.value_stack.pop() - }); + let opt_return_value = self + .return_type + .map(|vt| self.value_stack.pop().with_type(vt)); // Ensure that stack is empty after the execution. This is guaranteed by the validation properties. assert!(self.value_stack.len() == 0); @@ -131,25 +130,18 @@ impl Interpreter { let mut resumable_state = InterpreterState::Started; swap(&mut self.state, &mut resumable_state); - let expected_ty = match resumable_state { - InterpreterState::Resumable(ty) => ty, - _ => unreachable!("Resumable arm is checked above is_resumable; qed"), - }; - - let value_ty = return_val.as_ref().map(|val| val.value_type()); - if value_ty != expected_ty { - return Err(TrapKind::UnexpectedSignature.into()); - } if let Some(return_val) = return_val { - self.value_stack.push(return_val).map_err(Trap::new)?; + self.value_stack + .push(return_val.into()) + .map_err(Trap::new)?; } self.run_interpreter_loop(externals)?; - let opt_return_value = self.return_type.map(|_vt| { - self.value_stack.pop() - }); + let opt_return_value = self + .return_type + .map(|vt| self.value_stack.pop().with_type(vt)); // Ensure that stack is empty after the execution. This is guaranteed by the validation properties. assert!(self.value_stack.len() == 0); @@ -222,7 +214,9 @@ impl Interpreter { } if let Some(return_val) = return_val { - self.value_stack.push(return_val).map_err(Trap::new)?; + self.value_stack + .push(return_val.into()) + .map_err(Trap::new)?; } } } @@ -311,8 +305,8 @@ impl Interpreter { &isa::Instruction::I32Const(val) => self.run_const(val.into()), &isa::Instruction::I64Const(val) => self.run_const(val.into()), - &isa::Instruction::F32Const(val) => self.run_const(RuntimeValue::decode_f32(val)), - &isa::Instruction::F64Const(val) => self.run_const(RuntimeValue::decode_f64(val)), + &isa::Instruction::F32Const(val) => self.run_const(val.into()), + &isa::Instruction::F64Const(val) => self.run_const(val.into()), &isa::Instruction::I32Eqz => self.run_eqz::(), &isa::Instruction::I32Eq => self.run_eq::(), @@ -545,9 +539,7 @@ impl Interpreter { .value_stack .pop_triple(); - let condition = right - .try_into() - .expect("Due to validation stack top should be I32"); + let condition = <_>::from_runtime_value_internal(right); let val = if condition { left } else { mid }; self.value_stack.push(val)?; Ok(InstructionOutcome::RunNextInstruction) @@ -586,7 +578,7 @@ impl Interpreter { .global_by_index(index) .expect("Due to validation global should exists"); let val = global.get(); - self.value_stack.push(val)?; + self.value_stack.push(val.into())?; Ok(InstructionOutcome::RunNextInstruction) } @@ -602,20 +594,23 @@ impl Interpreter { .module() .global_by_index(index) .expect("Due to validation global should exists"); - global.set(val).expect("Due to validation set to a global should succeed"); + global + .set(val.with_type(global.value_type())) + .expect("Due to validation set to a global should succeed"); Ok(InstructionOutcome::RunNextInstruction) } - fn run_load(&mut self, context: &mut FunctionContext, offset: u32) -> Result - where RuntimeValue: From, T: LittleEndianConvert { - let raw_address = self - .value_stack - .pop_as(); - let address = - effective_address( - offset, - raw_address, - )?; + fn run_load( + &mut self, + context: &mut FunctionContext, + offset: u32, + ) -> Result + where + RuntimeValueInternal: From, + T: LittleEndianConvert, + { + let raw_address = self.value_stack.pop_as(); + let address = effective_address(offset, raw_address)?; let m = context .memory() .expect("Due to validation memory should exists"); @@ -625,16 +620,18 @@ impl Interpreter { Ok(InstructionOutcome::RunNextInstruction) } - fn run_load_extend(&mut self, context: &mut FunctionContext, offset: u32) -> Result - where T: ExtendInto, RuntimeValue: From, T: LittleEndianConvert { - let raw_address = self - .value_stack - .pop_as(); - let address = - effective_address( - offset, - raw_address, - )?; + fn run_load_extend( + &mut self, + context: &mut FunctionContext, + offset: u32, + ) -> Result + where + T: ExtendInto, + RuntimeValueInternal: From, + T: LittleEndianConvert, + { + let raw_address = self.value_stack.pop_as(); + let address = effective_address(offset, raw_address)?; let m = context .memory() .expect("Due to validation memory should exists"); @@ -648,19 +645,18 @@ impl Interpreter { .map(|_| InstructionOutcome::RunNextInstruction) } - fn run_store(&mut self, context: &mut FunctionContext, offset: u32) -> Result - where T: FromRuntimeValue, T: LittleEndianConvert { - let stack_value = self - .value_stack - .pop_as::(); - let raw_address = self - .value_stack - .pop_as::(); - let address = - effective_address( - offset, - raw_address, - )?; + fn run_store( + &mut self, + context: &mut FunctionContext, + offset: u32, + ) -> Result + where + T: FromRuntimeValueInternal, + T: LittleEndianConvert, + { + let stack_value = self.value_stack.pop_as::(); + let raw_address = self.value_stack.pop_as::(); + let address = effective_address(offset, raw_address)?; let m = context .memory() @@ -676,15 +672,11 @@ impl Interpreter { offset: u32, ) -> Result where - T: FromRuntimeValue, + T: FromRuntimeValueInternal, T: WrapInto, U: LittleEndianConvert, { - let stack_value: T = self - .value_stack - .pop() - .try_into() - .expect("Due to validation value should be of proper type"); + let stack_value: T = <_>::from_runtime_value_internal(self.value_stack.pop()); let stack_value = stack_value.wrap_into(); let raw_address = self .value_stack @@ -707,9 +699,7 @@ impl Interpreter { .memory() .expect("Due to validation memory should exists"); let s = m.current_size().0; - self - .value_stack - .push(RuntimeValue::I32(s as i32))?; + self.value_stack.push(RuntimeValueInternal(s as _))?; Ok(InstructionOutcome::RunNextInstruction) } @@ -724,83 +714,93 @@ impl Interpreter { Ok(Pages(new_size)) => new_size as u32, Err(_) => u32::MAX, // Returns -1 (or 0xFFFFFFFF) in case of error. }; - self - .value_stack - .push(RuntimeValue::I32(m as i32))?; + self.value_stack.push(RuntimeValueInternal(m as _))?; Ok(InstructionOutcome::RunNextInstruction) } fn run_const(&mut self, val: RuntimeValue) -> Result { self .value_stack - .push(val) + .push(val.into()) .map_err(Into::into) .map(|_| InstructionOutcome::RunNextInstruction) } fn run_relop(&mut self, f: F) -> Result where - T: FromRuntimeValue, + T: FromRuntimeValueInternal, F: FnOnce(T, T) -> bool, { let (left, right) = self .value_stack .pop_pair_as::(); let v = if f(left, right) { - RuntimeValue::I32(1) + RuntimeValueInternal(1) } else { - RuntimeValue::I32(0) + RuntimeValueInternal(0) }; self.value_stack.push(v)?; Ok(InstructionOutcome::RunNextInstruction) } fn run_eqz(&mut self) -> Result - where T: FromRuntimeValue, T: PartialEq + Default { - let v = self - .value_stack - .pop_as::(); - let v = RuntimeValue::I32(if v == Default::default() { 1 } else { 0 }); + where + T: FromRuntimeValueInternal, + T: PartialEq + Default, + { + let v = self.value_stack.pop_as::(); + let v = RuntimeValueInternal(if v == Default::default() { 1 } else { 0 }); self.value_stack.push(v)?; Ok(InstructionOutcome::RunNextInstruction) } fn run_eq(&mut self) -> Result - where T: FromRuntimeValue + PartialEq + where + T: FromRuntimeValueInternal + PartialEq, { self.run_relop(|left: T, right: T| left == right) } fn run_ne(&mut self) -> Result - where T: FromRuntimeValue + PartialEq { + where + T: FromRuntimeValueInternal + PartialEq, + { self.run_relop(|left: T, right: T| left != right) } fn run_lt(&mut self) -> Result - where T: FromRuntimeValue + PartialOrd { + where + T: FromRuntimeValueInternal + PartialOrd, + { self.run_relop(|left: T, right: T| left < right) } fn run_gt(&mut self) -> Result - where T: FromRuntimeValue + PartialOrd { + where + T: FromRuntimeValueInternal + PartialOrd, + { self.run_relop(|left: T, right: T| left > right) } fn run_lte(&mut self) -> Result - where T: FromRuntimeValue + PartialOrd { + where + T: FromRuntimeValueInternal + PartialOrd, + { self.run_relop(|left: T, right: T| left <= right) } fn run_gte(&mut self) -> Result - where T: FromRuntimeValue + PartialOrd { + where + T: FromRuntimeValueInternal + PartialOrd, + { self.run_relop(|left: T, right: T| left >= right) } fn run_unop(&mut self, f: F) -> Result where F: FnOnce(T) -> U, - T: FromRuntimeValue, - RuntimeValue: From + T: FromRuntimeValueInternal, + RuntimeValueInternal: From, { let v = self .value_stack @@ -811,55 +811,69 @@ impl Interpreter { } fn run_clz(&mut self) -> Result - where RuntimeValue: From, T: Integer + FromRuntimeValue { + where + RuntimeValueInternal: From, + T: Integer + FromRuntimeValueInternal, + { self.run_unop(|v: T| v.leading_zeros()) } fn run_ctz(&mut self) -> Result - where RuntimeValue: From, T: Integer + FromRuntimeValue { + where + RuntimeValueInternal: From, + T: Integer + FromRuntimeValueInternal, + { self.run_unop(|v: T| v.trailing_zeros()) } fn run_popcnt(&mut self) -> Result - where RuntimeValue: From, T: Integer + FromRuntimeValue { + where + RuntimeValueInternal: From, + T: Integer + FromRuntimeValueInternal, + { self.run_unop(|v: T| v.count_ones()) } fn run_add(&mut self) -> Result - where RuntimeValue: From, T: ArithmeticOps + FromRuntimeValue { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From, + T: ArithmeticOps + FromRuntimeValueInternal, + { + let (left, right) = self.value_stack.pop_pair_as::(); let v = left.add(right); self.value_stack.push(v.into())?; Ok(InstructionOutcome::RunNextInstruction) } fn run_sub(&mut self) -> Result - where RuntimeValue: From, T: ArithmeticOps + FromRuntimeValue { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From, + T: ArithmeticOps + FromRuntimeValueInternal, + { + let (left, right) = self.value_stack.pop_pair_as::(); let v = left.sub(right); self.value_stack.push(v.into())?; Ok(InstructionOutcome::RunNextInstruction) } fn run_mul(&mut self) -> Result - where RuntimeValue: From, T: ArithmeticOps + FromRuntimeValue { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From, + T: ArithmeticOps + FromRuntimeValueInternal, + { + let (left, right) = self.value_stack.pop_pair_as::(); let v = left.mul(right); self.value_stack.push(v.into())?; Ok(InstructionOutcome::RunNextInstruction) } fn run_div(&mut self) -> Result - where RuntimeValue: From, T: TransmuteInto + FromRuntimeValue, U: ArithmeticOps + TransmuteInto { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From, + T: TransmuteInto + FromRuntimeValueInternal, + U: ArithmeticOps + TransmuteInto, + { + let (left, right) = self.value_stack.pop_pair_as::(); let (left, right) = (left.transmute_into(), right.transmute_into()); let v = left.div(right)?; let v = v.transmute_into(); @@ -868,10 +882,12 @@ impl Interpreter { } fn run_rem(&mut self) -> Result - where RuntimeValue: From, T: TransmuteInto + FromRuntimeValue, U: Integer + TransmuteInto { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From, + T: TransmuteInto + FromRuntimeValueInternal, + U: Integer + TransmuteInto, + { + let (left, right) = self.value_stack.pop_pair_as::(); let (left, right) = (left.transmute_into(), right.transmute_into()); let v = left.rem(right)?; let v = v.transmute_into(); @@ -880,50 +896,57 @@ impl Interpreter { } fn run_and(&mut self) -> Result - where RuntimeValue: From<::Output>, T: ops::BitAnd + FromRuntimeValue { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From<::Output>, + T: ops::BitAnd + FromRuntimeValueInternal, + { + let (left, right) = self.value_stack.pop_pair_as::(); let v = left.bitand(right); self.value_stack.push(v.into())?; Ok(InstructionOutcome::RunNextInstruction) } fn run_or(&mut self) -> Result - where RuntimeValue: From<::Output>, T: ops::BitOr + FromRuntimeValue { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From<::Output>, + T: ops::BitOr + FromRuntimeValueInternal, + { + let (left, right) = self.value_stack.pop_pair_as::(); let v = left.bitor(right); self.value_stack.push(v.into())?; Ok(InstructionOutcome::RunNextInstruction) } fn run_xor(&mut self) -> Result - where RuntimeValue: From<::Output>, T: ops::BitXor + FromRuntimeValue { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From<::Output>, + T: ops::BitXor + FromRuntimeValueInternal, + { + let (left, right) = self.value_stack.pop_pair_as::(); let v = left.bitxor(right); self.value_stack.push(v.into())?; Ok(InstructionOutcome::RunNextInstruction) } fn run_shl(&mut self, mask: T) -> Result - where RuntimeValue: From<>::Output>, T: ops::Shl + ops::BitAnd + FromRuntimeValue { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From<>::Output>, + T: ops::Shl + ops::BitAnd + FromRuntimeValueInternal, + { + let (left, right) = self.value_stack.pop_pair_as::(); let v = left.shl(right & mask); self.value_stack.push(v.into())?; Ok(InstructionOutcome::RunNextInstruction) } fn run_shr(&mut self, mask: U) -> Result - where RuntimeValue: From, T: TransmuteInto + FromRuntimeValue, U: ops::Shr + ops::BitAnd, >::Output: TransmuteInto { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From, + T: TransmuteInto + FromRuntimeValueInternal, + U: ops::Shr + ops::BitAnd, + >::Output: TransmuteInto, + { + let (left, right) = self.value_stack.pop_pair_as::(); let (left, right) = (left.transmute_into(), right.transmute_into()); let v = left.shr(right & mask); let v = v.transmute_into(); @@ -932,17 +955,20 @@ impl Interpreter { } fn run_rotl(&mut self) -> Result - where RuntimeValue: From, T: Integer + FromRuntimeValue { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From, + T: Integer + FromRuntimeValueInternal, + { + let (left, right) = self.value_stack.pop_pair_as::(); let v = left.rotl(right); self.value_stack.push(v.into())?; Ok(InstructionOutcome::RunNextInstruction) } fn run_rotr(&mut self) -> Result - where RuntimeValue: From, T: Integer + FromRuntimeValue + where + RuntimeValueInternal: From, + T: Integer + FromRuntimeValueInternal, { let (left, right) = self .value_stack @@ -953,51 +979,65 @@ impl Interpreter { } fn run_abs(&mut self) -> Result - where RuntimeValue: From, T: Float + FromRuntimeValue + where + RuntimeValueInternal: From, + T: Float + FromRuntimeValueInternal, { self.run_unop(|v: T| v.abs()) } fn run_neg(&mut self) -> Result where - RuntimeValue: From<::Output>, - T: ops::Neg + FromRuntimeValue + RuntimeValueInternal: From<::Output>, + T: ops::Neg + FromRuntimeValueInternal, { self.run_unop(|v: T| v.neg()) } fn run_ceil(&mut self) -> Result - where RuntimeValue: From, T: Float + FromRuntimeValue + where + RuntimeValueInternal: From, + T: Float + FromRuntimeValueInternal, { self.run_unop(|v: T| v.ceil()) } fn run_floor(&mut self) -> Result - where RuntimeValue: From, T: Float + FromRuntimeValue + where + RuntimeValueInternal: From, + T: Float + FromRuntimeValueInternal, { self.run_unop(|v: T| v.floor()) } fn run_trunc(&mut self) -> Result - where RuntimeValue: From, T: Float + FromRuntimeValue + where + RuntimeValueInternal: From, + T: Float + FromRuntimeValueInternal, { self.run_unop(|v: T| v.trunc()) } fn run_nearest(&mut self) -> Result - where RuntimeValue: From, T: Float + FromRuntimeValue + where + RuntimeValueInternal: From, + T: Float + FromRuntimeValueInternal, { self.run_unop(|v: T| v.nearest()) } fn run_sqrt(&mut self) -> Result - where RuntimeValue: From, T: Float + FromRuntimeValue + where + RuntimeValueInternal: From, + T: Float + FromRuntimeValueInternal, { self.run_unop(|v: T| v.sqrt()) } fn run_min(&mut self) -> Result - where RuntimeValue: From, T: Float + FromRuntimeValue + where + RuntimeValueInternal: From, + T: Float + FromRuntimeValueInternal, { let (left, right) = self .value_stack @@ -1008,35 +1048,42 @@ impl Interpreter { } fn run_max(&mut self) -> Result - where RuntimeValue: From, T: Float + FromRuntimeValue { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From, + T: Float + FromRuntimeValueInternal, + { + let (left, right) = self.value_stack.pop_pair_as::(); let v = left.max(right); self.value_stack.push(v.into())?; Ok(InstructionOutcome::RunNextInstruction) } fn run_copysign(&mut self) -> Result - where RuntimeValue: From, T: Float + FromRuntimeValue { - let (left, right) = self - .value_stack - .pop_pair_as::(); + where + RuntimeValueInternal: From, + T: Float + FromRuntimeValueInternal, + { + let (left, right) = self.value_stack.pop_pair_as::(); let v = left.copysign(right); self.value_stack.push(v.into())?; Ok(InstructionOutcome::RunNextInstruction) } fn run_wrap(&mut self) -> Result - where RuntimeValue: From, T: WrapInto + FromRuntimeValue { + where + RuntimeValueInternal: From, + T: WrapInto + FromRuntimeValueInternal, + { self.run_unop(|v: T| v.wrap_into()) } fn run_trunc_to_int(&mut self) -> Result - where RuntimeValue: From, T: TryTruncateInto + FromRuntimeValue, U: TransmuteInto, { - let v = self - .value_stack - .pop_as::(); + where + RuntimeValueInternal: From, + T: TryTruncateInto + FromRuntimeValueInternal, + U: TransmuteInto, + { + let v = self.value_stack.pop_as::(); v.try_truncate_into() .map(|v| v.transmute_into()) @@ -1046,11 +1093,11 @@ impl Interpreter { fn run_extend(&mut self) -> Result where - RuntimeValue: From, T: ExtendInto + FromRuntimeValue, U: TransmuteInto + RuntimeValueInternal: From, + T: ExtendInto + FromRuntimeValueInternal, + U: TransmuteInto, { - let v = self - .value_stack - .pop_as::(); + let v = self.value_stack.pop_as::(); let v = v.extend_into().transmute_into(); self.value_stack.push(v.into())?; @@ -1060,11 +1107,11 @@ impl Interpreter { fn run_reinterpret(&mut self) -> Result where - RuntimeValue: From, T: FromRuntimeValue, T: TransmuteInto + RuntimeValueInternal: From, + T: FromRuntimeValueInternal, + T: TransmuteInto, { - let v = self - .value_stack - .pop_as::(); + let v = self.value_stack.pop_as::(); let v = v.transmute_into(); self.value_stack.push(v.into())?; @@ -1108,11 +1155,11 @@ impl FunctionContext { pub fn initialize(&mut self, locals: &[Local], value_stack: &mut ValueStack) -> Result<(), TrapKind> { debug_assert!(!self.is_initialized); - let locals = locals.iter() - .flat_map(|l| repeat(l.value_type()).take(l.count() as usize)) - .map(::types::ValueType::from_elements) - .map(RuntimeValue::default) - .collect::>(); + let num_locals = locals + .iter() + .map(|l| l.count() as usize) + .sum(); + let locals = vec![Default::default(); num_locals]; // TODO: Replace with extend. for local in locals { @@ -1150,14 +1197,14 @@ fn prepare_function_args( signature: &Signature, caller_stack: &mut ValueStack, ) -> Vec { - let mut args = signature + let mut out = signature .params() .iter() - .map(|_| caller_stack.pop()) + .rev() + .map(|¶m_ty| caller_stack.pop().with_type(param_ty)) .collect::>(); - args.reverse(); - check_function_args(signature, &args).expect("Due to validation arguments should match"); - args + out.reverse(); + out } pub fn check_function_args(signature: &Signature, args: &[RuntimeValue]) -> Result<(), Trap> { @@ -1179,7 +1226,7 @@ pub fn check_function_args(signature: &Signature, args: &[RuntimeValue]) -> Resu #[derive(Debug)] struct ValueStack { - buf: Box<[RuntimeValue]>, + buf: Box<[RuntimeValueInternal]>, /// Index of the first free place in the stack. sp: usize, } @@ -1187,7 +1234,7 @@ struct ValueStack { impl ValueStack { fn with_limit(limit: usize) -> ValueStack { let mut buf = Vec::new(); - buf.resize(limit, RuntimeValue::I32(0)); + buf.resize(limit, RuntimeValueInternal(0)); ValueStack { buf: buf.into_boxed_slice(), @@ -1209,16 +1256,17 @@ impl ValueStack { #[inline] fn pop_as(&mut self) -> T where - T: FromRuntimeValue, + T: FromRuntimeValueInternal, { let value = self.pop(); - value.try_into().expect("Due to validation stack top's type should match") + + T::from_runtime_value_internal(value) } #[inline] fn pop_pair_as(&mut self) -> (T, T) where - T: FromRuntimeValue, + T: FromRuntimeValueInternal, { let right = self.pop_as(); let left = self.pop_as(); @@ -1226,7 +1274,13 @@ impl ValueStack { } #[inline] - fn pop_triple(&mut self) -> (RuntimeValue, RuntimeValue, RuntimeValue) { + fn pop_triple( + &mut self, + ) -> ( + RuntimeValueInternal, + RuntimeValueInternal, + RuntimeValueInternal, + ) { let right = self.pop(); let mid = self.pop(); let left = self.pop(); @@ -1234,28 +1288,31 @@ impl ValueStack { } #[inline] - fn top(&self) -> &RuntimeValue { + fn top(&self) -> &RuntimeValueInternal { self.pick(1) } - fn pick(&self, depth: usize) -> &RuntimeValue { + fn pick(&self, depth: usize) -> &RuntimeValueInternal { &self.buf[self.sp - depth] } #[inline] - fn pick_mut(&mut self, depth: usize) -> &mut RuntimeValue { + fn pick_mut(&mut self, depth: usize) -> &mut RuntimeValueInternal { &mut self.buf[self.sp - depth] } #[inline] - fn pop(&mut self) -> RuntimeValue { + fn pop(&mut self) -> RuntimeValueInternal { self.sp -= 1; self.buf[self.sp] } #[inline] - fn push(&mut self, value: RuntimeValue) -> Result<(), TrapKind> { - let cell = self.buf.get_mut(self.sp).ok_or_else(|| TrapKind::StackOverflow)?; + fn push(&mut self, value: RuntimeValueInternal) -> Result<(), TrapKind> { + let cell = self + .buf + .get_mut(self.sp) + .ok_or_else(|| TrapKind::StackOverflow)?; *cell = value; self.sp += 1; Ok(()) diff --git a/src/value.rs b/src/value.rs index 87eabb5..d0db835 100644 --- a/src/value.rs +++ b/src/value.rs @@ -27,6 +27,93 @@ pub enum RuntimeValue { F64(F64), } +#[derive(Copy, Clone, Debug, PartialEq, Default)] +pub(crate) struct RuntimeValueInternal(pub u64); + +impl RuntimeValueInternal { + pub fn with_type(self, ty: ValueType) -> RuntimeValue { + match ty { + ValueType::I32 => RuntimeValue::I32(<_>::from_runtime_value_internal(self)), + ValueType::I64 => RuntimeValue::I64(<_>::from_runtime_value_internal(self)), + ValueType::F32 => RuntimeValue::F32(<_>::from_runtime_value_internal(self)), + ValueType::F64 => RuntimeValue::F64(<_>::from_runtime_value_internal(self)), + } + } +} + +pub(crate) trait FromRuntimeValueInternal +where + Self: Sized, +{ + fn from_runtime_value_internal(val: RuntimeValueInternal) -> Self; +} + +macro_rules! impl_from_runtime_value_internal { + ($($t:ty),*) => { + $( + impl FromRuntimeValueInternal for $t { + fn from_runtime_value_internal( + RuntimeValueInternal(val): RuntimeValueInternal, + ) -> Self { + val as _ + } + } + + impl From<$t> for RuntimeValueInternal { + fn from(other: $t) -> Self { + RuntimeValueInternal(other as _) + } + } + )* + }; +} + +macro_rules! impl_from_runtime_value_internal_float { + ($($t:ty),*) => { + $( + impl FromRuntimeValueInternal for $t { + fn from_runtime_value_internal( + RuntimeValueInternal(val): RuntimeValueInternal, + ) -> Self { + <$t>::from_bits(val as _) + } + } + + impl From<$t> for RuntimeValueInternal { + fn from(other: $t) -> Self { + RuntimeValueInternal(other.to_bits() as _) + } + } + )* + }; +} + +impl_from_runtime_value_internal!(i8, u8, i16, u16, i32, u32, i64, u64); +impl_from_runtime_value_internal_float!(f32, f64, F32, F64); + +impl From for RuntimeValueInternal { + fn from(other: bool) -> Self { + (if other { 1 } else { 0 }).into() + } +} + +impl FromRuntimeValueInternal for bool { + fn from_runtime_value_internal(RuntimeValueInternal(val): RuntimeValueInternal) -> Self { + val != 0 + } +} + +impl From for RuntimeValueInternal { + fn from(other: RuntimeValue) -> Self { + match other { + RuntimeValue::I32(val) => val.into(), + RuntimeValue::I64(val) => val.into(), + RuntimeValue::F32(val) => val.into(), + RuntimeValue::F64(val) => val.into(), + } + } +} + /// Trait for creating value from a [`RuntimeValue`]. /// /// Typically each implementation can create a value from the specific type. @@ -132,12 +219,12 @@ pub trait Float: ArithmeticOps { impl RuntimeValue { /// Creates new default value of given type. - pub fn default(value_type: ::types::ValueType) -> Self { + pub fn default(value_type: ValueType) -> Self { match value_type { - ::types::ValueType::I32 => RuntimeValue::I32(0), - ::types::ValueType::I64 => RuntimeValue::I64(0), - ::types::ValueType::F32 => RuntimeValue::F32(0f32.into()), - ::types::ValueType::F64 => RuntimeValue::F64(0f64.into()), + ValueType::I32 => RuntimeValue::I32(0), + ValueType::I64 => RuntimeValue::I64(0), + ValueType::F32 => RuntimeValue::F32(0f32.into()), + ValueType::F64 => RuntimeValue::F64(0f64.into()), } } @@ -152,12 +239,12 @@ impl RuntimeValue { } /// Get variable type for this value. - pub fn value_type(&self) -> ::types::ValueType { + pub fn value_type(&self) -> ValueType { match *self { - RuntimeValue::I32(_) => ::types::ValueType::I32, - RuntimeValue::I64(_) => ::types::ValueType::I64, - RuntimeValue::F32(_) => ::types::ValueType::F32, - RuntimeValue::F64(_) => ::types::ValueType::F64, + RuntimeValue::I32(_) => ValueType::I32, + RuntimeValue::I64(_) => ValueType::I64, + RuntimeValue::F32(_) => ValueType::F32, + RuntimeValue::F64(_) => ValueType::F64, } }