Skip to content

Commit

Permalink
Refactor how error-context.* intrinsics are imported (#2067)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
alexcrichton authored Feb 24, 2025
1 parent 53d1e22 commit 90545d4
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 113 deletions.
30 changes: 12 additions & 18 deletions crates/wit-component/src/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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,
},
}

Expand Down Expand Up @@ -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,
Expand All @@ -2304,7 +2299,6 @@ impl<'a> Shims<'a> {
kind: ShimKind::ErrorContextDebugMessage {
for_module,
encoding: *encoding,
realloc,
},
sig: WasmSignature {
params: vec![WasmType::I32; 2],
Expand Down
78 changes: 26 additions & 52 deletions crates/wit-component/src/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down Expand Up @@ -633,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());
Expand Down Expand Up @@ -1271,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);
}
Expand Down Expand Up @@ -1420,7 +1421,7 @@ trait NameMangling {
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,
Expand Down Expand Up @@ -1519,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> {
Expand Down Expand Up @@ -1701,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]")
Expand Down Expand Up @@ -2043,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,
}
}
Loading

0 comments on commit 90545d4

Please sign in to comment.