Skip to content

Commit 9d7b320

Browse files
authored
Update the guest C generator for world-based generation (#396)
This commit removes the `Generator` trait impl for the C generator and adds the `WorldGenerator` trait impl to replace it. This is the equivalent of #386 for the guest C generator. The generated C code is largely the same, except that the entire world is represented in one header file instead of per-interface header files as before. Additionally a tiny amount of "type sharing" is now done where all interfaces share the same string type (namespaced by the world name). More type sharing should come with a more first-class implementation of worlds. There was quite a lot of code movement within the generator as I got it working again, but at the surface level very little has changed and it should largely be the same as before.
1 parent b6df951 commit 9d7b320

File tree

21 files changed

+1277
-1304
lines changed

21 files changed

+1277
-1304
lines changed

crates/bindgen-core/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,7 @@ mod tests {
564564

565565
pub trait WorldGenerator {
566566
fn generate(&mut self, name: &str, interfaces: &ComponentInterfaces, files: &mut Files) {
567+
self.preprocess(name);
567568
for (name, import) in interfaces.imports.iter() {
568569
self.import(name, import, files);
569570
}
@@ -576,6 +577,10 @@ pub trait WorldGenerator {
576577
self.finish(name, interfaces, files);
577578
}
578579

580+
fn preprocess(&mut self, name: &str) {
581+
drop(name);
582+
}
583+
579584
fn import(&mut self, name: &str, iface: &Interface, files: &mut Files);
580585
fn export(&mut self, name: &str, iface: &Interface, files: &mut Files);
581586
fn export_default(&mut self, name: &str, iface: &Interface, files: &mut Files);

crates/gen-guest-c/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ heck = { workspace = true }
1717
clap = { workspace = true, optional = true }
1818

1919
[dev-dependencies]
20-
test-helpers = { path = '../test-helpers', default-features = false }
20+
test-helpers = { path = '../test-helpers', default-features = false, features = ['macros'] }

crates/gen-guest-c/src/component_type_object.rs

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,14 @@ use heck::ToSnakeCase;
33
use wasm_encoder::{
44
CodeSection, CustomSection, Encode, Function, FunctionSection, Module, TypeSection,
55
};
6-
use wit_bindgen_core::{wit_parser::Interface, Direction};
7-
use wit_component::ComponentEncoder;
6+
use wit_component::{ComponentEncoder, ComponentInterfaces};
87

9-
pub fn linking_symbol(iface: &Interface, direction: Direction) -> String {
10-
format!(
11-
"__component_type_object_force_link_{}_{}",
12-
iface.name.to_snake_case(),
13-
match direction {
14-
Direction::Import => "import",
15-
Direction::Export => "export",
16-
}
17-
)
8+
pub fn linking_symbol(name: &str) -> String {
9+
let snake = name.to_snake_case();
10+
format!("__component_type_object_force_link_{snake}")
1811
}
1912

20-
pub fn object(iface: &Interface, direction: Direction) -> Result<Vec<u8>> {
13+
pub fn object(name: &str, interfaces: &ComponentInterfaces) -> Result<Vec<u8>> {
2114
let mut module = Module::new();
2215

2316
// Build a module with one function that's a "dummy function"
@@ -31,32 +24,28 @@ pub fn object(iface: &Interface, direction: Direction) -> Result<Vec<u8>> {
3124
code.function(&Function::new([]));
3225
module.section(&code);
3326

34-
let mut encoder = ComponentEncoder::default();
35-
encoder = match direction {
36-
Direction::Import => encoder.imports([iface.clone()])?,
37-
Direction::Export => encoder.interface(iface.clone())?,
38-
};
27+
let mut encoder = ComponentEncoder::default()
28+
.imports(interfaces.imports.values().cloned())?
29+
.exports(interfaces.exports.values().cloned())?;
30+
31+
if let Some(default) = &interfaces.default {
32+
encoder = encoder.interface(default.clone())?;
33+
}
34+
3935
let data = encoder
4036
.types_only(true)
4137
.encode()
42-
.with_context(|| format!("translating interface {} to component type", iface.name))?;
38+
.with_context(|| format!("translating {name} to component type"))?;
4339

4440
// The custom section name here must start with "component-type" but
4541
// otherwise is attempted to be unique here to ensure that this doesn't get
4642
// concatenated to other custom sections by LLD by accident since LLD will
4743
// concatenate custom sections of the same name.
48-
let name = format!(
49-
"component-type:{}:{}",
50-
match direction {
51-
Direction::Import => "import",
52-
Direction::Export => "export",
53-
},
54-
iface.name
55-
);
44+
let section_name = format!("component-type:{name}",);
5645

5746
// Add our custom section
5847
module.section(&CustomSection {
59-
name: &name,
48+
name: &section_name,
6049
data: data.as_slice(),
6150
});
6251

@@ -69,7 +58,7 @@ pub fn object(iface: &Interface, direction: Direction) -> Result<Vec<u8>> {
6958
subsection.push(0x00); // SYMTAB_FUNCTION
7059
0u32.encode(&mut subsection); // flags
7160
0u32.encode(&mut subsection); // index
72-
linking_symbol(iface, direction).encode(&mut subsection); // name
61+
linking_symbol(name).encode(&mut subsection); // name
7362

7463
data.push(0x08); // `WASM_SYMBOL_TABLE`
7564
subsection.encode(&mut data);

0 commit comments

Comments
 (0)