Skip to content

Commit 3c83513

Browse files
committed
Plumb (implements "...") support throughout
This commit plumbs the type system support for `(implement "...")` in the component model throughout Wasmtime. Notably the fields and such are all faithfully carried over from wasmparser into the type reflection within Wasmtime itself. This'll be needed for loading components with this field. Note that no bindings generation is not updated yet, this is only the compiler/runtime side of `(implement "...")` and bindings generation will be a subsequent update.
1 parent b8e47ab commit 3c83513

26 files changed

Lines changed: 295 additions & 119 deletions

File tree

crates/c-api/src/component/types/component.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ pub unsafe extern "C" fn wasmtime_component_type_import_get(
3737
};
3838
match ty.ty.get_import(&engine.engine, name) {
3939
Some(item) => {
40-
ret.write(item.into());
40+
ret.write(item.ty.into());
4141
true
4242
}
4343
None => false,
@@ -58,7 +58,7 @@ pub extern "C" fn wasmtime_component_type_import_nth(
5858
let name: &str = name;
5959
name_ret.write(name.as_ptr());
6060
name_len_ret.write(name.len());
61-
type_ret.write(item.into());
61+
type_ret.write(item.ty.into());
6262
true
6363
}
6464
None => false,
@@ -87,7 +87,7 @@ pub unsafe extern "C" fn wasmtime_component_type_export_get(
8787
};
8888
match ty.ty.get_export(&engine.engine, name) {
8989
Some(item) => {
90-
ret.write(item.into());
90+
ret.write(item.ty.into());
9191
true
9292
}
9393
None => false,
@@ -108,7 +108,7 @@ pub extern "C" fn wasmtime_component_type_export_nth(
108108
let name: &str = name;
109109
name_ret.write(name.as_ptr());
110110
name_len_ret.write(name.len());
111-
type_ret.write(item.into());
111+
type_ret.write(item.ty.into());
112112
true
113113
}
114114
None => false,

crates/c-api/src/component/types/instance.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ pub unsafe extern "C" fn wasmtime_component_instance_type_export_get(
3333
};
3434
match ty.ty.get_export(&engine.engine, name) {
3535
Some(item) => {
36-
ret.write(item.into());
36+
ret.write(item.ty.into());
3737
true
3838
}
3939
None => false,
@@ -54,7 +54,7 @@ pub extern "C" fn wasmtime_component_instance_type_export_nth(
5454
let name: &str = name;
5555
name_ret.write(name.as_ptr());
5656
name_len_ret.write(name.len());
57-
type_ret.write(item.into());
57+
type_ret.write(item.ty.into());
5858
true
5959
}
6060
None => false,

crates/cli-flags/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,9 @@ wasmtime_option_group! {
460460
/// Component model support for fixed-length lists: this corresponds
461461
/// to the 🔧 emoji in the component model specification
462462
pub component_model_fixed_length_lists: Option<bool>,
463+
/// Component model support for `(implements ...)`, corresponds to the
464+
/// 🏷️ emoji in the upstream spec.
465+
pub component_model_implements: Option<bool>,
463466
/// Whether or not any concurrency infrastructure in Wasmtime is
464467
/// enabled or not.
465468
pub concurrency_support: Option<bool>,
@@ -1223,6 +1226,7 @@ impl CommonOptions {
12231226
("component-model", component_model_error_context, wasm_component_model_error_context)
12241227
("component-model", component_model_map, wasm_component_model_map)
12251228
("component-model", component_model_fixed_length_lists, wasm_component_model_fixed_length_lists)
1229+
("component-model", component_model_implements, wasm_component_model_implements)
12261230
("threads", threads, wasm_threads)
12271231
("gc", gc, wasm_gc)
12281232
("gc", reference_types, wasm_reference_types)

crates/environ/src/component/dfg.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,13 @@ use wasmparser::component_types::ComponentCoreModuleTypeId;
4343
#[derive(Default)]
4444
pub struct ComponentDfg {
4545
/// Same as `Component::import_types`
46-
pub import_types: PrimaryMap<ImportIndex, (String, TypeDef)>,
46+
pub import_types: PrimaryMap<ImportIndex, (String, ComponentExtern)>,
4747

4848
/// Same as `Component::imports`
4949
pub imports: PrimaryMap<RuntimeImportIndex, (ImportIndex, Vec<String>)>,
5050

5151
/// Same as `Component::exports`
52-
pub exports: IndexMap<String, Export>,
52+
pub exports: IndexMap<String, (Export, ComponentExternData)>,
5353

5454
/// All trampolines and their type signature which will need to get
5555
/// compiled by Cranelift.
@@ -254,7 +254,7 @@ pub enum Export {
254254
},
255255
Instance {
256256
ty: TypeComponentInstanceIndex,
257-
exports: IndexMap<String, Export>,
257+
exports: IndexMap<String, (Export, ComponentExternData)>,
258258
},
259259
Type(TypeDef),
260260
}
@@ -639,10 +639,10 @@ impl ComponentDfg {
639639
// creating some lowered imports, perhaps some saved modules, etc.
640640
let mut export_items = PrimaryMap::new();
641641
let mut exports = NameMap::default();
642-
for (name, export) in self.exports.iter() {
642+
for (name, (export, data)) in self.exports.iter() {
643643
let export =
644644
linearize.export(export, &mut export_items, wasmtime_types, wasmparser_types)?;
645-
exports.insert(name, &mut NameMapNoIntern, false, export)?;
645+
exports.insert(name, &mut NameMapNoIntern, false, (export, data.clone()))?;
646646
}
647647

648648
// With all those pieces done the results of the dataflow-based
@@ -802,10 +802,10 @@ impl LinearizeDfg<'_> {
802802
ty: *ty,
803803
exports: {
804804
let mut map = NameMap::default();
805-
for (name, export) in exports {
805+
for (name, (export, data)) in exports {
806806
let export =
807807
self.export(export, items, wasmtime_types, wasmparser_types)?;
808-
map.insert(name, &mut NameMapNoIntern, false, export)?;
808+
map.insert(name, &mut NameMapNoIntern, false, (export, data.clone()))?;
809809
}
810810
map
811811
},

crates/environ/src/component/info.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ pub struct Component {
7676
///
7777
/// Note that each name is given an `ImportIndex` here for the next map to
7878
/// refer back to.
79-
pub import_types: PrimaryMap<ImportIndex, (String, TypeDef)>,
79+
pub import_types: PrimaryMap<ImportIndex, (String, ComponentExtern)>,
8080

8181
/// A list of "flattened" imports that are used by this instance.
8282
///
@@ -107,7 +107,7 @@ pub struct Component {
107107
pub imports: PrimaryMap<RuntimeImportIndex, (ImportIndex, Vec<String>)>,
108108

109109
/// This component's own root exports from the component itself.
110-
pub exports: NameMap<TryString, ExportIndex>,
110+
pub exports: NameMap<TryString, (ExportIndex, ComponentExternData)>,
111111

112112
/// All exports of this component and exported instances of this component.
113113
///
@@ -491,7 +491,7 @@ pub enum Export {
491491
/// Instance type index, if such is assigned
492492
ty: TypeComponentInstanceIndex,
493493
/// Instance export map
494-
exports: NameMap<TryString, ExportIndex>,
494+
exports: NameMap<TryString, (ExportIndex, ComponentExternData)>,
495495
},
496496
/// An exported type from a component or instance, currently only
497497
/// informational.

crates/environ/src/component/translate.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ struct Translation<'data> {
159159

160160
/// The list of exports from this component, as pairs of names and an
161161
/// index into an index space of what's being exported.
162-
exports: IndexMap<&'data str, ComponentItem>,
162+
exports: IndexMap<&'data str, (ComponentItem, wasmparser::ComponentExternName<'data>)>,
163163

164164
/// Type information produced by `wasmparser` for this component.
165165
///
@@ -355,7 +355,10 @@ enum LocalInitializer<'data> {
355355
HashMap<&'data str, ComponentItem>,
356356
ComponentInstanceTypeId,
357357
),
358-
ComponentSynthetic(HashMap<&'data str, ComponentItem>, ComponentInstanceTypeId),
358+
ComponentSynthetic(
359+
HashMap<&'data str, (ComponentItem, wasmparser::ComponentExternName<'data>)>,
360+
ComponentInstanceTypeId,
361+
),
359362

360363
// alias section
361364
AliasExportFunc(ModuleInstanceIndex, &'data str),
@@ -1310,7 +1313,10 @@ impl<'a, 'data> Translator<'a, 'data> {
13101313
for export in s {
13111314
let export = export?;
13121315
let item = self.kind_to_item(export.kind, export.index)?;
1313-
let prev = self.result.exports.insert(export.name.name, item);
1316+
let prev = self
1317+
.result
1318+
.exports
1319+
.insert(export.name.name, (item, export.name));
13141320
assert!(prev.is_none());
13151321
self.result
13161322
.initializers
@@ -1452,7 +1458,7 @@ impl<'a, 'data> Translator<'a, 'data> {
14521458
let mut map = HashMap::with_capacity(exports.len());
14531459
for export in exports {
14541460
let idx = self.kind_to_item(export.kind, export.index)?;
1455-
map.insert(export.name.name, idx);
1461+
map.insert(export.name.name, (idx, export.name));
14561462
}
14571463

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

crates/environ/src/component/translate/inline.rs

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,13 @@ pub(super) fn run(
114114
if let TypeDef::Interface(_) = ty {
115115
continue;
116116
}
117-
let index = inliner
118-
.result
119-
.import_types
120-
.push((name.name.to_string(), ty));
117+
let index = inliner.result.import_types.push((
118+
name.name.to_string(),
119+
ComponentExtern {
120+
ty,
121+
data: ComponentExternData::new(name),
122+
},
123+
));
121124
let path = ImportPath::root(index);
122125
args.insert(name.name, ComponentItemDef::from_import(path, ty)?);
123126
}
@@ -134,8 +137,9 @@ pub(super) fn run(
134137
assert!(frames.is_empty());
135138

136139
let mut export_map = Default::default();
137-
for (name, def) in exports {
138-
inliner.record_export(name, def, types, &mut export_map)?;
140+
for (name, (def, data)) in exports {
141+
let data = ComponentExternData::new(data);
142+
inliner.record_export(name, def, data, types, &mut export_map)?;
139143
}
140144
inliner.result.exports = export_map;
141145
inliner.result.num_future_tables = types.num_future_tables();
@@ -346,7 +350,7 @@ enum ComponentInstanceDef<'a> {
346350
// FIXME: same as the issue on `ComponentClosure` where this is cloned a lot
347351
// and may need `Rc`.
348352
Items(
349-
IndexMap<&'a str, ComponentItemDef<'a>>,
353+
IndexMap<&'a str, (ComponentItemDef<'a>, wasmparser::ComponentExternName<'a>)>,
350354
TypeComponentInstanceIndex,
351355
),
352356
}
@@ -376,7 +380,8 @@ impl<'a> Inliner<'a> {
376380
&mut self,
377381
types: &mut ComponentTypesBuilder,
378382
frames: &mut Vec<(InlinerFrame<'a>, ResourcesBuilder)>,
379-
) -> Result<IndexMap<&'a str, ComponentItemDef<'a>>> {
383+
) -> Result<IndexMap<&'a str, (ComponentItemDef<'a>, wasmparser::ComponentExternName<'a>)>>
384+
{
380385
// This loop represents the execution of the instantiation of a
381386
// component. This is an iterative process which is finished once all
382387
// initializers are processed. Currently this is modeled as an infinite
@@ -407,7 +412,7 @@ impl<'a> Inliner<'a> {
407412
.translation
408413
.exports
409414
.iter()
410-
.map(|(name, item)| Ok((*name, frame.item(*item, types)?)))
415+
.map(|(name, (item, data))| Ok((*name, (frame.item(*item, types)?, *data))))
411416
.collect::<Result<_>>()?;
412417
let instance_ty = frame.instance_ty;
413418
let (_, snapshot) = frames.pop().unwrap();
@@ -1295,7 +1300,7 @@ impl<'a> Inliner<'a> {
12951300
ComponentSynthetic(map, ty) => {
12961301
let items = map
12971302
.iter()
1298-
.map(|(name, index)| Ok((*name, frame.item(*index, types)?)))
1303+
.map(|(name, (index, data))| Ok((*name, (frame.item(*index, types)?, *data))))
12991304
.collect::<Result<_>>()?;
13001305
let types_ref = frame.translation.types_ref();
13011306
let ty = types.convert_instance(types_ref, *ty)?;
@@ -1401,15 +1406,16 @@ impl<'a> Inliner<'a> {
14011406
// item is then pushed in the relevant index space.
14021407
ComponentInstanceDef::Import(path, ty) => {
14031408
let path = path.push(*name);
1404-
let def = ComponentItemDef::from_import(path, types[*ty].exports[*name])?;
1409+
let def =
1410+
ComponentItemDef::from_import(path, types[*ty].exports[*name].ty)?;
14051411
frame.push_item(def);
14061412
}
14071413

14081414
// Given a component instance which was either created
14091415
// through instantiation of a component or through a
14101416
// synthetic renaming of items we just schlep around the
14111417
// definitions of various items here.
1412-
ComponentInstanceDef::Items(map, _) => frame.push_item(map[*name].clone()),
1418+
ComponentInstanceDef::Items(map, _) => frame.push_item(map[*name].0.clone()),
14131419
}
14141420
}
14151421

@@ -1615,8 +1621,9 @@ impl<'a> Inliner<'a> {
16151621
&mut self,
16161622
name: &str,
16171623
def: ComponentItemDef<'a>,
1624+
data: ComponentExternData,
16181625
types: &'a ComponentTypesBuilder,
1619-
map: &mut IndexMap<String, dfg::Export>,
1626+
map: &mut IndexMap<String, (dfg::Export, ComponentExternData)>,
16201627
) -> Result<()> {
16211628
let export = match def {
16221629
// Exported modules are currently saved in a `PrimaryMap`, at
@@ -1676,8 +1683,8 @@ impl<'a> Inliner<'a> {
16761683
ComponentInstanceDef::Import(path, ty) => {
16771684
for (name, ty) in types[ty].exports.iter() {
16781685
let path = path.push(name);
1679-
let def = ComponentItemDef::from_import(path, *ty)?;
1680-
self.record_export(name, def, types, &mut exports)?;
1686+
let def = ComponentItemDef::from_import(path, ty.ty)?;
1687+
self.record_export(name, def, ty.data.clone(), types, &mut exports)?;
16811688
}
16821689
dfg::Export::Instance { ty, exports }
16831690
}
@@ -1686,8 +1693,9 @@ impl<'a> Inliner<'a> {
16861693
// translated recursively here to our `exports` map which is
16871694
// the bag of items we're exporting.
16881695
ComponentInstanceDef::Items(map, ty) => {
1689-
for (name, def) in map {
1690-
self.record_export(name, def, types, &mut exports)?;
1696+
for (name, (def, data)) in map {
1697+
let data = ComponentExternData::new(data);
1698+
self.record_export(name, def, data.clone(), types, &mut exports)?;
16911699
}
16921700
dfg::Export::Instance { ty, exports }
16931701
}
@@ -1703,7 +1711,7 @@ impl<'a> Inliner<'a> {
17031711
ComponentItemDef::Type(def) => dfg::Export::Type(def),
17041712
};
17051713

1706-
map.insert(name.to_string(), export);
1714+
map.insert(name.to_string(), (export, data));
17071715
Ok(())
17081716
}
17091717
}
@@ -1838,7 +1846,7 @@ impl<'a> InlinerFrame<'a> {
18381846
/// and which component instantiated it.
18391847
fn finish_instantiate(
18401848
&mut self,
1841-
exports: IndexMap<&'a str, ComponentItemDef<'a>>,
1849+
exports: IndexMap<&'a str, (ComponentItemDef<'a>, wasmparser::ComponentExternName<'a>)>,
18421850
ty: ComponentInstanceTypeId,
18431851
types: &mut ComponentTypesBuilder,
18441852
) -> Result<()> {
@@ -1852,7 +1860,7 @@ impl<'a> InlinerFrame<'a> {
18521860
&mut path,
18531861
&mut |path| match path {
18541862
[] => unreachable!(),
1855-
[name, rest @ ..] => exports[name].lookup_resource(rest, types),
1863+
[name, rest @ ..] => exports[name].0.lookup_resource(rest, types),
18561864
},
18571865
);
18581866
}
@@ -1916,7 +1924,7 @@ impl<'a> ComponentItemDef<'a> {
19161924
cur = match instance {
19171925
// If this instance is a "bag of things" then this is as easy as
19181926
// looking up the name in the bag of names.
1919-
ComponentInstanceDef::Items(names, _) => names[element].clone(),
1927+
ComponentInstanceDef::Items(names, _) => names[element].0.clone(),
19201928

19211929
// If, however, this instance is an imported instance then this
19221930
// is a further projection within the import with one more path
@@ -1925,7 +1933,7 @@ impl<'a> ComponentItemDef<'a> {
19251933
// in conjunction with a one-longer `path` to produce a new item
19261934
// definition.
19271935
ComponentInstanceDef::Import(path, ty) => {
1928-
ComponentItemDef::from_import(path.push(element), types[ty].exports[element])
1936+
ComponentItemDef::from_import(path.push(element), types[ty].exports[element].ty)
19291937
.unwrap()
19301938
}
19311939
ComponentInstanceDef::Intrinsics => {
@@ -1948,3 +1956,11 @@ enum InstanceModule {
19481956
Static(StaticModuleIndex),
19491957
Import(TypeModuleIndex),
19501958
}
1959+
1960+
impl ComponentExternData {
1961+
fn new(data: wasmparser::ComponentExternName<'_>) -> Self {
1962+
ComponentExternData {
1963+
implements: data.implements.map(|s| s.to_string()),
1964+
}
1965+
}
1966+
}

0 commit comments

Comments
 (0)