Skip to content

Commit

Permalink
feat: initial error-context implementation
Browse files Browse the repository at this point in the history
This commit implements error-context related functions inside the VM,
along with tests to ensure that basic error-context.new and
error-context.debug-message functionality works.

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>
  • Loading branch information
vados-cosmonic committed Jan 16, 2025
1 parent 742e18f commit 89f1f81
Show file tree
Hide file tree
Showing 19 changed files with 407 additions and 95 deletions.
10 changes: 5 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -297,9 +297,9 @@ io-extras = "0.18.1"
rustix = "0.38.43"
# wit-bindgen:
# TODO: switch to crates.io once https://github.com/bytecodealliance/wit-bindgen/pull/1124 has been released
wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", default-features = false }
wit-bindgen-rt = { git = "https://github.com/bytecodealliance/wit-bindgen", default-features = false }
wit-bindgen-rust-macro = { git = "https://github.com/bytecodealliance/wit-bindgen", default-features = false }
wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "341c47375d44bb82dc726d34e94bbb2e92b4b595", default-features = false }
wit-bindgen-rt = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "341c47375d44bb82dc726d34e94bbb2e92b4b595", default-features = false }
wit-bindgen-rust-macro = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "341c47375d44bb82dc726d34e94bbb2e92b4b595", default-features = false }

# wasm-tools family:
wasmparser = { version = "0.223.0", default-features = false, features = ['simd'] }
Expand Down
11 changes: 11 additions & 0 deletions cranelift/entity/src/primary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,17 @@ where
self.elems.get_mut(k.index())
}

/// Get the element at `k` if it exists, mutable version.
pub fn get_mut_or_insert_with(&mut self, k: K, f: impl FnOnce() -> V) -> &mut V {
if self.elems.get(k.index()).is_none() {
self.elems.insert(k.index(), f());
}

self.elems
.get_mut(k.index())
.expect("missing existing element")
}

/// Is this map completely empty?
pub fn is_empty(&self) -> bool {
self.elems.is_empty()
Expand Down
4 changes: 2 additions & 2 deletions crates/cranelift/src/compiler/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1288,7 +1288,7 @@ impl<'a> TrampolineCompiler<'a> {

fn translate_error_context_call(
&mut self,
ty: TypeErrorContextTableIndex,
ty: TypeComponentLocalErrorContextTableIndex,
options: &CanonicalOptions,
offset: u32,
params: Vec<ir::AbiParam>,
Expand Down Expand Up @@ -1379,7 +1379,7 @@ impl<'a> TrampolineCompiler<'a> {
}
}

fn translate_error_context_drop_call(&mut self, ty: TypeErrorContextTableIndex) {
fn translate_error_context_drop_call(&mut self, ty: TypeComponentLocalErrorContextTableIndex) {
match self.abi {
Abi::Wasm => {}

Expand Down
6 changes: 3 additions & 3 deletions crates/environ/src/component/dfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,15 +354,15 @@ pub enum Trampoline {
ty: TypeFutureTableIndex,
},
ErrorContextNew {
ty: TypeErrorContextTableIndex,
ty: TypeComponentLocalErrorContextTableIndex,
options: CanonicalOptions,
},
ErrorContextDebugMessage {
ty: TypeErrorContextTableIndex,
ty: TypeComponentLocalErrorContextTableIndex,
options: CanonicalOptions,
},
ErrorContextDrop {
ty: TypeErrorContextTableIndex,
ty: TypeComponentLocalErrorContextTableIndex,
},
ResourceTransferOwn,
ResourceTransferBorrow,
Expand Down
6 changes: 3 additions & 3 deletions crates/environ/src/component/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -849,7 +849,7 @@ pub enum Trampoline {
/// specified debug message.
ErrorContextNew {
/// The table index for the `error-context` type in the caller instance.
ty: TypeErrorContextTableIndex,
ty: TypeComponentLocalErrorContextTableIndex,
/// String encoding, memory, etc. to use when loading debug message.
options: CanonicalOptions,
},
Expand All @@ -861,15 +861,15 @@ pub enum Trampoline {
/// to `error.new`.
ErrorContextDebugMessage {
/// The table index for the `error-context` type in the caller instance.
ty: TypeErrorContextTableIndex,
ty: TypeComponentLocalErrorContextTableIndex,
/// String encoding, memory, etc. to use when storing debug message.
options: CanonicalOptions,
},

/// A `error-context.drop` intrinsic to drop a specified `error-context`.
ErrorContextDrop {
/// The table index for the `error-context` type in the caller instance.
ty: TypeErrorContextTableIndex,
ty: TypeComponentLocalErrorContextTableIndex,
},

/// An intrinsic used by FACT-generated modules which will transfer an owned
Expand Down
16 changes: 12 additions & 4 deletions crates/environ/src/component/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,19 @@ indices! {
/// This is analogous to `TypeResourceTableIndex` in that it tracks
/// ownership of stream within each (sub)component instance.
pub struct TypeStreamTableIndex(u32);

/// Index pointing to a error context table within a component.
///
/// This is analogous to `TypeResourceTableIndex` in that it tracks
/// ownership of error contexts within each (sub)component instance.
pub struct TypeErrorContextTableIndex(u32);
pub struct TypeComponentLocalErrorContextTableIndex(u32);

/// Index pointing to a (component) globally tracked error context table entry
///
/// Unlike [`TypeComponentLocalErrorContextTableIndex`], this index refers to
/// the global state table for error contexts at the level of the entire component,
/// not just a subcomponent.
pub struct TypeComponentGlobalErrorContextTableIndex(u32);

/// Index pointing to an interned `task.return` type within a component.
pub struct TypeTaskReturnIndex(u32);
Expand Down Expand Up @@ -267,7 +275,7 @@ pub struct ComponentTypes {
pub(super) future_tables: PrimaryMap<TypeFutureTableIndex, TypeFutureTable>,
pub(super) streams: PrimaryMap<TypeStreamIndex, TypeStream>,
pub(super) stream_tables: PrimaryMap<TypeStreamTableIndex, TypeStreamTable>,
pub(super) error_context_tables: PrimaryMap<TypeErrorContextTableIndex, TypeErrorContextTable>,
pub(super) error_context_tables: PrimaryMap<TypeComponentLocalErrorContextTableIndex, TypeErrorContextTable>,
pub(super) task_returns: PrimaryMap<TypeTaskReturnIndex, TypeTaskReturn>,
}

Expand Down Expand Up @@ -357,7 +365,7 @@ impl_index! {
impl Index<TypeStreamIndex> for ComponentTypes { TypeStream => streams }
impl Index<TypeFutureTableIndex> for ComponentTypes { TypeFutureTable => future_tables }
impl Index<TypeStreamTableIndex> for ComponentTypes { TypeStreamTable => stream_tables }
impl Index<TypeErrorContextTableIndex> for ComponentTypes { TypeErrorContextTable => error_context_tables }
impl Index<TypeComponentLocalErrorContextTableIndex> for ComponentTypes { TypeErrorContextTable => error_context_tables }
}

// Additionally forward anything that can index `ModuleTypes` to `ModuleTypes`
Expand Down Expand Up @@ -518,7 +526,7 @@ pub enum InterfaceType {
Borrow(TypeResourceTableIndex),
Future(TypeFutureTableIndex),
Stream(TypeStreamTableIndex),
ErrorContext(TypeErrorContextTableIndex),
ErrorContext(TypeComponentLocalErrorContextTableIndex),
}

impl From<&wasmparser::PrimitiveValType> for InterfaceType {
Expand Down
10 changes: 5 additions & 5 deletions crates/environ/src/component/types_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub struct ComponentTypesBuilder {
streams: HashMap<TypeStream, TypeStreamIndex>,
future_tables: HashMap<TypeFutureTable, TypeFutureTableIndex>,
stream_tables: HashMap<TypeStreamTable, TypeStreamTableIndex>,
error_context_tables: HashMap<TypeErrorContextTable, TypeErrorContextTableIndex>,
error_context_tables: HashMap<TypeErrorContextTable, TypeComponentLocalErrorContextTableIndex>,
task_returns: HashMap<TypeTaskReturn, TypeTaskReturnIndex>,

component_types: ComponentTypes,
Expand Down Expand Up @@ -210,7 +210,7 @@ impl ComponentTypesBuilder {
}

/// Returns the number of error-context tables allocated so far, or the maximum
/// `TypeErrorContextTableIndex`.
/// `TypeComponentLocalErrorContextTableIndex`.
pub fn num_error_context_tables(&self) -> usize {
self.component_types.error_context_tables.len()
}
Expand Down Expand Up @@ -444,7 +444,7 @@ impl ComponentTypesBuilder {
}

/// Retrieve Wasmtime's type representation of the `error-context` type.
pub fn error_context_type(&mut self) -> Result<TypeErrorContextTableIndex> {
pub fn error_context_type(&mut self) -> Result<TypeComponentLocalErrorContextTableIndex> {
self.error_context_table_type()
}

Expand Down Expand Up @@ -599,7 +599,7 @@ impl ComponentTypesBuilder {
}))
}

fn error_context_table_type(&mut self) -> Result<TypeErrorContextTableIndex> {
fn error_context_table_type(&mut self) -> Result<TypeComponentLocalErrorContextTableIndex> {
Ok(self.add_error_context_table_type(TypeErrorContextTable {
instance: self.resources.get_current_instance().unwrap(),
}))
Expand Down Expand Up @@ -694,7 +694,7 @@ impl ComponentTypesBuilder {
pub fn add_error_context_table_type(
&mut self,
ty: TypeErrorContextTable,
) -> TypeErrorContextTableIndex {
) -> TypeComponentLocalErrorContextTableIndex {
intern(
&mut self.error_context_tables,
&mut self.component_types.error_context_tables,
Expand Down
4 changes: 2 additions & 2 deletions crates/environ/src/fact/trampoline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use crate::component::{
CanonicalAbiInfo, ComponentTypesBuilder, FixedEncoding as FE, FlatType, InterfaceType,
StringEncoding, Transcode, TypeEnumIndex, TypeErrorContextTableIndex, TypeFlagsIndex,
StringEncoding, Transcode, TypeEnumIndex, TypeComponentLocalErrorContextTableIndex, TypeFlagsIndex,
TypeFutureTableIndex, TypeListIndex, TypeOptionIndex, TypeRecordIndex, TypeResourceTableIndex,
TypeResultIndex, TypeStreamTableIndex, TypeTupleIndex, TypeVariantIndex, VariantInfo,
FLAG_MAY_ENTER, FLAG_MAY_LEAVE, MAX_FLAT_PARAMS, MAX_FLAT_RESULTS,
Expand Down Expand Up @@ -2935,7 +2935,7 @@ impl Compiler<'_, '_> {

fn translate_error_context_context(
&mut self,
src_ty: TypeErrorContextTableIndex,
src_ty: TypeComponentLocalErrorContextTableIndex,
src: &Source<'_>,
dst_ty: &InterfaceType,
dst: &Destination,
Expand Down
5 changes: 5 additions & 0 deletions crates/misc/component-async-tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1289,4 +1289,9 @@ mod test {
&fs::read(test_programs_artifacts::ASYNC_HTTP_MIDDLEWARE_COMPONENT).await?;
test_http_echo(&compose(middleware, echo).await?, true).await
}

#[tokio::test]
async fn async_error_context() -> Result<()> {
test_run(&fs::read(test_programs_artifacts::ASYNC_ERROR_CONTEXT_COMPONENT).await?).await
}
}
4 changes: 4 additions & 0 deletions crates/misc/component-async-tests/wit/test.wit
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,7 @@ world borrowing-host {
import borrowing-types;
export run-bool;
}

world error-context-usage {
export run;
}
2 changes: 1 addition & 1 deletion crates/test-programs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ anyhow = { workspace = true, features = ['std'] }
wasi = "0.11.0"
wasi-nn = "0.6.0"
wit-bindgen = { workspace = true, features = ['default'] }
wit-bindgen-rt = { workspace = true }
wit-bindgen-rt = { workspace = true, features = ['async'] }
libc = { workspace = true }
getrandom = "0.2.9"
futures = { workspace = true, default-features = false, features = ['alloc'] }
Expand Down
29 changes: 29 additions & 0 deletions crates/test-programs/src/bin/async_error_context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
mod bindings {
wit_bindgen::generate!({
path: "../misc/component-async-tests/wit",
world: "error-context-usage",
async: {
exports: [
"local:local/run#run",
],
}
});

use super::Component;
export!(Component);
}
use bindings::exports::local::local::run::Guest;

use wit_bindgen_rt::async_support::error_context_new;

struct Component;

impl Guest for Component {
async fn run() {
let err_ctx = error_context_new("error".into());
_ = err_ctx.debug_message();
}
}

// Unused function; required since this file is built as a `bin`:
fn main() {}
Loading

0 comments on commit 89f1f81

Please sign in to comment.