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