Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ mod path;
pub use path::name_package_module;
mod async_;
pub use async_::AsyncFilterSet;
pub mod symbol_name;

#[derive(Default, Copy, Clone, PartialEq, Eq, Debug)]
pub enum Direction {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use wit_bindgen_core::abi;
use crate::abi;

fn hexdigit(v: u32) -> char {
if v < 10 {
Expand Down
6 changes: 3 additions & 3 deletions crates/cpp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ use std::{
process::{Command, Stdio},
str::FromStr,
};
use symbol_name::{make_external_component, make_external_symbol};
use wit_bindgen_c::to_c_ident;
use wit_bindgen_core::{
Files, InterfaceGenerator, Source, Types, WorldGenerator,
abi::{self, AbiVariant, Bindgen, Bitcast, LiftLower, WasmSignature, WasmType},
name_package_module, uwrite, uwriteln,
name_package_module,
symbol_name::{make_external_component, make_external_symbol},
uwrite, uwriteln,
wit_parser::{
Alignment, ArchitectureSize, Docs, Function, FunctionKind, Handle, Int, InterfaceId, Param,
Resolve, SizeAlign, Stability, Type, TypeDef, TypeDefKind, TypeId, TypeOwner, WorldId,
Expand All @@ -24,7 +25,6 @@ use wit_bindgen_core::{
use wit_parser::TypeIdVisitor;

// mod wamr;
mod symbol_name;

pub const RESOURCE_IMPORT_BASE_CLASS_NAME: &str = "ResourceImportBase";
pub const RESOURCE_EXPORT_BASE_CLASS_NAME: &str = "ResourceExportBase";
Expand Down
33 changes: 33 additions & 0 deletions crates/guest-rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -894,6 +894,39 @@ extern crate std;
/// });
/// ```
///
/// ## Native (non-WebAssembly) targets
///
/// Generated bindings also compile for native targets, which is useful for
/// testing component code without a wasm runtime or for building it as a
/// `cdylib` plugin. Native linkers don't accept the `:`, `/`, `#`, `[` and
/// `]` characters that canonical ABI symbol names use, so on native targets
/// symbols are hex-encoded with the scheme in
/// `wit_bindgen_core::symbol_name` (the same one the C++ generator uses).
///
/// Imports are not resolved by the native linker. Each import calls through
/// a function pointer that starts out null, and a host provides an
/// implementation at load time by calling the generated
/// `__wit_bindgen_register_<world><import>` function with a function pointer
/// of the import's core signature (`<import>` here is
/// `make_external_symbol(module, name, GuestImport)`). This means everything
/// links whether or not a host is present: a host only needs to register the
/// imports it actually implements, and calling an import that was never
/// registered aborts with a message naming the import and its registration
/// function.
///
/// Exports, including post-return functions, async callbacks, and resource
/// destructors, are exported under their hex-encoded core export names. A
/// `__wit_bindgen_cabi_realloc_<world>` function is also exported so hosts
/// can allocate guest-owned memory when lowering arguments, as the canonical
/// ABI requires.
///
/// The `<world>` prefix above is a hex-encoded
/// `<package>/<world><type_section_suffix>`, which keeps two `generate!`
/// invocations in one binary from defining the same symbols. Note that
/// binding the same world twice in one native binary will fail to link with
/// duplicate symbols unless `type_section_suffix` is used to tell the two
/// apart.
///
/// [WIT package]: https://component-model.bytecodealliance.org/design/packages.html
#[cfg(feature = "macros")]
pub use wit_bindgen_rust_macro::generate;
Expand Down
2 changes: 1 addition & 1 deletion crates/guest-rust/src/rt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ pub fn maybe_link_cabi_realloc() {
/// `cabi_realloc` module above. It's otherwise never explicitly called.
///
/// For more information about this see `./ci/rebuild-libwit-bindgen-cabi.sh`.
#[cfg(any(target_env = "p1", target_env = ""))]
#[cfg(any(target_env = "p1", target_env = "", not(target_arch = "wasm32")))]
pub unsafe fn cabi_realloc(
old_ptr: *mut u8,
old_len: usize,
Expand Down
1 change: 1 addition & 0 deletions crates/rust/src/bindgen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
&rust_name,
params,
results,
self.r#gen.r#gen.native_symbols(),
));
rust_name
}
Expand Down
45 changes: 32 additions & 13 deletions crates/rust/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use std::fmt::Write as _;
use std::mem;
use wit_bindgen_core::abi::{self, AbiVariant, LiftLower};
use wit_bindgen_core::{
AnonymousTypeGenerator, Source, TypeInfo, dealias, uwrite, uwriteln, wit_parser::*,
AnonymousTypeGenerator, Source, TypeInfo, dealias, symbol_name, uwrite, uwriteln, wit_parser::*,
};

pub struct InterfaceGenerator<'a> {
Expand Down Expand Up @@ -212,13 +212,15 @@ impl<'i> InterfaceGenerator<'i> {
"new",
&[abi::WasmType::Pointer],
&[abi::WasmType::I32],
self.r#gen.native_symbols(),
);
let import_rep = crate::declare_import(
&wasm_import_module,
&format!("[resource-rep]{resource_name}"),
"rep",
&[abi::WasmType::I32],
&[abi::WasmType::Pointer],
self.r#gen.native_symbols(),
);
uwriteln!(
self.src,
Expand Down Expand Up @@ -347,7 +349,6 @@ macro_rules! {macro_name} {{
};
self.generate_raw_cabi_export(func, &ty, "$($path_to_types)*", async_);
}
let export_prefix = self.r#gen.opts.export_prefix.as_deref().unwrap_or("");
for name in resources_to_drop {
let module = match self.identifier {
Identifier::Interface(_, key) => self.resolve.name_world_key(key),
Expand All @@ -356,13 +357,13 @@ macro_rules! {macro_name} {{
}
};
let camel = name.to_upper_camel_case();
let attrs = self.core_export_attrs(&format!("{module}#[dtor]{name}"));
uwriteln!(
self.src,
r#"
const _: () = {{
#[doc(hidden)]
#[unsafe(export_name = "{export_prefix}{module}#[dtor]{name}")]
#[allow(non_snake_case)]
{attrs}#[allow(non_snake_case)]
unsafe extern "C" fn dtor(rep: *mut u8) {{
unsafe {{
$($path_to_types)*::{camel}::dtor::<
Expand Down Expand Up @@ -1019,6 +1020,7 @@ fn abi_layout(&mut self) -> ::core::alloc::Layout {{
"call",
&sig.params,
&sig.results,
self.r#gen.native_symbols(),
);
let mut args = String::new();
for i in 0..params_lower.len() {
Expand Down Expand Up @@ -1281,21 +1283,20 @@ unsafe fn call_import(&mut self, _params: Self::ParamsLower, _results: *mut u8)
Identifier::World(_) => None,
Identifier::StreamOrFuturePayload => unreachable!(),
};
let export_prefix = self.r#gen.opts.export_prefix.as_deref().unwrap_or("");
let export_name = func.legacy_core_export_name(wasm_module_export_name.as_deref());
let export_name = if async_ {
format!("[async-lift]{export_name}")
} else {
export_name.to_string()
};

let attrs = self.core_export_attrs(&export_name);
uwrite!(
self.src,
"\
#[unsafe(export_name = \"{export_prefix}{export_name}\")]
unsafe extern \"C\" fn export_{name_snake}\
{attrs}unsafe extern \"C\" fn export_{name_snake}\
",
);

let params = self.print_export_sig(func, async_);
self.push_str(" {\n");
uwriteln!(
Expand All @@ -1305,25 +1306,24 @@ unsafe fn call_import(&mut self, _params: Self::ParamsLower, _results: *mut u8)
);
self.push_str("}\n");

let export_prefix = self.r#gen.opts.export_prefix.as_deref().unwrap_or("");
if async_ {
let attrs = self.core_export_attrs(&format!("[callback]{export_name}"));
uwrite!(
self.src,
"\
#[unsafe(export_name = \"{export_prefix}[callback]{export_name}\")]
unsafe extern \"C\" fn _callback_{name_snake}(event0: u32, event1: u32, event2: u32) -> u32 {{
{attrs}unsafe extern \"C\" fn _callback_{name_snake}(event0: u32, event1: u32, event2: u32) -> u32 {{
unsafe {{
{path_to_self}::__callback_{name_snake}(event0, event1, event2)
}}
}}
"
);
} else if abi::guest_export_needs_post_return(self.resolve, func) {
let attrs = self.core_export_attrs(&format!("cabi_post_{export_name}"));
uwrite!(
self.src,
"\
#[unsafe(export_name = \"{export_prefix}cabi_post_{export_name}\")]
unsafe extern \"C\" fn _post_return_{name_snake}\
{attrs}unsafe extern \"C\" fn _post_return_{name_snake}\
"
);
let params = self.print_post_return_sig(func);
Expand All @@ -1337,6 +1337,24 @@ unsafe fn call_import(&mut self, _params: Self::ParamsLower, _results: *mut u8)
}
}

/// Returns the `export_name` attributes for a core export named
/// `export_name`.
///
/// Has to exist due to the fact that native names cannot contain
/// special characters that wasm32 can like '/'.
///
/// `cfg_attr` conditions are mutually exclusive, so exactly one attribute
/// applies on any target (for names that survive encoding unchanged, such
/// as `$root` exports, both carry the same string).
fn core_export_attrs(&self, export_name: &str) -> String {
let prefix = self.r#gen.opts.export_prefix.as_deref().unwrap_or("");
let native = symbol_name::make_external_component(export_name);
format!(
"#[cfg_attr(target_arch = \"wasm32\", unsafe(export_name = \"{prefix}{export_name}\"))]\n\
#[cfg_attr(not(target_arch = \"wasm32\"), unsafe(export_name = \"{prefix}{native}\"))]\n"
)
}

fn print_export_sig(&mut self, func: &Function, async_: bool) -> Vec<String> {
self.src.push_str("(");
let variant = if async_ {
Expand Down Expand Up @@ -2952,6 +2970,7 @@ impl<'a> {camel}Borrow<'a>{{
"drop",
&[abi::WasmType::I32],
&[],
self.r#gen.native_symbols(),
);
uwriteln!(
self.src,
Expand Down
Loading
Loading