Skip to content

Commit

Permalink
implement direction disambiguation for C++, fixes #28
Browse files Browse the repository at this point in the history
  • Loading branch information
cpetig committed Sep 14, 2024
1 parent 5ccecf8 commit fb670b1
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 7 deletions.
77 changes: 72 additions & 5 deletions crates/cpp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@ struct SourceWithState {
namespace: Vec<String>,
}

#[derive(Eq, Hash, PartialEq, Clone, Copy, Debug)]
enum Direction {
Import,
Export,
}

#[derive(Default)]
struct Cpp {
opts: Opts,
Expand All @@ -113,6 +119,10 @@ struct Cpp {
imported_interfaces: HashSet<InterfaceId>,
user_class_files: HashMap<String, String>,
defined_types: HashSet<(Vec<String>, String)>,

// needed for symmetric disambiguation
interface_prefixes: HashMap<(Direction, WorldKey), String>,
import_prefix: Option<String>,
}

#[derive(Default, Debug, Clone, Copy)]
Expand Down Expand Up @@ -493,6 +503,13 @@ impl WorldGenerator for Cpp {
id: InterfaceId,
_files: &mut Files,
) -> anyhow::Result<()> {
if let Some(prefix) = self
.interface_prefixes
.get(&(Direction::Import, name.clone()))
{
self.import_prefix = Some(prefix.clone());
}

let store = self.start_new_file(None);
self.imported_interfaces.insert(id);
let wasm_import_module = resolve.name_world_key(name);
Expand All @@ -509,6 +526,7 @@ impl WorldGenerator for Cpp {
}
}
self.finish_file(&namespace, store);
let _ = self.import_prefix.take();
Ok(())
}

Expand All @@ -519,6 +537,14 @@ impl WorldGenerator for Cpp {
id: InterfaceId,
_files: &mut Files,
) -> anyhow::Result<()> {
let old_prefix = self.opts.export_prefix.clone();
if let Some(prefix) = self
.interface_prefixes
.get(&(Direction::Export, name.clone()))
{
self.opts.export_prefix =
Some(prefix.clone() + old_prefix.as_ref().unwrap_or(&String::new()));
}
let store = self.start_new_file(None);
self.h_src
.src
Expand All @@ -538,6 +564,7 @@ impl WorldGenerator for Cpp {
}
}
self.finish_file(&namespace, store);
self.opts.export_prefix = old_prefix;
Ok(())
}

Expand Down Expand Up @@ -787,6 +814,30 @@ impl WorldGenerator for Cpp {
);
Ok(())
}

fn apply_resolve_options(&mut self, resolve: &mut Resolve, world: &mut WorldId) {
if self.opts.symmetric {
let world = &resolve.worlds[*world];
let exports: HashMap<&WorldKey, &wit_bindgen_core::wit_parser::WorldItem> =
world.exports.iter().collect();
for (key, _item) in world.imports.iter() {
// duplicate found
if exports.contains_key(key)
&& !self
.interface_prefixes
.contains_key(&(Direction::Import, key.clone()))
&& !self
.interface_prefixes
.contains_key(&(Direction::Export, key.clone()))
{
self.interface_prefixes
.insert((Direction::Import, key.clone()), "imp_".into());
self.interface_prefixes
.insert((Direction::Export, key.clone()), "exp_".into());
}
}
}
}
}

// determine namespace (for the lifted C++ function)
Expand Down Expand Up @@ -1072,10 +1123,14 @@ impl CppInterfaceGenerator<'_> {
res.push('#');
res
});
uwriteln!(
self.gen.c_src.src,
r#"extern "C" __attribute__((__export_name__("{module_prefix}{func_name}")))"#
);
if self.gen.opts.symmetric {
uwriteln!(self.gen.c_src.src, r#"extern "C" "#);
} else {
uwriteln!(
self.gen.c_src.src,
r#"extern "C" __attribute__((__export_name__("{module_prefix}{func_name}")))"#
);
}
}
let return_via_pointer = signature.retptr && self.gen.opts.host_side();
self.gen
Expand All @@ -1091,6 +1146,9 @@ impl CppInterfaceGenerator<'_> {
Some(ref module_name) => make_external_symbol(&module_name, &func_name, symbol_variant),
None => make_external_component(&func_name),
};
if let Some(prefix) = self.gen.opts.export_prefix.as_ref() {
self.gen.c_src.src.push_str(prefix);
}
self.gen.c_src.src.push_str(&export_name);
self.gen.c_src.src.push_str("(");
let mut first_arg = true;
Expand Down Expand Up @@ -3475,7 +3533,16 @@ impl<'a, 'b> Bindgen for FunctionBindgen<'a, 'b> {
.gen
.wasm_import_module
.as_ref()
.map(|e| String::from(*module_prefix) + e)
.map(|e| {
self.gen
.gen
.import_prefix
.as_ref()
.cloned()
.unwrap_or_default()
+ *module_prefix
+ e
})
.unwrap();
if self.gen.gen.opts.host {
uwriteln!(self.src, "wasm_function_inst_t wasm_func = wasm_runtime_lookup_function(wasm_runtime_get_module_inst(exec_env), \n\
Expand Down
6 changes: 4 additions & 2 deletions crates/cpp/tests/symmetric.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ fn tests(
assert!(status.success());

for path in cpp.iter() {
let (resolve, world) = resolve_wit_dir(&dir);
let (mut resolve, mut world) = resolve_wit_dir(&dir);
let world_name = &resolve.worlds[world].name;
let cpp_dir = out_dir.join("cpp");
drop(fs::remove_dir_all(&cpp_dir));
Expand All @@ -131,7 +131,9 @@ fn tests(
opts.new_api = true;
}
}
opts.build().generate(&resolve, world, &mut files).unwrap();
let mut cpp = opts.build();
cpp.apply_resolve_options(&mut resolve, &mut world);
cpp.generate(&resolve, world, &mut files).unwrap();

for (file, contents) in files.iter() {
let dst = cpp_dir.join(file);
Expand Down

0 comments on commit fb670b1

Please sign in to comment.