Introduce Keep and DropKeep structs in isa
This commit is contained in:
parent
0f6da829de
commit
29002153ec
21
src/isa.rs
21
src/isa.rs
|
@ -40,11 +40,23 @@
|
|||
//! - Reserved immediates are ignored for `call_indirect`, `current_memory`, `grow_memory`.
|
||||
//!
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Keep {
|
||||
None,
|
||||
Single,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct DropKeep {
|
||||
pub drop: u32,
|
||||
pub keep: Keep,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Target {
|
||||
pub dst_pc: u32,
|
||||
pub drop: u32,
|
||||
pub keep: u8,
|
||||
pub drop_keep: DropKeep,
|
||||
}
|
||||
|
||||
#[allow(unused)] // TODO: Remove
|
||||
|
@ -71,10 +83,7 @@ pub enum Instruction {
|
|||
BrTable(Box<[Target]>),
|
||||
|
||||
Unreachable,
|
||||
Return {
|
||||
drop: u32,
|
||||
keep: u8,
|
||||
},
|
||||
Return(DropKeep),
|
||||
|
||||
Call(u32),
|
||||
CallIndirect(u32),
|
||||
|
|
|
@ -33,7 +33,7 @@ pub enum InstructionOutcome {
|
|||
/// Execute function call.
|
||||
ExecuteCall(FuncRef),
|
||||
/// Return from current function block.
|
||||
Return(u32, u8),
|
||||
Return(isa::DropKeep),
|
||||
}
|
||||
|
||||
/// Function run result.
|
||||
|
@ -157,14 +157,14 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
InstructionOutcome::RunNextInstruction => function_context.position += 1,
|
||||
InstructionOutcome::Branch(target) => {
|
||||
function_context.position = target.dst_pc as usize;
|
||||
self.value_stack.drop_keep(target.drop, target.keep);
|
||||
self.value_stack.drop_keep(target.drop_keep);
|
||||
},
|
||||
InstructionOutcome::ExecuteCall(func_ref) => {
|
||||
function_context.position += 1;
|
||||
return Ok(RunResult::NestedCall(func_ref));
|
||||
},
|
||||
InstructionOutcome::Return(drop, keep) => {
|
||||
self.value_stack.drop_keep(drop, keep);
|
||||
InstructionOutcome::Return(drop_keep) => {
|
||||
self.value_stack.drop_keep(drop_keep);
|
||||
break;
|
||||
},
|
||||
}
|
||||
|
@ -182,7 +182,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
&isa::Instruction::BrIfEqz(ref target) => self.run_br_eqz(target.clone()),
|
||||
&isa::Instruction::BrIfNez(ref target) => self.run_br_nez(target.clone()),
|
||||
&isa::Instruction::BrTable(ref targets) => self.run_br_table(targets),
|
||||
&isa::Instruction::Return { drop, keep } => self.run_return(drop, keep),
|
||||
&isa::Instruction::Return(drop_keep) => self.run_return(drop_keep),
|
||||
|
||||
&isa::Instruction::Call(index) => self.run_call(context, index),
|
||||
&isa::Instruction::CallIndirect(index) => self.run_call_indirect(context, index),
|
||||
|
@ -405,8 +405,8 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
|||
Ok(InstructionOutcome::Branch(dst))
|
||||
}
|
||||
|
||||
fn run_return(&mut self, drop: u32, keep: u8) -> Result<InstructionOutcome, TrapKind> {
|
||||
Ok(InstructionOutcome::Return(drop, keep))
|
||||
fn run_return(&mut self, drop_keep: isa::DropKeep) -> Result<InstructionOutcome, TrapKind> {
|
||||
Ok(InstructionOutcome::Return(drop_keep))
|
||||
}
|
||||
|
||||
fn run_call(
|
||||
|
@ -1127,16 +1127,14 @@ impl ValueStack {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn drop_keep(&mut self, drop: u32, keep: u8) {
|
||||
assert!(keep <= 1);
|
||||
|
||||
if keep == 1 {
|
||||
fn drop_keep(&mut self, drop_keep: isa::DropKeep) {
|
||||
if drop_keep.keep == isa::Keep::Single {
|
||||
let top = *self.top();
|
||||
*self.pick_mut(drop as usize + 1) = top;
|
||||
*self.pick_mut(drop_keep.drop as usize + 1) = top;
|
||||
}
|
||||
|
||||
let cur_stack_len = self.len();
|
||||
self.sp = cur_stack_len - drop as usize;
|
||||
self.sp = cur_stack_len - drop_keep.drop as usize;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -283,7 +283,7 @@ impl Validator {
|
|||
|
||||
context.sink.emit_br_eqz(Target {
|
||||
label: if_not,
|
||||
drop_keep: DropKeep { drop: 0, keep: 0 },
|
||||
drop_keep: isa::DropKeep { drop: 0, keep: isa::Keep::None, },
|
||||
});
|
||||
}
|
||||
Else => {
|
||||
|
@ -303,7 +303,7 @@ impl Validator {
|
|||
// to the "end_label" (it will be resolved at End).
|
||||
context.sink.emit_br(Target {
|
||||
label: end_label,
|
||||
drop_keep: DropKeep { drop: 0, keep: 0 },
|
||||
drop_keep: isa::DropKeep { drop: 0, keep: isa::Keep::None, },
|
||||
});
|
||||
|
||||
// Resolve `if_not` to here so when if condition is unsatisfied control flow
|
||||
|
@ -375,15 +375,12 @@ impl Validator {
|
|||
)?;
|
||||
}
|
||||
|
||||
let DropKeep { drop, keep } = drop_keep_return(
|
||||
let drop_keep = drop_keep_return(
|
||||
&context.locals,
|
||||
&context.value_stack,
|
||||
&context.frame_stack,
|
||||
);
|
||||
context.sink.emit(isa::Instruction::Return {
|
||||
drop,
|
||||
keep,
|
||||
});
|
||||
context.sink.emit(isa::Instruction::Return(drop_keep));
|
||||
}
|
||||
|
||||
pop_label(&mut context.value_stack, &mut context.frame_stack)?;
|
||||
|
@ -441,15 +438,12 @@ impl Validator {
|
|||
tee_value(&mut context.value_stack, &context.frame_stack, value_type.into())?;
|
||||
}
|
||||
|
||||
let DropKeep { drop, keep } = drop_keep_return(
|
||||
let drop_keep = drop_keep_return(
|
||||
&context.locals,
|
||||
&context.value_stack,
|
||||
&context.frame_stack
|
||||
);
|
||||
context.sink.emit(isa::Instruction::Return {
|
||||
drop,
|
||||
keep,
|
||||
});
|
||||
context.sink.emit(isa::Instruction::Return(drop_keep));
|
||||
|
||||
return Ok(InstructionOutcome::Unreachable);
|
||||
}
|
||||
|
@ -1549,13 +1543,13 @@ fn require_target(
|
|||
require_label(depth, frame_stack).expect("require_target called with a bogus depth");
|
||||
|
||||
// Find out how many values we need to keep (copy to the new stack location after the drop).
|
||||
let keep: u8 = match (frame.frame_type, frame.block_type) {
|
||||
let keep: isa::Keep = match (frame.frame_type, frame.block_type) {
|
||||
// A loop doesn't take a value upon a branch. It can return value
|
||||
// only via reaching it's closing `End` operator.
|
||||
(BlockFrameType::Loop { .. }, _) => 0,
|
||||
(BlockFrameType::Loop { .. }, _) => isa::Keep::None,
|
||||
|
||||
(_, BlockType::Value(_)) => 1,
|
||||
(_, BlockType::NoResult) => 0,
|
||||
(_, BlockType::Value(_)) => isa::Keep::Single,
|
||||
(_, BlockType::NoResult) => isa::Keep::None,
|
||||
};
|
||||
|
||||
// Find out how many values we need to discard.
|
||||
|
@ -1573,7 +1567,7 @@ fn require_target(
|
|||
);
|
||||
assert!(
|
||||
(value_stack_height as u32 - frame.value_stack_len as u32) >= keep as u32,
|
||||
"Stack underflow detected: asked to keep {} values, but there are only {}",
|
||||
"Stack underflow detected: asked to keep {:?} values, but there are only {}",
|
||||
keep,
|
||||
value_stack_height as u32 - frame.value_stack_len as u32,
|
||||
);
|
||||
|
@ -1582,7 +1576,7 @@ fn require_target(
|
|||
|
||||
Target {
|
||||
label: frame.frame_type.br_destination(),
|
||||
drop_keep: DropKeep { drop, keep },
|
||||
drop_keep: isa::DropKeep { drop, keep },
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1590,7 +1584,7 @@ fn drop_keep_return(
|
|||
locals: &Locals,
|
||||
value_stack: &StackWithLimit<StackValueType>,
|
||||
frame_stack: &StackWithLimit<BlockFrame>,
|
||||
) -> DropKeep {
|
||||
) -> isa::DropKeep {
|
||||
assert!(
|
||||
!frame_stack.is_empty(),
|
||||
"drop_keep_return can't be called with the frame stack empty"
|
||||
|
@ -1627,16 +1621,10 @@ fn relative_local_depth(
|
|||
Ok(depth)
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct DropKeep {
|
||||
drop: u32,
|
||||
keep: u8,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Target {
|
||||
label: LabelId,
|
||||
drop_keep: DropKeep,
|
||||
drop_keep: isa::DropKeep,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -1694,51 +1682,39 @@ impl Sink {
|
|||
fn emit_br(&mut self, target: Target) {
|
||||
let Target {
|
||||
label,
|
||||
drop_keep: DropKeep {
|
||||
drop,
|
||||
keep,
|
||||
},
|
||||
drop_keep,
|
||||
} = target;
|
||||
let pc = self.cur_pc();
|
||||
let dst_pc = self.pc_or_placeholder(label, || Reloc::Br { pc });
|
||||
self.ins.push(isa::Instruction::Br(isa::Target {
|
||||
dst_pc,
|
||||
drop,
|
||||
keep,
|
||||
drop_keep: drop_keep.into(),
|
||||
}));
|
||||
}
|
||||
|
||||
fn emit_br_eqz(&mut self, target: Target) {
|
||||
let Target {
|
||||
label,
|
||||
drop_keep: DropKeep {
|
||||
drop,
|
||||
keep,
|
||||
},
|
||||
drop_keep,
|
||||
} = target;
|
||||
let pc = self.cur_pc();
|
||||
let dst_pc = self.pc_or_placeholder(label, || Reloc::Br { pc });
|
||||
self.ins.push(isa::Instruction::BrIfEqz(isa::Target {
|
||||
dst_pc,
|
||||
drop,
|
||||
keep,
|
||||
drop_keep: drop_keep.into(),
|
||||
}));
|
||||
}
|
||||
|
||||
fn emit_br_nez(&mut self, target: Target) {
|
||||
let Target {
|
||||
label,
|
||||
drop_keep: DropKeep {
|
||||
drop,
|
||||
keep,
|
||||
},
|
||||
drop_keep,
|
||||
} = target;
|
||||
let pc = self.cur_pc();
|
||||
let dst_pc = self.pc_or_placeholder(label, || Reloc::Br { pc });
|
||||
self.ins.push(isa::Instruction::BrIfNez(isa::Target {
|
||||
dst_pc,
|
||||
drop,
|
||||
keep,
|
||||
drop_keep: drop_keep.into(),
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -1747,16 +1723,12 @@ impl Sink {
|
|||
|
||||
let pc = self.cur_pc();
|
||||
let mut isa_targets = Vec::new();
|
||||
for (idx, &Target { label, drop_keep: DropKeep {
|
||||
drop,
|
||||
keep,
|
||||
}}) in targets.iter().chain(iter::once(&default)).enumerate() {
|
||||
for (idx, &Target { label, drop_keep }) in targets.iter().chain(iter::once(&default)).enumerate() {
|
||||
let dst_pc = self.pc_or_placeholder(label, || Reloc::BrTable { pc, idx });
|
||||
isa_targets.push(
|
||||
isa::Target {
|
||||
dst_pc,
|
||||
keep,
|
||||
drop,
|
||||
drop_keep: drop_keep.into(),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -327,10 +327,10 @@ fn implicit_return_no_value() {
|
|||
assert_eq!(
|
||||
code,
|
||||
vec![
|
||||
isa::Instruction::Return {
|
||||
isa::Instruction::Return(isa::DropKeep {
|
||||
drop: 0,
|
||||
keep: 0,
|
||||
}
|
||||
keep: isa::Keep::None,
|
||||
})
|
||||
]
|
||||
)
|
||||
}
|
||||
|
@ -348,10 +348,10 @@ fn implicit_return_with_value() {
|
|||
code,
|
||||
vec![
|
||||
isa::Instruction::I32Const(0),
|
||||
isa::Instruction::Return {
|
||||
isa::Instruction::Return(isa::DropKeep {
|
||||
drop: 0,
|
||||
keep: 1,
|
||||
}
|
||||
keep: isa::Keep::Single,
|
||||
}),
|
||||
]
|
||||
)
|
||||
}
|
||||
|
@ -367,10 +367,10 @@ fn implicit_return_param() {
|
|||
assert_eq!(
|
||||
code,
|
||||
vec![
|
||||
isa::Instruction::Return {
|
||||
isa::Instruction::Return(isa::DropKeep {
|
||||
drop: 1,
|
||||
keep: 0,
|
||||
}
|
||||
keep: isa::Keep::None,
|
||||
}),
|
||||
]
|
||||
)
|
||||
}
|
||||
|
@ -388,10 +388,10 @@ fn get_local() {
|
|||
code,
|
||||
vec![
|
||||
isa::Instruction::GetLocal(1),
|
||||
isa::Instruction::Return {
|
||||
isa::Instruction::Return(isa::DropKeep {
|
||||
drop: 1,
|
||||
keep: 1,
|
||||
}
|
||||
keep: isa::Keep::Single,
|
||||
}),
|
||||
]
|
||||
)
|
||||
}
|
||||
|
@ -410,14 +410,14 @@ fn explicit_return() {
|
|||
code,
|
||||
vec![
|
||||
isa::Instruction::GetLocal(1),
|
||||
isa::Instruction::Return {
|
||||
isa::Instruction::Return(isa::DropKeep {
|
||||
drop: 1,
|
||||
keep: 1,
|
||||
},
|
||||
isa::Instruction::Return {
|
||||
keep: isa::Keep::Single,
|
||||
}),
|
||||
isa::Instruction::Return(isa::DropKeep {
|
||||
drop: 1,
|
||||
keep: 1,
|
||||
}
|
||||
keep: isa::Keep::Single,
|
||||
}),
|
||||
]
|
||||
)
|
||||
}
|
||||
|
@ -444,10 +444,10 @@ fn add_params() {
|
|||
isa::Instruction::GetLocal(2),
|
||||
isa::Instruction::GetLocal(2),
|
||||
isa::Instruction::I32Add,
|
||||
isa::Instruction::Return {
|
||||
isa::Instruction::Return(isa::DropKeep {
|
||||
drop: 2,
|
||||
keep: 1,
|
||||
}
|
||||
keep: isa::Keep::Single,
|
||||
}),
|
||||
]
|
||||
)
|
||||
}
|
||||
|
@ -468,10 +468,10 @@ fn drop_locals() {
|
|||
vec![
|
||||
isa::Instruction::GetLocal(2),
|
||||
isa::Instruction::SetLocal(1),
|
||||
isa::Instruction::Return {
|
||||
isa::Instruction::Return(isa::DropKeep {
|
||||
drop: 2,
|
||||
keep: 0,
|
||||
}
|
||||
keep: isa::Keep::None,
|
||||
}),
|
||||
]
|
||||
)
|
||||
}
|
||||
|
@ -496,19 +496,21 @@ fn if_without_else() {
|
|||
isa::Instruction::I32Const(1),
|
||||
isa::Instruction::BrIfEqz(isa::Target {
|
||||
dst_pc: 4,
|
||||
drop: 0,
|
||||
keep: 0,
|
||||
drop_keep: isa::DropKeep {
|
||||
drop: 0,
|
||||
keep: isa::Keep::None,
|
||||
},
|
||||
}),
|
||||
isa::Instruction::I32Const(2),
|
||||
isa::Instruction::Return {
|
||||
isa::Instruction::Return(isa::DropKeep {
|
||||
drop: 1, // 1 param
|
||||
keep: 1, // 1 result
|
||||
},
|
||||
keep: isa::Keep::Single, // 1 result
|
||||
}),
|
||||
isa::Instruction::I32Const(3),
|
||||
isa::Instruction::Return {
|
||||
isa::Instruction::Return(isa::DropKeep {
|
||||
drop: 1,
|
||||
keep: 1,
|
||||
},
|
||||
keep: isa::Keep::Single,
|
||||
}),
|
||||
]
|
||||
)
|
||||
}
|
||||
|
@ -536,22 +538,26 @@ fn if_else() {
|
|||
isa::Instruction::I32Const(1),
|
||||
isa::Instruction::BrIfEqz(isa::Target {
|
||||
dst_pc: 5,
|
||||
drop: 0,
|
||||
keep: 0,
|
||||
drop_keep: isa::DropKeep {
|
||||
drop: 0,
|
||||
keep: isa::Keep::None,
|
||||
},
|
||||
}),
|
||||
isa::Instruction::I32Const(2),
|
||||
isa::Instruction::SetLocal(1),
|
||||
isa::Instruction::Br(isa::Target {
|
||||
dst_pc: 7,
|
||||
drop: 0,
|
||||
keep: 0,
|
||||
drop_keep: isa::DropKeep {
|
||||
drop: 0,
|
||||
keep: isa::Keep::None,
|
||||
},
|
||||
}),
|
||||
isa::Instruction::I32Const(3),
|
||||
isa::Instruction::SetLocal(1),
|
||||
isa::Instruction::Return {
|
||||
isa::Instruction::Return(isa::DropKeep {
|
||||
drop: 1,
|
||||
keep: 0,
|
||||
},
|
||||
keep: isa::Keep::None,
|
||||
}),
|
||||
]
|
||||
)
|
||||
}
|
||||
|
@ -577,21 +583,25 @@ fn if_else_returns_result() {
|
|||
isa::Instruction::I32Const(1),
|
||||
isa::Instruction::BrIfEqz(isa::Target {
|
||||
dst_pc: 4,
|
||||
drop: 0,
|
||||
keep: 0,
|
||||
drop_keep: isa::DropKeep {
|
||||
drop: 0,
|
||||
keep: isa::Keep::None,
|
||||
},
|
||||
}),
|
||||
isa::Instruction::I32Const(2),
|
||||
isa::Instruction::Br(isa::Target {
|
||||
dst_pc: 5,
|
||||
drop: 0,
|
||||
keep: 0,
|
||||
drop_keep: isa::DropKeep {
|
||||
drop: 0,
|
||||
keep: isa::Keep::None,
|
||||
},
|
||||
}),
|
||||
isa::Instruction::I32Const(3),
|
||||
isa::Instruction::Drop,
|
||||
isa::Instruction::Return {
|
||||
isa::Instruction::Return(isa::DropKeep {
|
||||
drop: 0,
|
||||
keep: 0,
|
||||
},
|
||||
keep: isa::Keep::None,
|
||||
}),
|
||||
]
|
||||
)
|
||||
}
|
||||
|
@ -621,29 +631,35 @@ fn if_else_branch_from_true_branch() {
|
|||
isa::Instruction::I32Const(1),
|
||||
isa::Instruction::BrIfEqz(isa::Target {
|
||||
dst_pc: 8,
|
||||
drop: 0,
|
||||
keep: 0,
|
||||
drop_keep: isa::DropKeep {
|
||||
drop: 0,
|
||||
keep: isa::Keep::None,
|
||||
},
|
||||
}),
|
||||
isa::Instruction::I32Const(1),
|
||||
isa::Instruction::I32Const(1),
|
||||
isa::Instruction::BrIfNez(isa::Target {
|
||||
dst_pc: 9,
|
||||
drop: 0,
|
||||
keep: 1,
|
||||
drop_keep: isa::DropKeep {
|
||||
drop: 0,
|
||||
keep: isa::Keep::Single,
|
||||
},
|
||||
}),
|
||||
isa::Instruction::Drop,
|
||||
isa::Instruction::I32Const(2),
|
||||
isa::Instruction::Br(isa::Target {
|
||||
dst_pc: 9,
|
||||
drop: 0,
|
||||
keep: 0,
|
||||
drop_keep: isa::DropKeep {
|
||||
drop: 0,
|
||||
keep: isa::Keep::None,
|
||||
},
|
||||
}),
|
||||
isa::Instruction::I32Const(3),
|
||||
isa::Instruction::Drop,
|
||||
isa::Instruction::Return {
|
||||
isa::Instruction::Return(isa::DropKeep {
|
||||
drop: 0,
|
||||
keep: 0,
|
||||
},
|
||||
keep: isa::Keep::None,
|
||||
}),
|
||||
]
|
||||
)
|
||||
}
|
||||
|
@ -673,29 +689,35 @@ fn if_else_branch_from_false_branch() {
|
|||
isa::Instruction::I32Const(1),
|
||||
isa::Instruction::BrIfEqz(isa::Target {
|
||||
dst_pc: 4,
|
||||
drop: 0,
|
||||
keep: 0,
|
||||
drop_keep: isa::DropKeep {
|
||||
drop: 0,
|
||||
keep: isa::Keep::None,
|
||||
},
|
||||
}),
|
||||
isa::Instruction::I32Const(1),
|
||||
isa::Instruction::Br(isa::Target {
|
||||
dst_pc: 9,
|
||||
drop: 0,
|
||||
keep: 0,
|
||||
drop_keep: isa::DropKeep {
|
||||
drop: 0,
|
||||
keep: isa::Keep::None,
|
||||
},
|
||||
}),
|
||||
isa::Instruction::I32Const(2),
|
||||
isa::Instruction::I32Const(1),
|
||||
isa::Instruction::BrIfNez(isa::Target {
|
||||
dst_pc: 9,
|
||||
drop: 0,
|
||||
keep: 1,
|
||||
drop_keep: isa::DropKeep {
|
||||
drop: 0,
|
||||
keep: isa::Keep::Single,
|
||||
},
|
||||
}),
|
||||
isa::Instruction::Drop,
|
||||
isa::Instruction::I32Const(3),
|
||||
isa::Instruction::Drop,
|
||||
isa::Instruction::Return {
|
||||
isa::Instruction::Return(isa::DropKeep {
|
||||
drop: 0,
|
||||
keep: 0,
|
||||
},
|
||||
keep: isa::Keep::None,
|
||||
}),
|
||||
]
|
||||
)
|
||||
}
|
||||
|
@ -720,15 +742,17 @@ fn loop_() {
|
|||
isa::Instruction::I32Const(1),
|
||||
isa::Instruction::BrIfNez(isa::Target {
|
||||
dst_pc: 0,
|
||||
drop: 0,
|
||||
keep: 0,
|
||||
drop_keep: isa::DropKeep {
|
||||
drop: 0,
|
||||
keep: isa::Keep::None,
|
||||
},
|
||||
}),
|
||||
isa::Instruction::I32Const(2),
|
||||
isa::Instruction::Drop,
|
||||
isa::Instruction::Return {
|
||||
isa::Instruction::Return(isa::DropKeep {
|
||||
drop: 0,
|
||||
keep: 0,
|
||||
},
|
||||
keep: isa::Keep::None,
|
||||
}),
|
||||
]
|
||||
)
|
||||
}
|
||||
|
@ -746,10 +770,10 @@ fn loop_empty() {
|
|||
assert_eq!(
|
||||
code,
|
||||
vec![
|
||||
isa::Instruction::Return {
|
||||
isa::Instruction::Return(isa::DropKeep {
|
||||
drop: 0,
|
||||
keep: 0,
|
||||
},
|
||||
keep: isa::Keep::None,
|
||||
}),
|
||||
]
|
||||
)
|
||||
}
|
||||
|
@ -776,20 +800,24 @@ fn brtable() {
|
|||
vec![
|
||||
isa::Target {
|
||||
dst_pc: 0,
|
||||
keep: 0,
|
||||
drop: 0,
|
||||
drop_keep: isa::DropKeep {
|
||||
drop: 0,
|
||||
keep: isa::Keep::None,
|
||||
},
|
||||
},
|
||||
isa::Target {
|
||||
dst_pc: 2,
|
||||
keep: 0,
|
||||
drop: 0,
|
||||
drop_keep: isa::DropKeep {
|
||||
drop: 0,
|
||||
keep: isa::Keep::None,
|
||||
},
|
||||
},
|
||||
].into_boxed_slice()
|
||||
),
|
||||
isa::Instruction::Return {
|
||||
isa::Instruction::Return(isa::DropKeep {
|
||||
drop: 0,
|
||||
keep: 0,
|
||||
},
|
||||
keep: isa::Keep::None,
|
||||
}),
|
||||
]
|
||||
)
|
||||
}
|
||||
|
@ -820,22 +848,26 @@ fn brtable_returns_result() {
|
|||
vec![
|
||||
isa::Target {
|
||||
dst_pc: 3,
|
||||
keep: 1,
|
||||
drop: 0,
|
||||
drop_keep: isa::DropKeep {
|
||||
drop: 0,
|
||||
keep: isa::Keep::Single,
|
||||
},
|
||||
},
|
||||
isa::Target {
|
||||
dst_pc: 4,
|
||||
keep: 1,
|
||||
drop: 0,
|
||||
drop_keep: isa::DropKeep {
|
||||
keep: isa::Keep::Single,
|
||||
drop: 0,
|
||||
},
|
||||
},
|
||||
].into_boxed_slice()
|
||||
),
|
||||
isa::Instruction::Unreachable,
|
||||
isa::Instruction::Drop,
|
||||
isa::Instruction::Return {
|
||||
isa::Instruction::Return(isa::DropKeep {
|
||||
drop: 0,
|
||||
keep: 0,
|
||||
},
|
||||
keep: isa::Keep::None,
|
||||
}),
|
||||
]
|
||||
)
|
||||
}
|
||||
|
@ -862,24 +894,25 @@ fn wabt_example() {
|
|||
isa::Instruction::GetLocal(1),
|
||||
isa::Instruction::BrIfNez(isa::Target {
|
||||
dst_pc: 4,
|
||||
keep: 0,
|
||||
drop: 0,
|
||||
drop_keep: isa::DropKeep {
|
||||
drop: 0,
|
||||
keep: isa::Keep::None,
|
||||
},
|
||||
}),
|
||||
isa::Instruction::I32Const(1),
|
||||
isa::Instruction::Return {
|
||||
isa::Instruction::Return(isa::DropKeep {
|
||||
drop: 1, // 1 parameter
|
||||
keep: 1, // return value
|
||||
},
|
||||
keep: isa::Keep::Single,
|
||||
}),
|
||||
isa::Instruction::I32Const(2),
|
||||
isa::Instruction::Return {
|
||||
isa::Instruction::Return(isa::DropKeep {
|
||||
drop: 1,
|
||||
keep: 1,
|
||||
},
|
||||
isa::Instruction::Return {
|
||||
keep: isa::Keep::Single,
|
||||
}),
|
||||
isa::Instruction::Return(isa::DropKeep {
|
||||
drop: 1,
|
||||
keep: 1,
|
||||
},
|
||||
keep: isa::Keep::Single,
|
||||
}),
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -123,12 +123,9 @@ mod tests {
|
|||
Local::new(u32::max_value(), ValueType::I32),
|
||||
Local::new(1, ValueType::I64),
|
||||
];
|
||||
let locals = Locals::new(&[], &local_groups).unwrap();
|
||||
|
||||
assert_matches!(
|
||||
locals.type_of_local(u32::max_value() - 1),
|
||||
Ok(ValueType::I32)
|
||||
Locals::new(&[], &local_groups),
|
||||
Err(_)
|
||||
);
|
||||
assert_matches!(locals.type_of_local(u32::max_value()), Err(_));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue