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
12 changes: 12 additions & 0 deletions crates/wasm-encoder/src/component/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,12 @@ impl ComponentBuilder {
self.core_funcs.add(Some("stream.write"))
}

/// Declares a new `stream.forward` intrinsic.
pub fn stream_forward(&mut self, ty: u32) -> u32 {
self.canonical_functions().stream_forward(ty);
self.core_funcs.add(Some("stream.forward"))
}

/// Declares a new `stream.cancel-read` intrinsic.
pub fn stream_cancel_read(&mut self, ty: u32, async_: bool) -> u32 {
self.canonical_functions().stream_cancel_read(ty, async_);
Expand Down Expand Up @@ -606,6 +612,12 @@ impl ComponentBuilder {
self.core_funcs.add(Some("future.write"))
}

/// Declares a new `future.forward` intrinsic.
pub fn future_forward(&mut self, ty: u32) -> u32 {
self.canonical_functions().future_forward(ty);
self.core_funcs.add(Some("future.forward"))
}

/// Declares a new `future.cancel-read` intrinsic.
pub fn future_cancel_read(&mut self, ty: u32, async_: bool) -> u32 {
self.canonical_functions().future_cancel_read(ty, async_);
Expand Down
20 changes: 20 additions & 0 deletions crates/wasm-encoder/src/component/canonicals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,16 @@ impl CanonicalFunctionSection {
self
}

/// Defines a function to forward all remaining elements from the readable
/// end of one `stream` to the writable end of another `stream` of the
/// specified type, transferring both ends out of the calling instance.
pub fn stream_forward(&mut self, ty: u32) -> &mut Self {
self.bytes.push(0x2e);
ty.encode(&mut self.bytes);
self.num_added += 1;
self
}

/// Defines a function to cancel an in-progress read from a `stream` of the
/// specified type.
pub fn stream_cancel_read(&mut self, ty: u32, async_: bool) -> &mut Self {
Expand Down Expand Up @@ -371,6 +381,16 @@ impl CanonicalFunctionSection {
self
}

/// Defines a function to forward the value of the readable end of one
/// `future` to the writable end of another `future` of the specified
/// type, transferring both ends out of the calling instance.
pub fn future_forward(&mut self, ty: u32) -> &mut Self {
self.bytes.push(0x2f);
ty.encode(&mut self.bytes);
self.num_added += 1;
self
}

/// Defines a function to cancel an in-progress read from a `future` of the
/// specified type.
pub fn future_cancel_read(&mut self, ty: u32, async_: bool) -> &mut Self {
Expand Down
6 changes: 6 additions & 0 deletions crates/wasm-encoder/src/reencode/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1030,6 +1030,9 @@ pub mod component_utils {
.collect::<Result<Vec<_>, _>>()?;
section.stream_write(reencoder.component_type_index(ty), options);
}
wasmparser::CanonicalFunction::StreamForward { ty } => {
section.stream_forward(reencoder.component_type_index(ty));
}
wasmparser::CanonicalFunction::StreamCancelRead { ty, async_ } => {
section.stream_cancel_read(reencoder.component_type_index(ty), async_);
}
Expand Down Expand Up @@ -1059,6 +1062,9 @@ pub mod component_utils {
.collect::<Result<Vec<_>, _>>()?;
section.future_write(reencoder.component_type_index(ty), options);
}
wasmparser::CanonicalFunction::FutureForward { ty } => {
section.future_forward(reencoder.component_type_index(ty));
}
wasmparser::CanonicalFunction::FutureCancelRead { ty, async_ } => {
section.future_cancel_read(reencoder.component_type_index(ty), async_);
}
Expand Down
24 changes: 24 additions & 0 deletions crates/wasmparser/src/readers/component/canonicals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,17 @@ pub enum CanonicalFunction {
/// memory.
options: Box<[CanonicalOption]>,
},
/// A function to forward all remaining elements from the readable end of
/// one `stream` to the writable end of another `stream` of the same
/// specified type, transferring both ends out of the calling instance.
///
/// 🚧 This is an experimental builtin sketched in
/// <https://github.com/WebAssembly/component-model/issues/658> and not yet
/// part of the Component Model specification.
StreamForward {
/// The `stream` type to expect.
ty: u32,
},
/// A function to cancel an in-progress read from a `stream` of the
/// specified type.
StreamCancelRead {
Expand Down Expand Up @@ -207,6 +218,17 @@ pub enum CanonicalFunction {
/// memory.
options: Box<[CanonicalOption]>,
},
/// A function to forward the value of the readable end of one `future`
/// to the writable end of another `future` of the same specified type,
/// transferring both ends out of the calling instance.
///
/// 🚧 This is an experimental builtin sketched in
/// <https://github.com/WebAssembly/component-model/issues/658> and not yet
/// part of the Component Model specification.
FutureForward {
/// The `future` type to expect.
ty: u32,
},
/// A function to cancel an in-progress read from a `future` of the
/// specified type.
FutureCancelRead {
Expand Down Expand Up @@ -371,6 +393,7 @@ impl<'a> FromReader<'a> for CanonicalFunction {
ty: reader.read()?,
options: read_opts(reader)?,
},
0x2e => CanonicalFunction::StreamForward { ty: reader.read()? },
0x11 => CanonicalFunction::StreamCancelRead {
ty: reader.read()?,
async_: reader.read()?,
Expand All @@ -390,6 +413,7 @@ impl<'a> FromReader<'a> for CanonicalFunction {
ty: reader.read()?,
options: read_opts(reader)?,
},
0x2f => CanonicalFunction::FutureForward { ty: reader.read()? },
0x18 => CanonicalFunction::FutureCancelRead {
ty: reader.read()?,
async_: reader.read()?,
Expand Down
46 changes: 46 additions & 0 deletions crates/wasmparser/src/validator/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1242,6 +1242,7 @@ impl ComponentState {
CanonicalFunction::StreamWrite { ty, options } => {
self.stream_write(ty, &options, types, offset)
}
CanonicalFunction::StreamForward { ty } => self.stream_forward(ty, types, offset),
CanonicalFunction::StreamCancelRead { ty, async_ } => {
self.stream_cancel_read(ty, async_, types, offset)
}
Expand All @@ -1261,6 +1262,7 @@ impl ComponentState {
CanonicalFunction::FutureWrite { ty, options } => {
self.future_write(ty, &options, types, offset)
}
CanonicalFunction::FutureForward { ty } => self.future_forward(ty, types, offset),
CanonicalFunction::FutureCancelRead { ty, async_ } => {
self.future_cancel_read(ty, async_, types, offset)
}
Expand Down Expand Up @@ -1728,6 +1730,28 @@ impl ComponentState {
Ok(())
}

fn stream_forward(&mut self, ty: u32, types: &mut TypeAlloc, offset: u64) -> Result<()> {
require_feature::cm_async(
self.features,
"`stream.forward` requires the component model async feature",
offset,
)?;
require_feature::cm_more_async_builtins(
self.features,
"`stream.forward` requires the component model more async builtins feature",
offset,
)?;

let ty = self.defined_type_at(ty, offset)?;
let ComponentDefinedType::Stream { .. } = &types[ty] else {
bail!(offset, "`stream.forward` requires a stream type")
};

self.core_funcs
.push(types.intern_func_type(FuncType::new([ValType::I32; 2], []), offset));
Ok(())
}

fn stream_cancel_read(
&mut self,
ty: u32,
Expand Down Expand Up @@ -1917,6 +1941,28 @@ impl ComponentState {
Ok(())
}

fn future_forward(&mut self, ty: u32, types: &mut TypeAlloc, offset: u64) -> Result<()> {
require_feature::cm_async(
self.features,
"`future.forward` requires the component model async feature",
offset,
)?;
require_feature::cm_more_async_builtins(
self.features,
"`future.forward` requires the component model more async builtins feature",
offset,
)?;

let ty = self.defined_type_at(ty, offset)?;
let ComponentDefinedType::Future { .. } = &types[ty] else {
bail!(offset, "`future.forward` requires a future type")
};

self.core_funcs
.push(types.intern_func_type(FuncType::new([ValType::I32; 2], []), offset));
Ok(())
}

fn future_cancel_read(
&mut self,
ty: u32,
Expand Down
10 changes: 10 additions & 0 deletions crates/wasmprinter/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1048,6 +1048,11 @@ impl Printer<'_, '_> {
me.print_canonical_options(state, &options)
})?;
}
CanonicalFunction::StreamForward { ty } => {
self.print_intrinsic(state, "canon stream.forward ", &|me, state| {
me.print_idx(&state.component.type_names, ty)
})?;
}
CanonicalFunction::StreamCancelRead { ty, async_ } => {
self.print_intrinsic(state, "canon stream.cancel-read ", &|me, state| {
me.print_idx(&state.component.type_names, ty)?;
Expand Down Expand Up @@ -1093,6 +1098,11 @@ impl Printer<'_, '_> {
me.print_canonical_options(state, &options)
})?;
}
CanonicalFunction::FutureForward { ty } => {
self.print_intrinsic(state, "canon future.forward ", &|me, state| {
me.print_idx(&state.component.type_names, ty)
})?;
}
CanonicalFunction::FutureCancelRead { ty, async_ } => {
self.print_intrinsic(state, "canon future.cancel-read ", &|me, state| {
me.print_idx(&state.component.type_names, ty)?;
Expand Down
8 changes: 8 additions & 0 deletions crates/wast/src/component/binary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,10 @@ impl<'a> Encoder<'a> {
self.funcs
.stream_write((&info.ty).into(), info.opts.iter().map(Into::into));
}
CoreFuncKind::StreamForward(info) => {
self.core_func_names.push(name);
self.funcs.stream_forward((&info.ty).into());
}
CoreFuncKind::StreamCancelRead(info) => {
self.core_func_names.push(name);
self.funcs
Expand Down Expand Up @@ -450,6 +454,10 @@ impl<'a> Encoder<'a> {
self.funcs
.future_write((&info.ty).into(), info.opts.iter().map(Into::into));
}
CoreFuncKind::FutureForward(info) => {
self.core_func_names.push(name);
self.funcs.future_forward((&info.ty).into());
}
CoreFuncKind::FutureCancelRead(info) => {
self.core_func_names.push(name);
self.funcs
Expand Down
40 changes: 40 additions & 0 deletions crates/wast/src/component/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,15 @@ pub enum CoreFuncKind<'a> {
StreamNew(CanonStreamNew<'a>),
StreamRead(CanonStreamRead<'a>),
StreamWrite(CanonStreamWrite<'a>),
StreamForward(CanonStreamForward<'a>),
StreamCancelRead(CanonStreamCancelRead<'a>),
StreamCancelWrite(CanonStreamCancelWrite<'a>),
StreamDropReadable(CanonStreamDropReadable<'a>),
StreamDropWritable(CanonStreamDropWritable<'a>),
FutureNew(CanonFutureNew<'a>),
FutureRead(CanonFutureRead<'a>),
FutureWrite(CanonFutureWrite<'a>),
FutureForward(CanonFutureForward<'a>),
FutureCancelRead(CanonFutureCancelRead<'a>),
FutureCancelWrite(CanonFutureCancelWrite<'a>),
FutureDropReadable(CanonFutureDropReadable<'a>),
Expand Down Expand Up @@ -157,6 +159,8 @@ impl<'a> CoreFuncKind<'a> {
Ok(CoreFuncKind::StreamRead(parser.parse()?))
} else if l.peek::<kw::stream_write>()? {
Ok(CoreFuncKind::StreamWrite(parser.parse()?))
} else if l.peek::<kw::stream_forward>()? {
Ok(CoreFuncKind::StreamForward(parser.parse()?))
} else if l.peek::<kw::stream_cancel_read>()? {
Ok(CoreFuncKind::StreamCancelRead(parser.parse()?))
} else if l.peek::<kw::stream_cancel_write>()? {
Expand All @@ -171,6 +175,8 @@ impl<'a> CoreFuncKind<'a> {
Ok(CoreFuncKind::FutureRead(parser.parse()?))
} else if l.peek::<kw::future_write>()? {
Ok(CoreFuncKind::FutureWrite(parser.parse()?))
} else if l.peek::<kw::future_forward>()? {
Ok(CoreFuncKind::FutureForward(parser.parse()?))
} else if l.peek::<kw::future_cancel_read>()? {
Ok(CoreFuncKind::FutureCancelRead(parser.parse()?))
} else if l.peek::<kw::future_cancel_write>()? {
Expand Down Expand Up @@ -720,6 +726,23 @@ impl<'a> Parse<'a> for CanonStreamWrite<'a> {
}
}

/// Information relating to the `stream.forward` intrinsic.
#[derive(Debug)]
pub struct CanonStreamForward<'a> {
/// The stream type to forward.
pub ty: ItemRef<'a, kw::r#type>,
}

impl<'a> Parse<'a> for CanonStreamForward<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
parser.parse::<kw::stream_forward>()?;

Ok(Self {
ty: parser.parse::<IndexOrRef<'_, _>>()?.0,
})
}
}

/// Information relating to the `stream.cancel-read` intrinsic.
#[derive(Debug)]
pub struct CanonStreamCancelRead<'a> {
Expand Down Expand Up @@ -853,6 +876,23 @@ impl<'a> Parse<'a> for CanonFutureWrite<'a> {
}
}

/// Information relating to the `future.forward` intrinsic.
#[derive(Debug)]
pub struct CanonFutureForward<'a> {
/// The future type to forward.
pub ty: ItemRef<'a, kw::r#type>,
}

impl<'a> Parse<'a> for CanonFutureForward<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
parser.parse::<kw::future_forward>()?;

Ok(Self {
ty: parser.parse::<IndexOrRef<'_, _>>()?.0,
})
}
}

/// Information relating to the `future.cancel-read` intrinsic.
#[derive(Debug)]
pub struct CanonFutureCancelRead<'a> {
Expand Down
6 changes: 6 additions & 0 deletions crates/wast/src/component/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,9 @@ impl<'a> Resolver<'a> {
self.component_item_ref(&mut info.ty)?;
self.canon_opts(&mut info.opts)?;
}
CoreFuncKind::StreamForward(info) => {
self.component_item_ref(&mut info.ty)?;
}
CoreFuncKind::StreamCancelRead(info) => {
self.component_item_ref(&mut info.ty)?;
}
Expand All @@ -532,6 +535,9 @@ impl<'a> Resolver<'a> {
self.component_item_ref(&mut info.ty)?;
self.canon_opts(&mut info.opts)?;
}
CoreFuncKind::FutureForward(info) => {
self.component_item_ref(&mut info.ty)?;
}
CoreFuncKind::FutureCancelRead(info) => {
self.component_item_ref(&mut info.ty)?;
}
Expand Down
2 changes: 2 additions & 0 deletions crates/wast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -575,13 +575,15 @@ pub mod kw {
custom_keyword!(stream_new = "stream.new");
custom_keyword!(stream_read = "stream.read");
custom_keyword!(stream_write = "stream.write");
custom_keyword!(stream_forward = "stream.forward");
custom_keyword!(stream_cancel_read = "stream.cancel-read");
custom_keyword!(stream_cancel_write = "stream.cancel-write");
custom_keyword!(stream_drop_readable = "stream.drop-readable");
custom_keyword!(stream_drop_writable = "stream.drop-writable");
custom_keyword!(future_new = "future.new");
custom_keyword!(future_read = "future.read");
custom_keyword!(future_write = "future.write");
custom_keyword!(future_forward = "future.forward");
custom_keyword!(future_cancel_read = "future.cancel-read");
custom_keyword!(future_cancel_write = "future.cancel-write");
custom_keyword!(future_drop_readable = "future.drop-readable");
Expand Down
Loading
Loading