Skip to content
Draft
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
27 changes: 27 additions & 0 deletions crates/wasm-encoder/src/core/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1316,6 +1316,20 @@ pub enum Instruction<'a> {
I64Sub128,
I64MulWideS,
I64MulWideU,

RefGetDesc(u32),
RefCastDescNonNull(HeapType),
RefCastDescNullable(HeapType),
BrOnCastDesc {
relative_depth: u32,
from_ref_type: RefType,
to_ref_type: RefType,
},
BrOnCastDescFail {
relative_depth: u32,
from_ref_type: RefType,
to_ref_type: RefType,
},
}

impl Encode for Instruction<'_> {
Expand Down Expand Up @@ -2144,6 +2158,19 @@ impl Encode for Instruction<'_> {
Instruction::I64Sub128 => sink.i64_sub128(),
Instruction::I64MulWideS => sink.i64_mul_wide_s(),
Instruction::I64MulWideU => sink.i64_mul_wide_u(),
Instruction::RefGetDesc(type_index) => sink.ref_get_desc(type_index),
Instruction::RefCastDescNonNull(hty) => sink.ref_cast_desc_non_null(hty),
Instruction::RefCastDescNullable(hty) => sink.ref_cast_desc_nullable(hty),
Instruction::BrOnCastDesc {
relative_depth,
from_ref_type,
to_ref_type,
} => sink.br_on_cast_desc(relative_depth, from_ref_type, to_ref_type),
Instruction::BrOnCastDescFail {
relative_depth,
from_ref_type,
to_ref_type,
} => sink.br_on_cast_desc_fail(relative_depth, from_ref_type, to_ref_type),
};
}
}
Expand Down
54 changes: 54 additions & 0 deletions crates/wasm-encoder/src/core/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4609,4 +4609,58 @@ impl<'a> InstructionSink<'a> {
22u32.encode(self.sink);
self
}

/// Encode [`Instruction::RefGetDesc`].
pub fn ref_get_desc(&mut self, type_index: u32) -> &mut Self {
self.sink.push(0xFB);
34u32.encode(self.sink);
type_index.encode(self.sink);
self
}
/// Encode [`Instruction::RefCastDescNonNull`].
Comment on lines +4619 to +4620
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Super nitty pick: all other methods have a newline between each other, we should match that with these new ones.

pub fn ref_cast_desc_non_null(&mut self, ht: HeapType) -> &mut Self {
self.sink.push(0xFB);
35u32.encode(self.sink);
ht.encode(self.sink);
self
}
/// Encode [`Instruction::RefCastDescNullable`].
pub fn ref_cast_desc_nullable(&mut self, ht: HeapType) -> &mut Self {
self.sink.push(0xFB);
36u32.encode(self.sink);
ht.encode(self.sink);
self
}
/// Encode [`Instruction::BrOnCastDesc`].
pub fn br_on_cast_desc(
&mut self,
relative_depth: u32,
from_ref_type: RefType,
to_ref_type: RefType,
) -> &mut Self {
self.sink.push(0xFB);
37u32.encode(self.sink);
let cast_flags = (from_ref_type.nullable as u8) | ((to_ref_type.nullable as u8) << 1);
self.sink.push(cast_flags);
relative_depth.encode(self.sink);
from_ref_type.heap_type.encode(self.sink);
to_ref_type.heap_type.encode(self.sink);
self
}
/// Encode [`Instruction::BrOnCastDescFail`].
pub fn br_on_cast_desc_fail(
&mut self,
relative_depth: u32,
from_ref_type: RefType,
to_ref_type: RefType,
) -> &mut Self {
self.sink.push(0xFB);
38u32.encode(self.sink);
let cast_flags = (from_ref_type.nullable as u8) | ((to_ref_type.nullable as u8) << 1);
self.sink.push(cast_flags);
relative_depth.encode(self.sink);
from_ref_type.heap_type.encode(self.sink);
to_ref_type.heap_type.encode(self.sink);
self
}
}
19 changes: 19 additions & 0 deletions crates/wasm-encoder/src/core/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ pub struct CompositeType {
/// Whether the type is shared. This is part of the
/// shared-everything-threads proposal.
pub shared: bool,
/// Optional descriptor attribute.
pub descriptor: Option<u32>,
/// Optional describes attribute.
pub describes: Option<u32>,
}

/// A [`CompositeType`] can contain one of these types.
Expand Down Expand Up @@ -362,6 +366,8 @@ pub enum HeapType {

/// A concrete Wasm-defined type at the given index.
Concrete(u32),
/// An exact type.
Exact(u32),
}

impl HeapType {
Expand Down Expand Up @@ -402,6 +408,11 @@ impl Encode for HeapType {
// 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),
// Exact type is u32
HeapType::Exact(i) => {
sink.push(0x62);
u32::from(*i).encode(sink)
}
}
}
}
Expand Down Expand Up @@ -669,6 +680,14 @@ impl<'a> CoreTypeEncoder<'a> {
if ty.composite_type.shared {
self.bytes.push(0x65);
}
if let Some(index) = ty.composite_type.describes {
self.bytes.push(0x4c);
index.encode(self.bytes);
}
if let Some(index) = ty.composite_type.descriptor {
self.bytes.push(0x4d);
index.encode(self.bytes);
}
match &ty.composite_type.inner {
CompositeInnerType::Func(ty) => {
self.encode_function(ty.params().iter().copied(), ty.results().iter().copied())
Expand Down
11 changes: 11 additions & 0 deletions crates/wasm-encoder/src/reencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1170,6 +1170,14 @@ pub mod utils {
Ok(crate::CompositeType {
inner,
shared: composite_ty.shared,
descriptor: composite_ty
.descriptor_idx
.map(|i| reencoder.type_index_unpacked(i.unpack()))
.transpose()?,
describes: composite_ty
.describes_idx
.map(|i| reencoder.type_index_unpacked(i.unpack()))
.transpose()?,
})
}

Expand Down Expand Up @@ -1269,6 +1277,9 @@ pub mod utils {
wasmparser::HeapType::Concrete(i) => {
crate::HeapType::Concrete(reencoder.type_index_unpacked(i)?)
}
wasmparser::HeapType::Exact(i) => {
crate::HeapType::Exact(reencoder.type_index_unpacked(i)?)
}
wasmparser::HeapType::Abstract { shared, ty } => crate::HeapType::Abstract {
shared,
ty: reencoder.abstract_heap_type(ty)?,
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 @@ -87,6 +87,7 @@ pub fn map_ref_type(ref_ty: wasmparser::RefType) -> Result<RefType> {
nullable: ref_ty.is_nullable(),
heap_type: match ref_ty.heap_type() {
wasmparser::HeapType::Concrete(i) => HeapType::Concrete(i.as_module_index().unwrap()),
wasmparser::HeapType::Exact(i) => HeapType::Exact(i.as_module_index().unwrap()),
wasmparser::HeapType::Abstract { shared, ty } => {
let ty = ty.into();
HeapType::Abstract { shared, ty }
Expand Down
12 changes: 11 additions & 1 deletion crates/wasm-smith/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,8 @@ impl From<&CompositeType> for wasm_encoder::CompositeType {
wasm_encoder::CompositeType {
shared: ty.shared,
inner,
descriptor: None,
describes: None,
}
}
}
Expand Down Expand Up @@ -568,6 +570,10 @@ impl Module {
return false;
}
},

(HT::Exact(_), _) => todo!(),

(_, HT::Exact(_)) => todo!(),
}
}

Expand Down Expand Up @@ -892,6 +898,7 @@ impl Module {
}
}
}
HT::Exact(_) => todo!(),
}
Ok(*u.choose(&choices)?)
}
Expand Down Expand Up @@ -1036,6 +1043,7 @@ impl Module {
idx = supertype;
}
}
HT::Exact(_) => todo!(),
}
Ok(*u.choose(&choices)?)
}
Expand Down Expand Up @@ -2972,7 +2980,9 @@ impl Module {
fn is_shared_ref_type(&self, ty: RefType) -> bool {
match ty.heap_type {
HeapType::Abstract { shared, .. } => shared,
HeapType::Concrete(i) => self.types[i as usize].composite_type.shared,
HeapType::Concrete(i) | HeapType::Exact(i) => {
self.types[i as usize].composite_type.shared
}
}
}

Expand Down
42 changes: 40 additions & 2 deletions crates/wasmparser/src/arity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,26 @@ fn visit_call_indirect(module: &dyn ModuleArity, ty: u32, _table: u32) -> Option
}

fn visit_struct_new(module: &dyn ModuleArity, ty: u32) -> Option<(u32, u32)> {
let (params, _results) = module.sub_type_arity(module.sub_type_at(ty)?)?;
Some((params, 1))
let ty = module.sub_type_at(ty)?;
let descriptor = if let Some(_) = ty.composite_type.descriptor_idx {
1
} else {
0
};
let (params, _results) = module.sub_type_arity(ty)?;
Some((params + descriptor, 1))
}

fn visit_struct_new_default(module: &dyn ModuleArity, ty: u32) -> Option<(u32, u32)> {
let ty = module.sub_type_at(ty)?;
Some((
if let Some(_) = ty.composite_type.descriptor_idx {
1
} else {
0
},
1,
))
}

fn visit_array_new_fixed(_module: &dyn ModuleArity, _ty: u32, size: u32) -> Option<(u32, u32)> {
Expand Down Expand Up @@ -289,3 +307,23 @@ fn visit_switch(module: &dyn ModuleArity, cont: u32, _tag: u32) -> Option<(u32,
module.sub_type_arity(module.sub_type_of_ref_type(&last_param.as_reference_type()?)?)?;
Some((params, cont_params))
}

fn visit_br_on_cast_desc(
module: &dyn ModuleArity,
depth: u32,
_from: RefType,
_to: RefType,
) -> Option<(u32, u32)> {
let (params, _) = visit_br(module, depth)?;
Some((params + 1, params))
}

fn visit_br_on_cast_desc_fail(
module: &dyn ModuleArity,
depth: u32,
_from: RefType,
_to: RefType,
) -> Option<(u32, u32)> {
let (params, _) = visit_br(module, depth)?;
Some((params + 1, params))
}
50 changes: 50 additions & 0 deletions crates/wasmparser/src/binary_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1362,6 +1362,56 @@ impl<'a> BinaryReader<'a> {
0x1d => visitor.visit_i31_get_s(),
0x1e => visitor.visit_i31_get_u(),

0x22 => visitor.visit_ref_get_desc(self.read()?),
0x23 => visitor.visit_ref_cast_desc_non_null(self.read()?),
0x24 => visitor.visit_ref_cast_desc_nullable(self.read()?),
0x25 => {
let pos = self.original_position();
let cast_flags = self.read_u8()?;
let relative_depth = self.read_var_u32()?;
let (from_type_nullable, to_type_nullable) = match cast_flags {
0b00 => (false, false),
0b01 => (true, false),
0b10 => (false, true),
0b11 => (true, true),
_ => bail!(pos, "invalid cast flags: {cast_flags:08b}"),
};
let from_heap_type = self.read()?;
let from_ref_type =
RefType::new(from_type_nullable, from_heap_type).ok_or_else(|| {
format_err!(pos, "implementation error: type index too large")
})?;
let to_heap_type = self.read()?;
let to_ref_type =
RefType::new(to_type_nullable, to_heap_type).ok_or_else(|| {
format_err!(pos, "implementation error: type index too large")
})?;
visitor.visit_br_on_cast_desc(relative_depth, from_ref_type, to_ref_type)
}
0x26 => {
let pos = self.original_position();
let cast_flags = self.read_u8()?;
let relative_depth = self.read_var_u32()?;
let (from_type_nullable, to_type_nullable) = match cast_flags {
0 => (false, false),
1 => (true, false),
2 => (false, true),
3 => (true, true),
_ => bail!(pos, "invalid cast flags: {cast_flags:08b}"),
};
let from_heap_type = self.read()?;
let from_ref_type =
RefType::new(from_type_nullable, from_heap_type).ok_or_else(|| {
format_err!(pos, "implementation error: type index too large")
})?;
let to_heap_type = self.read()?;
let to_ref_type =
RefType::new(to_type_nullable, to_heap_type).ok_or_else(|| {
format_err!(pos, "implementation error: type index too large")
})?;
visitor.visit_br_on_cast_desc_fail(relative_depth, from_ref_type, to_ref_type)
}

_ => bail!(pos, "unknown 0xfb subopcode: 0x{code:x}"),
})
}
Expand Down
3 changes: 3 additions & 0 deletions crates/wasmparser/src/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,9 @@ define_wasm_features! {
///
/// This is a subcomponent of the "lime1" feature.
pub bulk_memory_opt: BULK_MEMORY_OPT(1 << 34) = true;

// Custom descriptors proposal.
pub custom_descriptors: CUSTOM_DESCRIPTORS(1 << 35) = false;
}
}

Expand Down
16 changes: 15 additions & 1 deletion crates/wasmparser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ macro_rules! _for_each_operator_group {
@gc {
RefEq => visit_ref_eq (arity 2 -> 1)
StructNew { struct_type_index: u32 } => visit_struct_new (arity custom)
StructNewDefault { struct_type_index: u32 } => visit_struct_new_default (arity 0 -> 1)
StructNewDefault { struct_type_index: u32 } => visit_struct_new_default (arity custom)
StructGet { struct_type_index: u32, field_index: u32 } => visit_struct_get (arity 1 -> 1)
StructGetS { struct_type_index: u32, field_index: u32 } => visit_struct_get_s (arity 1 -> 1)
StructGetU { struct_type_index: u32, field_index: u32 } => visit_struct_get_u (arity 1 -> 1)
Expand Down Expand Up @@ -297,6 +297,20 @@ macro_rules! _for_each_operator_group {
RefI31 => visit_ref_i31 (arity 1 -> 1)
I31GetS => visit_i31_get_s (arity 1 -> 1)
I31GetU => visit_i31_get_u (arity 1 -> 1)

RefGetDesc { type_index: u32 } => visit_ref_get_desc (arity 1 -> 1)
RefCastDescNonNull { hty: $crate::HeapType } => visit_ref_cast_desc_non_null (arity 2 -> 1)
RefCastDescNullable { hty: $crate::HeapType } => visit_ref_cast_desc_nullable (arity 2 -> 1)
BrOnCastDesc {
relative_depth: u32,
from_ref_type: $crate::RefType,
to_ref_type: $crate::RefType
} => visit_br_on_cast_desc (arity custom)
BrOnCastDescFail {
relative_depth: u32,
from_ref_type: $crate::RefType,
to_ref_type: $crate::RefType
} => visit_br_on_cast_desc_fail (arity custom)
}

// 0xFC operators
Expand Down
Loading
Loading