Skip to content

Commit

Permalink
feat: support component type introspection (#7804)
Browse files Browse the repository at this point in the history
* feat: support component instance import type introspection

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* refactor: implement `import_types` on `Linker`

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* refactor: flatten `types::ComponentItem` members

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* refactor: remove `types` re-exports

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* feat: implement component type introspection

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* chore: derive `Debug` for `Field`

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* refactor: return `ExactSizeIterator` for component function parameters/results

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* tests: add `introspection` test

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* chore: derive `Clone` on `ComponentItem` types

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* feat: support module and instance type introspection

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

---------

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
  • Loading branch information
rvolosatovs authored Jan 26, 2024
1 parent 5c0027b commit 2288538
Show file tree
Hide file tree
Showing 10 changed files with 748 additions and 67 deletions.
23 changes: 17 additions & 6 deletions crates/environ/src/component/dfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,14 @@ pub enum Export {
options: CanonicalOptions,
},
ModuleStatic(StaticModuleIndex),
ModuleImport(RuntimeImportIndex),
Instance(IndexMap<String, Export>),
ModuleImport {
ty: TypeModuleIndex,
import: RuntimeImportIndex,
},
Instance {
ty: Option<TypeComponentInstanceIndex>,
exports: IndexMap<String, Export>,
},
Type(TypeDef),
}

Expand Down Expand Up @@ -487,12 +493,17 @@ impl LinearizeDfg<'_> {
}
}
Export::ModuleStatic(i) => info::Export::ModuleStatic(*i),
Export::ModuleImport(i) => info::Export::ModuleImport(*i),
Export::Instance(map) => info::Export::Instance(
map.iter()
Export::ModuleImport { ty, import } => info::Export::ModuleImport {
ty: *ty,
import: *import,
},
Export::Instance { ty, exports } => info::Export::Instance {
ty: *ty,
exports: exports
.iter()
.map(|(name, export)| (name.clone(), self.export(export)))
.collect(),
),
},
Export::Type(def) => info::Export::Type(*def),
}
}
Expand Down
14 changes: 12 additions & 2 deletions crates/environ/src/component/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,10 +402,20 @@ pub enum Export {
/// A module defined within this component is exported.
ModuleStatic(StaticModuleIndex),
/// A module imported into this component is exported.
ModuleImport(RuntimeImportIndex),
ModuleImport {
/// Module type index
ty: TypeModuleIndex,
/// Module runtime import index
import: RuntimeImportIndex,
},
/// A nested instance is being exported which has recursively defined
/// `Export` items.
Instance(IndexMap<String, Export>),
Instance {
/// Instance type index, if such is assigned
ty: Option<TypeComponentInstanceIndex>,
/// Instance export map
exports: IndexMap<String, Export>,
},
/// An exported type from a component or instance, currently only
/// informational.
Type(TypeDef),
Expand Down
11 changes: 6 additions & 5 deletions crates/environ/src/component/translate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ enum LocalInitializer<'data> {
HashMap<&'data str, ComponentItem>,
ComponentInstanceTypeId,
),
ComponentSynthetic(HashMap<&'data str, ComponentItem>),
ComponentSynthetic(HashMap<&'data str, ComponentItem>, ComponentInstanceTypeId),

// alias section
AliasExportFunc(ModuleInstanceIndex, &'data str),
Expand Down Expand Up @@ -581,18 +581,18 @@ impl<'a, 'data> Translator<'a, 'data> {
let mut index = self.validator.types(0).unwrap().component_instance_count();
self.validator.component_instance_section(&s)?;
for instance in s {
let types = self.validator.types(0).unwrap();
let ty = types.component_instance_at(index);
let init = match instance? {
wasmparser::ComponentInstance::Instantiate {
component_index,
args,
} => {
let types = self.validator.types(0).unwrap();
let ty = types.component_instance_at(index);
let index = ComponentIndex::from_u32(component_index);
self.instantiate_component(index, &args, ty)?
}
wasmparser::ComponentInstance::FromExports(exports) => {
self.instantiate_component_from_exports(&exports)?
self.instantiate_component_from_exports(&exports, ty)?
}
};
self.result.initializers.push(init);
Expand Down Expand Up @@ -746,14 +746,15 @@ impl<'a, 'data> Translator<'a, 'data> {
fn instantiate_component_from_exports(
&mut self,
exports: &[wasmparser::ComponentExport<'data>],
ty: ComponentInstanceTypeId,
) -> Result<LocalInitializer<'data>> {
let mut map = HashMap::with_capacity(exports.len());
for export in exports {
let idx = self.kind_to_item(export.kind, export.index)?;
map.insert(export.name.0, idx);
}

Ok(LocalInitializer::ComponentSynthetic(map))
Ok(LocalInitializer::ComponentSynthetic(map, ty))
}

fn kind_to_item(
Expand Down
38 changes: 25 additions & 13 deletions crates/environ/src/component/translate/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,10 @@ enum ComponentInstanceDef<'a> {
//
// FIXME: same as the issue on `ComponentClosure` where this is cloned a lot
// and may need `Rc`.
Items(IndexMap<&'a str, ComponentItemDef<'a>>),
Items(
IndexMap<&'a str, ComponentItemDef<'a>>,
Option<TypeComponentInstanceIndex>,
),
}

#[derive(Clone)]
Expand Down Expand Up @@ -397,7 +400,7 @@ impl<'a> Inliner<'a> {
match frames.last_mut() {
Some((parent, _)) => {
parent.finish_instantiate(
ComponentInstanceDef::Items(exports),
ComponentInstanceDef::Items(exports, None),
instance_ty.unwrap(),
types,
);
Expand Down Expand Up @@ -783,14 +786,16 @@ impl<'a> Inliner<'a> {
return Ok(Some(frame));
}

ComponentSynthetic(map) => {
ComponentSynthetic(map, ty) => {
let items = map
.iter()
.map(|(name, index)| Ok((*name, frame.item(*index, types)?)))
.collect::<Result<_>>()?;
let types_ref = frame.translation.types_ref();
let ty = types.convert_instance(types_ref, *ty)?;
frame
.component_instances
.push(ComponentInstanceDef::Items(items));
.push(ComponentInstanceDef::Items(items, Some(ty)));
}

// Core wasm aliases, this and the cases below, are creating
Expand Down Expand Up @@ -846,7 +851,7 @@ impl<'a> Inliner<'a> {
// through instantiation of a component or through a
// synthetic renaming of items we just schlep around the
// definitions of various items here.
ComponentInstanceDef::Items(map) => frame.push_item(map[*name].clone()),
ComponentInstanceDef::Items(map, _) => frame.push_item(map[*name].clone()),
}
}

Expand Down Expand Up @@ -1029,7 +1034,10 @@ impl<'a> Inliner<'a> {
// from.
ComponentItemDef::Module(module) => match module {
ModuleDef::Static(idx) => dfg::Export::ModuleStatic(idx),
ModuleDef::Import(path, _) => dfg::Export::ModuleImport(self.runtime_import(&path)),
ModuleDef::Import(path, ty) => dfg::Export::ModuleImport {
ty,
import: self.runtime_import(&path),
},
},

ComponentItemDef::Func(func) => match func {
Expand All @@ -1051,7 +1059,7 @@ impl<'a> Inliner<'a> {
},

ComponentItemDef::Instance(instance) => {
let mut result = IndexMap::new();
let mut exports = IndexMap::new();
match instance {
// If this instance is one that was originally imported by
// the component itself then the imports are translated here
Expand All @@ -1064,20 +1072,24 @@ impl<'a> Inliner<'a> {
for (name, ty) in types[ty].exports.iter() {
let path = path.push(name);
let def = ComponentItemDef::from_import(path, *ty)?;
self.record_export(name, def, types, &mut result)?;
self.record_export(name, def, types, &mut exports)?;
}
dfg::Export::Instance {
ty: Some(ty),
exports,
}
}

// An exported instance which is itself a bag of items is
// translated recursively here to our `result` map which is
// translated recursively here to our `exports` map which is
// the bag of items we're exporting.
ComponentInstanceDef::Items(map) => {
ComponentInstanceDef::Items(map, ty) => {
for (name, def) in map {
self.record_export(name, def, types, &mut result)?;
self.record_export(name, def, types, &mut exports)?;
}
dfg::Export::Instance { ty, exports }
}
}
dfg::Export::Instance(result)
}

// FIXME(#4283) should make an official decision on whether this is
Expand Down Expand Up @@ -1292,7 +1304,7 @@ impl<'a> ComponentItemDef<'a> {
cur = match instance {
// If this instance is a "bag of things" then this is as easy as
// looking up the name in the bag of names.
ComponentInstanceDef::Items(names) => names[element].clone(),
ComponentInstanceDef::Items(names, _) => names[element].clone(),

// If, however, this instance is an imported instance then this
// is a further projection within the import with one more path
Expand Down
70 changes: 63 additions & 7 deletions crates/environ/src/component/types.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::component::{MAX_FLAT_PARAMS, MAX_FLAT_RESULTS};
use crate::component::{Export, MAX_FLAT_PARAMS, MAX_FLAT_RESULTS};
use crate::{
EntityType, ModuleTypes, ModuleTypesBuilder, PrimaryMap, SignatureIndex, TypeConvert,
WasmHeapType, WasmType,
CompiledModuleInfo, EntityType, ModuleTypes, ModuleTypesBuilder, PrimaryMap, SignatureIndex,
TypeConvert, WasmHeapType, WasmType,
};
use anyhow::{bail, Result};
use cranelift_entity::EntityRef;
Expand Down Expand Up @@ -397,11 +397,67 @@ macro_rules! intern_and_fill_flat_types {
}

impl ComponentTypesBuilder {
fn export_type_def(
&mut self,
static_modules: &PrimaryMap<StaticModuleIndex, CompiledModuleInfo>,
ty: &Export,
) -> TypeDef {
match ty {
Export::LiftedFunction { ty, .. } => TypeDef::ComponentFunc(*ty),
Export::ModuleStatic(idx) => {
let mut module_ty = TypeModule::default();
let module = &static_modules[*idx].module;
for (namespace, name, ty) in module.imports() {
module_ty
.imports
.insert((namespace.to_string(), name.to_string()), ty);
}
for (name, ty) in module.exports.iter() {
module_ty
.exports
.insert(name.to_string(), module.type_of(*ty));
}
TypeDef::Module(self.component_types.modules.push(module_ty))
}
Export::ModuleImport { ty, .. } => TypeDef::Module(*ty),
Export::Instance { ty: Some(ty), .. } => TypeDef::ComponentInstance(*ty),
Export::Instance { exports, .. } => {
let mut instance_ty = TypeComponentInstance::default();
for (name, ty) in exports {
instance_ty
.exports
.insert(name.to_string(), self.export_type_def(static_modules, ty));
}
TypeDef::ComponentInstance(
self.component_types.component_instances.push(instance_ty),
)
}
Export::Type(ty) => *ty,
}
}

/// Finishes this list of component types and returns the finished
/// structure.
pub fn finish(mut self) -> ComponentTypes {
/// structure and the [`TypeComponentIndex`] corresponding to top-level component
/// with `imports` and `exports` specified.
pub fn finish<'a>(
mut self,
static_modules: &PrimaryMap<StaticModuleIndex, CompiledModuleInfo>,
imports: impl IntoIterator<Item = (String, TypeDef)>,
exports: impl IntoIterator<Item = (String, &'a Export)>,
) -> (ComponentTypes, TypeComponentIndex) {
let mut component_ty = TypeComponent::default();
for (name, ty) in imports {
component_ty.imports.insert(name, ty);
}
for (name, ty) in exports {
component_ty
.exports
.insert(name, self.export_type_def(static_modules, ty));
}
let ty = self.component_types.components.push(component_ty);

self.component_types.module_types = self.module_types.finish();
self.component_types
(self.component_types, ty)
}

/// Smaller helper method to find a `SignatureIndex` which corresponds to
Expand Down Expand Up @@ -558,7 +614,7 @@ impl ComponentTypesBuilder {
Ok(self.component_types.components.push(result))
}

fn convert_instance(
pub(crate) fn convert_instance(
&mut self,
types: types::TypesRef<'_>,
id: types::ComponentInstanceTypeId,
Expand Down
Loading

0 comments on commit 2288538

Please sign in to comment.