Skip to content
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
53 changes: 46 additions & 7 deletions crates/wasm-encoder/src/component/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,9 +425,9 @@ impl ComponentBuilder {
inc(&mut self.core_funcs)
}

/// Declares a new `task.yield` intrinsic.
pub fn yield_(&mut self, async_: bool) -> u32 {
self.canonical_functions().yield_(async_);
/// Declares a new `thread.yield` intrinsic.
pub fn thread_yield(&mut self, cancellable: bool) -> u32 {
self.canonical_functions().thread_yield(cancellable);
inc(&mut self.core_funcs)
}

Expand Down Expand Up @@ -577,14 +577,16 @@ impl ComponentBuilder {
}

/// Declares a new `waitable-set.wait` intrinsic.
pub fn waitable_set_wait(&mut self, async_: bool, memory: u32) -> u32 {
self.canonical_functions().waitable_set_wait(async_, memory);
pub fn waitable_set_wait(&mut self, cancellable: bool, memory: u32) -> u32 {
self.canonical_functions()
.waitable_set_wait(cancellable, memory);
inc(&mut self.core_funcs)
}

/// Declares a new `waitable-set.poll` intrinsic.
pub fn waitable_set_poll(&mut self, async_: bool, memory: u32) -> u32 {
self.canonical_functions().waitable_set_poll(async_, memory);
pub fn waitable_set_poll(&mut self, cancellable: bool, memory: u32) -> u32 {
self.canonical_functions()
.waitable_set_poll(cancellable, memory);
inc(&mut self.core_funcs)
}

Expand All @@ -600,6 +602,43 @@ impl ComponentBuilder {
inc(&mut self.core_funcs)
}

/// Declares a new `thread.index` intrinsic.
pub fn thread_index(&mut self) -> u32 {
self.canonical_functions().thread_index();
inc(&mut self.core_funcs)
}

/// Declares a new `thread.new_indirect` intrinsic.
pub fn thread_new_indirect(&mut self, func_ty_idx: u32, table_index: u32) -> u32 {
self.canonical_functions()
.thread_new_indirect(func_ty_idx, table_index);
inc(&mut self.core_funcs)
}

/// Declares a new `thread.switch-to` intrinsic.
pub fn thread_switch_to(&mut self, cancellable: bool) -> u32 {
self.canonical_functions().thread_switch_to(cancellable);
inc(&mut self.core_funcs)
}

/// Declares a new `thread.suspend` intrinsic.
pub fn thread_suspend(&mut self, cancellable: bool) -> u32 {
self.canonical_functions().thread_suspend(cancellable);
inc(&mut self.core_funcs)
}

/// Declares a new `thread.resume-later` intrinsic.
pub fn thread_resume_later(&mut self) -> u32 {
self.canonical_functions().thread_resume_later();
inc(&mut self.core_funcs)
}

/// Declares a new `thread.yield-to` intrinsic.
pub fn thread_yield_to(&mut self, cancellable: bool) -> u32 {
self.canonical_functions().thread_yield_to(cancellable);
inc(&mut self.core_funcs)
}

/// Adds a new custom section to this component.
pub fn custom_section(&mut self, section: &CustomSection<'_>) {
self.flush();
Expand Down
59 changes: 56 additions & 3 deletions crates/wasm-encoder/src/component/canonicals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,10 +249,10 @@ impl CanonicalFunctionSection {
/// Defines a function which yields control to the host so that other tasks
/// are able to make progress, if any.
///
/// If `async_` is true, the caller instance may be reentered.
pub fn yield_(&mut self, async_: bool) -> &mut Self {
/// If `cancellable` is true, the caller instance may be reentered.
pub fn thread_yield(&mut self, cancellable: bool) -> &mut Self {
self.bytes.push(0x0c);
self.bytes.push(if async_ { 1 } else { 0 });
self.bytes.push(if cancellable { 1 } else { 0 });
self.num_added += 1;
self
}
Expand Down Expand Up @@ -498,6 +498,59 @@ impl CanonicalFunctionSection {
self
}

/// Declare a new `thread.index` intrinsic, used to get the index of the
/// current thread.
pub fn thread_index(&mut self) -> &mut Self {
self.bytes.push(0x26);
self.num_added += 1;
self
}

/// Declare a new `thread.new_indirect` intrinsic, used to create a new
/// thread by invoking a function indirectly through a `funcref` table.
pub fn thread_new_indirect(&mut self, ty_index: u32, table_index: u32) -> &mut Self {
self.bytes.push(0x27);
ty_index.encode(&mut self.bytes);
table_index.encode(&mut self.bytes);
self.num_added += 1;
self
}

/// Declare a new `thread.switch-to` intrinsic, used to switch execution to
/// another thread.
pub fn thread_switch_to(&mut self, cancellable: bool) -> &mut Self {
self.bytes.push(0x28);
self.bytes.push(if cancellable { 1 } else { 0 });
self.num_added += 1;
self
}

/// Declare a new `thread.suspend` intrinsic, used to suspend execution of
/// the current thread.
pub fn thread_suspend(&mut self, cancellable: bool) -> &mut Self {
self.bytes.push(0x29);
self.bytes.push(if cancellable { 1 } else { 0 });
self.num_added += 1;
self
}

/// Declare a new `thread.resume-later` intrinsic, used to resume execution
/// of the given thread.
pub fn thread_resume_later(&mut self) -> &mut Self {
self.bytes.push(0x2a);
self.num_added += 1;
self
}

/// Declare a new `thread.yield-to` intrinsic, used to yield execution to
/// a given thread.
pub fn thread_yield_to(&mut self, cancellable: bool) -> &mut Self {
self.bytes.push(0x2b);
self.bytes.push(if cancellable { 1 } else { 0 });
self.num_added += 1;
self
}

fn encode_options<O>(&mut self, options: O) -> &mut Self
where
O: IntoIterator<Item = CanonicalOption>,
Expand Down
41 changes: 35 additions & 6 deletions crates/wasm-encoder/src/reencode/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -995,8 +995,8 @@ pub mod component_utils {
wasmparser::CanonicalFunction::ContextSet(i) => {
section.context_set(i);
}
wasmparser::CanonicalFunction::Yield { async_ } => {
section.yield_(async_);
wasmparser::CanonicalFunction::ThreadYield { cancellable } => {
section.thread_yield(cancellable);
}
wasmparser::CanonicalFunction::SubtaskDrop => {
section.subtask_drop();
Expand Down Expand Up @@ -1082,18 +1082,47 @@ pub mod component_utils {
wasmparser::CanonicalFunction::WaitableSetNew => {
section.waitable_set_new();
}
wasmparser::CanonicalFunction::WaitableSetWait { async_, memory } => {
section.waitable_set_wait(async_, reencoder.memory_index(memory)?);
wasmparser::CanonicalFunction::WaitableSetWait {
cancellable,
memory,
} => {
section.waitable_set_wait(cancellable, reencoder.memory_index(memory)?);
}
wasmparser::CanonicalFunction::WaitableSetPoll { async_, memory } => {
section.waitable_set_poll(async_, reencoder.memory_index(memory)?);
wasmparser::CanonicalFunction::WaitableSetPoll {
cancellable,
memory,
} => {
section.waitable_set_poll(cancellable, reencoder.memory_index(memory)?);
}
wasmparser::CanonicalFunction::WaitableSetDrop => {
section.waitable_set_drop();
}
wasmparser::CanonicalFunction::WaitableJoin => {
section.waitable_join();
}
wasmparser::CanonicalFunction::ThreadIndex => {
section.thread_index();
}
wasmparser::CanonicalFunction::ThreadNewIndirect {
func_ty_index,
table_index,
} => {
let func_ty = reencoder.type_index(func_ty_index)?;
let table_index = reencoder.table_index(table_index)?;
section.thread_new_indirect(func_ty, table_index);
}
wasmparser::CanonicalFunction::ThreadSwitchTo { cancellable } => {
section.thread_switch_to(cancellable);
}
wasmparser::CanonicalFunction::ThreadSuspend { cancellable } => {
section.thread_suspend(cancellable);
}
wasmparser::CanonicalFunction::ThreadResumeLater => {
section.thread_resume_later();
}
wasmparser::CanonicalFunction::ThreadYieldTo { cancellable } => {
section.thread_yield_to(cancellable);
}
}
Ok(())
}
Expand Down
15 changes: 10 additions & 5 deletions crates/wasmparser/src/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,36 +265,41 @@ define_wasm_features! {
/// Corresponds to the 🚝 character in
/// <https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md>.
pub cm_async_builtins: CM_ASYNC_BUILTINS(1 << 29) = false;
/// Support for threading in the component model proposal.
///
/// Corresponds to the 🧵 character in
/// <https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md>.
pub cm_threading: CM_THREADING(1 << 30) = false;
/// Gates some intrinsics being marked with `error-context` in the component
/// model async proposal.
///
/// Corresponds to the 📝 character in
/// <https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md>.
pub cm_error_context: CM_ERROR_CONTEXT(1 << 30) = false;
pub cm_error_context: CM_ERROR_CONTEXT(1 << 31) = false;
/// Support for fixed size lists
///
/// Corresponds to the 🔧 character in
/// <https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md>.
pub cm_fixed_size_list: CM_FIXED_SIZE_LIST(1 << 31) = false;
pub cm_fixed_size_list: CM_FIXED_SIZE_LIST(1 << 32) = false;
/// Support for Wasm GC in the component model proposal.
///
/// Corresponds to the 🛸 character in
/// <https://github.com/WebAssembly/component-model/blob/main/design/mvp/Explainer.md>.
pub cm_gc: CM_GC(1 << 32) = false;
pub cm_gc: CM_GC(1 << 33) = false;

/// Subset of the reference-types WebAssembly proposal which only
/// encompasses the leb-encoding of the table immediate to the
/// `call_indirect` instruction, enabling over-long encodings of an
/// integer for example.
///
/// This is a subcomponent of the "lime1" feature.
pub call_indirect_overlong: CALL_INDIRECT_OVERLONG(1 << 33) = true;
pub call_indirect_overlong: CALL_INDIRECT_OVERLONG(1 << 34) = true;

/// Subset of the bulk-memory proposal covering just the `memory.copy`
/// and `memory.fill` instructions.
///
/// This is a subcomponent of the "lime1" feature.
pub bulk_memory_opt: BULK_MEMORY_OPT(1 << 34) = true;
pub bulk_memory_opt: BULK_MEMORY_OPT(1 << 35) = true;
}
}

Expand Down
57 changes: 49 additions & 8 deletions crates/wasmparser/src/readers/component/canonicals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,9 @@ pub enum CanonicalFunction {
ContextSet(u32),
/// A function which yields control to the host so that other tasks are able
/// to make progress, if any.
Yield {
ThreadYield {
/// If `true`, indicates the caller instance maybe reentered.
async_: bool,
cancellable: bool,
},
/// A function to drop a specified task which has completed.
SubtaskDrop,
Expand Down Expand Up @@ -246,22 +246,48 @@ pub enum CanonicalFunction {
WaitableSetWait {
/// Whether or not the guest can be reentered while calling this
/// function.
async_: bool,
cancellable: bool,
/// Which memory the results of this operation are stored in.
memory: u32,
},
/// A function to check if any items are ready within a `waitable-set`.
WaitableSetPoll {
/// Whether or not the guest can be reentered while calling this
/// function.
async_: bool,
cancellable: bool,
/// Which memory the results of this operation are stored in.
memory: u32,
},
/// A function to drop a `waitable-set`.
WaitableSetDrop,
/// A function to add an item to a `waitable-set`.
WaitableJoin,
/// A function to get the index of the current thread.
ThreadIndex,
/// A function to create a new thread with the specified start function.
ThreadNewIndirect {
/// The index of the function type to use as the start function.
func_ty_index: u32,
/// The index of the table to use.
table_index: u32,
},
/// A function to suspend the current thread and switch to the given thread.
ThreadSwitchTo {
/// Whether or not the thread can be cancelled while awaiting resumption.
cancellable: bool,
},
/// A function to suspend the current thread, immediately yielding to any transitive async-lowered calling component.
ThreadSuspend {
/// Whether or not the thread can be cancelled while suspended.
cancellable: bool,
},
/// A function to schedule the given thread to be resumed later.
ThreadResumeLater,
/// A function to suspend the current thread and switch to the given thread.
ThreadYieldTo {
/// Whether or not the thread can be cancelled while yielding.
cancellable: bool,
},
}

/// A reader for the canonical section of a WebAssembly component.
Expand Down Expand Up @@ -310,8 +336,8 @@ impl<'a> FromReader<'a> for CanonicalFunction {
0x7f => CanonicalFunction::ContextSet(reader.read_var_u32()?),
x => return reader.invalid_leading_byte(x, "context.set intrinsic type"),
},
0x0c => CanonicalFunction::Yield {
async_: reader.read()?,
0x0c => CanonicalFunction::ThreadYield {
cancellable: reader.read()?,
},
0x0d => CanonicalFunction::SubtaskDrop,
0x0e => CanonicalFunction::StreamNew { ty: reader.read()? },
Expand Down Expand Up @@ -362,15 +388,30 @@ impl<'a> FromReader<'a> for CanonicalFunction {

0x1f => CanonicalFunction::WaitableSetNew,
0x20 => CanonicalFunction::WaitableSetWait {
async_: reader.read()?,
cancellable: reader.read()?,
memory: reader.read()?,
},
0x21 => CanonicalFunction::WaitableSetPoll {
async_: reader.read()?,
cancellable: reader.read()?,
memory: reader.read()?,
},
0x22 => CanonicalFunction::WaitableSetDrop,
0x23 => CanonicalFunction::WaitableJoin,
0x26 => CanonicalFunction::ThreadIndex,
0x27 => CanonicalFunction::ThreadNewIndirect {
func_ty_index: reader.read()?,
table_index: reader.read()?,
},
0x28 => CanonicalFunction::ThreadSwitchTo {
cancellable: reader.read()?,
},
0x29 => CanonicalFunction::ThreadSuspend {
cancellable: reader.read()?,
},
0x2a => CanonicalFunction::ThreadResumeLater,
0x2b => CanonicalFunction::ThreadYieldTo {
cancellable: reader.read()?,
},
0x06 => CanonicalFunction::SubtaskCancel {
async_: reader.read()?,
},
Expand Down
Loading
Loading