Hide instruction storage details (#129)
* Hide Instructions implementation behind an iterator * Hide instruction encoding behind isa::Instructions::push() * Consistently use u32 for program counter storage * Refer to instructions by position rather than index
This commit is contained in:
parent
9170303aad
commit
7509477a61
80
src/isa.rs
80
src/isa.rs
|
@ -93,6 +93,22 @@ pub struct Target {
|
||||||
pub drop_keep: DropKeep,
|
pub drop_keep: DropKeep,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A relocation entry that specifies.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Reloc {
|
||||||
|
/// Patch the destination of the branch instruction (br, br_eqz, br_nez)
|
||||||
|
/// at the specified pc.
|
||||||
|
Br {
|
||||||
|
pc: u32,
|
||||||
|
},
|
||||||
|
/// Patch the specified destination index inside of br_table instruction at
|
||||||
|
/// the specified pc.
|
||||||
|
BrTable {
|
||||||
|
pc: u32,
|
||||||
|
idx: usize,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Instruction {
|
pub enum Instruction {
|
||||||
/// Push a local variable or an argument from the specified depth.
|
/// Push a local variable or an argument from the specified depth.
|
||||||
|
@ -299,5 +315,67 @@ pub enum Instruction {
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Instructions {
|
pub struct Instructions {
|
||||||
pub code: Vec<Instruction>,
|
vec: Vec<Instruction>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Instructions {
|
||||||
|
pub fn with_capacity(capacity: usize) -> Self {
|
||||||
|
Instructions {
|
||||||
|
vec: Vec::with_capacity(capacity),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn current_pc(&self) -> u32 {
|
||||||
|
self.vec.len() as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push(&mut self, instruction: Instruction) {
|
||||||
|
self.vec.push(instruction);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn patch_relocation(&mut self, reloc: Reloc, dst_pc: u32) {
|
||||||
|
match reloc {
|
||||||
|
Reloc::Br { pc } => match self.vec[pc as usize] {
|
||||||
|
Instruction::Br(ref mut target)
|
||||||
|
| Instruction::BrIfEqz(ref mut target)
|
||||||
|
| Instruction::BrIfNez(ref mut target) => target.dst_pc = dst_pc,
|
||||||
|
_ => panic!("branch relocation points to a non-branch instruction"),
|
||||||
|
},
|
||||||
|
Reloc::BrTable { pc, idx } => match self.vec[pc as usize] {
|
||||||
|
Instruction::BrTable(ref mut targets) => targets[idx].dst_pc = dst_pc,
|
||||||
|
_ => panic!("brtable relocation points to not brtable instruction"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iterate_from(&self, position: u32) -> InstructionIter {
|
||||||
|
InstructionIter{
|
||||||
|
instructions: &self.vec,
|
||||||
|
position,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct InstructionIter<'a> {
|
||||||
|
instructions: &'a [Instruction],
|
||||||
|
position: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> InstructionIter<'a> {
|
||||||
|
#[inline]
|
||||||
|
pub fn position(&self) -> u32 {
|
||||||
|
self.position
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for InstructionIter<'a> {
|
||||||
|
type Item = &'a Instruction;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
|
||||||
|
self.instructions.get(self.position as usize).map(|instruction| {
|
||||||
|
self.position += 1;
|
||||||
|
instruction
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -175,7 +175,7 @@ impl Interpreter {
|
||||||
let function_return =
|
let function_return =
|
||||||
self.do_run_function(
|
self.do_run_function(
|
||||||
&mut function_context,
|
&mut function_context,
|
||||||
&function_body.code.code,
|
&function_body.code,
|
||||||
).map_err(Trap::new)?;
|
).map_err(Trap::new)?;
|
||||||
|
|
||||||
match function_return {
|
match function_return {
|
||||||
|
@ -229,18 +229,24 @@ impl Interpreter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_run_function(&mut self, function_context: &mut FunctionContext, instructions: &[isa::Instruction]) -> Result<RunResult, TrapKind> {
|
fn do_run_function(&mut self, function_context: &mut FunctionContext, instructions: &isa::Instructions)
|
||||||
|
-> Result<RunResult, TrapKind>
|
||||||
|
{
|
||||||
|
let mut iter = instructions.iterate_from(function_context.position);
|
||||||
loop {
|
loop {
|
||||||
let instruction = &instructions[function_context.position];
|
let instruction = iter.next().expect("instruction");
|
||||||
|
|
||||||
match self.run_instruction(function_context, instruction)? {
|
match self.run_instruction(function_context, instruction)? {
|
||||||
InstructionOutcome::RunNextInstruction => function_context.position += 1,
|
InstructionOutcome::RunNextInstruction => {
|
||||||
|
function_context.position = iter.position();
|
||||||
|
},
|
||||||
InstructionOutcome::Branch(target) => {
|
InstructionOutcome::Branch(target) => {
|
||||||
function_context.position = target.dst_pc as usize;
|
function_context.position = target.dst_pc;
|
||||||
|
iter = instructions.iterate_from(function_context.position);
|
||||||
self.value_stack.drop_keep(target.drop_keep);
|
self.value_stack.drop_keep(target.drop_keep);
|
||||||
},
|
},
|
||||||
InstructionOutcome::ExecuteCall(func_ref) => {
|
InstructionOutcome::ExecuteCall(func_ref) => {
|
||||||
function_context.position += 1;
|
function_context.position = iter.position();
|
||||||
return Ok(RunResult::NestedCall(func_ref));
|
return Ok(RunResult::NestedCall(func_ref));
|
||||||
},
|
},
|
||||||
InstructionOutcome::Return(drop_keep) => {
|
InstructionOutcome::Return(drop_keep) => {
|
||||||
|
@ -1077,7 +1083,7 @@ struct FunctionContext {
|
||||||
pub module: ModuleRef,
|
pub module: ModuleRef,
|
||||||
pub memory: Option<MemoryRef>,
|
pub memory: Option<MemoryRef>,
|
||||||
/// Current instruction position.
|
/// Current instruction position.
|
||||||
pub position: usize,
|
pub position: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FunctionContext {
|
impl FunctionContext {
|
||||||
|
|
|
@ -1406,9 +1406,7 @@ impl<'a> FunctionValidationContext<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_code(self) -> isa::Instructions {
|
fn into_code(self) -> isa::Instructions {
|
||||||
isa::Instructions {
|
self.sink.into_inner()
|
||||||
code: self.sink.into_inner(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1628,22 +1626,6 @@ struct Target {
|
||||||
drop_keep: isa::DropKeep,
|
drop_keep: isa::DropKeep,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A relocation entry that specifies.
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum Reloc {
|
|
||||||
/// Patch the destination of the branch instruction (br, br_eqz, br_nez)
|
|
||||||
/// at the specified pc.
|
|
||||||
Br {
|
|
||||||
pc: u32,
|
|
||||||
},
|
|
||||||
/// Patch the specified destination index inside of br_table instruction at
|
|
||||||
/// the specified pc.
|
|
||||||
BrTable {
|
|
||||||
pc: u32,
|
|
||||||
idx: usize,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Identifier of a label.
|
/// Identifier of a label.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
struct LabelId(usize);
|
struct LabelId(usize);
|
||||||
|
@ -1655,23 +1637,23 @@ enum Label {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Sink {
|
struct Sink {
|
||||||
ins: Vec<isa::Instruction>,
|
ins: isa::Instructions,
|
||||||
labels: Vec<(Label, Vec<Reloc>)>,
|
labels: Vec<(Label, Vec<isa::Reloc>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sink {
|
impl Sink {
|
||||||
fn with_instruction_capacity(capacity: usize) -> Sink {
|
fn with_instruction_capacity(capacity: usize) -> Sink {
|
||||||
Sink {
|
Sink {
|
||||||
ins: Vec::with_capacity(capacity),
|
ins: isa::Instructions::with_capacity(capacity),
|
||||||
labels: Vec::new(),
|
labels: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cur_pc(&self) -> u32 {
|
fn cur_pc(&self) -> u32 {
|
||||||
self.ins.len() as u32
|
self.ins.current_pc()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pc_or_placeholder<F: FnOnce() -> Reloc>(&mut self, label: LabelId, reloc_creator: F) -> u32 {
|
fn pc_or_placeholder<F: FnOnce() -> isa::Reloc>(&mut self, label: LabelId, reloc_creator: F) -> u32 {
|
||||||
match self.labels[label.0] {
|
match self.labels[label.0] {
|
||||||
(Label::Resolved(dst_pc), _) => dst_pc,
|
(Label::Resolved(dst_pc), _) => dst_pc,
|
||||||
(Label::NotResolved, ref mut unresolved) => {
|
(Label::NotResolved, ref mut unresolved) => {
|
||||||
|
@ -1692,7 +1674,7 @@ impl Sink {
|
||||||
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, || isa::Reloc::Br { pc });
|
||||||
self.ins.push(isa::Instruction::Br(isa::Target {
|
self.ins.push(isa::Instruction::Br(isa::Target {
|
||||||
dst_pc,
|
dst_pc,
|
||||||
drop_keep: drop_keep.into(),
|
drop_keep: drop_keep.into(),
|
||||||
|
@ -1705,7 +1687,7 @@ impl Sink {
|
||||||
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, || isa::Reloc::Br { pc });
|
||||||
self.ins.push(isa::Instruction::BrIfEqz(isa::Target {
|
self.ins.push(isa::Instruction::BrIfEqz(isa::Target {
|
||||||
dst_pc,
|
dst_pc,
|
||||||
drop_keep: drop_keep.into(),
|
drop_keep: drop_keep.into(),
|
||||||
|
@ -1718,7 +1700,7 @@ impl Sink {
|
||||||
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, || isa::Reloc::Br { pc });
|
||||||
self.ins.push(isa::Instruction::BrIfNez(isa::Target {
|
self.ins.push(isa::Instruction::BrIfNez(isa::Target {
|
||||||
dst_pc,
|
dst_pc,
|
||||||
drop_keep: drop_keep.into(),
|
drop_keep: drop_keep.into(),
|
||||||
|
@ -1731,7 +1713,7 @@ 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 }) 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 });
|
let dst_pc = self.pc_or_placeholder(label, || isa::Reloc::BrTable { pc, idx });
|
||||||
isa_targets.push(
|
isa_targets.push(
|
||||||
isa::Target {
|
isa::Target {
|
||||||
dst_pc,
|
dst_pc,
|
||||||
|
@ -1768,26 +1750,15 @@ impl Sink {
|
||||||
// particular label.
|
// particular label.
|
||||||
let unresolved_rels = mem::replace(&mut self.labels[label.0].1, Vec::new());
|
let unresolved_rels = mem::replace(&mut self.labels[label.0].1, Vec::new());
|
||||||
for reloc in unresolved_rels {
|
for reloc in unresolved_rels {
|
||||||
match reloc {
|
self.ins.patch_relocation(reloc, dst_pc);
|
||||||
Reloc::Br { pc } => match self.ins[pc as usize] {
|
|
||||||
isa::Instruction::Br(ref mut target)
|
|
||||||
| isa::Instruction::BrIfEqz(ref mut target)
|
|
||||||
| isa::Instruction::BrIfNez(ref mut target) => target.dst_pc = dst_pc,
|
|
||||||
_ => panic!("branch relocation points to a non-branch instruction"),
|
|
||||||
},
|
|
||||||
Reloc::BrTable { pc, idx } => match self.ins[pc as usize] {
|
|
||||||
isa::Instruction::BrTable(ref mut targets) => targets[idx].dst_pc = dst_pc,
|
|
||||||
_ => panic!("brtable relocation points to not brtable instruction"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark this label as resolved.
|
// Mark this label as resolved.
|
||||||
self.labels[label.0] = (Label::Resolved(dst_pc), Vec::new());
|
self.labels[label.0] = (Label::Resolved(dst_pc), Vec::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consume this Sink and returns isa::Instruction.
|
/// Consume this Sink and returns isa::Instructions.
|
||||||
fn into_inner(self) -> Vec<isa::Instruction> {
|
fn into_inner(self) -> isa::Instructions {
|
||||||
// At this moment all labels should be resolved.
|
// At this moment all labels should be resolved.
|
||||||
assert!({
|
assert!({
|
||||||
self.labels.iter().all(|(state, unresolved)|
|
self.labels.iter().all(|(state, unresolved)|
|
||||||
|
|
|
@ -310,15 +310,29 @@ fn validate(wat: &str) -> ValidatedModule {
|
||||||
validated_module
|
validated_module
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile(wat: &str) -> Vec<isa::Instruction> {
|
fn compile(wat: &str) -> (Vec<isa::Instruction>, Vec<u32>) {
|
||||||
let validated_module = validate(wat);
|
let validated_module = validate(wat);
|
||||||
let code = &validated_module.code_map[0];
|
let code = &validated_module.code_map[0];
|
||||||
code.code.clone()
|
|
||||||
|
let mut instructions = Vec::new();
|
||||||
|
let mut pcs = Vec::new();
|
||||||
|
let mut iter = code.iterate_from(0);
|
||||||
|
loop {
|
||||||
|
let pc = iter.position();
|
||||||
|
if let Some(instruction) = iter.next() {
|
||||||
|
instructions.push(instruction.clone());
|
||||||
|
pcs.push(pc);
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(instructions, pcs)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn implicit_return_no_value() {
|
fn implicit_return_no_value() {
|
||||||
let code = compile(r#"
|
let (code, _) = compile(r#"
|
||||||
(module
|
(module
|
||||||
(func (export "call")
|
(func (export "call")
|
||||||
)
|
)
|
||||||
|
@ -337,7 +351,7 @@ fn implicit_return_no_value() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn implicit_return_with_value() {
|
fn implicit_return_with_value() {
|
||||||
let code = compile(r#"
|
let (code, _) = compile(r#"
|
||||||
(module
|
(module
|
||||||
(func (export "call") (result i32)
|
(func (export "call") (result i32)
|
||||||
i32.const 0
|
i32.const 0
|
||||||
|
@ -358,7 +372,7 @@ fn implicit_return_with_value() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn implicit_return_param() {
|
fn implicit_return_param() {
|
||||||
let code = compile(r#"
|
let (code, _) = compile(r#"
|
||||||
(module
|
(module
|
||||||
(func (export "call") (param i32)
|
(func (export "call") (param i32)
|
||||||
)
|
)
|
||||||
|
@ -377,7 +391,7 @@ fn implicit_return_param() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn get_local() {
|
fn get_local() {
|
||||||
let code = compile(r#"
|
let (code, _) = compile(r#"
|
||||||
(module
|
(module
|
||||||
(func (export "call") (param i32) (result i32)
|
(func (export "call") (param i32) (result i32)
|
||||||
get_local 0
|
get_local 0
|
||||||
|
@ -398,7 +412,7 @@ fn get_local() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn explicit_return() {
|
fn explicit_return() {
|
||||||
let code = compile(r#"
|
let (code, _) = compile(r#"
|
||||||
(module
|
(module
|
||||||
(func (export "call") (param i32) (result i32)
|
(func (export "call") (param i32) (result i32)
|
||||||
get_local 0
|
get_local 0
|
||||||
|
@ -424,7 +438,7 @@ fn explicit_return() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn add_params() {
|
fn add_params() {
|
||||||
let code = compile(r#"
|
let (code, _) = compile(r#"
|
||||||
(module
|
(module
|
||||||
(func (export "call") (param i32) (param i32) (result i32)
|
(func (export "call") (param i32) (param i32) (result i32)
|
||||||
get_local 0
|
get_local 0
|
||||||
|
@ -454,7 +468,7 @@ fn add_params() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn drop_locals() {
|
fn drop_locals() {
|
||||||
let code = compile(r#"
|
let (code, _) = compile(r#"
|
||||||
(module
|
(module
|
||||||
(func (export "call") (param i32)
|
(func (export "call") (param i32)
|
||||||
(local i32)
|
(local i32)
|
||||||
|
@ -478,7 +492,7 @@ fn drop_locals() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn if_without_else() {
|
fn if_without_else() {
|
||||||
let code = compile(r#"
|
let (code, pcs) = compile(r#"
|
||||||
(module
|
(module
|
||||||
(func (export "call") (param i32) (result i32)
|
(func (export "call") (param i32) (result i32)
|
||||||
i32.const 1
|
i32.const 1
|
||||||
|
@ -495,7 +509,7 @@ fn if_without_else() {
|
||||||
vec![
|
vec![
|
||||||
isa::Instruction::I32Const(1),
|
isa::Instruction::I32Const(1),
|
||||||
isa::Instruction::BrIfEqz(isa::Target {
|
isa::Instruction::BrIfEqz(isa::Target {
|
||||||
dst_pc: 4,
|
dst_pc: pcs[4],
|
||||||
drop_keep: isa::DropKeep {
|
drop_keep: isa::DropKeep {
|
||||||
drop: 0,
|
drop: 0,
|
||||||
keep: isa::Keep::None,
|
keep: isa::Keep::None,
|
||||||
|
@ -517,7 +531,7 @@ fn if_without_else() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn if_else() {
|
fn if_else() {
|
||||||
let code = compile(r#"
|
let (code, pcs) = compile(r#"
|
||||||
(module
|
(module
|
||||||
(func (export "call")
|
(func (export "call")
|
||||||
(local i32)
|
(local i32)
|
||||||
|
@ -537,7 +551,7 @@ fn if_else() {
|
||||||
vec![
|
vec![
|
||||||
isa::Instruction::I32Const(1),
|
isa::Instruction::I32Const(1),
|
||||||
isa::Instruction::BrIfEqz(isa::Target {
|
isa::Instruction::BrIfEqz(isa::Target {
|
||||||
dst_pc: 5,
|
dst_pc: pcs[5],
|
||||||
drop_keep: isa::DropKeep {
|
drop_keep: isa::DropKeep {
|
||||||
drop: 0,
|
drop: 0,
|
||||||
keep: isa::Keep::None,
|
keep: isa::Keep::None,
|
||||||
|
@ -546,7 +560,7 @@ fn if_else() {
|
||||||
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: pcs[7],
|
||||||
drop_keep: isa::DropKeep {
|
drop_keep: isa::DropKeep {
|
||||||
drop: 0,
|
drop: 0,
|
||||||
keep: isa::Keep::None,
|
keep: isa::Keep::None,
|
||||||
|
@ -564,7 +578,7 @@ fn if_else() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn if_else_returns_result() {
|
fn if_else_returns_result() {
|
||||||
let code = compile(r#"
|
let (code, pcs) = compile(r#"
|
||||||
(module
|
(module
|
||||||
(func (export "call")
|
(func (export "call")
|
||||||
i32.const 1
|
i32.const 1
|
||||||
|
@ -582,7 +596,7 @@ fn if_else_returns_result() {
|
||||||
vec![
|
vec![
|
||||||
isa::Instruction::I32Const(1),
|
isa::Instruction::I32Const(1),
|
||||||
isa::Instruction::BrIfEqz(isa::Target {
|
isa::Instruction::BrIfEqz(isa::Target {
|
||||||
dst_pc: 4,
|
dst_pc: pcs[4],
|
||||||
drop_keep: isa::DropKeep {
|
drop_keep: isa::DropKeep {
|
||||||
drop: 0,
|
drop: 0,
|
||||||
keep: isa::Keep::None,
|
keep: isa::Keep::None,
|
||||||
|
@ -590,7 +604,7 @@ fn if_else_returns_result() {
|
||||||
}),
|
}),
|
||||||
isa::Instruction::I32Const(2),
|
isa::Instruction::I32Const(2),
|
||||||
isa::Instruction::Br(isa::Target {
|
isa::Instruction::Br(isa::Target {
|
||||||
dst_pc: 5,
|
dst_pc: pcs[5],
|
||||||
drop_keep: isa::DropKeep {
|
drop_keep: isa::DropKeep {
|
||||||
drop: 0,
|
drop: 0,
|
||||||
keep: isa::Keep::None,
|
keep: isa::Keep::None,
|
||||||
|
@ -608,7 +622,7 @@ fn if_else_returns_result() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn if_else_branch_from_true_branch() {
|
fn if_else_branch_from_true_branch() {
|
||||||
let code = compile(r#"
|
let (code, pcs) = compile(r#"
|
||||||
(module
|
(module
|
||||||
(func (export "call")
|
(func (export "call")
|
||||||
i32.const 1
|
i32.const 1
|
||||||
|
@ -630,7 +644,7 @@ fn if_else_branch_from_true_branch() {
|
||||||
vec![
|
vec![
|
||||||
isa::Instruction::I32Const(1),
|
isa::Instruction::I32Const(1),
|
||||||
isa::Instruction::BrIfEqz(isa::Target {
|
isa::Instruction::BrIfEqz(isa::Target {
|
||||||
dst_pc: 8,
|
dst_pc: pcs[8],
|
||||||
drop_keep: isa::DropKeep {
|
drop_keep: isa::DropKeep {
|
||||||
drop: 0,
|
drop: 0,
|
||||||
keep: isa::Keep::None,
|
keep: isa::Keep::None,
|
||||||
|
@ -639,7 +653,7 @@ fn if_else_branch_from_true_branch() {
|
||||||
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: pcs[9],
|
||||||
drop_keep: isa::DropKeep {
|
drop_keep: isa::DropKeep {
|
||||||
drop: 0,
|
drop: 0,
|
||||||
keep: isa::Keep::Single,
|
keep: isa::Keep::Single,
|
||||||
|
@ -648,7 +662,7 @@ fn if_else_branch_from_true_branch() {
|
||||||
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: pcs[9],
|
||||||
drop_keep: isa::DropKeep {
|
drop_keep: isa::DropKeep {
|
||||||
drop: 0,
|
drop: 0,
|
||||||
keep: isa::Keep::None,
|
keep: isa::Keep::None,
|
||||||
|
@ -666,7 +680,7 @@ fn if_else_branch_from_true_branch() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn if_else_branch_from_false_branch() {
|
fn if_else_branch_from_false_branch() {
|
||||||
let code = compile(r#"
|
let (code, pcs) = compile(r#"
|
||||||
(module
|
(module
|
||||||
(func (export "call")
|
(func (export "call")
|
||||||
i32.const 1
|
i32.const 1
|
||||||
|
@ -688,7 +702,7 @@ fn if_else_branch_from_false_branch() {
|
||||||
vec![
|
vec![
|
||||||
isa::Instruction::I32Const(1),
|
isa::Instruction::I32Const(1),
|
||||||
isa::Instruction::BrIfEqz(isa::Target {
|
isa::Instruction::BrIfEqz(isa::Target {
|
||||||
dst_pc: 4,
|
dst_pc: pcs[4],
|
||||||
drop_keep: isa::DropKeep {
|
drop_keep: isa::DropKeep {
|
||||||
drop: 0,
|
drop: 0,
|
||||||
keep: isa::Keep::None,
|
keep: isa::Keep::None,
|
||||||
|
@ -696,7 +710,7 @@ fn if_else_branch_from_false_branch() {
|
||||||
}),
|
}),
|
||||||
isa::Instruction::I32Const(1),
|
isa::Instruction::I32Const(1),
|
||||||
isa::Instruction::Br(isa::Target {
|
isa::Instruction::Br(isa::Target {
|
||||||
dst_pc: 9,
|
dst_pc: pcs[9],
|
||||||
drop_keep: isa::DropKeep {
|
drop_keep: isa::DropKeep {
|
||||||
drop: 0,
|
drop: 0,
|
||||||
keep: isa::Keep::None,
|
keep: isa::Keep::None,
|
||||||
|
@ -705,7 +719,7 @@ fn if_else_branch_from_false_branch() {
|
||||||
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: pcs[9],
|
||||||
drop_keep: isa::DropKeep {
|
drop_keep: isa::DropKeep {
|
||||||
drop: 0,
|
drop: 0,
|
||||||
keep: isa::Keep::Single,
|
keep: isa::Keep::Single,
|
||||||
|
@ -724,7 +738,7 @@ fn if_else_branch_from_false_branch() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn loop_() {
|
fn loop_() {
|
||||||
let code = compile(r#"
|
let (code, _) = compile(r#"
|
||||||
(module
|
(module
|
||||||
(func (export "call")
|
(func (export "call")
|
||||||
loop (result i32)
|
loop (result i32)
|
||||||
|
@ -759,7 +773,7 @@ fn loop_() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn loop_empty() {
|
fn loop_empty() {
|
||||||
let code = compile(r#"
|
let (code, _) = compile(r#"
|
||||||
(module
|
(module
|
||||||
(func (export "call")
|
(func (export "call")
|
||||||
loop
|
loop
|
||||||
|
@ -780,7 +794,7 @@ fn loop_empty() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn brtable() {
|
fn brtable() {
|
||||||
let code = compile(r#"
|
let (code, pcs) = compile(r#"
|
||||||
(module
|
(module
|
||||||
(func (export "call")
|
(func (export "call")
|
||||||
block $1
|
block $1
|
||||||
|
@ -806,7 +820,7 @@ fn brtable() {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
isa::Target {
|
isa::Target {
|
||||||
dst_pc: 2,
|
dst_pc: pcs[2],
|
||||||
drop_keep: isa::DropKeep {
|
drop_keep: isa::DropKeep {
|
||||||
drop: 0,
|
drop: 0,
|
||||||
keep: isa::Keep::None,
|
keep: isa::Keep::None,
|
||||||
|
@ -824,7 +838,7 @@ fn brtable() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn brtable_returns_result() {
|
fn brtable_returns_result() {
|
||||||
let code = compile(r#"
|
let (code, pcs) = compile(r#"
|
||||||
(module
|
(module
|
||||||
(func (export "call")
|
(func (export "call")
|
||||||
block $1 (result i32)
|
block $1 (result i32)
|
||||||
|
@ -847,14 +861,14 @@ fn brtable_returns_result() {
|
||||||
isa::Instruction::BrTable(
|
isa::Instruction::BrTable(
|
||||||
vec![
|
vec![
|
||||||
isa::Target {
|
isa::Target {
|
||||||
dst_pc: 3,
|
dst_pc: pcs[3],
|
||||||
drop_keep: isa::DropKeep {
|
drop_keep: isa::DropKeep {
|
||||||
drop: 0,
|
drop: 0,
|
||||||
keep: isa::Keep::Single,
|
keep: isa::Keep::Single,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
isa::Target {
|
isa::Target {
|
||||||
dst_pc: 4,
|
dst_pc: pcs[4],
|
||||||
drop_keep: isa::DropKeep {
|
drop_keep: isa::DropKeep {
|
||||||
keep: isa::Keep::Single,
|
keep: isa::Keep::Single,
|
||||||
drop: 0,
|
drop: 0,
|
||||||
|
@ -874,7 +888,7 @@ fn brtable_returns_result() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn wabt_example() {
|
fn wabt_example() {
|
||||||
let code = compile(r#"
|
let (code, pcs) = compile(r#"
|
||||||
(module
|
(module
|
||||||
(func (export "call") (param i32) (result i32)
|
(func (export "call") (param i32) (result i32)
|
||||||
block $exit
|
block $exit
|
||||||
|
@ -893,7 +907,7 @@ fn wabt_example() {
|
||||||
vec![
|
vec![
|
||||||
isa::Instruction::GetLocal(1),
|
isa::Instruction::GetLocal(1),
|
||||||
isa::Instruction::BrIfNez(isa::Target {
|
isa::Instruction::BrIfNez(isa::Target {
|
||||||
dst_pc: 4,
|
dst_pc: pcs[4],
|
||||||
drop_keep: isa::DropKeep {
|
drop_keep: isa::DropKeep {
|
||||||
drop: 0,
|
drop: 0,
|
||||||
keep: isa::Keep::None,
|
keep: isa::Keep::None,
|
||||||
|
|
Loading…
Reference in New Issue