diff --git a/crates/wasmi/src/engine/bytecode/construct.rs b/crates/wasmi/src/engine/bytecode/construct.rs index 655fc47659..740dc90b7c 100644 --- a/crates/wasmi/src/engine/bytecode/construct.rs +++ b/crates/wasmi/src/engine/bytecode/construct.rs @@ -1,19 +1,20 @@ use super::{ utils::{BranchOffset16, Sign}, AnyConst32, + BoundedRegSpan, BranchOffset, Const16, Const32, Data, Elem, EngineFunc, + FixedRegSpan, Func, FuncType, Global, Instruction, Reg, RegSpan, - RegSpanIter, Table, }; use crate::core::TrapCode; @@ -89,7 +90,7 @@ impl Instruction { } /// Creates a new [`Instruction::ReturnSpan`] from the given `values`. - pub fn return_span(values: RegSpanIter) -> Self { + pub fn return_span(values: BoundedRegSpan) -> Self { Self::ReturnSpan { values } } @@ -152,7 +153,7 @@ impl Instruction { } /// Creates a new [`Instruction::ReturnNezMany`] for the given `condition` and `values`. - pub fn return_nez_span(condition: Reg, values: RegSpanIter) -> Self { + pub fn return_nez_span(condition: Reg, values: BoundedRegSpan) -> Self { Self::ReturnNezSpan { condition, values } } @@ -262,7 +263,7 @@ impl Instruction { /// Creates a new [`Instruction::Copy2`]. pub fn copy2(results: RegSpan, value0: impl Into, value1: impl Into) -> Self { Self::Copy2 { - results, + results: >::new(results).unwrap(), values: [value0.into(), value1.into()], } } @@ -293,10 +294,7 @@ impl Instruction { /// Creates a new [`Instruction::CopySpan`] copying multiple consecutive values. pub fn copy_span(results: RegSpan, values: RegSpan, len: u16) -> Self { - debug_assert!(RegSpanIter::has_overlapping_copies( - results.iter(len), - values.iter(len) - )); + debug_assert!(RegSpan::has_overlapping_copies(results, values, len)); Self::CopySpan { results, values, @@ -306,10 +304,7 @@ impl Instruction { /// Creates a new [`Instruction::CopySpanNonOverlapping`] copying multiple consecutive values. pub fn copy_span_non_overlapping(results: RegSpan, values: RegSpan, len: u16) -> Self { - debug_assert!(!RegSpanIter::has_overlapping_copies( - results.iter(len), - values.iter(len) - )); + debug_assert!(!RegSpan::has_overlapping_copies(results, values, len)); Self::CopySpanNonOverlapping { results, values, @@ -1025,7 +1020,7 @@ impl Instruction { } /// Creates a new [`Instruction::RegisterSpan`]. - pub fn register_span(span: RegSpanIter) -> Self { + pub fn register_span(span: BoundedRegSpan) -> Self { Self::RegisterSpan { span } } diff --git a/crates/wasmi/src/engine/bytecode/mod.rs b/crates/wasmi/src/engine/bytecode/mod.rs index 2982014706..1e5392afe2 100644 --- a/crates/wasmi/src/engine/bytecode/mod.rs +++ b/crates/wasmi/src/engine/bytecode/mod.rs @@ -17,7 +17,7 @@ pub mod index { pub use self::{ error::Error as IrError, immediate::{AnyConst32, Const16, Const32}, - span::{BoundedRegSpan, FixedRegSpan, RegSpan, RegSpanIter}, + span::{BoundedRegSpan, FixedRegSpan, RegSpan}, utils::{ BlockFuel, BranchOffset, @@ -142,10 +142,10 @@ pub enum Instruction { /// /// # Note /// - /// Returns values as stored in the [`RegSpanIter`]. + /// Returns values as stored in the [`BoundedRegSpan`]. ReturnSpan { - /// The underlying [`RegSpanIter`] value. - values: RegSpanIter, + /// The underlying [`BoundedRegSpan`] value. + values: BoundedRegSpan, }, /// A Wasm `return` instruction. /// @@ -246,7 +246,7 @@ pub enum Instruction { /// The register holding the condition to evaluate against zero. condition: Reg, /// The returned values. - values: RegSpanIter, + values: BoundedRegSpan, }, /// A conditional `return` instruction. /// @@ -1118,7 +1118,7 @@ pub enum Instruction { /// This is a Wasmi utility instruction used to translate Wasm control flow. Copy2 { /// The registers holding the result of the instruction. - results: RegSpan, + results: FixedRegSpan<2>, /// The registers holding the values to copy. values: [Reg; 2], }, @@ -5446,8 +5446,8 @@ pub enum Instruction { /// The 32-bit immediate value. imm: AnyConst32, }, - /// A [`RegSpanIter`] instruction parameter. - RegisterSpan { span: RegSpanIter }, + /// A [`BoundedRegSpan`] instruction parameter. + RegisterSpan { span: BoundedRegSpan }, /// A [`Reg`] instruction parameter. /// /// # Note diff --git a/crates/wasmi/src/engine/bytecode/span.rs b/crates/wasmi/src/engine/bytecode/span.rs index 7951afbb01..bee87a6301 100644 --- a/crates/wasmi/src/engine/bytecode/span.rs +++ b/crates/wasmi/src/engine/bytecode/span.rs @@ -42,6 +42,18 @@ impl RegSpan { pub fn head_mut(&mut self) -> &mut Reg { &mut self.0 } + + /// Returns `true` if `copy_span results <- values` has overlapping copies. + /// + /// # Examples + /// + /// - `[ ]`: empty never overlaps + /// - `[ 1 <- 0 ]`: single element never overlaps + /// - `[ 0 <- 1, 1 <- 2, 2 <- 3 ]`: no overlap + /// - `[ 1 <- 0, 2 <- 1 ]`: overlaps! + pub fn has_overlapping_copies(results: Self, values: Self, len: u16) -> bool { + RegSpanIter::has_overlapping_copies(results.iter(len), values.iter(len)) + } } /// A [`RegSpan`] with a statically known number of [`Reg`]. diff --git a/crates/wasmi/src/engine/bytecode/tests.rs b/crates/wasmi/src/engine/bytecode/tests.rs index 5c441e6a85..1baf6397f0 100644 --- a/crates/wasmi/src/engine/bytecode/tests.rs +++ b/crates/wasmi/src/engine/bytecode/tests.rs @@ -14,7 +14,7 @@ fn has_overlapping_copy_spans_works() { } fn has_overlapping_copy_spans(results: RegSpan, values: RegSpan, len: u16) -> bool { - RegSpanIter::has_overlapping_copies(results.iter(len), values.iter(len)) + RegSpan::has_overlapping_copies(results, values, len) } // len == 0 diff --git a/crates/wasmi/src/engine/bytecode/visit_regs.rs b/crates/wasmi/src/engine/bytecode/visit_regs.rs index c12af2b298..5084434557 100644 --- a/crates/wasmi/src/engine/bytecode/visit_regs.rs +++ b/crates/wasmi/src/engine/bytecode/visit_regs.rs @@ -1,4 +1,4 @@ -use super::{BoundedRegSpan, FixedRegSpan, Instruction, Reg, RegSpan, RegSpanIter}; +use super::{BoundedRegSpan, FixedRegSpan, Instruction, Reg, RegSpan}; impl Instruction { /// Visit [`Reg`]s of `self` via the `visitor`. @@ -58,16 +58,6 @@ impl HostVisitor for &'_ mut FixedRegSpan { } } -impl HostVisitor for &'_ mut RegSpanIter { - fn host_visitor(self, _visitor: &mut V) { - // let len = self.len_as_u16(); - // let mut span = self.span(); - // visitor.visit_input_regs(&mut span, Some(len)); - // *self = span.iter(len); - todo!() - } -} - /// Type-wrapper to signal that the wrapped [`Reg`], [`RegSpan`] (etc.) is a result. pub struct Res(T); @@ -83,6 +73,19 @@ impl HostVisitor for Res<&'_ mut RegSpan> { } } +impl HostVisitor for Res<&'_ mut BoundedRegSpan> { + fn host_visitor(self, visitor: &mut V) { + let len = self.0.len(); + visitor.visit_result_regs(self.0.span_mut(), Some(len)); + } +} + +impl HostVisitor for Res<&'_ mut FixedRegSpan> { + fn host_visitor(self, visitor: &mut V) { + visitor.visit_result_regs(self.0.span_mut(), Some(N)); + } +} + macro_rules! host_visitor { ( $visitor:expr => $($r:expr),* $(,)? ) => {{ $( HostVisitor::host_visitor($r, $visitor) );* diff --git a/crates/wasmi/src/engine/executor/instrs/branch.rs b/crates/wasmi/src/engine/executor/instrs/branch.rs index e489aea1de..5e22b06c3c 100644 --- a/crates/wasmi/src/engine/executor/instrs/branch.rs +++ b/crates/wasmi/src/engine/executor/instrs/branch.rs @@ -121,7 +121,7 @@ impl<'engine> Executor<'engine> { let Instruction::RegisterSpan { span: values } = *self.ip.get() else { unreachable!() }; - let len = values.len_as_u16(); + let len = values.len(); let values = values.span(); self.ip.add(offset); match *self.ip.get() { diff --git a/crates/wasmi/src/engine/executor/instrs/copy.rs b/crates/wasmi/src/engine/executor/instrs/copy.rs index f161d28968..4674a1d670 100644 --- a/crates/wasmi/src/engine/executor/instrs/copy.rs +++ b/crates/wasmi/src/engine/executor/instrs/copy.rs @@ -1,7 +1,7 @@ use super::{Executor, InstructionPtr}; use crate::{ core::UntypedVal, - engine::bytecode::{AnyConst32, Const32, Instruction, Reg, RegSpan}, + engine::bytecode::{AnyConst32, Const32, FixedRegSpan, Instruction, Reg, RegSpan}, }; use core::slice; use smallvec::SmallVec; @@ -23,15 +23,15 @@ impl<'engine> Executor<'engine> { /// Executes an [`Instruction::Copy2`]. #[inline(always)] - pub fn execute_copy_2(&mut self, results: RegSpan, values: [Reg; 2]) { + pub fn execute_copy_2(&mut self, results: FixedRegSpan<2>, values: [Reg; 2]) { self.execute_copy_2_impl(results, values); self.next_instr() } /// Internal implementation of [`Instruction::Copy2`] execution. #[inline(always)] - fn execute_copy_2_impl(&mut self, results: RegSpan, values: [Reg; 2]) { - let result0 = results.head(); + fn execute_copy_2_impl(&mut self, results: FixedRegSpan<2>, values: [Reg; 2]) { + let result0 = results.span().head(); let result1 = result0.next(); // We need `tmp` in case `results[0] == values[1]` to avoid overwriting `values[1]` before reading it. let tmp = self.get_register(values[1]); diff --git a/crates/wasmi/src/engine/executor/instrs/return_.rs b/crates/wasmi/src/engine/executor/instrs/return_.rs index 280c63cd62..0200267a27 100644 --- a/crates/wasmi/src/engine/executor/instrs/return_.rs +++ b/crates/wasmi/src/engine/executor/instrs/return_.rs @@ -2,7 +2,7 @@ use super::{Executor, InstructionPtr}; use crate::{ core::UntypedVal, engine::{ - bytecode::{AnyConst32, Const32, Instruction, Reg, RegSpan, RegSpanIter}, + bytecode::{AnyConst32, BoundedRegSpan, Const32, Instruction, Reg, RegSpan}, executor::stack::FrameRegisters, }, store::StoreInner, @@ -189,10 +189,10 @@ impl<'engine> Executor<'engine> { pub fn execute_return_span( &mut self, store: &mut StoreInner, - values: RegSpanIter, + values: BoundedRegSpan, ) -> ReturnOutcome { let (mut caller_sp, results) = self.return_caller_results(); - let results = results.iter(values.len_as_u16()); + let results = results.iter(values.len()); for (result, value) in results.zip(values) { // Safety: The `callee.results()` always refer to a span of valid // registers of the `caller` that does not overlap with the @@ -342,7 +342,7 @@ impl<'engine> Executor<'engine> { &mut self, store: &mut StoreInner, condition: Reg, - values: RegSpanIter, + values: BoundedRegSpan, ) -> ReturnOutcome { self.execute_return_nez_impl(store, condition, values, Self::execute_return_span) } diff --git a/crates/wasmi/src/engine/translator/control_frame.rs b/crates/wasmi/src/engine/translator/control_frame.rs index b960e594c7..6e514dc2bd 100644 --- a/crates/wasmi/src/engine/translator/control_frame.rs +++ b/crates/wasmi/src/engine/translator/control_frame.rs @@ -5,7 +5,7 @@ use super::LabelRef; use super::ValueStack; use crate::{ engine::{ - bytecode::{RegSpan, RegSpanIter}, + bytecode::{BoundedRegSpan, RegSpan}, BlockType, Instr, TranslationError, @@ -106,9 +106,8 @@ impl BlockControlFrame { } /// Returns an iterator over the registers holding the branching parameters of the [`BlockControlFrame`]. - pub fn branch_params(&self, engine: &Engine) -> RegSpanIter { - self.branch_params - .iter(self.block_type().len_results(engine)) + pub fn branch_params(&self, engine: &Engine) -> BoundedRegSpan { + BoundedRegSpan::new(self.branch_params, self.block_type().len_results(engine)) } /// Returns the label for the branch destination of the [`BlockControlFrame`]. @@ -211,9 +210,8 @@ impl LoopControlFrame { } /// Returns an iterator over the registers holding the branching parameters of the [`LoopControlFrame`]. - pub fn branch_params(&self, engine: &Engine) -> RegSpanIter { - self.branch_params - .iter(self.block_type().len_params(engine)) + pub fn branch_params(&self, engine: &Engine) -> BoundedRegSpan { + BoundedRegSpan::new(self.branch_params, self.block_type().len_params(engine)) } /// Returns the label for the branch destination of the [`LoopControlFrame`]. @@ -381,9 +379,8 @@ impl IfControlFrame { } /// Returns an iterator over the registers holding the branching parameters of the [`IfControlFrame`]. - pub fn branch_params(&self, engine: &Engine) -> RegSpanIter { - self.branch_params - .iter(self.block_type().len_results(engine)) + pub fn branch_params(&self, engine: &Engine) -> BoundedRegSpan { + BoundedRegSpan::new(self.branch_params, self.block_type().len_results(engine)) } /// Returns the label for the branch destination of the [`IfControlFrame`]. @@ -602,7 +599,7 @@ impl ControlFrame { } /// Returns an iterator over the registers holding the branch parameters of the [`ControlFrame`]. - pub fn branch_params(&self, engine: &Engine) -> RegSpanIter { + pub fn branch_params(&self, engine: &Engine) -> BoundedRegSpan { match self { Self::Block(frame) => frame.branch_params(engine), Self::Loop(frame) => frame.branch_params(engine), diff --git a/crates/wasmi/src/engine/translator/instr_encoder.rs b/crates/wasmi/src/engine/translator/instr_encoder.rs index 4f906aae82..9cd7b0ccd3 100644 --- a/crates/wasmi/src/engine/translator/instr_encoder.rs +++ b/crates/wasmi/src/engine/translator/instr_encoder.rs @@ -11,6 +11,7 @@ use crate::{ core::{UntypedVal, ValType, F32}, engine::{ bytecode::{ + BoundedRegSpan, BranchOffset, BranchOffset16, Comparator, @@ -20,7 +21,6 @@ use crate::{ Instruction, Reg, RegSpan, - RegSpanIter, }, translator::{stack::RegisterSpace, ValueStack}, FuelCosts, @@ -447,21 +447,21 @@ impl InstrEncoder { pub fn encode_copies( &mut self, stack: &mut ValueStack, - mut results: RegSpanIter, + mut results: BoundedRegSpan, values: &[TypedProvider], fuel_info: FuelInfo, ) -> Result, Error> { - assert_eq!(results.len(), values.len()); + assert_eq!(usize::from(results.len()), values.len()); + let result = results.span().head(); if let Some((TypedProvider::Register(value), rest)) = values.split_first() { - if results.span().head() == *value { + if result == *value { // Case: `result` and `value` are equal thus this is a no-op copy which we can avoid. // Applied recursively we thereby remove all no-op copies at the start of the // copy sequence until the first actual copy. - results.next(); + results = BoundedRegSpan::new(RegSpan::new(result.next()), results.len() - 1); return self.encode_copies(stack, results, rest, fuel_info); } } - let result = results.span().head(); match values { [] => { // The copy sequence is empty, nothing to encode in this case. @@ -489,7 +489,7 @@ impl InstrEncoder { self.bump_fuel_consumption(fuel_info, |costs| { costs.fuel_for_copies(rest.len() as u64 + 3) })?; - if let Some(values) = RegSpanIter::from_providers(values) { + if let Some(values) = BoundedRegSpan::from_providers(values) { let make_instr = match Self::has_overlapping_copy_spans( results.span(), values.span(), @@ -498,11 +498,8 @@ impl InstrEncoder { true => Instruction::copy_span, false => Instruction::copy_span_non_overlapping, }; - let instr = self.push_instr(make_instr( - results.span(), - values.span(), - values.len_as_u16(), - ))?; + let instr = + self.push_instr(make_instr(results.span(), values.span(), values.len()))?; return Ok(Some(instr)); } let make_instr = match Self::has_overlapping_copies(results, values) { @@ -526,8 +523,8 @@ impl InstrEncoder { /// - `[ 1 <- 0 ]`: single element never overlaps /// - `[ 0 <- 1, 1 <- 2, 2 <- 3 ]``: no overlap /// - `[ 1 <- 0, 2 <- 1 ]`: overlaps! - pub fn has_overlapping_copy_spans(results: RegSpan, values: RegSpan, len: usize) -> bool { - RegSpanIter::has_overlapping_copies(results.iter_sized(len), values.iter_sized(len)) + pub fn has_overlapping_copy_spans(results: RegSpan, values: RegSpan, len: u16) -> bool { + RegSpan::has_overlapping_copies(results, values, len) } /// Returns `true` if the `copy results <- values` instruction has overlaps. @@ -539,14 +536,14 @@ impl InstrEncoder { /// is written to in the first copy but read from in the next. /// - The sequence `[ 3 <- 1, 4 <- 2, 5 <- 3 ]` has overlapping copies since register `3` /// is written to in the first copy but read from in the third. - pub fn has_overlapping_copies(results: RegSpanIter, values: &[TypedProvider]) -> bool { - debug_assert_eq!(results.len(), values.len()); + pub fn has_overlapping_copies(results: BoundedRegSpan, values: &[TypedProvider]) -> bool { + debug_assert_eq!(usize::from(results.len()), values.len()); if results.is_empty() { // Note: An empty set of copies can never have overlapping copies. return false; } let result0 = results.span().head(); - for (result, value) in results.zip(values) { + for (result, value) in results.iter().zip(values) { // Note: We only have to check the register case since constant value // copies can never overlap. if let TypedProvider::Register(value) = *value { @@ -625,7 +622,7 @@ impl InstrEncoder { self.bump_fuel_consumption(fuel_info, |costs| { costs.fuel_for_copies(rest.len() as u64 + 3) })?; - if let Some(span) = RegSpanIter::from_providers(values) { + if let Some(span) = BoundedRegSpan::from_providers(values) { self.push_instr(Instruction::return_span(span))?; return Ok(()); } @@ -687,7 +684,7 @@ impl InstrEncoder { self.bump_fuel_consumption(fuel_info, |costs| { costs.fuel_for_copies(rest.len() as u64 + 3) })?; - if let Some(span) = RegSpanIter::from_providers(values) { + if let Some(span) = BoundedRegSpan::from_providers(values) { self.push_instr(Instruction::return_nez_span(condition, span))?; return Ok(()); } @@ -1497,36 +1494,37 @@ mod tests { use super::*; use crate::core::TypedVal; + fn bspan(reg: i16, len: u16) -> BoundedRegSpan { + BoundedRegSpan::new(RegSpan::new(Reg::from(reg)), len) + } + #[test] fn has_overlapping_copies_works() { + assert!(!InstrEncoder::has_overlapping_copies(bspan(0, 0), &[],)); assert!(!InstrEncoder::has_overlapping_copies( - RegSpan::new(Reg::from(0)).iter(0), - &[], - )); - assert!(!InstrEncoder::has_overlapping_copies( - RegSpan::new(Reg::from(0)).iter(2), + bspan(0, 2), &[TypedProvider::register(0), TypedProvider::register(1),], )); assert!(!InstrEncoder::has_overlapping_copies( - RegSpan::new(Reg::from(0)).iter(2), + bspan(0, 2), &[ TypedProvider::Const(TypedVal::from(10_i32)), TypedProvider::Const(TypedVal::from(20_i32)), ], )); assert!(InstrEncoder::has_overlapping_copies( - RegSpan::new(Reg::from(0)).iter(2), + bspan(0, 2), &[ TypedProvider::Const(TypedVal::from(10_i32)), TypedProvider::register(0), ], )); assert!(InstrEncoder::has_overlapping_copies( - RegSpan::new(Reg::from(0)).iter(2), + bspan(0, 2), &[TypedProvider::register(0), TypedProvider::register(0),], )); assert!(InstrEncoder::has_overlapping_copies( - RegSpan::new(Reg::from(3)).iter(3), + bspan(3, 3), &[ TypedProvider::register(2), TypedProvider::register(3), @@ -1534,7 +1532,7 @@ mod tests { ], )); assert!(InstrEncoder::has_overlapping_copies( - RegSpan::new(Reg::from(3)).iter(4), + bspan(3, 4), &[ TypedProvider::register(-1), TypedProvider::register(10), diff --git a/crates/wasmi/src/engine/translator/mod.rs b/crates/wasmi/src/engine/translator/mod.rs index 9c89c1d332..c373a62ebd 100644 --- a/crates/wasmi/src/engine/translator/mod.rs +++ b/crates/wasmi/src/engine/translator/mod.rs @@ -39,13 +39,13 @@ pub use self::{ stack::TypedProvider, }; use super::{ - bytecode::{index, BranchOffset}, + bytecode::{index, BoundedRegSpan, BranchOffset}, code_map::CompiledFuncEntity, }; use crate::{ core::{TrapCode, Typed, TypedVal, UntypedVal, ValType}, engine::{ - bytecode::{Const16, Const32, Instruction, Reg, RegSpan, RegSpanIter, Sign}, + bytecode::{Const16, Const32, Instruction, Reg, RegSpan, Sign}, config::FuelCosts, BlockType, EngineFunc, @@ -824,8 +824,14 @@ impl FuncTranslator { (i16::from(b.preserved) - i16::from(a.preserved)) == 1 }); for copy_group in copy_groups { - let len = copy_group.len(); - let results = RegSpan::new(copy_group[0].preserved).iter_sized(len); + let len = u16::try_from(copy_group.len()).unwrap_or_else(|error| { + panic!( + "too many ({}) registers in copy group: {}", + copy_group.len(), + error + ) + }); + let results = BoundedRegSpan::new(RegSpan::new(copy_group[0].preserved), len); let providers = &mut self.alloc.buffer.providers; providers.clear(); providers.extend( @@ -848,14 +854,16 @@ impl FuncTranslator { } /// Convenience function to copy the parameters when branching to a control frame. - fn translate_copy_branch_params(&mut self, branch_params: RegSpanIter) -> Result<(), Error> { + fn translate_copy_branch_params(&mut self, branch_params: BoundedRegSpan) -> Result<(), Error> { if branch_params.is_empty() { // If the block does not have branch parameters there is no need to copy anything. return Ok(()); } let fuel_info = self.fuel_info(); let params = &mut self.alloc.buffer.providers; - self.alloc.stack.pop_n(branch_params.len(), params); + self.alloc + .stack + .pop_n(usize::from(branch_params.len()), params); self.alloc.instr_encoder.encode_copies( &mut self.alloc.stack, branch_params, @@ -2504,7 +2512,7 @@ impl FuncTranslator { fn translate_br_table_targets( &mut self, values: &[TypedProvider], - make_target: impl Fn(RegSpanIter, BranchOffset) -> Instruction, + make_target: impl Fn(BoundedRegSpan, BranchOffset) -> Instruction, ) -> Result<(), Error> { let engine = self.engine().clone(); let fuel_info = self.fuel_info(); @@ -2641,18 +2649,18 @@ impl FuncTranslator { } /// Translates a Wasm `br_table` instruction with 4 or more inputs. - fn translate_br_table_n(&mut self, index: Reg, len_values: usize) -> Result<(), Error> { + fn translate_br_table_n(&mut self, index: Reg, len_values: u16) -> Result<(), Error> { debug_assert!(len_values > 3); let values = &mut self.alloc.buffer.providers; - self.alloc.stack.pop_n(len_values, values); - match RegSpanIter::from_providers(values) { + self.alloc.stack.pop_n(usize::from(len_values), values); + match BoundedRegSpan::from_providers(values) { Some(span) => self.translate_br_table_span(index, span), None => self.translate_br_table_many(index), } } /// Translates a Wasm `br_table` instruction with 4 or more inputs that form a [`RegSpan`]. - fn translate_br_table_span(&mut self, index: Reg, values: RegSpanIter) -> Result<(), Error> { + fn translate_br_table_span(&mut self, index: Reg, values: BoundedRegSpan) -> Result<(), Error> { debug_assert!(values.len() > 3); let fuel_info = self.fuel_info(); let targets = &mut self.alloc.buffer.br_table_targets; diff --git a/crates/wasmi/src/engine/translator/tests/fuzz/mod.rs b/crates/wasmi/src/engine/translator/tests/fuzz/mod.rs index 586509352e..7168c04b79 100644 --- a/crates/wasmi/src/engine/translator/tests/fuzz/mod.rs +++ b/crates/wasmi/src/engine/translator/tests/fuzz/mod.rs @@ -449,7 +449,7 @@ fn audit_0_codegen() { Instruction::branch_table_target(RegSpan::new(Reg::from(0)), BranchOffset::from(3)), Instruction::Return, Instruction::Return, - Instruction::return_span(RegSpan::new(Reg::from(0)).iter(4)), + Instruction::return_span(bspan(0, 4)), ]) .consts([0]), ) diff --git a/crates/wasmi/src/engine/translator/tests/mod.rs b/crates/wasmi/src/engine/translator/tests/mod.rs index dd937e7365..2d4af90436 100644 --- a/crates/wasmi/src/engine/translator/tests/mod.rs +++ b/crates/wasmi/src/engine/translator/tests/mod.rs @@ -12,7 +12,7 @@ use self::{ }; use crate::{ core::UntypedVal, - engine::bytecode::{AnyConst32, Const16, Const32, Instruction, Reg}, + engine::bytecode::{AnyConst32, BoundedRegSpan, Const16, Const32, Instruction, Reg, RegSpan}, Config, Engine, Module, @@ -62,6 +62,11 @@ where testcase.run(); } +/// Creates a new [`BoundedRegSpan`] starting with `reg` and with `len`. +fn bspan(reg: impl Into, len: u16) -> BoundedRegSpan { + BoundedRegSpan::new(RegSpan::new(reg.into()), len) +} + /// Identifier for a Wasm operator. /// /// # Note diff --git a/crates/wasmi/src/engine/translator/tests/op/br_if.rs b/crates/wasmi/src/engine/translator/tests/op/br_if.rs index d8dc9cc0ec..4d4a2a3e82 100644 --- a/crates/wasmi/src/engine/translator/tests/op/br_if.rs +++ b/crates/wasmi/src/engine/translator/tests/op/br_if.rs @@ -542,7 +542,7 @@ fn return_if_results_3_span() { )"; TranslationTest::from_wat(wasm) .expect_func_instrs([ - Instruction::return_nez_span(Reg::from(3), RegSpan::new(Reg::from(0)).iter(3)), + Instruction::return_nez_span(Reg::from(3), bspan(0, 3)), Instruction::return_reg3(0, 1, 2), ]) .run() @@ -614,8 +614,8 @@ fn return_if_results_4_span() { )"; TranslationTest::from_wat(wasm) .expect_func_instrs([ - Instruction::return_nez_span(Reg::from(4), RegSpan::new(Reg::from(0)).iter(4)), - Instruction::return_span(RegSpan::new(Reg::from(0)).iter(4)), + Instruction::return_nez_span(Reg::from(4), bspan(0, 4)), + Instruction::return_span(bspan(0, 4)), ]) .run() } @@ -954,7 +954,7 @@ fn branch_if_results_4_mixed_1() { Instruction::branch(BranchOffset::from(3)), Instruction::copy_many_non_overlapping(RegSpan::new(Reg::from(3)), -1, 0), Instruction::register2(1, -2), - Instruction::return_span(RegSpan::new(Reg::from(3)).iter(4)), + Instruction::return_span(bspan(3, 4)), ]) .consts([10_i32, 20]), ) @@ -987,7 +987,7 @@ fn branch_if_results_4_mixed_2() { Instruction::branch(BranchOffset::from(3)), Instruction::copy_many_non_overlapping(RegSpan::new(Reg::from(3)), 0, 0), Instruction::register2(1, 1), - Instruction::return_span(RegSpan::new(Reg::from(3)).iter(4)), + Instruction::return_span(bspan(3, 4)), ]) .run() } diff --git a/crates/wasmi/src/engine/translator/tests/op/br_table.rs b/crates/wasmi/src/engine/translator/tests/op/br_table.rs index 382c812bfd..913e44defb 100644 --- a/crates/wasmi/src/engine/translator/tests/op/br_table.rs +++ b/crates/wasmi/src/engine/translator/tests/op/br_table.rs @@ -616,12 +616,12 @@ fn reg_params_4_span() { .expect_func_instrs([ Instruction::i32_popcnt(Reg::from(5), Reg::from(0)), Instruction::branch_table_span(4, 4), - Instruction::register_span(RegSpan::new(Reg::from(0)).iter(4)), + Instruction::register_span(bspan(0, 4)), Instruction::branch_table_target_non_overlapping( RegSpan::new(Reg::from(5)), BranchOffset::from(8), ), - Instruction::return_span(RegSpan::new(Reg::from(0)).iter(4)), + Instruction::return_span(bspan(0, 4)), Instruction::branch_table_target_non_overlapping( RegSpan::new(Reg::from(5)), BranchOffset::from(4), @@ -631,11 +631,11 @@ fn reg_params_4_span() { BranchOffset::from(1), ), Instruction::i32_add_imm16(Reg::from(9), Reg::from(9), 10_i16), - Instruction::return_span(RegSpan::new(Reg::from(6)).iter(4)), + Instruction::return_span(bspan(6, 4)), Instruction::i32_add_imm16(Reg::from(8), Reg::from(8), 20_i16), - Instruction::return_span(RegSpan::new(Reg::from(5)).iter(4)), + Instruction::return_span(bspan(5, 4)), Instruction::i32_add_imm16(Reg::from(8), Reg::from(8), 30_i16), - Instruction::return_span(RegSpan::new(Reg::from(5)).iter(4)), + Instruction::return_span(bspan(5, 4)), ]) .run() } @@ -683,11 +683,11 @@ fn reg_params_4_many() { BranchOffset::from(1), ), Instruction::i32_add_imm16(Reg::from(9), Reg::from(9), 10_i16), - Instruction::return_span(RegSpan::new(Reg::from(6)).iter(4)), + Instruction::return_span(bspan(6, 4)), Instruction::i32_add_imm16(Reg::from(8), Reg::from(8), 20_i16), - Instruction::return_span(RegSpan::new(Reg::from(5)).iter(4)), + Instruction::return_span(bspan(5, 4)), Instruction::i32_add_imm16(Reg::from(8), Reg::from(8), 30_i16), - Instruction::return_span(RegSpan::new(Reg::from(5)).iter(4)), + Instruction::return_span(bspan(5, 4)), ]) .run() } diff --git a/crates/wasmi/src/engine/translator/tests/op/call/imported.rs b/crates/wasmi/src/engine/translator/tests/op/call/imported.rs index a78e536753..8563b138af 100644 --- a/crates/wasmi/src/engine/translator/tests/op/call/imported.rs +++ b/crates/wasmi/src/engine/translator/tests/op/call/imported.rs @@ -214,7 +214,7 @@ fn params7_reg() { Instruction::register_list(0, 1, 2), Instruction::register_list(3, 4, 5), Instruction::register(6), - Instruction::return_span(RegSpan::new(Reg::from(7)).iter(7)), + Instruction::return_span(bspan(7, 7)), ]) .run(); } @@ -244,7 +244,7 @@ fn params7_reg_rev() { Instruction::register_list(6, 5, 4), Instruction::register_list(3, 2, 1), Instruction::register(0), - Instruction::return_span(RegSpan::new(Reg::from(7)).iter(7)), + Instruction::return_span(bspan(7, 7)), ]) .run(); } @@ -275,7 +275,7 @@ fn params7_imm() { Instruction::register_list(-1, -2, -3), Instruction::register_list(-4, -5, -6), Instruction::register(-7), - Instruction::return_span(RegSpan::new(Reg::from(0)).iter(7)), + Instruction::return_span(bspan(0, 7)), ]) .consts([10, 20, 30, 40, 50, 60, 70]), ) @@ -308,7 +308,7 @@ fn params8_reg() { Instruction::register_list(0, 1, 2), Instruction::register_list(3, 4, 5), Instruction::register2(6, 7), - Instruction::return_span(RegSpan::new(Reg::from(8)).iter(8)), + Instruction::return_span(bspan(8, 8)), ]) .run(); } @@ -339,7 +339,7 @@ fn params8_reg_rev() { Instruction::register_list(7, 6, 5), Instruction::register_list(4, 3, 2), Instruction::register2(1, 0), - Instruction::return_span(RegSpan::new(Reg::from(8)).iter(8)), + Instruction::return_span(bspan(8, 8)), ]) .run(); } @@ -371,7 +371,7 @@ fn params8_imm() { Instruction::register_list(-1, -2, -3), Instruction::register_list(-4, -5, -6), Instruction::register2(-7, -8), - Instruction::return_span(RegSpan::new(Reg::from(0)).iter(8)), + Instruction::return_span(bspan(0, 8)), ]) .consts([10, 20, 30, 40, 50, 60, 70, 80]), ) @@ -405,7 +405,7 @@ fn params9_reg() { Instruction::register_list(0, 1, 2), Instruction::register_list(3, 4, 5), Instruction::register3(6, 7, 8), - Instruction::return_span(RegSpan::new(Reg::from(9)).iter(9)), + Instruction::return_span(bspan(9, 9)), ]) .run(); } @@ -437,7 +437,7 @@ fn params9_reg_rev() { Instruction::register_list(8, 7, 6), Instruction::register_list(5, 4, 3), Instruction::register3(2, 1, 0), - Instruction::return_span(RegSpan::new(Reg::from(9)).iter(9)), + Instruction::return_span(bspan(9, 9)), ]) .run(); } @@ -470,7 +470,7 @@ fn params9_imm() { Instruction::register_list(-1, -2, -3), Instruction::register_list(-4, -5, -6), Instruction::register3(-7, -8, -9), - Instruction::return_span(RegSpan::new(Reg::from(0)).iter(9)), + Instruction::return_span(bspan(0, 9)), ]) .consts([10, 20, 30, 40, 50, 60, 70, 80, 90]), ) diff --git a/crates/wasmi/src/engine/translator/tests/op/call/indirect.rs b/crates/wasmi/src/engine/translator/tests/op/call/indirect.rs index 872187ed6a..8ce0c3ada3 100644 --- a/crates/wasmi/src/engine/translator/tests/op/call/indirect.rs +++ b/crates/wasmi/src/engine/translator/tests/op/call/indirect.rs @@ -606,7 +606,7 @@ fn params7_reg_index_local() { Instruction::register_list(1, 2, 3), Instruction::register_list(4, 5, 6), Instruction::register(7), - Instruction::return_span(RegSpan::new(Reg::from(8)).iter(7)), + Instruction::return_span(bspan(8, 7)), ]) .run(); } @@ -639,7 +639,7 @@ fn params7_imm_index_local() { Instruction::register_list(-1, -2, -3), Instruction::register_list(-4, -5, -6), Instruction::register(-7), - Instruction::return_span(RegSpan::new(Reg::from(1)).iter(7)), + Instruction::return_span(bspan(1, 7)), ]) .consts([10_i32, 20, 30, 40, 50, 60, 70]), ) @@ -674,7 +674,7 @@ fn params8_reg_index_local() { Instruction::register_list(1, 2, 3), Instruction::register_list(4, 5, 6), Instruction::register2(7, 8), - Instruction::return_span(RegSpan::new(Reg::from(9)).iter(8)), + Instruction::return_span(bspan(9, 8)), ]) .run(); } @@ -708,7 +708,7 @@ fn params8_imm_index_local() { Instruction::register_list(-1, -2, -3), Instruction::register_list(-4, -5, -6), Instruction::register2(-7, -8), - Instruction::return_span(RegSpan::new(Reg::from(1)).iter(8)), + Instruction::return_span(bspan(1, 8)), ]) .consts([10_i32, 20, 30, 40, 50, 60, 70, 80]), ) @@ -744,7 +744,7 @@ fn params9_reg_index_local() { Instruction::register_list(1, 2, 3), Instruction::register_list(4, 5, 6), Instruction::register3(7, 8, 9), - Instruction::return_span(RegSpan::new(Reg::from(10)).iter(9)), + Instruction::return_span(bspan(10, 9)), ]) .run(); } @@ -779,7 +779,7 @@ fn params9_imm_index_local() { Instruction::register_list(-1, -2, -3), Instruction::register_list(-4, -5, -6), Instruction::register3(-7, -8, -9), - Instruction::return_span(RegSpan::new(Reg::from(1)).iter(9)), + Instruction::return_span(bspan(1, 9)), ]) .consts([10_i32, 20, 30, 40, 50, 60, 70, 80, 90]), ) diff --git a/crates/wasmi/src/engine/translator/tests/op/call/internal.rs b/crates/wasmi/src/engine/translator/tests/op/call/internal.rs index fa8ef135c7..0d9e056b9a 100644 --- a/crates/wasmi/src/engine/translator/tests/op/call/internal.rs +++ b/crates/wasmi/src/engine/translator/tests/op/call/internal.rs @@ -251,13 +251,13 @@ fn params7_reg() { ) "#; TranslationTest::from_wat(wasm) - .expect_func_instrs([Instruction::return_span(RegSpan::new(Reg::from(0)).iter(7))]) + .expect_func_instrs([Instruction::return_span(bspan(0, 7))]) .expect_func_instrs([ Instruction::call_internal(RegSpan::new(Reg::from(7)), EngineFunc::from_u32(0)), Instruction::register_list(0, 1, 2), Instruction::register_list(3, 4, 5), Instruction::register(6), - Instruction::return_span(RegSpan::new(Reg::from(7)).iter(7)), + Instruction::return_span(bspan(7, 7)), ]) .run(); } @@ -290,13 +290,13 @@ fn params7_reg_rev() { ) "#; TranslationTest::from_wat(wasm) - .expect_func_instrs([Instruction::return_span(RegSpan::new(Reg::from(0)).iter(7))]) + .expect_func_instrs([Instruction::return_span(bspan(0, 7))]) .expect_func_instrs([ Instruction::call_internal(RegSpan::new(Reg::from(7)), EngineFunc::from_u32(0)), Instruction::register_list(6, 5, 4), Instruction::register_list(3, 2, 1), Instruction::register(0), - Instruction::return_span(RegSpan::new(Reg::from(7)).iter(7)), + Instruction::return_span(bspan(7, 7)), ]) .run(); } @@ -329,14 +329,14 @@ fn params7_imm() { ) "#; TranslationTest::from_wat(wasm) - .expect_func_instrs([Instruction::return_span(RegSpan::new(Reg::from(0)).iter(7))]) + .expect_func_instrs([Instruction::return_span(bspan(0, 7))]) .expect_func( ExpectedFunc::new([ Instruction::call_internal(RegSpan::new(Reg::from(0)), EngineFunc::from_u32(0)), Instruction::register_list(-1, -2, -3), Instruction::register_list(-4, -5, -6), Instruction::register(-7), - Instruction::return_span(RegSpan::new(Reg::from(0)).iter(7)), + Instruction::return_span(bspan(0, 7)), ]) .consts([10, 20, 30, 40, 50, 60, 70]), ) @@ -373,13 +373,13 @@ fn params8_reg() { ) "#; TranslationTest::from_wat(wasm) - .expect_func_instrs([Instruction::return_span(RegSpan::new(Reg::from(0)).iter(8))]) + .expect_func_instrs([Instruction::return_span(bspan(0, 8))]) .expect_func_instrs([ Instruction::call_internal(RegSpan::new(Reg::from(8)), EngineFunc::from_u32(0)), Instruction::register_list(0, 1, 2), Instruction::register_list(3, 4, 5), Instruction::register2(6, 7), - Instruction::return_span(RegSpan::new(Reg::from(8)).iter(8)), + Instruction::return_span(bspan(8, 8)), ]) .run(); } @@ -414,13 +414,13 @@ fn params8_reg_rev() { ) "#; TranslationTest::from_wat(wasm) - .expect_func_instrs([Instruction::return_span(RegSpan::new(Reg::from(0)).iter(8))]) + .expect_func_instrs([Instruction::return_span(bspan(0, 8))]) .expect_func_instrs([ Instruction::call_internal(RegSpan::new(Reg::from(8)), EngineFunc::from_u32(0)), Instruction::register_list(7, 6, 5), Instruction::register_list(4, 3, 2), Instruction::register2(1, 0), - Instruction::return_span(RegSpan::new(Reg::from(8)).iter(8)), + Instruction::return_span(bspan(8, 8)), ]) .run(); } @@ -455,14 +455,14 @@ fn params8_imm() { ) "#; TranslationTest::from_wat(wasm) - .expect_func_instrs([Instruction::return_span(RegSpan::new(Reg::from(0)).iter(8))]) + .expect_func_instrs([Instruction::return_span(bspan(0, 8))]) .expect_func( ExpectedFunc::new([ Instruction::call_internal(RegSpan::new(Reg::from(0)), EngineFunc::from_u32(0)), Instruction::register_list(-1, -2, -3), Instruction::register_list(-4, -5, -6), Instruction::register2(-7, -8), - Instruction::return_span(RegSpan::new(Reg::from(0)).iter(8)), + Instruction::return_span(bspan(0, 8)), ]) .consts([10, 20, 30, 40, 50, 60, 70, 80]), ) @@ -501,13 +501,13 @@ fn params9_reg() { ) "#; TranslationTest::from_wat(wasm) - .expect_func_instrs([Instruction::return_span(RegSpan::new(Reg::from(0)).iter(9))]) + .expect_func_instrs([Instruction::return_span(bspan(0, 9))]) .expect_func_instrs([ Instruction::call_internal(RegSpan::new(Reg::from(9)), EngineFunc::from_u32(0)), Instruction::register_list(0, 1, 2), Instruction::register_list(3, 4, 5), Instruction::register3(6, 7, 8), - Instruction::return_span(RegSpan::new(Reg::from(9)).iter(9)), + Instruction::return_span(bspan(9, 9)), ]) .run(); } @@ -544,13 +544,13 @@ fn params9_reg_rev() { ) "#; TranslationTest::from_wat(wasm) - .expect_func_instrs([Instruction::return_span(RegSpan::new(Reg::from(0)).iter(9))]) + .expect_func_instrs([Instruction::return_span(bspan(0, 9))]) .expect_func_instrs([ Instruction::call_internal(RegSpan::new(Reg::from(9)), EngineFunc::from_u32(0)), Instruction::register_list(8, 7, 6), Instruction::register_list(5, 4, 3), Instruction::register3(2, 1, 0), - Instruction::return_span(RegSpan::new(Reg::from(9)).iter(9)), + Instruction::return_span(bspan(9, 9)), ]) .run(); } @@ -587,14 +587,14 @@ fn params9_imm() { ) "#; TranslationTest::from_wat(wasm) - .expect_func_instrs([Instruction::return_span(RegSpan::new(Reg::from(0)).iter(9))]) + .expect_func_instrs([Instruction::return_span(bspan(0, 9))]) .expect_func( ExpectedFunc::new([ Instruction::call_internal(RegSpan::new(Reg::from(0)), EngineFunc::from_u32(0)), Instruction::register_list(-1, -2, -3), Instruction::register_list(-4, -5, -6), Instruction::register3(-7, -8, -9), - Instruction::return_span(RegSpan::new(Reg::from(0)).iter(9)), + Instruction::return_span(bspan(0, 9)), ]) .consts([10, 20, 30, 40, 50, 60, 70, 80, 90]), ) diff --git a/crates/wasmi/src/engine/translator/tests/op/loop_.rs b/crates/wasmi/src/engine/translator/tests/op/loop_.rs index 9c0e2c90d0..14dc55a3a6 100644 --- a/crates/wasmi/src/engine/translator/tests/op/loop_.rs +++ b/crates/wasmi/src/engine/translator/tests/op/loop_.rs @@ -180,7 +180,7 @@ fn identity_loop_4_mixed_1() { ExpectedFunc::new([ Instruction::copy_many_non_overlapping(RegSpan::new(Reg::from(2)), -1, 0), Instruction::register2(1, -2), - Instruction::return_span(RegSpan::new(Reg::from(2)).iter(4)), + Instruction::return_span(bspan(2, 4)), ]) .consts([10_i32, 20]), ) @@ -204,7 +204,7 @@ fn identity_loop_4_mixed_2() { .expect_func_instrs([ Instruction::copy_many_non_overlapping(RegSpan::new(Reg::from(2)), 0, 0), Instruction::register2(1, 1), - Instruction::return_span(RegSpan::new(Reg::from(2)).iter(4)), + Instruction::return_span(bspan(2, 4)), ]) .run() } diff --git a/crates/wasmi/src/engine/translator/tests/op/mod.rs b/crates/wasmi/src/engine/translator/tests/op/mod.rs index c46b9a96a9..7dcbe1f086 100644 --- a/crates/wasmi/src/engine/translator/tests/op/mod.rs +++ b/crates/wasmi/src/engine/translator/tests/op/mod.rs @@ -24,6 +24,7 @@ mod table; mod unary; use super::{ + bspan, display_wasm::DisplayValueType, driver::ExpectedFunc, swap_ops, diff --git a/crates/wasmi/src/engine/translator/tests/op/return_.rs b/crates/wasmi/src/engine/translator/tests/op/return_.rs index 5253bc2226..327e0cff72 100644 --- a/crates/wasmi/src/engine/translator/tests/op/return_.rs +++ b/crates/wasmi/src/engine/translator/tests/op/return_.rs @@ -1,5 +1,5 @@ use super::*; -use crate::engine::{bytecode::RegSpan, translator::tests::wasm_type::WasmTy}; +use crate::engine::translator::tests::wasm_type::WasmTy; use core::fmt::Display; #[test] @@ -264,7 +264,7 @@ fn return_4_span() { ) )"; TranslationTest::from_wat(wasm) - .expect_func_instrs([Instruction::return_span(RegSpan::new(Reg::from(0)).iter(4))]) + .expect_func_instrs([Instruction::return_span(bspan(0, 4))]) .run() } @@ -301,7 +301,7 @@ fn return_5_span() { ) )"; TranslationTest::from_wat(wasm) - .expect_func_instrs([Instruction::return_span(RegSpan::new(Reg::from(0)).iter(5))]) + .expect_func_instrs([Instruction::return_span(bspan(0, 5))]) .run() } diff --git a/crates/wasmi/src/engine/translator/tests/op/return_call/internal.rs b/crates/wasmi/src/engine/translator/tests/op/return_call/internal.rs index 76c6f2d663..2b4d03c890 100644 --- a/crates/wasmi/src/engine/translator/tests/op/return_call/internal.rs +++ b/crates/wasmi/src/engine/translator/tests/op/return_call/internal.rs @@ -1,5 +1,5 @@ use super::*; -use crate::engine::{EngineFunc, RegSpan}; +use crate::engine::EngineFunc; #[test] #[cfg_attr(miri, ignore)] @@ -240,7 +240,7 @@ fn params7_reg() { ) "#; TranslationTest::from_wat(wasm) - .expect_func_instrs([Instruction::return_span(RegSpan::new(Reg::from(0)).iter(7))]) + .expect_func_instrs([Instruction::return_span(bspan(0, 7))]) .expect_func_instrs([ Instruction::return_call_internal(EngineFunc::from_u32(0)), Instruction::register_list(0, 1, 2), @@ -278,7 +278,7 @@ fn params7_reg_rev() { ) "#; TranslationTest::from_wat(wasm) - .expect_func_instrs([Instruction::return_span(RegSpan::new(Reg::from(0)).iter(7))]) + .expect_func_instrs([Instruction::return_span(bspan(0, 7))]) .expect_func_instrs([ Instruction::return_call_internal(EngineFunc::from_u32(0)), Instruction::register_list(6, 5, 4), @@ -316,7 +316,7 @@ fn params7_imm() { ) "#; TranslationTest::from_wat(wasm) - .expect_func_instrs([Instruction::return_span(RegSpan::new(Reg::from(0)).iter(7))]) + .expect_func_instrs([Instruction::return_span(bspan(0, 7))]) .expect_func( ExpectedFunc::new([ Instruction::return_call_internal(EngineFunc::from_u32(0)), @@ -359,7 +359,7 @@ fn params8_reg() { ) "#; TranslationTest::from_wat(wasm) - .expect_func_instrs([Instruction::return_span(RegSpan::new(Reg::from(0)).iter(8))]) + .expect_func_instrs([Instruction::return_span(bspan(0, 8))]) .expect_func_instrs([ Instruction::return_call_internal(EngineFunc::from_u32(0)), Instruction::register_list(0, 1, 2), @@ -399,7 +399,7 @@ fn params8_reg_rev() { ) "#; TranslationTest::from_wat(wasm) - .expect_func_instrs([Instruction::return_span(RegSpan::new(Reg::from(0)).iter(8))]) + .expect_func_instrs([Instruction::return_span(bspan(0, 8))]) .expect_func_instrs([ Instruction::return_call_internal(EngineFunc::from_u32(0)), Instruction::register_list(7, 6, 5), @@ -439,7 +439,7 @@ fn params8_imm() { ) "#; TranslationTest::from_wat(wasm) - .expect_func_instrs([Instruction::return_span(RegSpan::new(Reg::from(0)).iter(8))]) + .expect_func_instrs([Instruction::return_span(bspan(0, 8))]) .expect_func( ExpectedFunc::new([ Instruction::return_call_internal(EngineFunc::from_u32(0)), @@ -484,7 +484,7 @@ fn params9_reg() { ) "#; TranslationTest::from_wat(wasm) - .expect_func_instrs([Instruction::return_span(RegSpan::new(Reg::from(0)).iter(9))]) + .expect_func_instrs([Instruction::return_span(bspan(0, 9))]) .expect_func_instrs([ Instruction::return_call_internal(EngineFunc::from_u32(0)), Instruction::register_list(0, 1, 2), @@ -526,7 +526,7 @@ fn params9_reg_rev() { ) "#; TranslationTest::from_wat(wasm) - .expect_func_instrs([Instruction::return_span(RegSpan::new(Reg::from(0)).iter(9))]) + .expect_func_instrs([Instruction::return_span(bspan(0, 9))]) .expect_func_instrs([ Instruction::return_call_internal(EngineFunc::from_u32(0)), Instruction::register_list(8, 7, 6), @@ -568,7 +568,7 @@ fn params9_imm() { ) "#; TranslationTest::from_wat(wasm) - .expect_func_instrs([Instruction::return_span(RegSpan::new(Reg::from(0)).iter(9))]) + .expect_func_instrs([Instruction::return_span(bspan(0, 9))]) .expect_func( ExpectedFunc::new([ Instruction::return_call_internal(EngineFunc::from_u32(0)), diff --git a/crates/wasmi/src/engine/translator/utils.rs b/crates/wasmi/src/engine/translator/utils.rs index 0bec1200bc..a0ac8dd3fc 100644 --- a/crates/wasmi/src/engine/translator/utils.rs +++ b/crates/wasmi/src/engine/translator/utils.rs @@ -1,6 +1,6 @@ use super::{stack::ValueStack, Provider, TypedProvider, TypedVal}; use crate::{ - engine::bytecode::{Const16, Reg, RegSpanIter, Sign}, + engine::bytecode::{BoundedRegSpan, Const16, Reg, RegSpan, Sign}, Error, }; @@ -137,35 +137,36 @@ impl Provider> { } } -impl RegSpanIter { - /// Creates a [`RegSpanIter`] from the given slice of [`TypedProvider`] if possible. +impl TypedProvider { + /// Returns the `i16` [`Reg`] index if the [`TypedProvider`] is a [`Reg`]. + fn register_index(&self) -> Option { + match self { + TypedProvider::Register(index) => Some(i16::from(*index)), + TypedProvider::Const(_) => None, + } + } +} + +impl BoundedRegSpan { + /// Creates a [`BoundedRegSpan`] from the given slice of [`TypedProvider`] if possible. /// /// All [`TypedProvider`] must be [`Reg`] and have /// contiguous indices for the conversion to succeed. /// /// Returns `None` if the `providers` slice is empty. pub fn from_providers(providers: &[TypedProvider]) -> Option { - /// Returns the `i16` [`Reg`] index if the [`TypedProvider`] is a [`Reg`]. - fn register_index(provider: &TypedProvider) -> Option { - match provider { - TypedProvider::Register(index) => Some(i16::from(*index)), - TypedProvider::Const(_) => None, - } - } let (first, rest) = providers.split_first()?; - let first_index = register_index(first)?; + let first_index = first.register_index()?; let mut prev_index = first_index; for next in rest { - let next_index = register_index(next)?; + let next_index = next.register_index()?; if next_index.checked_sub(prev_index)? != 1 { return None; } prev_index = next_index; } let end_index = prev_index.checked_add(1)?; - Some(Self::from_raw_parts( - Reg::from(first_index), - Reg::from(end_index), - )) + let len = (end_index - first_index) as u16; + Some(Self::new(RegSpan::new(Reg::from(first_index)), len)) } } diff --git a/crates/wasmi/src/engine/translator/visit.rs b/crates/wasmi/src/engine/translator/visit.rs index fea4150c21..610656eae9 100644 --- a/crates/wasmi/src/engine/translator/visit.rs +++ b/crates/wasmi/src/engine/translator/visit.rs @@ -17,7 +17,7 @@ use super::{ use crate::{ core::{TrapCode, ValType, F32, F64}, engine::{ - bytecode::{self, Const16, FuncType, Instruction, Reg}, + bytecode::{self, BoundedRegSpan, Const16, FuncType, Instruction, Reg}, translator::{AcquiredTarget, Provider}, BlockType, FuelCosts, @@ -165,7 +165,7 @@ impl<'a> VisitOperator<'a> for FuncTranslator { let fuel_info = self.fuel_info(); self.alloc.instr_encoder.encode_copies( &mut self.alloc.stack, - branch_params.iter(len_block_params), + BoundedRegSpan::new(branch_params, len_block_params), &self.alloc.buffer.providers[..], fuel_info, )?; @@ -419,16 +419,17 @@ impl<'a> VisitOperator<'a> for FuncTranslator { )?; return Ok(()); } - self.alloc - .stack - .peek_n(branch_params.len(), &mut self.alloc.buffer.providers); + self.alloc.stack.peek_n( + usize::from(branch_params.len()), + &mut self.alloc.buffer.providers, + ); if self .alloc .buffer .providers .iter() .copied() - .eq(branch_params.map(TypedProvider::Register)) + .eq(branch_params.iter().map(TypedProvider::Register)) { // Case: the providers on the stack are already as // expected by the branch params and therefore diff --git a/crates/wasmi/src/engine/translator/visit_register.rs b/crates/wasmi/src/engine/translator/visit_register.rs index 2d031e1ec8..4ef6a710bf 100644 --- a/crates/wasmi/src/engine/translator/visit_register.rs +++ b/crates/wasmi/src/engine/translator/visit_register.rs @@ -35,7 +35,7 @@ impl VisitInputRegisters for Instruction { // their results because preserved registers might be populating them. match self { | Self::Copy { result, .. } => f(result), - | Self::Copy2 { results, .. } + | Self::Copy2 { results, .. } => f(results.span_mut().head_mut()), | Self::CopySpan { results, .. } | Self::CopySpanNonOverlapping { results, .. } | Self::CopyMany { results, .. }