@@ -12,7 +12,7 @@ use std::fmt::Write as _;
1212use std:: mem;
1313use wit_bindgen_core:: abi:: { self , AbiVariant , LiftLower } ;
1414use wit_bindgen_core:: {
15- AnonymousTypeGenerator , Source , TypeInfo , dealias, uwrite, uwriteln, wit_parser:: * ,
15+ AnonymousTypeGenerator , Source , TypeInfo , dealias, symbol_name , uwrite, uwriteln, wit_parser:: * ,
1616} ;
1717
1818pub struct InterfaceGenerator < ' a > {
@@ -212,13 +212,15 @@ impl<'i> InterfaceGenerator<'i> {
212212 "new" ,
213213 & [ abi:: WasmType :: Pointer ] ,
214214 & [ abi:: WasmType :: I32 ] ,
215+ self . r#gen . native_symbols ( ) ,
215216 ) ;
216217 let import_rep = crate :: declare_import (
217218 & wasm_import_module,
218219 & format ! ( "[resource-rep]{resource_name}" ) ,
219220 "rep" ,
220221 & [ abi:: WasmType :: I32 ] ,
221222 & [ abi:: WasmType :: Pointer ] ,
223+ self . r#gen . native_symbols ( ) ,
222224 ) ;
223225 uwriteln ! (
224226 self . src,
@@ -347,7 +349,6 @@ macro_rules! {macro_name} {{
347349 } ;
348350 self . generate_raw_cabi_export ( func, & ty, "$($path_to_types)*" , async_) ;
349351 }
350- let export_prefix = self . r#gen . opts . export_prefix . as_deref ( ) . unwrap_or ( "" ) ;
351352 for name in resources_to_drop {
352353 let module = match self . identifier {
353354 Identifier :: Interface ( _, key) => self . resolve . name_world_key ( key) ,
@@ -356,23 +357,25 @@ macro_rules! {macro_name} {{
356357 }
357358 } ;
358359 let camel = name. to_upper_camel_case ( ) ;
359- uwriteln ! (
360- self . src,
361- r#"
362- const _: () = {{
363- #[doc(hidden)]
364- #[unsafe(export_name = "{export_prefix}{module}#[dtor]{name}")]
365- #[allow(non_snake_case)]
366- unsafe extern "C" fn dtor(rep: *mut u8) {{
367- unsafe {{
368- $($path_to_types)*::{camel}::dtor::<
369- <$ty as $($path_to_types)*::Guest>::{camel}
370- >(rep)
360+ for ( cfg, symbol) in self . core_export_symbols ( & format ! ( "{module}#[dtor]{name}" ) ) {
361+ uwriteln ! (
362+ self . src,
363+ r#"
364+ const _: () = {{
365+ #[doc(hidden)]
366+ {cfg}#[unsafe(export_name = "{symbol}")]
367+ #[allow(non_snake_case)]
368+ unsafe extern "C" fn dtor(rep: *mut u8) {{
369+ unsafe {{
370+ $($path_to_types)*::{camel}::dtor::<
371+ <$ty as $($path_to_types)*::Guest>::{camel}
372+ >(rep)
373+ }}
371374 }}
372- }}
373- }};
374- "#
375- ) ;
375+ }};
376+ "#
377+ ) ;
378+ }
376379 }
377380 uwriteln ! ( self . src, "}};);" ) ;
378381 uwriteln ! ( self . src, "}}" ) ;
@@ -1019,6 +1022,7 @@ fn abi_layout(&mut self) -> ::core::alloc::Layout {{
10191022 "call" ,
10201023 & sig. params ,
10211024 & sig. results ,
1025+ self . r#gen . native_symbols ( ) ,
10221026 ) ;
10231027 let mut args = String :: new ( ) ;
10241028 for i in 0 ..params_lower. len ( ) {
@@ -1281,60 +1285,93 @@ unsafe fn call_import(&mut self, _params: Self::ParamsLower, _results: *mut u8)
12811285 Identifier :: World ( _) => None ,
12821286 Identifier :: StreamOrFuturePayload => unreachable ! ( ) ,
12831287 } ;
1284- let export_prefix = self . r#gen . opts . export_prefix . as_deref ( ) . unwrap_or ( "" ) ;
12851288 let export_name = func. legacy_core_export_name ( wasm_module_export_name. as_deref ( ) ) ;
12861289 let export_name = if async_ {
12871290 format ! ( "[async-lift]{export_name}" )
12881291 } else {
12891292 export_name. to_string ( )
12901293 } ;
1291- uwrite ! (
1292- self . src,
1293- "\
1294- #[unsafe(export_name = \" {export_prefix}{export_name}\" )]
1295- unsafe extern \" C\" fn export_{name_snake}\
1296- ",
1297- ) ;
12981294
1299- let params = self . print_export_sig ( func, async_) ;
1300- self . push_str ( " {\n " ) ;
1301- uwriteln ! (
1302- self . src,
1303- "unsafe {{ {path_to_self}::_export_{name_snake}_cabi::<{ty}>({}) }}" ,
1304- params. join( ", " )
1305- ) ;
1306- self . push_str ( "}\n " ) ;
1307-
1308- let export_prefix = self . r#gen . opts . export_prefix . as_deref ( ) . unwrap_or ( "" ) ;
1309- if async_ {
1295+ for ( cfg, symbol) in self . core_export_symbols ( & export_name) {
13101296 uwrite ! (
13111297 self . src,
13121298 "\
1313- #[unsafe(export_name = \" {export_prefix}[callback]{export_name}\" )]
1314- unsafe extern \" C\" fn _callback_{name_snake}(event0: u32, event1: u32, event2: u32) -> u32 {{
1315- unsafe {{
1316- {path_to_self}::__callback_{name_snake}(event0, event1, event2)
1317- }}
1318- }}
1319- "
1320- ) ;
1321- } else if abi:: guest_export_needs_post_return ( self . resolve , func) {
1322- uwrite ! (
1323- self . src,
1324- "\
1325- #[unsafe(export_name = \" {export_prefix}cabi_post_{export_name}\" )]
1326- unsafe extern \" C\" fn _post_return_{name_snake}\
1327- "
1299+ {cfg}#[unsafe(export_name = \" {symbol}\" )]
1300+ unsafe extern \" C\" fn export_{name_snake}\
1301+ ",
13281302 ) ;
1329- let params = self . print_post_return_sig ( func) ;
1330- self . src . push_str ( "{\n " ) ;
1303+ let params = self . print_export_sig ( func, async_ ) ;
1304+ self . push_str ( " {\n " ) ;
13311305 uwriteln ! (
13321306 self . src,
1333- "unsafe {{ {path_to_self}::__post_return_ {name_snake}::<{ty}>({}) }}" ,
1307+ "unsafe {{ {path_to_self}::_export_ {name_snake}_cabi ::<{ty}>({}) }}" ,
13341308 params. join( ", " )
13351309 ) ;
1336- self . src . push_str ( "}\n " ) ;
1310+ self . push_str ( "}\n " ) ;
1311+ }
1312+
1313+ if async_ {
1314+ for ( cfg, symbol) in self . core_export_symbols ( & format ! ( "[callback]{export_name}" ) ) {
1315+ uwrite ! (
1316+ self . src,
1317+ "\
1318+ {cfg}#[unsafe(export_name = \" {symbol}\" )]
1319+ unsafe extern \" C\" fn _callback_{name_snake}(event0: u32, event1: u32, event2: u32) -> u32 {{
1320+ unsafe {{
1321+ {path_to_self}::__callback_{name_snake}(event0, event1, event2)
1322+ }}
1323+ }}
1324+ "
1325+ ) ;
1326+ }
1327+ } else if abi:: guest_export_needs_post_return ( self . resolve , func) {
1328+ for ( cfg, symbol) in self . core_export_symbols ( & format ! ( "cabi_post_{export_name}" ) ) {
1329+ uwrite ! (
1330+ self . src,
1331+ "\
1332+ {cfg}#[unsafe(export_name = \" {symbol}\" )]
1333+ unsafe extern \" C\" fn _post_return_{name_snake}\
1334+ "
1335+ ) ;
1336+ let params = self . print_post_return_sig ( func) ;
1337+ self . src . push_str ( "{\n " ) ;
1338+ uwriteln ! (
1339+ self . src,
1340+ "unsafe {{ {path_to_self}::__post_return_{name_snake}::<{ty}>({}) }}" ,
1341+ params. join( ", " )
1342+ ) ;
1343+ self . src . push_str ( "}\n " ) ;
1344+ }
1345+ }
1346+ }
1347+
1348+ /// Returns each copy of a core export named `export_name` that needs to be
1349+ /// emitted, as `(cfg, symbol)`: the `cfg` attribute to gate the copy with
1350+ /// and the symbol to export it as.
1351+ ///
1352+ /// Normally there's just one copy: the canonical ABI name with no `cfg`.
1353+ /// With `link_native_symbols` enabled a second, hex-encoded copy is emitted
1354+ /// for native targets as well, because native linkers reject the `:`, `/`,
1355+ /// `#`, `[` and `]` characters that canonical names contain. Names that
1356+ /// survive encoding unchanged (`$root` exports, for instance) are emitted
1357+ /// once with no `cfg` rather than twice.
1358+ fn core_export_symbols ( & self , export_name : & str ) -> Vec < ( & ' static str , String ) > {
1359+ let prefix = self . r#gen . opts . export_prefix . as_deref ( ) . unwrap_or ( "" ) ;
1360+ let wasm = format ! ( "{prefix}{export_name}" ) ;
1361+ if self . r#gen . native_symbols ( ) . is_none ( ) {
1362+ return vec ! [ ( "" , wasm) ] ;
1363+ }
1364+ let native = format ! (
1365+ "{prefix}{}" ,
1366+ symbol_name:: make_external_component( export_name)
1367+ ) ;
1368+ if native == wasm {
1369+ return vec ! [ ( "" , wasm) ] ;
13371370 }
1371+ vec ! [
1372+ ( "#[cfg(target_arch = \" wasm32\" )]\n " , wasm) ,
1373+ ( "#[cfg(not(target_arch = \" wasm32\" ))]\n " , native) ,
1374+ ]
13381375 }
13391376
13401377 fn print_export_sig ( & mut self , func : & Function , async_ : bool ) -> Vec < String > {
@@ -2952,6 +2989,7 @@ impl<'a> {camel}Borrow<'a>{{
29522989 "drop" ,
29532990 & [ abi:: WasmType :: I32 ] ,
29542991 & [ ] ,
2992+ self . r#gen . native_symbols ( ) ,
29552993 ) ;
29562994 uwriteln ! (
29572995 self . src,
0 commit comments