Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge initial support for exception handling validation #46

Merged
merged 3 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 51 additions & 4 deletions crates/wasm-encoder/src/core/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,10 +310,6 @@ pub enum Instruction<'a> {
Loop(BlockType),
If(BlockType),
Else,
Try(BlockType),
Delegate(u32),
Catch(u32),
CatchAll,
End,
Br(u32),
BrIf(u32),
Expand All @@ -333,7 +329,15 @@ pub enum Instruction<'a> {
ty: u32,
table: u32,
},
TryTable(BlockType, Cow<'a, [Catch]>),
Throw(u32),
ThrowRef,

// Deprecated exception-handling instructions
Try(BlockType),
Delegate(u32),
Catch(u32),
CatchAll,
Rethrow(u32),

// Parametric instructions.
Expand Down Expand Up @@ -1031,6 +1035,9 @@ impl Encode for Instruction<'_> {
sink.push(0x09);
l.encode(sink);
}
Instruction::ThrowRef => {
sink.push(0x0A);
}
Instruction::End => sink.push(0x0B),
Instruction::Br(l) => {
sink.push(0x0C);
Expand Down Expand Up @@ -1097,6 +1104,12 @@ impl Encode for Instruction<'_> {
[ty].encode(sink);
}

Instruction::TryTable(ty, ref catches) => {
sink.push(0x1f);
ty.encode(sink);
catches.encode(sink);
}

// Variable instructions.
Instruction::LocalGet(l) => {
sink.push(0x20);
Expand Down Expand Up @@ -3160,6 +3173,40 @@ impl Encode for Instruction<'_> {
}
}

#[derive(Clone, Debug)]
#[allow(missing_docs)]
pub enum Catch {
One { tag: u32, label: u32 },
OneRef { tag: u32, label: u32 },
All { label: u32 },
AllRef { label: u32 },
}

impl Encode for Catch {
fn encode(&self, sink: &mut Vec<u8>) {
match self {
Catch::One { tag, label } => {
sink.push(0x00);
tag.encode(sink);
label.encode(sink);
}
Catch::OneRef { tag, label } => {
sink.push(0x01);
tag.encode(sink);
label.encode(sink);
}
Catch::All { label } => {
sink.push(0x02);
label.encode(sink);
}
Catch::AllRef { label } => {
sink.push(0x03);
label.encode(sink);
}
}
}
}

/// A constant expression.
///
/// Usable in contexts such as offsets or initializers.
Expand Down
8 changes: 8 additions & 0 deletions crates/wasm-encoder/src/core/names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,14 @@ impl NameSection {
names.encode(&mut self.bytes);
}

/// Appends a subsection for the names of all tags in this wasm module.
///
/// This section should come after the data name subsection (if present).
pub fn tag(&mut self, names: &NameMap) {
self.subsection_header(Subsection::Tag, names.size());
names.encode(&mut self.bytes);
}

/// Appends a subsection for the names of fields within types in this
/// wasm module.
///
Expand Down
13 changes: 13 additions & 0 deletions crates/wasm-encoder/src/core/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,8 @@ impl ValType {
pub const FUNCREF: ValType = ValType::Ref(RefType::FUNCREF);
/// Alias for the `externref` type in WebAssembly
pub const EXTERNREF: ValType = ValType::Ref(RefType::EXTERNREF);
/// Alias for the `exnref` type in WebAssembly
pub const EXNREF: ValType = ValType::Ref(RefType::EXNREF);
}

impl Encode for StorageType {
Expand Down Expand Up @@ -305,6 +307,12 @@ impl RefType {
nullable: true,
heap_type: HeapType::Extern,
};

/// Alias for the `exnref` type in WebAssembly
pub const EXNREF: RefType = RefType {
nullable: true,
heap_type: HeapType::Exn,
};
}

impl Encode for RefType {
Expand Down Expand Up @@ -394,6 +402,9 @@ pub enum HeapType {
/// The unboxed `i31` heap type.
I31,

/// The abstract` exception` heap type.
Exn,

/// A concrete Wasm-defined type at the given index.
Concrete(u32),
}
Expand All @@ -411,6 +422,7 @@ impl Encode for HeapType {
HeapType::Struct => sink.push(0x6B),
HeapType::Array => sink.push(0x6A),
HeapType::I31 => sink.push(0x6C),
HeapType::Exn => sink.push(0x69),
// Note that this is encoded as a signed type rather than unsigned
// as it's decoded as an s33
HeapType::Concrete(i) => i64::from(*i).encode(sink),
Expand All @@ -437,6 +449,7 @@ impl TryFrom<wasmparser::HeapType> for HeapType {
wasmparser::HeapType::I31 => HeapType::I31,
wasmparser::HeapType::Cont => todo!(),
wasmparser::HeapType::NoCont => todo!(), // TODO(dhil): Shouldn't be too hard.
wasmparser::HeapType::Exn => HeapType::Exn,
})
}
}
Expand Down
3 changes: 2 additions & 1 deletion crates/wasm-metadata/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,8 @@ impl<'a> ModuleNames<'a> {
wasmparser::Name::Memory(m) => section.memories(&name_map(&m)?),
wasmparser::Name::Global(m) => section.globals(&name_map(&m)?),
wasmparser::Name::Element(m) => section.elements(&name_map(&m)?),
wasmparser::Name::Data(m) => section.types(&name_map(&m)?),
wasmparser::Name::Data(m) => section.data(&name_map(&m)?),
wasmparser::Name::Tag(m) => section.tags(&name_map(&m)?),
wasmparser::Name::Unknown { .. } => {} // wasm-encoder doesn't support it
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/wasm-mutate/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ pub fn map_ref_type(ref_ty: wasmparser::RefType) -> Result<RefType> {
wasmparser::HeapType::Array => HeapType::Array,
wasmparser::HeapType::I31 => HeapType::I31,
wasmparser::HeapType::Cont | wasmparser::HeapType::NoCont => todo!(), // TODO(dhil): Some day.
wasmparser::HeapType::Exn => HeapType::Exn,
wasmparser::HeapType::Concrete(i) => HeapType::Concrete(i.as_module_index().unwrap()),
},
})
Expand Down
7 changes: 7 additions & 0 deletions crates/wasm-mutate/src/mutators/translate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ pub fn heapty(t: &mut dyn Translator, ty: &wasmparser::HeapType) -> Result<HeapT
wasmparser::HeapType::Array => Ok(HeapType::Array),
wasmparser::HeapType::I31 => Ok(HeapType::I31),
wasmparser::HeapType::Cont | wasmparser::HeapType::NoCont => todo!(), // TODO(dhil): Some day.
wasmparser::HeapType::Exn => Ok(HeapType::Exn),
wasmparser::HeapType::Concrete(i) => Ok(HeapType::Concrete(
t.remap(Item::Type, i.as_module_index().unwrap())?,
)),
Expand Down Expand Up @@ -383,6 +384,7 @@ pub fn op(t: &mut dyn Translator, op: &Operator<'_>) -> Result<Instruction<'stat
(map $arg:ident field_index) => (*$arg);
(map $arg:ident from_type_nullable) => (*$arg);
(map $arg:ident to_type_nullable) => (*$arg);
(map $arg:ident try_table) => ($arg);

// This case takes the arguments of a wasmparser instruction and creates
// a wasm-encoder instruction. There are a few special cases for where
Expand All @@ -398,6 +400,7 @@ pub fn op(t: &mut dyn Translator, op: &Operator<'_>) -> Result<Instruction<'stat
(build F32Const $arg:ident) => (I::F32Const(f32::from_bits($arg.bits())));
(build F64Const $arg:ident) => (I::F64Const(f64::from_bits($arg.bits())));
(build V128Const $arg:ident) => (I::V128Const($arg.i128()));
(build TryTable $table:ident) => (unimplemented_try_table());
(build $op:ident $arg:ident) => (I::$op($arg));
(build CallIndirect $ty:ident $table:ident $_:ident) => (I::CallIndirect {
ty: $ty,
Expand All @@ -421,6 +424,10 @@ pub fn op(t: &mut dyn Translator, op: &Operator<'_>) -> Result<Instruction<'stat
wasmparser::for_each_operator!(translate)
}

fn unimplemented_try_table() -> wasm_encoder::Instruction<'static> {
unimplemented!()
}

pub fn block_type(t: &mut dyn Translator, ty: &wasmparser::BlockType) -> Result<BlockType> {
match ty {
wasmparser::BlockType::Empty => Ok(BlockType::Empty),
Expand Down
Loading