Improve handling of types and aliases in components (#5591)

This commit fixes more cases from #5565 where `export` items introducing
indices wasn't handled by accident. Additionally this fixes support for
aliasing types from instances which largely wasn't working before. Most
of the fixes here are about correctly maintaining Wasmtime's view of the
type index spaces.
This commit is contained in:
Alex Crichton
2023-01-18 18:39:21 -06:00
committed by GitHub
parent 5fd9cb405b
commit 0e92fba7e1
4 changed files with 135 additions and 7 deletions

View File

@@ -266,6 +266,7 @@ enum ComponentItemType {
Func(TypeFuncIndex),
Component(ComponentType),
Instance(ComponentInstanceType),
Type(TypeDef),
}
#[derive(Copy, Clone, PartialEq, Eq)]
@@ -621,6 +622,9 @@ impl<'a, 'data> Translator<'a, 'data> {
self.result
.initializers
.push(LocalInitializer::Export(item));
if let ComponentItem::Type(ty) = item {
self.types.push_component_typedef(ty);
}
}
}
@@ -775,7 +779,8 @@ impl<'a, 'data> Translator<'a, 'data> {
ComponentItem::ComponentInstance(i) => Some(ComponentItemType::Instance(
self.result.component_instances[i],
)),
ComponentItem::Module(_) | ComponentItem::Type(_) => None,
ComponentItem::Type(ty) => Some(ComponentItemType::Type(ty)),
ComponentItem::Module(_) => None,
};
map.insert(export.name, idx);
if let Some(ty) = ty {
@@ -848,6 +853,9 @@ impl<'a, 'data> Translator<'a, 'data> {
ComponentInstanceType::Index(ty) => {
let (_url, ty) = &self.types[ty].exports[name];
self.result.push_typedef(*ty);
if let TypeDef::Interface(_) = ty {
self.types.push_component_typedef(*ty);
}
}
// An imported component was instantiated so the type of the aliased
@@ -856,6 +864,9 @@ impl<'a, 'data> Translator<'a, 'data> {
ComponentInstanceType::InstantiatedIndex(ty) => {
let (_, ty) = self.types[ty].exports[name];
self.result.push_typedef(ty);
if let TypeDef::Interface(_) = ty {
self.types.push_component_typedef(ty);
}
}
// A static nested component was instantiated which means that the
@@ -902,6 +913,9 @@ impl<'a, 'data> Translator<'a, 'data> {
ComponentItemType::Instance(ty) => {
self.result.component_instances.push(ty);
}
ComponentItemType::Type(ty) => {
self.types.push_component_typedef(ty);
}
}
}
}

View File

@@ -683,9 +683,10 @@ impl<'a> Inliner<'a> {
TypeDef::Component(_) => {
unimplemented!("aliasing component export of component import")
}
TypeDef::Interface(_) => {
unimplemented!("aliasing type export of component import")
}
// This is handled during the initial translation
// pass and doesn't need further handling here.
TypeDef::Interface(_) => {}
// not possible with valid components
TypeDef::CoreFunc(_) => unreachable!(),

View File

@@ -335,6 +335,7 @@ pub struct ComponentTypesBuilder {
struct TypeScope {
core: PrimaryMap<TypeIndex, TypeDef>,
component: PrimaryMap<ComponentTypeIndex, TypeDef>,
instances: PrimaryMap<ComponentInstanceIndex, TypeComponentInstanceIndex>,
}
macro_rules! intern_and_fill_flat_types {
@@ -554,13 +555,13 @@ impl ComponentTypesBuilder {
ComponentTypeDeclaration::CoreType(ty) => self.type_declaration_core_type(ty)?,
ComponentTypeDeclaration::Alias(alias) => self.type_declaration_alias(alias)?,
ComponentTypeDeclaration::Export { name, url, ty } => {
let ty = self.component_type_ref(ty);
let ty = self.type_declaration_define(ty);
result
.exports
.insert(name.to_string(), (url.to_string(), ty));
}
ComponentTypeDeclaration::Import(import) => {
let ty = self.component_type_ref(&import.ty);
let ty = self.type_declaration_define(&import.ty);
result
.imports
.insert(import.name.to_string(), (import.url.to_string(), ty));
@@ -586,7 +587,7 @@ impl ComponentTypesBuilder {
InstanceTypeDeclaration::CoreType(ty) => self.type_declaration_core_type(ty)?,
InstanceTypeDeclaration::Alias(alias) => self.type_declaration_alias(alias)?,
InstanceTypeDeclaration::Export { name, url, ty } => {
let ty = self.component_type_ref(ty);
let ty = self.type_declaration_define(ty);
result
.exports
.insert(name.to_string(), (url.to_string(), ty));
@@ -629,11 +630,49 @@ impl ComponentTypesBuilder {
let ty = self.component_outer_type(*count, ComponentTypeIndex::from_u32(*index));
self.push_component_typedef(ty);
}
ComponentAlias::InstanceExport {
kind: _,
instance_index,
name,
} => {
let ty = self.type_scopes.last().unwrap().instances
[ComponentInstanceIndex::from_u32(*instance_index)];
let (_, ty) = self.component_types[ty].exports[*name];
self.push_component_typedef(ty);
}
a => unreachable!("invalid alias {a:?}"),
}
Ok(())
}
fn type_declaration_define(&mut self, ty: &wasmparser::ComponentTypeRef) -> TypeDef {
let ty = self.component_type_ref(ty);
let scope = self.type_scopes.last_mut().unwrap();
match ty {
// If an import or an export within a component or instance type
// references an interface type itself then that creates a new type
// which is effectively an alias, so push the type information here.
TypeDef::Interface(_) => {
self.push_component_typedef(ty);
}
// When an import or an export references a component instance then
// that creates a "pseudo-instance" which type information is
// maintained about. This is later used during the `InstanceExport`
// alias within a type declaration.
TypeDef::ComponentInstance(ty) => {
scope.instances.push(ty);
}
// All other valid types are ignored since we don't need to maintain
// metadata about them here as index spaces are modified that we're
// not interested in.
_ => {}
}
ty
}
fn func_type(&mut self, ty: &wasmparser::ComponentFuncType<'_>) -> TypeFuncIndex {
let ty = TypeFunc {
params: ty

View File

@@ -246,3 +246,77 @@
(type $t101 (list $t100))
)
"type nesting is too deep")
(component
(type (instance
(export $x "x" (instance
(type $t u32)
(export "y" (type (eq $t)))
))
(alias export $x "y" (type $t))
(export "my-y" (type (eq $t)))
))
(type (component
(import "x" (instance $x
(type $t u32)
(export "y" (type (eq $t)))
))
(alias export $x "y" (type $t))
(export "my-y" (type (eq $t)))
))
)
(component
(type $t u32)
(export $t2 "t" (type $t))
(type $r (record (field "x" $t2)))
(export "r" (type $r))
)
(component
(component
(import "x" (instance $i
(type $i u32)
(export "i" (type (eq $i)))
))
(alias export $i "i" (type $i))
(export "i" (type $i))
)
)
(component
(type $u u32)
(instance $i
(export "i" (type $u))
)
(alias export $i "i" (type $i))
(export "i" (type $i))
)
(component
(component $c
(type $t u32)
(export "t" (type $t))
)
(instance $c (instantiate $c))
(export "i" (type $c "t"))
)
(component
(component $c
(import "x" (component $c
(type $t u32)
(export "t" (type (eq $t)))
))
(instance $c (instantiate $c))
(export "i" (type $c "t"))
)
(component $x
(type $t u32)
(export "t" (type $t))
)
(instance $c (instantiate $c (with "x" (component $x))))
)