Skip to content

Commit cad13c0

Browse files
committed
add br_table execution handlers
1 parent 29493c7 commit cad13c0

File tree

3 files changed

+63
-1
lines changed

3 files changed

+63
-1
lines changed

crates/wasmi/src/engine/executor/handler/dispatch.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,8 @@ pub fn op_code_to_handler(code: OpCode) -> Handler {
371371
OpCode::MemoryGrow => exec::memory_grow,
372372
// unconditional branch
373373
OpCode::Branch => exec::branch,
374+
OpCode::BranchTable => exec::branch_table,
375+
OpCode::BranchTableSpan => exec::branch_table_span,
374376
// unary
375377
OpCode::I32Popcnt_Ss => exec::i32_popcnt_ss,
376378
OpCode::I32Ctz_Ss => exec::i32_ctz_ss,

crates/wasmi/src/engine/executor/handler/exec.rs

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use crate::{
1010
executor::handler::{
1111
state::DoneReason,
1212
utils::{
13+
exec_copy_span,
1314
exec_copy_span_asc,
1415
exec_copy_span_des,
1516
extract_mem0,
@@ -29,7 +30,7 @@ use crate::{
2930
ir::{Slot, SlotSpan},
3031
TrapCode,
3132
};
32-
use core::ptr::NonNull;
33+
use core::{cmp, ptr::NonNull};
3334

3435
unsafe fn decode_op<Op: ir::Decode>(ip: Ip) -> (Ip, Op) {
3536
let ip = match cfg!(feature = "compact") {
@@ -429,6 +430,57 @@ pub fn memory_grow(
429430
dispatch!(state, ip, sp, mem0, mem0_len, instance)
430431
}
431432

433+
/// Fetches the branch table index value and normalizes it to clamp between `0..len_targets`.
434+
fn fetch_branch_table_target(sp: Sp, index: Slot, len_targets: u32) -> usize {
435+
let index: u32 = get_value(index, sp);
436+
let max_index = len_targets - 1;
437+
cmp::min(index, max_index) as usize
438+
}
439+
440+
pub fn branch_table(
441+
state: &mut VmState,
442+
ip: Ip,
443+
sp: Sp,
444+
mem0: Mem0Ptr,
445+
mem0_len: Mem0Len,
446+
instance: NonNull<InstanceEntity>,
447+
) -> Done {
448+
let (ip, crate::ir::decode::BranchTable { len_targets, index }) = unsafe { decode_op(ip) };
449+
let chosen_target = fetch_branch_table_target(sp, index, len_targets);
450+
let target_offset = 4 * chosen_target;
451+
let ip = unsafe { ip.add(target_offset) };
452+
let (_, offset) = unsafe { ip.decode::<ir::BranchOffset>() };
453+
let ip = offset_ip(ip, offset);
454+
dispatch!(state, ip, sp, mem0, mem0_len, instance)
455+
}
456+
457+
pub fn branch_table_span(
458+
state: &mut VmState,
459+
ip: Ip,
460+
sp: Sp,
461+
mem0: Mem0Ptr,
462+
mem0_len: Mem0Len,
463+
instance: NonNull<InstanceEntity>,
464+
) -> Done {
465+
let (
466+
ip,
467+
crate::ir::decode::BranchTableSpan {
468+
len_targets,
469+
index,
470+
values,
471+
len_values,
472+
},
473+
) = unsafe { decode_op(ip) };
474+
let chosen_target = fetch_branch_table_target(sp, index, len_targets);
475+
let target_offset = 6 * chosen_target;
476+
let ip = unsafe { ip.add(target_offset) };
477+
let (_, ir::BranchTableTarget { results, offset }) =
478+
unsafe { ip.decode::<ir::BranchTableTarget>() };
479+
exec_copy_span(sp, results, values, len_values); // TODO: maybe provide 2 `br_table_span` operation variants if possible
480+
let ip = offset_ip(ip, offset);
481+
dispatch!(state, ip, sp, mem0, mem0_len, instance)
482+
}
483+
432484
macro_rules! handler_unary {
433485
( $( fn $handler:ident($op:ident) = $eval:expr );* $(;)? ) => {
434486
$(

crates/wasmi/src/engine/executor/handler/utils.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,14 @@ macro_rules! exec_return {
142142
}};
143143
}
144144

145+
pub fn exec_copy_span(sp: Sp, dst: SlotSpan, src: SlotSpan, len: u16) {
146+
let op = match dst.head() <= src.head() {
147+
true => exec_copy_span_asc,
148+
false => exec_copy_span_des,
149+
};
150+
op(sp, dst, src, len)
151+
}
152+
145153
pub fn exec_copy_span_asc(sp: Sp, dst: SlotSpan, src: SlotSpan, len: u16) {
146154
debug_assert!(dst.head() <= src.head());
147155
let dst = dst.iter(len);

0 commit comments

Comments
 (0)