Skip to content

Commit 641ad23

Browse files
committed
Implement custom descriptors proposal
1 parent 4c16e95 commit 641ad23

File tree

27 files changed

+981
-77
lines changed

27 files changed

+981
-77
lines changed

crates/wasm-encoder/src/core/code.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,6 +1316,20 @@ pub enum Instruction<'a> {
13161316
I64Sub128,
13171317
I64MulWideS,
13181318
I64MulWideU,
1319+
1320+
RefGetDesc(u32),
1321+
RefCastDescNonNull(HeapType),
1322+
RefCastDescNullable(HeapType),
1323+
BrOnCastDesc {
1324+
relative_depth: u32,
1325+
from_ref_type: RefType,
1326+
to_ref_type: RefType,
1327+
},
1328+
BrOnCastDescFail {
1329+
relative_depth: u32,
1330+
from_ref_type: RefType,
1331+
to_ref_type: RefType,
1332+
},
13191333
}
13201334

13211335
impl Encode for Instruction<'_> {
@@ -2144,6 +2158,19 @@ impl Encode for Instruction<'_> {
21442158
Instruction::I64Sub128 => sink.i64_sub128(),
21452159
Instruction::I64MulWideS => sink.i64_mul_wide_s(),
21462160
Instruction::I64MulWideU => sink.i64_mul_wide_u(),
2161+
Instruction::RefGetDesc(type_index) => sink.ref_get_desc(type_index),
2162+
Instruction::RefCastDescNonNull(hty) => sink.ref_cast_desc_non_null(hty),
2163+
Instruction::RefCastDescNullable(hty) => sink.ref_cast_desc_nullable(hty),
2164+
Instruction::BrOnCastDesc {
2165+
relative_depth,
2166+
from_ref_type,
2167+
to_ref_type,
2168+
} => sink.br_on_cast_desc(relative_depth, from_ref_type, to_ref_type),
2169+
Instruction::BrOnCastDescFail {
2170+
relative_depth,
2171+
from_ref_type,
2172+
to_ref_type,
2173+
} => sink.br_on_cast_desc_fail(relative_depth, from_ref_type, to_ref_type),
21472174
};
21482175
}
21492176
}

crates/wasm-encoder/src/core/instructions.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4609,4 +4609,58 @@ impl<'a> InstructionSink<'a> {
46094609
22u32.encode(self.sink);
46104610
self
46114611
}
4612+
4613+
/// Encode [`Instruction::RefGetDesc`].
4614+
pub fn ref_get_desc(&mut self, type_index: u32) -> &mut Self {
4615+
self.sink.push(0xFB);
4616+
34u32.encode(self.sink);
4617+
type_index.encode(self.sink);
4618+
self
4619+
}
4620+
/// Encode [`Instruction::RefCastDescNonNull`].
4621+
pub fn ref_cast_desc_non_null(&mut self, ht: HeapType) -> &mut Self {
4622+
self.sink.push(0xFB);
4623+
35u32.encode(self.sink);
4624+
ht.encode(self.sink);
4625+
self
4626+
}
4627+
/// Encode [`Instruction::RefCastDescNullable`].
4628+
pub fn ref_cast_desc_nullable(&mut self, ht: HeapType) -> &mut Self {
4629+
self.sink.push(0xFB);
4630+
36u32.encode(self.sink);
4631+
ht.encode(self.sink);
4632+
self
4633+
}
4634+
/// Encode [`Instruction::BrOnCastDesc`].
4635+
pub fn br_on_cast_desc(
4636+
&mut self,
4637+
relative_depth: u32,
4638+
from_ref_type: RefType,
4639+
to_ref_type: RefType,
4640+
) -> &mut Self {
4641+
self.sink.push(0xFB);
4642+
37u32.encode(self.sink);
4643+
let cast_flags = (from_ref_type.nullable as u8) | ((to_ref_type.nullable as u8) << 1);
4644+
self.sink.push(cast_flags);
4645+
relative_depth.encode(self.sink);
4646+
from_ref_type.heap_type.encode(self.sink);
4647+
to_ref_type.heap_type.encode(self.sink);
4648+
self
4649+
}
4650+
/// Encode [`Instruction::BrOnCastDescFail`].
4651+
pub fn br_on_cast_desc_fail(
4652+
&mut self,
4653+
relative_depth: u32,
4654+
from_ref_type: RefType,
4655+
to_ref_type: RefType,
4656+
) -> &mut Self {
4657+
self.sink.push(0xFB);
4658+
38u32.encode(self.sink);
4659+
let cast_flags = (from_ref_type.nullable as u8) | ((to_ref_type.nullable as u8) << 1);
4660+
self.sink.push(cast_flags);
4661+
relative_depth.encode(self.sink);
4662+
from_ref_type.heap_type.encode(self.sink);
4663+
to_ref_type.heap_type.encode(self.sink);
4664+
self
4665+
}
46124666
}

crates/wasm-encoder/src/core/types.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ pub struct CompositeType {
2222
/// Whether the type is shared. This is part of the
2323
/// shared-everything-threads proposal.
2424
pub shared: bool,
25+
/// Optional descriptor attribute.
26+
pub descriptor: Option<u32>,
27+
/// Optional describes attribute.
28+
pub describes: Option<u32>,
2529
}
2630

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

363367
/// A concrete Wasm-defined type at the given index.
364368
Concrete(u32),
369+
/// An exact type.
370+
Exact(u32),
365371
}
366372

367373
impl HeapType {
@@ -402,6 +408,11 @@ impl Encode for HeapType {
402408
// Note that this is encoded as a signed type rather than unsigned
403409
// as it's decoded as an s33
404410
HeapType::Concrete(i) => i64::from(*i).encode(sink),
411+
// Exact type is u32
412+
HeapType::Exact(i) => {
413+
sink.push(0x62);
414+
u32::from(*i).encode(sink)
415+
}
405416
}
406417
}
407418
}
@@ -669,6 +680,14 @@ impl<'a> CoreTypeEncoder<'a> {
669680
if ty.composite_type.shared {
670681
self.bytes.push(0x65);
671682
}
683+
if let Some(index) = ty.composite_type.describes {
684+
self.bytes.push(0x4c);
685+
index.encode(self.bytes);
686+
}
687+
if let Some(index) = ty.composite_type.descriptor {
688+
self.bytes.push(0x4d);
689+
index.encode(self.bytes);
690+
}
672691
match &ty.composite_type.inner {
673692
CompositeInnerType::Func(ty) => {
674693
self.encode_function(ty.params().iter().copied(), ty.results().iter().copied())

crates/wasm-encoder/src/reencode.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,6 +1170,14 @@ pub mod utils {
11701170
Ok(crate::CompositeType {
11711171
inner,
11721172
shared: composite_ty.shared,
1173+
descriptor: composite_ty
1174+
.descriptor_idx
1175+
.map(|i| reencoder.type_index_unpacked(i.unpack()))
1176+
.transpose()?,
1177+
describes: composite_ty
1178+
.describes_idx
1179+
.map(|i| reencoder.type_index_unpacked(i.unpack()))
1180+
.transpose()?,
11731181
})
11741182
}
11751183

@@ -1269,6 +1277,9 @@ pub mod utils {
12691277
wasmparser::HeapType::Concrete(i) => {
12701278
crate::HeapType::Concrete(reencoder.type_index_unpacked(i)?)
12711279
}
1280+
wasmparser::HeapType::Exact(i) => {
1281+
crate::HeapType::Exact(reencoder.type_index_unpacked(i)?)
1282+
}
12721283
wasmparser::HeapType::Abstract { shared, ty } => crate::HeapType::Abstract {
12731284
shared,
12741285
ty: reencoder.abstract_heap_type(ty)?,

crates/wasm-mutate/src/module.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ pub fn map_ref_type(ref_ty: wasmparser::RefType) -> Result<RefType> {
8787
nullable: ref_ty.is_nullable(),
8888
heap_type: match ref_ty.heap_type() {
8989
wasmparser::HeapType::Concrete(i) => HeapType::Concrete(i.as_module_index().unwrap()),
90+
wasmparser::HeapType::Exact(i) => HeapType::Exact(i.as_module_index().unwrap()),
9091
wasmparser::HeapType::Abstract { shared, ty } => {
9192
let ty = ty.into();
9293
HeapType::Abstract { shared, ty }

crates/wasm-smith/src/core.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,8 @@ impl From<&CompositeType> for wasm_encoder::CompositeType {
328328
wasm_encoder::CompositeType {
329329
shared: ty.shared,
330330
inner,
331+
descriptor: None,
332+
describes: None,
331333
}
332334
}
333335
}
@@ -568,6 +570,10 @@ impl Module {
568570
return false;
569571
}
570572
},
573+
574+
(HT::Exact(_), _) => todo!(),
575+
576+
(_, HT::Exact(_)) => todo!(),
571577
}
572578
}
573579

@@ -892,6 +898,7 @@ impl Module {
892898
}
893899
}
894900
}
901+
HT::Exact(_) => todo!(),
895902
}
896903
Ok(*u.choose(&choices)?)
897904
}
@@ -1036,6 +1043,7 @@ impl Module {
10361043
idx = supertype;
10371044
}
10381045
}
1046+
HT::Exact(_) => todo!(),
10391047
}
10401048
Ok(*u.choose(&choices)?)
10411049
}
@@ -2972,7 +2980,9 @@ impl Module {
29722980
fn is_shared_ref_type(&self, ty: RefType) -> bool {
29732981
match ty.heap_type {
29742982
HeapType::Abstract { shared, .. } => shared,
2975-
HeapType::Concrete(i) => self.types[i as usize].composite_type.shared,
2983+
HeapType::Concrete(i) | HeapType::Exact(i) => {
2984+
self.types[i as usize].composite_type.shared
2985+
}
29762986
}
29772987
}
29782988

crates/wasmparser/src/arity.rs

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,26 @@ fn visit_call_indirect(module: &dyn ModuleArity, ty: u32, _table: u32) -> Option
160160
}
161161

162162
fn visit_struct_new(module: &dyn ModuleArity, ty: u32) -> Option<(u32, u32)> {
163-
let (params, _results) = module.sub_type_arity(module.sub_type_at(ty)?)?;
164-
Some((params, 1))
163+
let ty = module.sub_type_at(ty)?;
164+
let descriptor = if let Some(_) = ty.composite_type.descriptor_idx {
165+
1
166+
} else {
167+
0
168+
};
169+
let (params, _results) = module.sub_type_arity(ty)?;
170+
Some((params + descriptor, 1))
171+
}
172+
173+
fn visit_struct_new_default(module: &dyn ModuleArity, ty: u32) -> Option<(u32, u32)> {
174+
let ty = module.sub_type_at(ty)?;
175+
Some((
176+
if let Some(_) = ty.composite_type.descriptor_idx {
177+
1
178+
} else {
179+
0
180+
},
181+
1,
182+
))
165183
}
166184

167185
fn visit_array_new_fixed(_module: &dyn ModuleArity, _ty: u32, size: u32) -> Option<(u32, u32)> {
@@ -289,3 +307,23 @@ fn visit_switch(module: &dyn ModuleArity, cont: u32, _tag: u32) -> Option<(u32,
289307
module.sub_type_arity(module.sub_type_of_ref_type(&last_param.as_reference_type()?)?)?;
290308
Some((params, cont_params))
291309
}
310+
311+
fn visit_br_on_cast_desc(
312+
module: &dyn ModuleArity,
313+
depth: u32,
314+
_from: RefType,
315+
_to: RefType,
316+
) -> Option<(u32, u32)> {
317+
let (params, _) = visit_br(module, depth)?;
318+
Some((params + 1, params))
319+
}
320+
321+
fn visit_br_on_cast_desc_fail(
322+
module: &dyn ModuleArity,
323+
depth: u32,
324+
_from: RefType,
325+
_to: RefType,
326+
) -> Option<(u32, u32)> {
327+
let (params, _) = visit_br(module, depth)?;
328+
Some((params + 1, params))
329+
}

crates/wasmparser/src/binary_reader.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,56 @@ impl<'a> BinaryReader<'a> {
13621362
0x1d => visitor.visit_i31_get_s(),
13631363
0x1e => visitor.visit_i31_get_u(),
13641364

1365+
0x22 => visitor.visit_ref_get_desc(self.read()?),
1366+
0x23 => visitor.visit_ref_cast_desc_non_null(self.read()?),
1367+
0x24 => visitor.visit_ref_cast_desc_nullable(self.read()?),
1368+
0x25 => {
1369+
let pos = self.original_position();
1370+
let cast_flags = self.read_u8()?;
1371+
let relative_depth = self.read_var_u32()?;
1372+
let (from_type_nullable, to_type_nullable) = match cast_flags {
1373+
0b00 => (false, false),
1374+
0b01 => (true, false),
1375+
0b10 => (false, true),
1376+
0b11 => (true, true),
1377+
_ => bail!(pos, "invalid cast flags: {cast_flags:08b}"),
1378+
};
1379+
let from_heap_type = self.read()?;
1380+
let from_ref_type =
1381+
RefType::new(from_type_nullable, from_heap_type).ok_or_else(|| {
1382+
format_err!(pos, "implementation error: type index too large")
1383+
})?;
1384+
let to_heap_type = self.read()?;
1385+
let to_ref_type =
1386+
RefType::new(to_type_nullable, to_heap_type).ok_or_else(|| {
1387+
format_err!(pos, "implementation error: type index too large")
1388+
})?;
1389+
visitor.visit_br_on_cast_desc(relative_depth, from_ref_type, to_ref_type)
1390+
}
1391+
0x26 => {
1392+
let pos = self.original_position();
1393+
let cast_flags = self.read_u8()?;
1394+
let relative_depth = self.read_var_u32()?;
1395+
let (from_type_nullable, to_type_nullable) = match cast_flags {
1396+
0 => (false, false),
1397+
1 => (true, false),
1398+
2 => (false, true),
1399+
3 => (true, true),
1400+
_ => bail!(pos, "invalid cast flags: {cast_flags:08b}"),
1401+
};
1402+
let from_heap_type = self.read()?;
1403+
let from_ref_type =
1404+
RefType::new(from_type_nullable, from_heap_type).ok_or_else(|| {
1405+
format_err!(pos, "implementation error: type index too large")
1406+
})?;
1407+
let to_heap_type = self.read()?;
1408+
let to_ref_type =
1409+
RefType::new(to_type_nullable, to_heap_type).ok_or_else(|| {
1410+
format_err!(pos, "implementation error: type index too large")
1411+
})?;
1412+
visitor.visit_br_on_cast_desc_fail(relative_depth, from_ref_type, to_ref_type)
1413+
}
1414+
13651415
_ => bail!(pos, "unknown 0xfb subopcode: 0x{code:x}"),
13661416
})
13671417
}

crates/wasmparser/src/features.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,9 @@ define_wasm_features! {
295295
///
296296
/// This is a subcomponent of the "lime1" feature.
297297
pub bulk_memory_opt: BULK_MEMORY_OPT(1 << 34) = true;
298+
299+
// Custom descriptors proposal.
300+
pub custom_descriptors: CUSTOM_DESCRIPTORS(1 << 35) = false;
298301
}
299302
}
300303

crates/wasmparser/src/lib.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ macro_rules! _for_each_operator_group {
259259
@gc {
260260
RefEq => visit_ref_eq (arity 2 -> 1)
261261
StructNew { struct_type_index: u32 } => visit_struct_new (arity custom)
262-
StructNewDefault { struct_type_index: u32 } => visit_struct_new_default (arity 0 -> 1)
262+
StructNewDefault { struct_type_index: u32 } => visit_struct_new_default (arity custom)
263263
StructGet { struct_type_index: u32, field_index: u32 } => visit_struct_get (arity 1 -> 1)
264264
StructGetS { struct_type_index: u32, field_index: u32 } => visit_struct_get_s (arity 1 -> 1)
265265
StructGetU { struct_type_index: u32, field_index: u32 } => visit_struct_get_u (arity 1 -> 1)
@@ -297,6 +297,20 @@ macro_rules! _for_each_operator_group {
297297
RefI31 => visit_ref_i31 (arity 1 -> 1)
298298
I31GetS => visit_i31_get_s (arity 1 -> 1)
299299
I31GetU => visit_i31_get_u (arity 1 -> 1)
300+
301+
RefGetDesc { type_index: u32 } => visit_ref_get_desc (arity 1 -> 1)
302+
RefCastDescNonNull { hty: $crate::HeapType } => visit_ref_cast_desc_non_null (arity 2 -> 1)
303+
RefCastDescNullable { hty: $crate::HeapType } => visit_ref_cast_desc_nullable (arity 2 -> 1)
304+
BrOnCastDesc {
305+
relative_depth: u32,
306+
from_ref_type: $crate::RefType,
307+
to_ref_type: $crate::RefType
308+
} => visit_br_on_cast_desc (arity custom)
309+
BrOnCastDescFail {
310+
relative_depth: u32,
311+
from_ref_type: $crate::RefType,
312+
to_ref_type: $crate::RefType
313+
} => visit_br_on_cast_desc_fail (arity custom)
300314
}
301315

302316
// 0xFC operators

0 commit comments

Comments
 (0)