Skip to content

Commit

Permalink
Add test case
Browse files Browse the repository at this point in the history
  • Loading branch information
neri committed Feb 7, 2024
1 parent bd95bf5 commit cef72b3
Show file tree
Hide file tree
Showing 8 changed files with 775 additions and 116 deletions.
61 changes: 58 additions & 3 deletions src/cg/intcode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,14 +222,31 @@ pub enum WasmImInstruction {
I64TruncSatF64S,
I64TruncSatF64U,

//
// Fused Instructions
//
/// Fusion of the following 4 instructions
///
/// ```plain
/// local.get $i
/// i32.const N
/// i32.add
/// local.set $i
/// ```
FusedI32AddConst(LocalVarIndex, i32),

/// Fusion of the following 2 instructions
///
/// ```plain
/// i32.const N
/// local.set $i
/// ```
FusedI32SetConst(LocalVarIndex, i32),
FusedI64SetConst(LocalVarIndex, i64),

/// Fusion of the following 2 instructions
///
/// ```plain
/// iXX.const N
/// iXX.binop
/// ```
FusedI32AddI(i32),
FusedI32AndI(u32),
FusedI32OrI(u32),
Expand All @@ -246,6 +263,12 @@ pub enum WasmImInstruction {
FusedI64ShrSI(u32),
FusedI64ShrUI(u32),

/// Fusion of the following 2 instructions
///
/// ```plain
/// iXX.cmpop
/// br_if N
/// ```
FusedI32BrZ(u32),
FusedI32BrEq(u32),
FusedI32BrNe(u32),
Expand All @@ -261,6 +284,14 @@ pub enum WasmImInstruction {
FusedI64BrZ(u32),
FusedI64BrEq(u32),
FusedI64BrNe(u32),
FusedI64BrLtS(u32),
FusedI64BrLtU(u32),
FusedI64BrGtS(u32),
FusedI64BrGtU(u32),
FusedI64BrLeS(u32),
FusedI64BrLeU(u32),
FusedI64BrGeS(u32),
FusedI64BrGeU(u32),
}

impl WasmImInstruction {
Expand Down Expand Up @@ -401,6 +432,30 @@ impl WasmImc {
FusedI64BrNe(target) => {
kernel(target, WasmMnemonic::BrIf)?;
}
FusedI64BrLtS(target) => {
kernel(target, WasmMnemonic::BrIf)?;
}
FusedI64BrLtU(target) => {
kernel(target, WasmMnemonic::BrIf)?;
}
FusedI64BrGtS(target) => {
kernel(target, WasmMnemonic::BrIf)?;
}
FusedI64BrGtU(target) => {
kernel(target, WasmMnemonic::BrIf)?;
}
FusedI64BrLeS(target) => {
kernel(target, WasmMnemonic::BrIf)?;
}
FusedI64BrLeU(target) => {
kernel(target, WasmMnemonic::BrIf)?;
}
FusedI64BrGeS(target) => {
kernel(target, WasmMnemonic::BrIf)?;
}
FusedI64BrGeU(target) => {
kernel(target, WasmMnemonic::BrIf)?;
}

BrTable(table) => {
for target in table.iter_mut() {
Expand Down
64 changes: 64 additions & 0 deletions src/cg/intr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1387,6 +1387,70 @@ impl WasmInterpreter<'_> {
codes.set_position(target)?;
}
}
WasmImInstruction::FusedI64BrLtS(target) => {
let stack_level = code.base_stack_level();
let rhs = unsafe { *value_stack.get(stack_level.succ(1)) };
let lhs = *value_stack.get(stack_level);
if unsafe { lhs.get_i64() < rhs.get_i64() } {
codes.set_position(target)?;
}
}
WasmImInstruction::FusedI64BrLtU(target) => {
let stack_level = code.base_stack_level();
let rhs = unsafe { *value_stack.get(stack_level.succ(1)) };
let lhs = *value_stack.get(stack_level);
if unsafe { lhs.get_u64() < rhs.get_u64() } {
codes.set_position(target)?;
}
}
WasmImInstruction::FusedI64BrGtS(target) => {
let stack_level = code.base_stack_level();
let rhs = unsafe { *value_stack.get(stack_level.succ(1)) };
let lhs = *value_stack.get(stack_level);
if unsafe { lhs.get_i64() > rhs.get_i64() } {
codes.set_position(target)?;
}
}
WasmImInstruction::FusedI64BrGtU(target) => {
let stack_level = code.base_stack_level();
let rhs = unsafe { *value_stack.get(stack_level.succ(1)) };
let lhs = *value_stack.get(stack_level);
if unsafe { lhs.get_u64() > rhs.get_u64() } {
codes.set_position(target)?;
}
}
WasmImInstruction::FusedI64BrLeS(target) => {
let stack_level = code.base_stack_level();
let rhs = unsafe { *value_stack.get(stack_level.succ(1)) };
let lhs = *value_stack.get(stack_level);
if unsafe { lhs.get_i64() <= rhs.get_i64() } {
codes.set_position(target)?;
}
}
WasmImInstruction::FusedI64BrLeU(target) => {
let stack_level = code.base_stack_level();
let rhs = unsafe { *value_stack.get(stack_level.succ(1)) };
let lhs = *value_stack.get(stack_level);
if unsafe { lhs.get_u64() <= rhs.get_u64() } {
codes.set_position(target)?;
}
}
WasmImInstruction::FusedI64BrGeS(target) => {
let stack_level = code.base_stack_level();
let rhs = unsafe { *value_stack.get(stack_level.succ(1)) };
let lhs = *value_stack.get(stack_level);
if unsafe { lhs.get_i64() >= rhs.get_i64() } {
codes.set_position(target)?;
}
}
WasmImInstruction::FusedI64BrGeU(target) => {
let stack_level = code.base_stack_level();
let rhs = unsafe { *value_stack.get(stack_level.succ(1)) };
let lhs = *value_stack.get(stack_level);
if unsafe { lhs.get_u64() >= rhs.get_u64() } {
codes.set_position(target)?;
}
}
}
}
if let Some(result_type) = result_types.first() {
Expand Down
24 changes: 24 additions & 0 deletions src/cg/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1513,6 +1513,30 @@ impl WasmCodeBlock {
(I64Ne, BrIf(target)) => {
fused2!(int_codes, i, FusedI64BrNe(*target));
}
(I64LtS, BrIf(target)) => {
fused2!(int_codes, i, FusedI64BrLtS(*target));
}
(I64LtU, BrIf(target)) => {
fused2!(int_codes, i, FusedI64BrLtU(*target));
}
(I64GtS, BrIf(target)) => {
fused2!(int_codes, i, FusedI64BrGtS(*target));
}
(I64GtU, BrIf(target)) => {
fused2!(int_codes, i, FusedI64BrGtU(*target));
}
(I64LeS, BrIf(target)) => {
fused2!(int_codes, i, FusedI64BrLeS(*target));
}
(I64LeU, BrIf(target)) => {
fused2!(int_codes, i, FusedI64BrLeU(*target));
}
(I64GeS, BrIf(target)) => {
fused2!(int_codes, i, FusedI64BrGeS(*target));
}
(I64GeU, BrIf(target)) => {
fused2!(int_codes, i, FusedI64BrGeU(*target));
}

_ => (),
}
Expand Down
34 changes: 16 additions & 18 deletions src/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,25 +98,23 @@ impl WasmMemory {

/// Write slice to memory
pub fn write_slice(&self, offset: usize, src: &[u8]) -> Result<(), WasmRuntimeErrorKind> {
self.borrowing(|memory| {
let count = src.len();
let limit = memory.len();
let Some(end) = offset.checked_add(count) else {
return Err(WasmRuntimeErrorKind::OutOfBounds);
};
if offset < limit && end <= limit {
unsafe {
memory
.as_mut_ptr()
.add(offset)
.copy_from_nonoverlapping(src.as_ptr(), count);
}
Ok(())
} else {
Err(WasmRuntimeErrorKind::OutOfBounds)
let memory = self.try_borrow()?;
let count = src.len();
let limit = memory.len();
let Some(end) = offset.checked_add(count) else {
return Err(WasmRuntimeErrorKind::OutOfBounds);
};
if offset < limit && end <= limit {
unsafe {
memory
.as_mut_ptr()
.add(offset)
.copy_from_nonoverlapping(src.as_ptr(), count);
}
})
.and_then(|v| v)
Ok(())
} else {
Err(WasmRuntimeErrorKind::OutOfBounds)
}
}

#[inline]
Expand Down
Loading

0 comments on commit cef72b3

Please sign in to comment.