diff --git a/src/instructions/exceptions.rs b/src/instructions/exceptions.rs new file mode 100644 index 0000000..0a5e3b3 --- /dev/null +++ b/src/instructions/exceptions.rs @@ -0,0 +1,49 @@ +use super::Instruction; +use crate::builtins::WasmbinCountable; +use crate::indices::{ExceptionId, LabelId}; +use crate::io::{encode_decode_as, Wasmbin}; +use crate::types::BlockType; +use crate::visit::Visit; + +#[derive(Wasmbin)] +#[repr(u8)] +enum CatchRepr { + Catch { + exception: ExceptionId, + target: LabelId, + } = 0x00, + CatchRef { + exception: ExceptionId, + target: LabelId, + } = 0x01, + CatchAll { + target: LabelId, + } = 0x02, + CatchAllRef { + target: LabelId, + } = 0x03, +} + +#[derive(WasmbinCountable, Debug, PartialEq, Eq, Hash, Clone, Visit)] +pub struct Catch { + /// Whether to store an exception reference on the stack. + pub catch_ref: bool, + /// Catch a specific exception or any exception if set to `None`. + pub exception_filter: Option, + /// Target label. + pub target: LabelId, +} + +encode_decode_as!(Catch, { + (Catch { catch_ref: false, exception_filter: Some(exception), target }) <=> (CatchRepr::Catch { exception, target }), + (Catch { catch_ref: true, exception_filter: Some(exception), target }) <=> (CatchRepr::CatchRef { exception, target }), + (Catch { catch_ref: false, exception_filter: None, target }) <=> (CatchRepr::CatchAll { target }), + (Catch { catch_ref: true, exception_filter: None, target }) <=> (CatchRepr::CatchAllRef { target }), +}); + +#[derive(Wasmbin, Debug, PartialEq, Eq, Hash, Clone, Visit)] +pub struct TryTable { + pub block_type: BlockType, + pub catches: Vec, + pub instructions: Vec, +} diff --git a/src/instructions/mod.rs b/src/instructions/mod.rs index 852986e..c501fa2 100644 --- a/src/instructions/mod.rs +++ b/src/instructions/mod.rs @@ -145,6 +145,10 @@ pub enum Instruction { LoopStart(BlockType) = OP_CODE_LOOP_START, IfStart(BlockType) = OP_CODE_IF_START, IfElse = 0x05, + #[cfg(feature = "exception-handling")] + Throw(crate::indices::ExceptionId) = 0x08, + #[cfg(feature = "exception-handling")] + ThrowRef = 0x0A, End = OP_CODE_END, Br(LabelId) = 0x0C, BrIf(LabelId) = 0x0D, @@ -162,6 +166,8 @@ pub enum Instruction { Drop = 0x1A, Select = 0x1B, SelectWithTypes(Vec) = 0x1C, + #[cfg(feature = "exception-handling")] + TryTable(TryTable) = 0x1F, LocalGet(LocalId) = 0x20, LocalSet(LocalId) = 0x21, LocalTee(LocalId) = 0x22, @@ -345,3 +351,8 @@ pub use simd::SIMD; pub mod threads; #[cfg(feature = "threads")] pub use threads::Atomic; + +#[cfg(feature = "exception-handling")] +pub mod exceptions; +#[cfg(feature = "exception-handling")] +pub use exceptions::{Catch, TryTable}; diff --git a/src/types.rs b/src/types.rs index 636b5fd..1aa46c3 100644 --- a/src/types.rs +++ b/src/types.rs @@ -182,6 +182,8 @@ encode_decode_as!(MemType, { pub enum RefType { Func = 0x70, Extern = 0x6F, + #[cfg(feature = "exception-handling")] + Exception = 0x69, } /// [Table type](https://webassembly.github.io/spec/core/binary/types.html#table-types).