Repository: bytecodealliance/wasm-tools
Pull request #2067 (2025-02-24 19:12:29)

Refactor how `error-context.*` intrinsics are imported
This commit refactors the `wit-component` conventions used to import `error-context.*` intrinsics. The first change is to drop the `realloc` option on the `error-context.debug-message` intrinsic in favor of inferring that from the "general purpose import realloc" option. This avoids the need to name a symbol and enables generally relying on there being a single option for this.

The second change is to change how `encoding=` is specified and bake it directly into the name instead of having a url-scheme-like encoding with multiple options. This is in theory the only option necessary for these intrinsics so it's possible to have a static set of a few names that might be chosen.


Patch:
diff --git a/crates/wasm-encoder/src/component/builder.rs b/crates/wasm-encoder/src/component/builder.rs
index e95dd060..06b78b64 100644
--- a/crates/wasm-encoder/src/component/builder.rs
+++ b/crates/wasm-encoder/src/component/builder.rs
@@ -408,8 +408,8 @@ impl ComponentBuilder {
     }
 
     /// Declares a new `task.yield` intrinsic.
-    pub fn task_yield(&mut self, async_: bool) -> u32 {
-        self.canonical_functions().task_yield(async_);
+    pub fn yield_(&mut self, async_: bool) -> u32 {
+        self.canonical_functions().yield_(async_);
         inc(&mut self.core_funcs)
     }
 
diff --git a/crates/wasm-encoder/src/component/canonicals.rs b/crates/wasm-encoder/src/component/canonicals.rs
index 4a757199..a20fae46 100644
--- a/crates/wasm-encoder/src/component/canonicals.rs
+++ b/crates/wasm-encoder/src/component/canonicals.rs
@@ -204,7 +204,7 @@ impl CanonicalFunctionSection {
     /// are able to make progress, if any.
     ///
     /// If `async_` is true, the caller instance may be reentered.
-    pub fn task_yield(&mut self, async_: bool) -> &mut Self {
+    pub fn yield_(&mut self, async_: bool) -> &mut Self {
         self.bytes.push(0x0c);
         self.bytes.push(if async_ { 1 } else { 0 });
         self.num_added += 1;
diff --git a/crates/wasm-encoder/src/reencode/component.rs b/crates/wasm-encoder/src/reencode/component.rs
index fa34b5e4..bbeecb3e 100644
--- a/crates/wasm-encoder/src/reencode/component.rs
+++ b/crates/wasm-encoder/src/reencode/component.rs
@@ -969,8 +969,8 @@ pub mod component_utils {
                     options.iter().map(|o| reencoder.canonical_option(*o)),
                 );
             }
-            wasmparser::CanonicalFunction::TaskYield { async_ } => {
-                section.task_yield(async_);
+            wasmparser::CanonicalFunction::Yield { async_ } => {
+                section.yield_(async_);
             }
             wasmparser::CanonicalFunction::SubtaskDrop => {
                 section.subtask_drop();
diff --git a/crates/wasmparser/src/readers/component/canonicals.rs b/crates/wasmparser/src/readers/component/canonicals.rs
index 47324df6..5a7be8b1 100644
--- a/crates/wasmparser/src/readers/component/canonicals.rs
+++ b/crates/wasmparser/src/readers/component/canonicals.rs
@@ -92,7 +92,7 @@ pub enum CanonicalFunction {
     },
     /// A function which yields control to the host so that other tasks are able
     /// to make progress, if any.
-    TaskYield {
+    Yield {
         /// If `true`, indicates the caller instance maybe reentered.
         async_: bool,
     },
@@ -282,7 +282,7 @@ impl<'a> FromReader<'a> for CanonicalFunction {
                 result: crate::read_resultlist(reader)?,
                 options: read_opts(reader)?,
             },
-            0x0c => CanonicalFunction::TaskYield {
+            0x0c => CanonicalFunction::Yield {
                 async_: reader.read()?,
             },
             0x0d => CanonicalFunction::SubtaskDrop,
diff --git a/crates/wasmparser/src/validator/component.rs b/crates/wasmparser/src/validator/component.rs
index d6577352..62b855c0 100644
--- a/crates/wasmparser/src/validator/component.rs
+++ b/crates/wasmparser/src/validator/component.rs
@@ -997,9 +997,7 @@ impl ComponentState {
             CanonicalFunction::TaskReturn { result, options } => {
                 self.task_return(&result, &options, types, offset, features)
             }
-            CanonicalFunction::TaskYield { async_ } => {
-                self.task_yield(async_, types, offset, features)
-            }
+            CanonicalFunction::Yield { async_ } => self.yield_(async_, types, offset, features),
             CanonicalFunction::SubtaskDrop => self.subtask_drop(types, offset, features),
             CanonicalFunction::StreamNew { ty } => self.stream_new(ty, types, offset, features),
             CanonicalFunction::StreamRead { ty, options } => {
@@ -1249,7 +1247,7 @@ impl ComponentState {
         Ok(())
     }
 
-    fn task_yield(
+    fn yield_(
         &mut self,
         _async_: bool,
         types: &mut TypeAlloc,
@@ -1257,10 +1255,7 @@ impl ComponentState {
         features: &WasmFeatures,
     ) -> Result<()> {
         if !features.component_model_async() {
-            bail!(
-                offset,
-                "`task.yield` requires the component model async feature"
-            )
+            bail!(offset, "`yield` requires the component model async feature")
         }
 
         self.core_funcs
diff --git a/crates/wasmprinter/src/component.rs b/crates/wasmprinter/src/component.rs
index 5913dc0f..d3664de4 100644
--- a/crates/wasmprinter/src/component.rs
+++ b/crates/wasmprinter/src/component.rs
@@ -800,7 +800,7 @@ impl Printer<'_, '_> {
                     self.print_idx(&state.core.func_names, *idx)?;
                     self.end_group()?;
                 }
-                CanonicalOption::Async => self.result.write_str("async")?,
+                CanonicalOption::Async => self.print_type_keyword("async")?,
                 CanonicalOption::Callback(idx) => {
                     self.start_group("callback ")?;
                     self.print_idx(&state.core.func_names, *idx)?;
@@ -928,10 +928,10 @@ impl Printer<'_, '_> {
                         Ok(())
                     })?;
                 }
-                CanonicalFunction::TaskYield { async_ } => {
-                    self.print_intrinsic(state, "canon task.yield", &|me, _| {
+                CanonicalFunction::Yield { async_ } => {
+                    self.print_intrinsic(state, "canon yield", &|me, _| {
                         if async_ {
-                            me.result.write_str(" async")?;
+                            me.print_type_keyword(" async")?;
                         }
                         Ok(())
                     })?;
@@ -960,7 +960,7 @@ impl Printer<'_, '_> {
                     self.print_intrinsic(state, "canon stream.cancel-read ", &|me, state| {
                         me.print_idx(&state.component.type_names, ty)?;
                         if async_ {
-                            me.result.write_str(" async")?;
+                            me.print_type_keyword(" async")?;
                         }
                         Ok(())
                     })?;
@@ -969,7 +969,7 @@ impl Printer<'_, '_> {
                     self.print_intrinsic(state, "canon stream.cancel-write ", &|me, state| {
                         me.print_idx(&state.component.type_names, ty)?;
                         if async_ {
-                            me.result.write_str(" async")?;
+                            me.print_type_keyword(" async")?;
                         }
                         Ok(())
                     })?;
@@ -1005,7 +1005,7 @@ impl Printer<'_, '_> {
                     self.print_intrinsic(state, "canon future.cancel-read ", &|me, state| {
                         me.print_idx(&state.component.type_names, ty)?;
                         if async_ {
-                            me.result.write_str(" async")?;
+                            me.print_type_keyword(" async")?;
                         }
                         Ok(())
                     })?;
@@ -1014,7 +1014,7 @@ impl Printer<'_, '_> {
                     self.print_intrinsic(state, "canon future.cancel-write ", &|me, state| {
                         me.print_idx(&state.component.type_names, ty)?;
                         if async_ {
-                            me.result.write_str(" async")?;
+                            me.print_type_keyword(" async")?;
                         }
                         Ok(())
                     })?;
diff --git a/crates/wast/src/component/binary.rs b/crates/wast/src/component/binary.rs
index 423644db..1598c6aa 100644
--- a/crates/wast/src/component/binary.rs
+++ b/crates/wast/src/component/binary.rs
@@ -370,9 +370,9 @@ impl<'a> Encoder<'a> {
                     info.opts.iter().map(Into::into),
                 );
             }
-            CanonicalFuncKind::TaskYield(info) => {
+            CanonicalFuncKind::Yield(info) => {
                 self.core_func_names.push(name);
-                self.funcs.task_yield(info.async_);
+                self.funcs.yield_(info.async_);
             }
             CanonicalFuncKind::SubtaskDrop => {
                 self.core_func_names.push(name);
diff --git a/crates/wast/src/component/expand.rs b/crates/wast/src/component/expand.rs
index 611dfbc8..30e65117 100644
--- a/crates/wast/src/component/expand.rs
+++ b/crates/wast/src/component/expand.rs
@@ -330,11 +330,11 @@ impl<'a> Expander<'a> {
                 name: func.name,
                 kind: CanonicalFuncKind::TaskReturn(info),
             }),
-            CoreFuncKind::TaskYield(info) => ComponentField::CanonicalFunc(CanonicalFunc {
+            CoreFuncKind::Yield(info) => ComponentField::CanonicalFunc(CanonicalFunc {
                 span: func.span,
                 id: func.id,
                 name: func.name,
-                kind: CanonicalFuncKind::TaskYield(info),
+                kind: CanonicalFuncKind::Yield(info),
             }),
             CoreFuncKind::SubtaskDrop => ComponentField::CanonicalFunc(CanonicalFunc {
                 span: func.span,
diff --git a/crates/wast/src/component/func.rs b/crates/wast/src/component/func.rs
index 5bd45222..680f7e06 100644
--- a/crates/wast/src/component/func.rs
+++ b/crates/wast/src/component/func.rs
@@ -55,7 +55,7 @@ pub enum CoreFuncKind<'a> {
     ThreadAvailableParallelism(CanonThreadAvailableParallelism),
     BackpressureSet,
     TaskReturn(CanonTaskReturn<'a>),
-    TaskYield(CanonTaskYield),
+    Yield(CanonYield),
     SubtaskDrop,
     StreamNew(CanonStreamNew<'a>),
     StreamRead(CanonStreamRead<'a>),
@@ -110,8 +110,8 @@ impl<'a> Parse<'a> for CoreFuncKind<'a> {
                 Ok(CoreFuncKind::BackpressureSet)
             } else if l.peek::<kw::task_return>()? {
                 Ok(CoreFuncKind::TaskReturn(parser.parse()?))
-            } else if l.peek::<kw::task_yield>()? {
-                Ok(CoreFuncKind::TaskYield(parser.parse()?))
+            } else if l.peek::<kw::yield_>()? {
+                Ok(CoreFuncKind::Yield(parser.parse()?))
             } else if l.peek::<kw::subtask_drop>()? {
                 parser.parse::<kw::subtask_drop>()?;
                 Ok(CoreFuncKind::SubtaskDrop)
@@ -357,7 +357,7 @@ pub enum CanonicalFuncKind<'a> {
 
     BackpressureSet,
     TaskReturn(CanonTaskReturn<'a>),
-    TaskYield(CanonTaskYield),
+    Yield(CanonYield),
     SubtaskDrop,
     StreamNew(CanonStreamNew<'a>),
     StreamRead(CanonStreamRead<'a>),
@@ -611,15 +611,15 @@ impl<'a> Parse<'a> for CanonWaitableSetPoll<'a> {
 
 /// Information relating to the `task.yield` intrinsic.
 #[derive(Debug)]
-pub struct CanonTaskYield {
+pub struct CanonYield {
     /// If true, the component instance may be reentered during a call to this
     /// intrinsic.
     pub async_: bool,
 }
 
-impl<'a> Parse<'a> for CanonTaskYield {
+impl<'a> Parse<'a> for CanonYield {
     fn parse(parser: Parser<'a>) -> Result<Self> {
-        parser.parse::<kw::task_yield>()?;
+        parser.parse::<kw::yield_>()?;
         let async_ = parser.parse::<Option<kw::r#async>>()?.is_some();
 
         Ok(Self { async_ })
diff --git a/crates/wast/src/component/resolve.rs b/crates/wast/src/component/resolve.rs
index f3ff0a1d..916efc4e 100644
--- a/crates/wast/src/component/resolve.rs
+++ b/crates/wast/src/component/resolve.rs
@@ -388,7 +388,7 @@ impl<'a> Resolver<'a> {
             }
             CanonicalFuncKind::ThreadAvailableParallelism(_)
             | CanonicalFuncKind::BackpressureSet
-            | CanonicalFuncKind::TaskYield(_)
+            | CanonicalFuncKind::Yield(_)
             | CanonicalFuncKind::SubtaskDrop
             | CanonicalFuncKind::ErrorContextDrop => {}
             CanonicalFuncKind::TaskReturn(info) => {
@@ -971,7 +971,7 @@ impl<'a> ComponentState<'a> {
                 | CanonicalFuncKind::ThreadAvailableParallelism(_)
                 | CanonicalFuncKind::BackpressureSet
                 | CanonicalFuncKind::TaskReturn(_)
-                | CanonicalFuncKind::TaskYield(_)
+                | CanonicalFuncKind::Yield(_)
                 | CanonicalFuncKind::SubtaskDrop
                 | CanonicalFuncKind::StreamNew(_)
                 | CanonicalFuncKind::StreamRead(_)
diff --git a/crates/wast/src/lib.rs b/crates/wast/src/lib.rs
index 9f294891..effe7729 100644
--- a/crates/wast/src/lib.rs
+++ b/crates/wast/src/lib.rs
@@ -558,7 +558,7 @@ pub mod kw {
     custom_keyword!(thread_available_parallelism = "thread.available_parallelism");
     custom_keyword!(backpressure_set = "backpressure.set");
     custom_keyword!(task_return = "task.return");
-    custom_keyword!(task_yield = "task.yield");
+    custom_keyword!(yield_ = "yield");
     custom_keyword!(subtask_drop = "subtask.drop");
     custom_keyword!(stream_new = "stream.new");
     custom_keyword!(stream_read = "stream.read");
diff --git a/crates/wit-component/src/encoding.rs b/crates/wit-component/src/encoding.rs
index b504b458..9c9fbc7c 100644
--- a/crates/wit-component/src/encoding.rs
+++ b/crates/wit-component/src/encoding.rs
@@ -1324,13 +1324,13 @@ impl<'a> EncodingState<'a> {
                     shim.options.into_iter(*encoding, self.memory_index, None)?,
                 ),
                 ShimKind::ErrorContextDebugMessage {
-                    encoding,
                     for_module,
-                    realloc,
+                    encoding,
                 } => {
                     let instance_index = self.instance_for(*for_module);
-                    let realloc_index =
-                        Some(self.core_alias_export(instance_index, realloc, ExportKind::Func));
+                    let realloc = self.info.exports_for(*for_module).import_realloc_fallback();
+                    let realloc_index = realloc
+                        .map(|r| self.core_alias_export(instance_index, r, ExportKind::Func));
 
                     self.component
                         .error_context_debug_message(shim.options.into_iter(
@@ -1652,8 +1652,8 @@ impl<'a> EncodingState<'a> {
                 Ok(self
                     .materialize_shim_import(shims, &ShimKind::WaitableSetPoll { async_: *async_ }))
             }
-            Import::TaskYield { async_ } => {
-                let index = self.component.task_yield(*async_);
+            Import::Yield { async_ } => {
+                let index = self.component.yield_(*async_);
                 Ok((ExportKind::Func, index))
             }
             Import::SubtaskDrop => {
@@ -1740,15 +1740,13 @@ impl<'a> EncodingState<'a> {
                     encoding: *encoding,
                 },
             )),
-            Import::ErrorContextDebugMessage { encoding, realloc } => Ok(self
-                .materialize_shim_import(
-                    shims,
-                    &ShimKind::ErrorContextDebugMessage {
-                        for_module,
-                        encoding: *encoding,
-                        realloc,
-                    },
-                )),
+            Import::ErrorContextDebugMessage { encoding } => Ok(self.materialize_shim_import(
+                shims,
+                &ShimKind::ErrorContextDebugMessage {
+                    for_module,
+                    encoding: *encoding,
+                },
+            )),
             Import::ErrorContextDrop => {
                 let index = self.component.error_context_drop();
                 Ok((ExportKind::Func, index))
@@ -2092,9 +2090,6 @@ enum ShimKind<'a> {
         for_module: CustomModule<'a>,
         /// The string encoding to use when lowering the debug message.
         encoding: StringEncoding,
-        /// The realloc function to use when allocating linear memory for the
-        /// debug message.
-        realloc: &'a str,
     },
 }
 
@@ -2144,7 +2139,7 @@ impl<'a> Shims<'a> {
                 | Import::ExportedResourceNew(..)
                 | Import::ErrorContextDrop
                 | Import::BackpressureSet
-                | Import::TaskYield { .. }
+                | Import::Yield { .. }
                 | Import::SubtaskDrop
                 | Import::FutureNew(..)
                 | Import::StreamNew(..)
@@ -2293,7 +2288,7 @@ impl<'a> Shims<'a> {
                     });
                 }
 
-                Import::ErrorContextDebugMessage { encoding, realloc } => {
+                Import::ErrorContextDebugMessage { encoding } => {
                     let name = self.shims.len().to_string();
                     self.push(Shim {
                         name,
@@ -2304,7 +2299,6 @@ impl<'a> Shims<'a> {
                         kind: ShimKind::ErrorContextDebugMessage {
                             for_module,
                             encoding: *encoding,
-                            realloc,
                         },
                         sig: WasmSignature {
                             params: vec![WasmType::I32; 2],
diff --git a/crates/wit-component/src/validation.rs b/crates/wit-component/src/validation.rs
index 3dc2ad76..aeb62614 100644
--- a/crates/wit-component/src/validation.rs
+++ b/crates/wit-component/src/validation.rs
@@ -284,11 +284,11 @@ pub enum Import {
     /// A `waitable.join` intrinsic.
     WaitableJoin,
 
-    /// A `canon task.wait` intrinsic.
+    /// A `canon yield` intrinsic.
     ///
     /// This allows the guest to yield (e.g. during an computationally-intensive
     /// operation) and allow other subtasks to make progress.
-    TaskYield { async_: bool },
+    Yield { async_: bool },
 
     /// A `canon subtask.drop` intrinsic.
     ///
@@ -383,10 +383,7 @@ pub enum Import {
     /// This allows the guest to retrieve the debug message from a
     /// `error-context` instance.  Note that the content of this message might
     /// not be identical to what was passed in to `error-context.new`.
-    ErrorContextDebugMessage {
-        encoding: StringEncoding,
-        realloc: String,
-    },
+    ErrorContextDebugMessage { encoding: StringEncoding },
 
     /// A `canon error-context.drop` intrinsic.
     ///
@@ -610,10 +607,11 @@ impl ImportMap {
                 return Ok(Import::WaitableJoin);
             }
 
-            if Some(name) == names.task_yield() {
+            if Some(name) == names.yield_() {
+                validate_not_async()?;
                 let expected = FuncType::new([], []);
                 validate_func_sig(name, &expected, ty)?;
-                return Ok(Import::TaskYield {
+                return Ok(Import::Yield {
                     async_: abi == AbiVariant::GuestImportAsync,
                 });
             }
@@ -632,14 +630,11 @@ impl ImportMap {
                 return Ok(Import::ErrorContextNew { encoding });
             }
 
-            if let Some((encoding, realloc)) = names.error_context_debug_message(name) {
+            if let Some(encoding) = names.error_context_debug_message(name) {
                 validate_not_async()?;
                 let expected = FuncType::new([ValType::I32; 2], []);
                 validate_func_sig(name, &expected, ty)?;
-                return Ok(Import::ErrorContextDebugMessage {
-                    encoding,
-                    realloc: realloc.to_owned(),
-                });
+                return Ok(Import::ErrorContextDebugMessage { encoding });
             }
 
             let key = WorldKey::Name(name.to_string());
@@ -1270,6 +1265,13 @@ impl ExportMap {
         // `cabi_realloc_{name}` or something like that.
         let _ = (interface, func);
 
+        self.import_realloc_fallback()
+    }
+
+    /// Returns the general-purpose realloc function to use for imports.
+    ///
+    /// Note that `import_realloc_for` should be used instead where possible.
+    pub fn import_realloc_fallback(&self) -> Option<&str> {
         if let Some(name) = self.find(|m| matches!(m, Export::GeneralPurposeImportRealloc)) {
             return Some(name);
         }
@@ -1413,13 +1415,13 @@ trait NameMangling {
     fn waitable_set_poll(&self) -> Option<&str>;
     fn waitable_set_drop(&self) -> Option<&str>;
     fn waitable_join(&self) -> Option<&str>;
-    fn task_yield(&self) -> Option<&str>;
+    fn yield_(&self) -> Option<&str>;
     fn subtask_drop(&self) -> Option<&str>;
     fn callback_name<'a>(&self, s: &'a str) -> Option<&'a str>;
     fn async_name<'a>(&self, s: &'a str) -> Option<&'a str>;
     fn async_stackful_name<'a>(&self, s: &'a str) -> Option<&'a str>;
     fn error_context_new(&self, s: &str) -> Option<StringEncoding>;
-    fn error_context_debug_message<'a>(&self, s: &'a str) -> Option<(StringEncoding, &'a str)>;
+    fn error_context_debug_message(&self, s: &str) -> Option<StringEncoding>;
     fn error_context_drop(&self) -> Option<&str>;
     fn module_to_interface(
         &self,
@@ -1500,7 +1502,7 @@ impl NameMangling for Standard {
     fn waitable_join(&self) -> Option<&str> {
         None
     }
-    fn task_yield(&self) -> Option<&str> {
+    fn yield_(&self) -> Option<&str> {
         None
     }
     fn subtask_drop(&self) -> Option<&str> {
@@ -1518,12 +1520,10 @@ impl NameMangling for Standard {
         _ = s;
         None
     }
-    fn error_context_new(&self, s: &str) -> Option<StringEncoding> {
-        _ = s;
+    fn error_context_new(&self, _: &str) -> Option<StringEncoding> {
         None
     }
-    fn error_context_debug_message<'a>(&self, s: &'a str) -> Option<(StringEncoding, &'a str)> {
-        _ = s;
+    fn error_context_debug_message(&self, _: &str) -> Option<StringEncoding> {
         None
     }
     fn error_context_drop(&self) -> Option<&str> {
@@ -1685,8 +1685,8 @@ impl NameMangling for Legacy {
     fn waitable_join(&self) -> Option<&str> {
         Some("[waitable-join]")
     }
-    fn task_yield(&self) -> Option<&str> {
-        Some("[task-yield]")
+    fn yield_(&self) -> Option<&str> {
+        Some("[yield]")
     }
     fn subtask_drop(&self) -> Option<&str> {
         Some("[subtask-drop]")
@@ -1700,37 +1700,21 @@ impl NameMangling for Legacy {
     fn async_stackful_name<'a>(&self, s: &'a str) -> Option<&'a str> {
         s.strip_prefix("[async-stackful]")
     }
-    fn error_context_new(&self, s: &str) -> Option<StringEncoding> {
-        parse_encoding(
-            s.strip_prefix("[error-context-new;encoding=")?
-                .strip_suffix("]")?,
-        )
+    fn error_context_new(&self, name: &str) -> Option<StringEncoding> {
+        match name {
+            "[error-context-new-utf8]" => Some(StringEncoding::UTF8),
+            "[error-context-new-utf16]" => Some(StringEncoding::UTF16),
+            "[error-context-new-latin1+utf16]" => Some(StringEncoding::CompactUTF16),
+            _ => None,
+        }
     }
-    fn error_context_debug_message<'a>(&self, s: &'a str) -> Option<(StringEncoding, &'a str)> {
-        let mut suffix = s.strip_prefix("[error-context-debug-message;")?;
-        let mut encoding = None;
-        let mut realloc = None;
-        loop {
-            if let Some(index) = suffix.find(';').or_else(|| suffix.find(']')) {
-                if let Some(suffix) = suffix[..index].strip_prefix("encoding=") {
-                    if encoding.is_some() {
-                        return None;
-                    }
-                    encoding = parse_encoding(suffix)
-                } else if let Some(suffix) = suffix[..index].strip_prefix("realloc=") {
-                    if realloc.is_some() {
-                        return None;
-                    }
-                    realloc = Some(suffix);
-                } else {
-                    return None;
-                }
-                suffix = &suffix[index + 1..];
-            } else {
-                break;
-            }
+    fn error_context_debug_message(&self, name: &str) -> Option<StringEncoding> {
+        match name {
+            "[error-context-debug-message-utf8]" => Some(StringEncoding::UTF8),
+            "[error-context-debug-message-utf16]" => Some(StringEncoding::UTF16),
+            "[error-context-debug-message-latin1+utf16]" => Some(StringEncoding::CompactUTF16),
+            _ => None,
         }
-        Some((encoding?, realloc?))
     }
     fn error_context_drop(&self) -> Option<&str> {
         Some("[error-context-drop]")
@@ -2042,12 +2026,3 @@ fn get_function<'a>(
     };
     Ok(function)
 }
-
-fn parse_encoding(s: &str) -> Option<StringEncoding> {
-    match s {
-        "utf8" => Some(StringEncoding::UTF8),
-        "utf16" => Some(StringEncoding::UTF16),
-        "compact-utf16" => Some(StringEncoding::CompactUTF16),
-        _ => None,
-    }
-}
diff --git a/src/bin/wasm-tools/dump.rs b/src/bin/wasm-tools/dump.rs
index ad06ffe1..49bde121 100644
--- a/src/bin/wasm-tools/dump.rs
+++ b/src/bin/wasm-tools/dump.rs
@@ -428,7 +428,7 @@ impl<'a> Dump<'a> {
                             | CanonicalFunction::WaitableSetPoll { .. }
                             | CanonicalFunction::WaitableSetDrop
                             | CanonicalFunction::WaitableJoin
-                            | CanonicalFunction::TaskYield { .. }
+                            | CanonicalFunction::Yield { .. }
                             | CanonicalFunction::SubtaskDrop
                             | CanonicalFunction::StreamNew { .. }
                             | CanonicalFunction::StreamRead { .. }


Test patch:
diff --git a/crates/wit-component/tests/components/async-builtins/component.wat b/crates/wit-component/tests/components/async-builtins/component.wat
index ae1c15d6..7ca0019b 100644
--- a/crates/wit-component/tests/components/async-builtins/component.wat
+++ b/crates/wit-component/tests/components/async-builtins/component.wat
@@ -14,23 +14,27 @@
     (import "$root" "[waitable-set-poll]" (func (;5;) (type 3)))
     (import "$root" "[waitable-set-drop]" (func (;6;) (type 0)))
     (import "$root" "[waitable-join]" (func (;7;) (type 1)))
-    (import "$root" "[task-yield]" (func (;8;) (type 4)))
+    (import "$root" "[yield]" (func (;8;) (type 4)))
     (import "$root" "[subtask-drop]" (func (;9;) (type 0)))
-    (import "$root" "[error-context-new;encoding=utf8]" (func (;10;) (type 3)))
-    (import "$root" "[error-context-debug-message;encoding=utf8;realloc=cabi_realloc]" (func (;11;) (type 1)))
-    (import "$root" "[error-context-drop]" (func (;12;) (type 0)))
+    (import "$root" "[error-context-new-utf8]" (func (;10;) (type 3)))
+    (import "$root" "[error-context-new-utf16]" (func (;11;) (type 3)))
+    (import "$root" "[error-context-new-latin1+utf16]" (func (;12;) (type 3)))
+    (import "$root" "[error-context-debug-message-utf8]" (func (;13;) (type 1)))
+    (import "$root" "[error-context-debug-message-utf16]" (func (;14;) (type 1)))
+    (import "$root" "[error-context-debug-message-latin1+utf16]" (func (;15;) (type 1)))
+    (import "$root" "[error-context-drop]" (func (;16;) (type 0)))
     (memory (;0;) 1)
-    (export "[async-stackful]foo" (func 13))
-    (export "[async-stackful]foo:foo/bar#foo" (func 14))
+    (export "[async-stackful]foo" (func 17))
+    (export "[async-stackful]foo:foo/bar#foo" (func 18))
     (export "memory" (memory 0))
-    (export "cabi_realloc" (func 15))
-    (func (;13;) (type 1) (param i32 i32)
+    (export "cabi_realloc" (func 19))
+    (func (;17;) (type 1) (param i32 i32)
       unreachable
     )
-    (func (;14;) (type 1) (param i32 i32)
+    (func (;18;) (type 1) (param i32 i32)
       unreachable
     )
-    (func (;15;) (type 5) (param i32 i32 i32 i32) (result i32)
+    (func (;19;) (type 5) (param i32 i32 i32 i32) (result i32)
       unreachable
     )
     (@producers
@@ -42,12 +46,16 @@
     (type (;0;) (func (param i32 i32) (result i32)))
     (type (;1;) (func (param i32 i32)))
     (type (;2;) (func (param i32 i32)))
-    (table (;0;) 5 5 funcref)
+    (table (;0;) 9 9 funcref)
     (export "0" (func $waitable-set.wait))
     (export "1" (func $waitable-set.poll))
     (export "2" (func $error-new))
-    (export "3" (func $error-debug-message))
-    (export "4" (func $task-return-foo))
+    (export "3" (func $"#func3 error-new"))
+    (export "4" (func $"#func4 error-new"))
+    (export "5" (func $error-debug-message))
+    (export "6" (func $"#func6 error-debug-message"))
+    (export "7" (func $"#func7 error-debug-message"))
+    (export "8" (func $task-return-foo))
     (export "$imports" (table 0))
     (func $waitable-set.wait (;0;) (type 0) (param i32 i32) (result i32)
       local.get 0
@@ -67,16 +75,40 @@
       i32.const 2
       call_indirect (type 0)
     )
-    (func $error-debug-message (;3;) (type 1) (param i32 i32)
+    (func $"#func3 error-new" (@name "error-new") (;3;) (type 0) (param i32 i32) (result i32)
       local.get 0
       local.get 1
       i32.const 3
-      call_indirect (type 1)
+      call_indirect (type 0)
     )
-    (func $task-return-foo (;4;) (type 2) (param i32 i32)
+    (func $"#func4 error-new" (@name "error-new") (;4;) (type 0) (param i32 i32) (result i32)
       local.get 0
       local.get 1
       i32.const 4
+      call_indirect (type 0)
+    )
+    (func $error-debug-message (;5;) (type 1) (param i32 i32)
+      local.get 0
+      local.get 1
+      i32.const 5
+      call_indirect (type 1)
+    )
+    (func $"#func6 error-debug-message" (@name "error-debug-message") (;6;) (type 1) (param i32 i32)
+      local.get 0
+      local.get 1
+      i32.const 6
+      call_indirect (type 1)
+    )
+    (func $"#func7 error-debug-message" (@name "error-debug-message") (;7;) (type 1) (param i32 i32)
+      local.get 0
+      local.get 1
+      i32.const 7
+      call_indirect (type 1)
+    )
+    (func $task-return-foo (;8;) (type 2) (param i32 i32)
+      local.get 0
+      local.get 1
+      i32.const 8
       call_indirect (type 2)
     )
     (@producers
@@ -90,10 +122,14 @@
     (import "" "0" (func (;0;) (type 0)))
     (import "" "1" (func (;1;) (type 0)))
     (import "" "2" (func (;2;) (type 0)))
-    (import "" "3" (func (;3;) (type 1)))
-    (import "" "4" (func (;4;) (type 2)))
-    (import "" "$imports" (table (;0;) 5 5 funcref))
-    (elem (;0;) (i32.const 0) func 0 1 2 3 4)
+    (import "" "3" (func (;3;) (type 0)))
+    (import "" "4" (func (;4;) (type 0)))
+    (import "" "5" (func (;5;) (type 1)))
+    (import "" "6" (func (;6;) (type 1)))
+    (import "" "7" (func (;7;) (type 1)))
+    (import "" "8" (func (;8;) (type 2)))
+    (import "" "$imports" (table (;0;) 9 9 funcref))
+    (elem (;0;) (i32.const 0) func 0 1 2 3 4 5 6 7 8)
     (@producers
       (processed-by "wit-component" "$CARGO_PKG_VERSION")
     )
@@ -105,11 +141,15 @@
   (alias core export 0 "1" (core func (;3;)))
   (core func (;4;) (canon waitable-set.drop))
   (core func (;5;) (canon waitable.join))
-  (core func (;6;) (canon task.yield))
+  (core func (;6;) (canon yield))
   (core func (;7;) (canon subtask.drop))
   (alias core export 0 "2" (core func (;8;)))
   (alias core export 0 "3" (core func (;9;)))
-  (core func (;10;) (canon error-context.drop))
+  (alias core export 0 "4" (core func (;10;)))
+  (alias core export 0 "5" (core func (;11;)))
+  (alias core export 0 "6" (core func (;12;)))
+  (alias core export 0 "7" (core func (;13;)))
+  (core func (;14;) (canon error-context.drop))
   (core instance (;1;)
     (export "[backpressure-set]" (func 0))
     (export "[waitable-set-new]" (func 1))
@@ -117,18 +157,22 @@
     (export "[waitable-set-poll]" (func 3))
     (export "[waitable-set-drop]" (func 4))
     (export "[waitable-join]" (func 5))
-    (export "[task-yield]" (func 6))
+    (export "[yield]" (func 6))
     (export "[subtask-drop]" (func 7))
-    (export "[error-context-new;encoding=utf8]" (func 8))
-    (export "[error-context-debug-message;encoding=utf8;realloc=cabi_realloc]" (func 9))
-    (export "[error-context-drop]" (func 10))
+    (export "[error-context-new-utf8]" (func 8))
+    (export "[error-context-new-utf16]" (func 9))
+    (export "[error-context-new-latin1+utf16]" (func 10))
+    (export "[error-context-debug-message-utf8]" (func 11))
+    (export "[error-context-debug-message-utf16]" (func 12))
+    (export "[error-context-debug-message-latin1+utf16]" (func 13))
+    (export "[error-context-drop]" (func 14))
   )
-  (alias core export 0 "4" (core func (;11;)))
+  (alias core export 0 "8" (core func (;15;)))
   (core instance (;2;)
-    (export "[task-return]foo" (func 11))
+    (export "[task-return]foo" (func 15))
   )
   (core instance (;3;)
-    (export "[task-return]foo" (func 11))
+    (export "[task-return]foo" (func 15))
   )
   (core instance (;4;) (instantiate 0
       (with "$root" (instance 1))
@@ -138,31 +182,39 @@
   )
   (alias core export 4 "memory" (core memory (;0;)))
   (alias core export 0 "$imports" (core table (;0;)))
-  (core func (;12;) (canon waitable-set.wait (memory 0)))
-  (core func (;13;) (canon waitable-set.poll (memory 0)))
-  (core func (;14;) (canon error-context.new (memory 0) string-encoding=utf8))
-  (alias core export 4 "cabi_realloc" (core func (;15;)))
-  (core func (;16;) (canon error-context.debug-message (memory 0) (realloc 15) string-encoding=utf8))
-  (core func (;17;) (canon task.return (result string) (memory 0) string-encoding=utf8))
+  (core func (;16;) (canon waitable-set.wait (memory 0)))
+  (core func (;17;) (canon waitable-set.poll (memory 0)))
+  (core func (;18;) (canon error-context.new (memory 0) string-encoding=utf8))
+  (core func (;19;) (canon error-context.new (memory 0) string-encoding=utf16))
+  (core func (;20;) (canon error-context.new (memory 0) string-encoding=latin1+utf16))
+  (alias core export 4 "cabi_realloc" (core func (;21;)))
+  (core func (;22;) (canon error-context.debug-message (memory 0) (realloc 21) string-encoding=utf8))
+  (core func (;23;) (canon error-context.debug-message (memory 0) (realloc 21) string-encoding=utf16))
+  (core func (;24;) (canon error-context.debug-message (memory 0) (realloc 21) string-encoding=latin1+utf16))
+  (core func (;25;) (canon task.return (result string) (memory 0) string-encoding=utf8))
   (core instance (;5;)
     (export "$imports" (table 0))
-    (export "0" (func 12))
-    (export "1" (func 13))
-    (export "2" (func 14))
-    (export "3" (func 16))
-    (export "4" (func 17))
+    (export "0" (func 16))
+    (export "1" (func 17))
+    (export "2" (func 18))
+    (export "3" (func 19))
+    (export "4" (func 20))
+    (export "5" (func 22))
+    (export "6" (func 23))
+    (export "7" (func 24))
+    (export "8" (func 25))
   )
   (core instance (;6;) (instantiate 2
       (with "" (instance 5))
     )
   )
   (type (;0;) (func (param "s" string) (result string)))
-  (alias core export 4 "[async-stackful]foo" (core func (;18;)))
-  (func (;0;) (type 0) (canon lift (core func 18) (memory 0) (realloc 15) string-encoding=utf8 async))
+  (alias core export 4 "[async-stackful]foo" (core func (;26;)))
+  (func (;0;) (type 0) (canon lift (core func 26) (memory 0) (realloc 21) string-encoding=utf8 async))
   (export (;1;) "foo" (func 0))
   (type (;1;) (func (param "s" string) (result string)))
-  (alias core export 4 "[async-stackful]foo:foo/bar#foo" (core func (;19;)))
-  (func (;2;) (type 1) (canon lift (core func 19) (memory 0) (realloc 15) string-encoding=utf8 async))
+  (alias core export 4 "[async-stackful]foo:foo/bar#foo" (core func (;27;)))
+  (func (;2;) (type 1) (canon lift (core func 27) (memory 0) (realloc 21) string-encoding=utf8 async))
   (component (;0;)
     (type (;0;) (func (param "s" string) (result string)))
     (import "import-func-foo" (func (;0;) (type 0)))
diff --git a/crates/wit-component/tests/components/async-builtins/module.wat b/crates/wit-component/tests/components/async-builtins/module.wat
index 8c100741..09cd2994 100644
--- a/crates/wit-component/tests/components/async-builtins/module.wat
+++ b/crates/wit-component/tests/components/async-builtins/module.wat
@@ -7,10 +7,14 @@
   (import "$root" "[waitable-set-poll]" (func (param i32 i32) (result i32)))
   (import "$root" "[waitable-set-drop]" (func (param i32)))
   (import "$root" "[waitable-join]" (func (param i32 i32)))
-  (import "$root" "[task-yield]" (func))
+  (import "$root" "[yield]" (func))
   (import "$root" "[subtask-drop]" (func (param i32)))
-  (import "$root" "[error-context-new;encoding=utf8]" (func (param i32 i32) (result i32)))
-  (import "$root" "[error-context-debug-message;encoding=utf8;realloc=cabi_realloc]" (func (param i32 i32)))
+  (import "$root" "[error-context-new-utf8]" (func (param i32 i32) (result i32)))
+  (import "$root" "[error-context-new-utf16]" (func (param i32 i32) (result i32)))
+  (import "$root" "[error-context-new-latin1+utf16]" (func (param i32 i32) (result i32)))
+  (import "$root" "[error-context-debug-message-utf8]" (func (param i32 i32)))
+  (import "$root" "[error-context-debug-message-utf16]" (func (param i32 i32)))
+  (import "$root" "[error-context-debug-message-latin1+utf16]" (func (param i32 i32)))
   (import "$root" "[error-context-drop]" (func (param i32)))
   (func (export "[async-stackful]foo") (param i32 i32) unreachable)
   (func (export "[async-stackful]foo:foo/bar#foo") (param i32 i32) unreachable)
diff --git a/tests/local/component-model-async/task-builtins.wast b/tests/local/component-model-async/task-builtins.wast
index 2066bd1a..b63ea92c 100644
--- a/tests/local/component-model-async/task-builtins.wast
+++ b/tests/local/component-model-async/task-builtins.wast
@@ -160,25 +160,25 @@
   "type mismatch for export `waitable.join` of module instantiation argument ``"
 )
 
-;; task.yield
+;; yield
 (component
   (core module $m
-    (import "" "task.yield" (func $task-yield))
+    (import "" "yield" (func $yield))
   )
-  (core func $task-yield (canon task.yield async))
-  (core instance $i (instantiate $m (with "" (instance (export "task.yield" (func $task-yield))))))
+  (core func $yield (canon yield async))
+  (core instance $i (instantiate $m (with "" (instance (export "yield" (func $yield))))))
 )
 
-;; task.yield; incorrect type
+;; yield; incorrect type
 (assert_invalid
   (component
     (core module $m
-      (import "" "task.yield" (func $task-yield (param i32) (result i32)))
+      (import "" "yield" (func $yield (param i32) (result i32)))
     )
-    (core func $task-yield (canon task.yield async))
-    (core instance $i (instantiate $m (with "" (instance (export "task.yield" (func $task-yield))))))
+    (core func $yield (canon yield async))
+    (core instance $i (instantiate $m (with "" (instance (export "yield" (func $yield))))))
   )
-  "type mismatch for export `task.yield` of module instantiation argument ``"
+  "type mismatch for export `yield` of module instantiation argument ``"
 )
 
 ;; subtask.drop
diff --git a/tests/local/missing-features/component-model/async.wast b/tests/local/missing-features/component-model/async.wast
index 5d0c51fe..000f9561 100644
--- a/tests/local/missing-features/component-model/async.wast
+++ b/tests/local/missing-features/component-model/async.wast
@@ -98,16 +98,16 @@
   "`waitable.join` requires the component model async feature"
 )
 
-;; task.yield
+;; yield
 (assert_invalid
   (component
     (core module $m
-      (import "" "task.yield" (func $task-yield))
+      (import "" "yield" (func $yield))
     )
-    (core func $task-yield (canon task.yield async))
-    (core instance $i (instantiate $m (with "" (instance (export "task.yield" (func $task-yield))))))
+    (core func $yield (canon yield async))
+    (core instance $i (instantiate $m (with "" (instance (export "yield" (func $yield))))))
   )
-  "`task.yield` requires the component model async feature"
+  "`yield` requires the component model async feature"
 )
 
 ;; subtask.drop
diff --git a/tests/snapshots/local/component-model-async/task-builtins.wast.json b/tests/snapshots/local/component-model-async/task-builtins.wast.json
index 5ee53942..688b2f8e 100644
--- a/tests/snapshots/local/component-model-async/task-builtins.wast.json
+++ b/tests/snapshots/local/component-model-async/task-builtins.wast.json
@@ -123,7 +123,7 @@
       "line": 174,
       "filename": "task-builtins.18.wasm",
       "module_type": "binary",
-      "text": "type mismatch for export `task.yield` of module instantiation argument ``"
+      "text": "type mismatch for export `yield` of module instantiation argument ``"
     },
     {
       "type": "module",
diff --git a/tests/snapshots/local/component-model-async/task-builtins.wast/17.print b/tests/snapshots/local/component-model-async/task-builtins.wast/17.print
index 0851c2de..7034e8c4 100644
--- a/tests/snapshots/local/component-model-async/task-builtins.wast/17.print
+++ b/tests/snapshots/local/component-model-async/task-builtins.wast/17.print
@@ -1,11 +1,11 @@
 (component
   (core module $m (;0;)
     (type (;0;) (func))
-    (import "" "task.yield" (func $task-yield (;0;) (type 0)))
+    (import "" "yield" (func $yield (;0;) (type 0)))
   )
-  (core func $task-yield (;0;) (canon task.yield async))
+  (core func $yield (;0;) (canon yield async))
   (core instance (;0;)
-    (export "task.yield" (func $task-yield))
+    (export "yield" (func $yield))
   )
   (core instance $i (;1;) (instantiate $m
       (with "" (instance 0))
diff --git a/tests/snapshots/local/missing-features/component-model/async.wast.json b/tests/snapshots/local/missing-features/component-model/async.wast.json
index b80ec6bf..407b1fce 100644
--- a/tests/snapshots/local/missing-features/component-model/async.wast.json
+++ b/tests/snapshots/local/missing-features/component-model/async.wast.json
@@ -69,7 +69,7 @@
       "line": 103,
       "filename": "async.9.wasm",
       "module_type": "binary",
-      "text": "`task.yield` requires the component model async feature"
+      "text": "`yield` requires the component model async feature"
     },
     {
       "type": "assert_invalid",