Skip to content

Commit

Permalink
Remove unwind instruction for exception handling
Browse files Browse the repository at this point in the history
This instruction was removed from the spec:

  WebAssembly/exception-handling#156
  • Loading branch information
takikawa committed Jun 14, 2021
1 parent 1d95745 commit 785c670
Show file tree
Hide file tree
Showing 10 changed files with 13 additions and 63 deletions.
1 change: 0 additions & 1 deletion crates/wasmparser/src/binary_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1110,7 +1110,6 @@ impl<'a> BinaryReader<'a> {
0x09 => Operator::Rethrow {
relative_depth: self.read_var_u32()?,
},
0x0a => Operator::Unwind,
0x0b => Operator::End,
0x0c => Operator::Br {
relative_depth: self.read_var_u32()?,
Expand Down
22 changes: 1 addition & 21 deletions crates/wasmparser/src/operators_validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ enum FrameKind {
Try,
Catch,
CatchAll,
Unwind,
}

impl OperatorValidator {
Expand Down Expand Up @@ -288,12 +287,7 @@ impl OperatorValidator {
// Read the expected type and expected height of the operand stack the
// end of the frame.
let frame = self.control.last().unwrap();
// The end of an `unwind` should check against the empty block type.
let ty = if frame.kind == FrameKind::Unwind {
TypeOrFuncType::Type(Type::EmptyBlockType)
} else {
frame.block_type
};
let ty = frame.block_type;
let height = frame.height;

// Pop all the result types, in reverse order, from the operand stack.
Expand Down Expand Up @@ -637,20 +631,6 @@ impl OperatorValidator {
}
self.unreachable();
}
Operator::Unwind => {
self.check_exceptions_enabled()?;
// Switch from `try` to an `unwind` frame.
let frame = self.pop_ctrl(resources)?;
if frame.kind != FrameKind::Try {
bail_op_err!("unwind found outside of an `try` block");
}
self.control.push(Frame {
kind: FrameKind::Unwind,
block_type: frame.block_type,
height: self.operands.len(),
unreachable: false,
});
}
Operator::Delegate { relative_depth } => {
self.check_exceptions_enabled()?;
let frame = self.pop_ctrl(resources)?;
Expand Down
1 change: 0 additions & 1 deletion crates/wasmparser/src/primitives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,6 @@ pub enum Operator<'a> {
Rethrow {
relative_depth: u32,
},
Unwind,
End,
Br {
relative_depth: u32,
Expand Down
4 changes: 1 addition & 3 deletions crates/wasmprinter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -683,8 +683,7 @@ impl Printer {
// our nesting level.
Operator::Else
| Operator::Catch { .. }
| Operator::CatchAll
| Operator::Unwind => {
| Operator::CatchAll => {
self.nesting -= 1;
self.newline();
self.nesting += 1;
Expand Down Expand Up @@ -762,7 +761,6 @@ impl Printer {
label(*relative_depth)
)?;
}
Unwind => self.result.push_str("unwind"),
End => self.result.push_str("end"),
Br { relative_depth } => {
write!(
Expand Down
20 changes: 6 additions & 14 deletions crates/wast/src/ast/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ enum If<'a> {
enum Try<'a> {
/// Next thing to parse is the `do` block.
Do(Instruction<'a>),
/// Next thing to parse is `catch`/`catch_all`, `unwind`, or `delegate`.
CatchUnwindOrDelegate,
/// Next thing to parse is `catch`/`catch_all`, or `delegate`.
CatchOrDelegate,
/// Next thing to parse is a `catch` block or `catch_all`.
Catch,
/// Finished parsing like the `End` case, but does not push `end` opcode.
Expand Down Expand Up @@ -199,9 +199,9 @@ impl<'a> ExpressionParser<'a> {
Level::Try(Try::Do(_)) => {
return Err(parser.error("previous `try` had no `do`"));
}
Level::Try(Try::CatchUnwindOrDelegate) => {
Level::Try(Try::CatchOrDelegate) => {
return Err(parser.error(
"previous `try` had no `catch`, `catch_all`, `unwind`, or `delegate`",
"previous `try` had no `catch`, `catch_all`, or `delegate`",
));
}
Level::Try(Try::Delegate) => {}
Expand Down Expand Up @@ -335,7 +335,7 @@ impl<'a> ExpressionParser<'a> {
if parser.parse::<Option<kw::r#do>>()?.is_some() {
// The state is advanced here only if the parse succeeds in
// order to strictly require the keyword.
*i = Try::CatchUnwindOrDelegate;
*i = Try::CatchOrDelegate;
self.stack.push(Level::TryArm);
return Ok(true);
}
Expand All @@ -346,7 +346,7 @@ impl<'a> ExpressionParser<'a> {
}

// After a try's `do`, there are several possible kinds of handlers.
if let Try::CatchUnwindOrDelegate = i {
if let Try::CatchOrDelegate = i {
// `catch` may be followed by more `catch`s or `catch_all`.
if parser.parse::<Option<kw::catch>>()?.is_some() {
let evt = parser.parse::<ast::Index<'a>>()?;
Expand All @@ -362,13 +362,6 @@ impl<'a> ExpressionParser<'a> {
self.stack.push(Level::TryArm);
return Ok(true);
}
// `unwind` is similar to `catch_all`.
if parser.parse::<Option<kw::unwind>>()?.is_some() {
self.instrs.push(Instruction::Unwind);
*i = Try::End;
self.stack.push(Level::TryArm);
return Ok(true);
}
// `delegate` has an index, and also ends the block like `end`.
if parser.parse::<Option<kw::delegate>>()?.is_some() {
let depth = parser.parse::<ast::Index<'a>>()?;
Expand Down Expand Up @@ -1132,7 +1125,6 @@ instructions! {
Catch(ast::Index<'a>) : [0x07] : "catch",
Throw(ast::Index<'a>) : [0x08] : "throw",
Rethrow(ast::Index<'a>) : [0x09] : "rethrow",
Unwind : [0x0a] : "unwind",
Delegate(ast::Index<'a>) : [0x18] : "delegate",
CatchAll : [0x19] : "catch_all",
}
Expand Down
1 change: 0 additions & 1 deletion crates/wast/src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,6 @@ pub mod kw {
custom_keyword!(table);
custom_keyword!(then);
custom_keyword!(r#try = "try");
custom_keyword!(unwind);
custom_keyword!(v128);
}

Expand Down
15 changes: 0 additions & 15 deletions tests/local/exception-handling.wast
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,6 @@
drop
drop
)
(func $check-unwind (local i32)
try
i32.const 1
local.set 0
call $check-throw
unwind
i32.const 0
local.set 0
end
)
)

(assert_invalid
Expand All @@ -51,11 +41,6 @@
(func try catch_all catch 0 end))
"catch found outside of an `try` block")

(assert_invalid
(module
(func try unwind i32.const 1 end))
"type mismatch: values remaining on stack at end of block")

(assert_invalid
(module
(func block try catch_all rethrow 1 end end))
Expand Down
6 changes: 0 additions & 6 deletions tests/local/try.wast
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,6 @@
)
"unexpected items after `catch`")

(assert_malformed
(module quote
"(func (try (do) (unwind) (drop)))"
)
"too many payloads inside of `(try)`")

(assert_malformed
(module quote
"(func (try (do) (delegate 0) (drop)))"
Expand Down
1 change: 0 additions & 1 deletion tests/local/try.wat
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
(func (try (do) (catch $exn rethrow 0)))
(func (try (do) (catch_all rethrow 0)))
(func (try (do) (catch $exn) (catch_all rethrow 0)))
(func (try (do) (unwind nop)))
(func (try (do (try (do) (delegate 0))) (catch $exn)))
(func (result i32)
(try (result i32)
Expand Down
5 changes: 5 additions & 0 deletions tests/roundtrip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,11 @@ fn skip_test(test: &Path, contents: &[u8]) -> bool {
// Usage of `assert_invalid` which should be `assert_malformed`
"testsuite/proposals/memory64/memory.wast",
"testsuite/proposals/memory64/address.wast",
// Unwind is being removed from the exceptions proposal.
"dump/try-unwind.txt",
"parse/expr/try-unwind.txt",
"roundtrip/try-unwind.txt",
"roundtrip/fold-try-unwind.txt",
];
if broken.iter().any(|x| test.ends_with(x)) {
return true;
Expand Down

0 comments on commit 785c670

Please sign in to comment.