Skip to content

Commit

Permalink
Merge pull request #41 from kariya-mitsuru/fix-label-handling
Browse files Browse the repository at this point in the history
Fix label handling
  • Loading branch information
rhysd authored Jul 13, 2020
2 parents eb62526 + c2e422d commit af89176
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 23 deletions.
33 changes: 15 additions & 18 deletions wain-exec/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -472,46 +472,43 @@ impl<'m, 's, I: Importer> Execute<'m, 's, I> for ast::Instruction {
// Control instructions
// https://webassembly.github.io/spec/core/exec/instructions.html#exec-block
Block { ty, body } => {
let label = runtime.stack.push_label(*ty);
let label = runtime.stack.push_label();
match body.execute(runtime)? {
ExecState::Continue => {}
ExecState::Ret => return Ok(ExecState::Ret),
ExecState::Breaking(0) => {}
ExecState::Breaking(0) => runtime.stack.pop_label(&label, ty.is_some()),
ExecState::Breaking(level) => return Ok(ExecState::Breaking(level - 1)),
}
runtime.stack.pop_label(label);
}
// https://webassembly.github.io/spec/core/exec/instructions.html#exec-loop
Loop { ty, body } => loop {
// Note: Difference between block and loop is the position on breaking. When reaching
// to the end of instruction sequence, loop instruction ends execution of subsequence.
let label = runtime.stack.push_label(*ty);
match body.execute(runtime)? {
ExecState::Continue => {
runtime.stack.pop_label(label);
break;
Loop { body, .. } => {
let label = runtime.stack.push_label();
loop {
// Note: Difference between block and loop is the position on breaking. When reaching
// to the end of instruction sequence, loop instruction ends execution of subsequence.
match body.execute(runtime)? {
ExecState::Continue => break,
ExecState::Ret => return Ok(ExecState::Ret),
ExecState::Breaking(0) => runtime.stack.pop_label(&label, false),
ExecState::Breaking(level) => return Ok(ExecState::Breaking(level - 1)),
}
ExecState::Ret => return Ok(ExecState::Ret),
ExecState::Breaking(0) => continue,
ExecState::Breaking(level) => return Ok(ExecState::Breaking(level - 1)),
}
},
}
// https://webassembly.github.io/spec/core/exec/instructions.html#exec-if
If {
ty,
then_body,
else_body,
} => {
let cond: i32 = runtime.stack.pop();
let label = runtime.stack.push_label(*ty);
let label = runtime.stack.push_label();
let insns = if cond != 0 { then_body } else { else_body };
match insns.execute(runtime)? {
ExecState::Continue => {}
ExecState::Ret => return Ok(ExecState::Ret),
ExecState::Breaking(0) => {}
ExecState::Breaking(0) => runtime.stack.pop_label(&label, ty.is_some()),
ExecState::Breaking(level) => return Ok(ExecState::Breaking(level - 1)),
}
runtime.stack.pop_label(label);
}
// https://webassembly.github.io/spec/core/exec/instructions.html#exec-unreachable
Unreachable => return Err(Trap::new(TrapReason::ReachUnreachable, self.start)),
Expand Down
8 changes: 3 additions & 5 deletions wain-exec/src/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,17 +192,16 @@ impl Stack {
self.types.truncate(type_idx);
}

pub fn push_label(&self, ty: Option<ValType>) -> Label {
pub fn push_label(&self) -> Label {
Label {
addr: self.top_addr(),
type_idx: self.top_idx(),
has_result: ty.is_some(),
}
}

pub fn pop_label(&mut self, label: Label) {
pub fn pop_label(&mut self, label: &Label, has_result: bool) {
// Part of 'br' instruction: https://webassembly.github.io/spec/core/exec/instructions.html#exec-br
if label.has_result {
if has_result {
let v: Value = self.pop();
self.restore(label.addr, label.type_idx);
self.push(v);
Expand Down Expand Up @@ -261,7 +260,6 @@ impl CallFrame {
pub struct Label {
addr: usize,
type_idx: usize,
has_result: bool,
}

#[cfg(test)]
Expand Down

0 comments on commit af89176

Please sign in to comment.