Skip to content

Commit

Permalink
implement comparison instruction execution
Browse files Browse the repository at this point in the history
  • Loading branch information
Robbepop committed Aug 22, 2023
1 parent bd13f02 commit 4174d70
Show file tree
Hide file tree
Showing 2 changed files with 189 additions and 53 deletions.
144 changes: 91 additions & 53 deletions crates/wasmi/src/engine/regmach/executor/instrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,17 @@ use crate::{
core::TrapCode,
engine::{
bytecode::{BlockFuel, BranchOffset, FuncIdx},
bytecode2::{AnyConst32, Const32, Instruction, Register, RegisterSpan, UnaryInstr},
bytecode2::{
AnyConst32,
BinInstr,
BinInstrImm16,
Const16,
Const32,
Instruction,
Register,
RegisterSpan,
UnaryInstr,
},
cache::InstanceCache,
code_map::{CodeMap2 as CodeMap, InstructionPtr2 as InstructionPtr},
config::FuelCosts,
Expand All @@ -21,6 +31,7 @@ use core::cmp;
use wasmi_core::UntypedValue;

mod call;
mod comparison;
mod conversion;
mod global;
mod load;
Expand Down Expand Up @@ -588,58 +599,58 @@ impl<'ctx, 'engine> Executor<'ctx, 'engine> {
Instr::F64Store(instr) => self.execute_f64_store(instr)?,
Instr::F64StoreOffset16(instr) => self.execute_f64_store_offset16(instr)?,
Instr::F64StoreAt(instr) => self.execute_f64_store_at(instr)?,
Instr::I32Eq(_) => todo!(),
Instr::I32EqImm16(_) => todo!(),
Instr::I64Eq(_) => todo!(),
Instr::I64EqImm16(_) => todo!(),
Instr::I32Ne(_) => todo!(),
Instr::I32NeImm16(_) => todo!(),
Instr::I64Ne(_) => todo!(),
Instr::I64NeImm16(_) => todo!(),
Instr::I32LtS(_) => todo!(),
Instr::I32LtU(_) => todo!(),
Instr::I32LtSImm16(_) => todo!(),
Instr::I32LtUImm16(_) => todo!(),
Instr::I64LtS(_) => todo!(),
Instr::I64LtU(_) => todo!(),
Instr::I64LtSImm16(_) => todo!(),
Instr::I64LtUImm16(_) => todo!(),
Instr::I32GtS(_) => todo!(),
Instr::I32GtU(_) => todo!(),
Instr::I32GtSImm16(_) => todo!(),
Instr::I32GtUImm16(_) => todo!(),
Instr::I64GtS(_) => todo!(),
Instr::I64GtU(_) => todo!(),
Instr::I64GtSImm16(_) => todo!(),
Instr::I64GtUImm16(_) => todo!(),
Instr::I32LeS(_) => todo!(),
Instr::I32LeU(_) => todo!(),
Instr::I32LeSImm16(_) => todo!(),
Instr::I32LeUImm16(_) => todo!(),
Instr::I64LeS(_) => todo!(),
Instr::I64LeU(_) => todo!(),
Instr::I64LeSImm16(_) => todo!(),
Instr::I64LeUImm16(_) => todo!(),
Instr::I32GeS(_) => todo!(),
Instr::I32GeU(_) => todo!(),
Instr::I32GeSImm16(_) => todo!(),
Instr::I32GeUImm16(_) => todo!(),
Instr::I64GeS(_) => todo!(),
Instr::I64GeU(_) => todo!(),
Instr::I64GeSImm16(_) => todo!(),
Instr::I64GeUImm16(_) => todo!(),
Instr::F32Eq(_) => todo!(),
Instr::F64Eq(_) => todo!(),
Instr::F32Ne(_) => todo!(),
Instr::F64Ne(_) => todo!(),
Instr::F32Lt(_) => todo!(),
Instr::F64Lt(_) => todo!(),
Instr::F32Le(_) => todo!(),
Instr::F64Le(_) => todo!(),
Instr::F32Gt(_) => todo!(),
Instr::F64Gt(_) => todo!(),
Instr::F32Ge(_) => todo!(),
Instr::F64Ge(_) => todo!(),
Instr::I32Eq(instr) => self.execute_i32_eq(instr),
Instr::I32EqImm16(instr) => self.execute_i32_eq_imm16(instr),
Instr::I32Ne(instr) => self.execute_i32_ne(instr),
Instr::I32NeImm16(instr) => self.execute_i32_ne_imm16(instr),
Instr::I32LtS(instr) => self.execute_i32_lt_s(instr),
Instr::I32LtSImm16(instr) => self.execute_i32_lt_s_imm16(instr),
Instr::I32LtU(instr) => self.execute_i32_lt_u(instr),
Instr::I32LtUImm16(instr) => self.execute_i32_lt_u_imm16(instr),
Instr::I32GtS(instr) => self.execute_i32_le_s(instr),
Instr::I32GtSImm16(instr) => self.execute_i32_le_s_imm16(instr),
Instr::I32GtU(instr) => self.execute_i32_le_u(instr),
Instr::I32GtUImm16(instr) => self.execute_i32_le_u_imm16(instr),
Instr::I32LeS(instr) => self.execute_i32_gt_s(instr),
Instr::I32LeSImm16(instr) => self.execute_i32_gt_s_imm16(instr),
Instr::I32LeU(instr) => self.execute_i32_gt_u(instr),
Instr::I32LeUImm16(instr) => self.execute_i32_gt_u_imm16(instr),
Instr::I32GeS(instr) => self.execute_i32_ge_s(instr),
Instr::I32GeSImm16(instr) => self.execute_i32_ge_s_imm16(instr),
Instr::I32GeU(instr) => self.execute_i32_ge_u(instr),
Instr::I32GeUImm16(instr) => self.execute_i32_ge_u_imm16(instr),
Instr::I64Eq(instr) => self.execute_i64_eq(instr),
Instr::I64EqImm16(instr) => self.execute_i64_eq_imm16(instr),
Instr::I64Ne(instr) => self.execute_i64_ne(instr),
Instr::I64NeImm16(instr) => self.execute_i64_ne_imm16(instr),
Instr::I64LtS(instr) => self.execute_i64_lt_s(instr),
Instr::I64LtSImm16(instr) => self.execute_i64_lt_s_imm16(instr),
Instr::I64LtU(instr) => self.execute_i64_lt_u(instr),
Instr::I64LtUImm16(instr) => self.execute_i64_lt_u_imm16(instr),
Instr::I64GtS(instr) => self.execute_i64_le_s(instr),
Instr::I64GtSImm16(instr) => self.execute_i64_le_s_imm16(instr),
Instr::I64GtU(instr) => self.execute_i64_le_u(instr),
Instr::I64GtUImm16(instr) => self.execute_i64_le_u_imm16(instr),
Instr::I64LeS(instr) => self.execute_i64_gt_s(instr),
Instr::I64LeSImm16(instr) => self.execute_i64_gt_s_imm16(instr),
Instr::I64LeU(instr) => self.execute_i64_gt_u(instr),
Instr::I64LeUImm16(instr) => self.execute_i64_gt_u_imm16(instr),
Instr::I64GeS(instr) => self.execute_i64_ge_s(instr),
Instr::I64GeSImm16(instr) => self.execute_i64_ge_s_imm16(instr),
Instr::I64GeU(instr) => self.execute_i64_ge_u(instr),
Instr::I64GeUImm16(instr) => self.execute_i64_ge_u_imm16(instr),
Instr::F32Eq(instr) => self.execute_f32_eq(instr),
Instr::F32Ne(instr) => self.execute_f32_ne(instr),
Instr::F32Lt(instr) => self.execute_f32_lt(instr),
Instr::F32Le(instr) => self.execute_f32_le(instr),
Instr::F32Gt(instr) => self.execute_f32_gt(instr),
Instr::F32Ge(instr) => self.execute_f32_ge(instr),
Instr::F64Eq(instr) => self.execute_f64_eq(instr),
Instr::F64Ne(instr) => self.execute_f64_ne(instr),
Instr::F64Lt(instr) => self.execute_f64_lt(instr),
Instr::F64Le(instr) => self.execute_f64_le(instr),
Instr::F64Gt(instr) => self.execute_f64_gt(instr),
Instr::F64Ge(instr) => self.execute_f64_ge(instr),
Instr::I32Clz(instr) => self.execute_i32_clz(instr),
Instr::I64Clz(instr) => self.execute_i64_clz(instr),
Instr::I32Ctz(instr) => self.execute_i32_ctz(instr),
Expand Down Expand Up @@ -1052,6 +1063,33 @@ impl<'ctx, 'engine> Executor<'ctx, 'engine> {
self.set_register(instr.result, op(value)?);
self.try_next_instr()
}

/// Executes a generic binary [`Instruction`].
fn execute_binary(
&mut self,
instr: BinInstr,
op: fn(UntypedValue, UntypedValue) -> UntypedValue,
) {
let lhs = self.get_register(instr.lhs);
let rhs = self.get_register(instr.rhs);
self.set_register(instr.result, op(lhs, rhs));
self.next_instr();
}

/// Executes a generic binary [`Instruction`].
fn execute_binary_imm16<T>(
&mut self,
instr: BinInstrImm16<T>,
op: fn(UntypedValue, UntypedValue) -> UntypedValue,
) where
T: From<Const16<T>>,
UntypedValue: From<T>,
{
let lhs = self.get_register(instr.reg_in);
let rhs = UntypedValue::from(<T>::from(instr.imm_in));
self.set_register(instr.result, op(lhs, rhs));
self.next_instr();
}
}

impl<'ctx, 'engine> Executor<'ctx, 'engine> {
Expand Down
98 changes: 98 additions & 0 deletions crates/wasmi/src/engine/regmach/executor/instrs/comparison.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
use super::Executor;
use crate::{
core::UntypedValue,
engine::bytecode2::{BinInstr, BinInstrImm16},
};

#[cfg(doc)]
use crate::engine::bytecode2::Instruction;

macro_rules! impl_comparison {
( $( (Instruction::$var_name:ident, $fn_name:ident, $op:expr) ),* $(,)? ) => {
$(
#[doc = concat!("Executes an [`Instruction::", stringify!($var_name), "`].")]
#[inline(always)]
pub fn $fn_name(&mut self, instr: BinInstr) {
self.execute_binary(instr, $op)
}
)*
};
}

impl<'ctx, 'engine> Executor<'ctx, 'engine> {
impl_comparison! {
(Instruction::I32Eq, execute_i32_eq, UntypedValue::i32_eq),
(Instruction::I32Ne, execute_i32_ne, UntypedValue::i32_ne),
(Instruction::I32LtS, execute_i32_lt_s, UntypedValue::i32_lt_s),
(Instruction::I32LtU, execute_i32_lt_u, UntypedValue::i32_lt_u),
(Instruction::I32LeS, execute_i32_le_s, UntypedValue::i32_le_s),
(Instruction::I32LeU, execute_i32_le_u, UntypedValue::i32_le_u),
(Instruction::I32GtS, execute_i32_gt_s, UntypedValue::i32_gt_s),
(Instruction::I32GtU, execute_i32_gt_u, UntypedValue::i32_gt_u),
(Instruction::I32GeS, execute_i32_ge_s, UntypedValue::i32_ge_s),
(Instruction::I32GeU, execute_i32_ge_u, UntypedValue::i32_ge_u),

(Instruction::I64Eq, execute_i64_eq, UntypedValue::i64_eq),
(Instruction::I64Ne, execute_i64_ne, UntypedValue::i64_ne),
(Instruction::I64LtS, execute_i64_lt_s, UntypedValue::i64_lt_s),
(Instruction::I64LtU, execute_i64_lt_u, UntypedValue::i64_lt_u),
(Instruction::I64LeS, execute_i64_le_s, UntypedValue::i64_le_s),
(Instruction::I64LeU, execute_i64_le_u, UntypedValue::i64_le_u),
(Instruction::I64GtS, execute_i64_gt_s, UntypedValue::i64_gt_s),
(Instruction::I64GtU, execute_i64_gt_u, UntypedValue::i64_gt_u),
(Instruction::I64GeS, execute_i64_ge_s, UntypedValue::i64_ge_s),
(Instruction::I64GeU, execute_i64_ge_u, UntypedValue::i64_ge_u),

(Instruction::F32Eq, execute_f32_eq, UntypedValue::f32_eq),
(Instruction::F32Ne, execute_f32_ne, UntypedValue::f32_ne),
(Instruction::F32Lt, execute_f32_lt, UntypedValue::f32_lt),
(Instruction::F32Le, execute_f32_le, UntypedValue::f32_le),
(Instruction::F32Gt, execute_f32_gt, UntypedValue::f32_gt),
(Instruction::F32Ge, execute_f32_ge, UntypedValue::f32_ge),

(Instruction::F64Eq, execute_f64_eq, UntypedValue::f64_eq),
(Instruction::F64Ne, execute_f64_ne, UntypedValue::f64_ne),
(Instruction::F64Lt, execute_f64_lt, UntypedValue::f64_lt),
(Instruction::F64Le, execute_f64_le, UntypedValue::f64_le),
(Instruction::F64Gt, execute_f64_gt, UntypedValue::f64_gt),
(Instruction::F64Ge, execute_f64_ge, UntypedValue::f64_ge),
}
}

macro_rules! impl_comparison_imm16 {
( $( ($ty:ty, Instruction::$var_name:ident, $fn_name:ident, $op:expr) ),* $(,)? ) => {
$(
#[doc = concat!("Executes an [`Instruction::", stringify!($var_name), "`].")]
#[inline(always)]
pub fn $fn_name(&mut self, instr: BinInstrImm16<$ty>) {
self.execute_binary_imm16(instr, $op)
}
)*
};
}

impl<'ctx, 'engine> Executor<'ctx, 'engine> {
impl_comparison_imm16! {
(i32, Instruction::I32EqImm16, execute_i32_eq_imm16, UntypedValue::i32_eq),
(i32, Instruction::I32NeImm16, execute_i32_ne_imm16, UntypedValue::i32_ne),
(i32, Instruction::I32LtSImm16, execute_i32_lt_s_imm16, UntypedValue::i32_lt_s),
(u32, Instruction::I32LtUImm16, execute_i32_lt_u_imm16, UntypedValue::i32_lt_u),
(i32, Instruction::I32LeSImm16, execute_i32_le_s_imm16, UntypedValue::i32_le_s),
(u32, Instruction::I32LeUImm16, execute_i32_le_u_imm16, UntypedValue::i32_le_u),
(i32, Instruction::I32GtSImm16, execute_i32_gt_s_imm16, UntypedValue::i32_gt_s),
(u32, Instruction::I32GtUImm16, execute_i32_gt_u_imm16, UntypedValue::i32_gt_u),
(i32, Instruction::I32GeSImm16, execute_i32_ge_s_imm16, UntypedValue::i32_ge_s),
(u32, Instruction::I32GeUImm16, execute_i32_ge_u_imm16, UntypedValue::i32_ge_u),

(i64, Instruction::I64EqImm16, execute_i64_eq_imm16, UntypedValue::i64_eq),
(i64, Instruction::I64NeImm16, execute_i64_ne_imm16, UntypedValue::i64_ne),
(i64, Instruction::I64LtSImm16, execute_i64_lt_s_imm16, UntypedValue::i64_lt_s),
(u64, Instruction::I64LtUImm16, execute_i64_lt_u_imm16, UntypedValue::i64_lt_u),
(i64, Instruction::I64LeSImm16, execute_i64_le_s_imm16, UntypedValue::i64_le_s),
(u64, Instruction::I64LeUImm16, execute_i64_le_u_imm16, UntypedValue::i64_le_u),
(i64, Instruction::I64GtSImm16, execute_i64_gt_s_imm16, UntypedValue::i64_gt_s),
(u64, Instruction::I64GtUImm16, execute_i64_gt_u_imm16, UntypedValue::i64_gt_u),
(i64, Instruction::I64GeSImm16, execute_i64_ge_s_imm16, UntypedValue::i64_ge_s),
(u64, Instruction::I64GeUImm16, execute_i64_ge_u_imm16, UntypedValue::i64_ge_u),
}
}

0 comments on commit 4174d70

Please sign in to comment.