@@ -26,12 +26,14 @@ struct DSig {
2626#[ derive( Default ) ]
2727struct D {
2828 used_interfaces : HashSet < ( WorldKey , InterfaceId ) > ,
29+ export_stubs : Vec < String > ,
2930
3031 interface_imports : Vec < String > ,
3132 interface_exports : Vec < String > ,
3233 type_imports_src : Source ,
3334 function_imports_src : Source ,
3435 function_exports_src : Source ,
36+ export_stubs_src : Source ,
3537
3638 opts : Opts ,
3739
@@ -57,6 +59,11 @@ pub struct Opts {
5759 /// Where to place output files
5860 #[ cfg_attr( feature = "clap" , arg( skip) ) ]
5961 out_dir : Option < PathBuf > ,
62+
63+ #[ cfg_attr( feature = "clap" , arg( long, default_value_t = false ) ) ]
64+ /// Whether stubs/declarations for exports should be emitted
65+ /// Only for testing purposes.
66+ emit_export_stubs : bool ,
6067}
6168
6269impl Opts {
@@ -313,6 +320,8 @@ impl D {
313320
314321 DInterfaceGenerator {
315322 src : Source :: default ( ) ,
323+ stub_src : Source :: default ( ) ,
324+ stubs : Vec :: default ( ) ,
316325 fqn : "" ,
317326 r#gen : self ,
318327 resolve,
@@ -487,7 +496,10 @@ impl WorldGenerator for D {
487496 types : & [ ( & str , TypeId ) ] ,
488497 _files : & mut Files ,
489498 ) {
499+ let fqn = self . world_fqn . clone ( ) ;
490500 let mut r#gen = self . interface ( resolve, Some ( Direction :: Import ) , None , Some ( "$root" ) ) ;
501+ r#gen. fqn = & fqn;
502+
491503 for ( name, id) in types. iter ( ) {
492504 r#gen. define_type ( name, * id) ;
493505 }
@@ -502,7 +514,10 @@ impl WorldGenerator for D {
502514 funcs : & [ ( & str , & Function ) ] ,
503515 _files : & mut Files ,
504516 ) {
517+ let fqn = self . world_fqn . clone ( ) ;
505518 let mut r#gen = self . interface ( resolve, Some ( Direction :: Import ) , None , Some ( "$root" ) ) ;
519+ r#gen. fqn = & fqn;
520+
506521 for ( _name, func) in funcs {
507522 r#gen. import_func ( func) ;
508523 }
@@ -604,12 +619,31 @@ impl WorldGenerator for D {
604619 let ret_area_decl = r#gen. emit_ret_area_if_needed ( ) ;
605620
606621 r#gen. src . push_str ( & ret_area_decl) ;
607- r#gen. src . push_str ( "}\n " ) ;
622+ r#gen. src . push_str ( "}\n \n " ) ;
623+
624+ let DInterfaceGenerator {
625+ mut src,
626+ stub_src,
627+ stubs,
628+ ..
629+ } = r#gen;
630+
631+ if self . opts . emit_export_stubs {
632+ src. append_src ( & stub_src) ;
633+
634+ src. push_str ( "alias STUBS = AliasSeq!(\n " ) ;
635+ src. indent ( 1 ) ;
636+ src. push_str ( & stubs. join ( ",\n " ) ) ;
637+ src. deindent ( 1 ) ;
638+ src. push_str ( "\n );\n " ) ;
639+
640+ self . export_stubs . push ( format ! ( "{fqn}.STUBS" ) ) ;
641+ }
608642
609643 let mut interface_filepath = PathBuf :: from_iter ( fqn. split ( "." ) ) ;
610644 interface_filepath. add_extension ( "d" ) ;
611645
612- files. push ( interface_filepath. to_str ( ) . unwrap ( ) , r#gen . src . as_bytes ( ) ) ;
646+ files. push ( interface_filepath. to_str ( ) . unwrap ( ) , src. as_bytes ( ) ) ;
613647
614648 self . cur_interface = None ;
615649 Ok ( ( ) )
@@ -622,7 +656,10 @@ impl WorldGenerator for D {
622656 funcs : & [ ( & str , & Function ) ] ,
623657 _files : & mut Files ,
624658 ) -> Result < ( ) > {
659+ let fqn = self . world_fqn . clone ( ) ;
625660 let mut r#gen = self . interface ( resolve, Some ( Direction :: Export ) , None , Some ( "$root" ) ) ;
661+ r#gen. fqn = & fqn;
662+
626663 for ( _name, func) in funcs {
627664 match func. kind {
628665 FunctionKind :: Freestanding | FunctionKind :: AsyncFreestanding => {
@@ -634,9 +671,21 @@ impl WorldGenerator for D {
634671
635672 let ret_area_decl = r#gen. emit_ret_area_if_needed ( ) ;
636673
637- self . function_exports_src = take ( & mut r#gen. src ) ;
674+ let DInterfaceGenerator {
675+ src,
676+ stub_src,
677+ mut stubs,
678+ ..
679+ } = r#gen;
680+
681+ self . function_exports_src = src;
638682 self . function_exports_src . push_str ( & ret_area_decl) ;
639683
684+ if self . opts . emit_export_stubs {
685+ self . export_stubs_src . append_src ( & stub_src) ;
686+ self . export_stubs . append ( & mut stubs) ;
687+ }
688+
640689 Ok ( ( ) )
641690 }
642691
@@ -714,6 +763,20 @@ impl WorldGenerator for D {
714763 world_src. push_str ( & self . function_exports_src . as_str ( ) ) ;
715764 world_src. push_str ( "}\n " ) ;
716765
766+ if self . opts . emit_export_stubs {
767+ self . export_stubs_src . push_str ( "alias STUBS = AliasSeq!(\n " ) ;
768+ self . export_stubs_src . indent ( 1 ) ;
769+ self . export_stubs_src
770+ . push_str ( & self . export_stubs . join ( ",\n " ) ) ;
771+ self . export_stubs_src . deindent ( 1 ) ;
772+ self . export_stubs_src . push_str ( "\n );\n " ) ;
773+
774+ self . export_stubs_src
775+ . push_str ( "alias Exports_STUB_INVOKE = Exports!(STUBS);\n " ) ;
776+
777+ world_src. append_src ( & self . export_stubs_src ) ;
778+ }
779+
717780 let mut world_filepath = PathBuf :: from_iter ( get_world_fqn ( world_id, resolve) . split ( "." ) ) ;
718781 world_filepath. push ( "package.d" ) ;
719782
@@ -726,6 +789,8 @@ impl WorldGenerator for D {
726789
727790struct DInterfaceGenerator < ' a > {
728791 src : Source ,
792+ stub_src : Source ,
793+ stubs : Vec < String > ,
729794 direction : Option < Direction > ,
730795 r#gen : & ' a mut D ,
731796 resolve : & ' a Resolve ,
@@ -1190,6 +1255,24 @@ impl<'a> DInterfaceGenerator<'a> {
11901255 }
11911256 ) ) ;
11921257
1258+ if self . r#gen . opts . emit_export_stubs {
1259+ self . stub_src . push_str ( & format ! (
1260+ "@witExport(\" {}\" , \" {}\" )\n {} {}_STUB({});\n " ,
1261+ self . wasm_import_module. unwrap( ) ,
1262+ func. name,
1263+ d_sig. result,
1264+ d_sig. name,
1265+ d_sig
1266+ . arguments
1267+ . iter( )
1268+ . map( |( name, ty) | "in " . to_owned( ) + ty + " " + name)
1269+ . collect:: <Vec <String >>( )
1270+ . join( ", " )
1271+ ) ) ;
1272+
1273+ self . stubs . push ( d_sig. name . clone ( ) + "_STUB" ) ;
1274+ }
1275+
11931276 self . src . push_str ( "/// ditto\n " ) ;
11941277 self . src . push_str ( & format ! (
11951278 "@wasmExport!(\" {}#{}\" )\n " ,
@@ -1991,7 +2074,7 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
19912074fn perform_cast ( op : & str , cast : & Bitcast ) -> String {
19922075 match cast {
19932076 Bitcast :: I32ToF32 | Bitcast :: I64ToF32 => {
1994- format ! ( "cast(uint)( {op}).reinterpretCast!float" )
2077+ format ! ( "( cast(uint){op}).reinterpretCast!float" )
19952078 }
19962079 Bitcast :: F32ToI32 | Bitcast :: F32ToI64 => {
19972080 format ! ( "({op}).reinterpretCast!uint" )
@@ -2260,13 +2343,14 @@ impl<'a, 'b> Bindgen for FunctionBindgen<'a, 'b> {
22602343 base,
22612344 } = self . blocks . pop ( ) . unwrap ( ) ;
22622345 let arr_src = & operands[ 0 ] ;
2346+ let arr_dst = & operands[ 1 ] ;
22632347 let size_str = self . r#gen . sizes . size ( element) . format ( "size_t.sizeof" ) ;
22642348
22652349 self . push_str ( & format ! (
22662350 "foreach ({block_element}_idx, const ref {block_element}; {arr_src}) {{\n "
22672351 ) ) ;
22682352 self . push_str ( & format ! (
2269- "const auto {base} = {arr_src } + {block_element}_idx * {size_str};\n "
2353+ "const auto {base} = {arr_dst } + {block_element}_idx * {size_str};\n "
22702354 ) ) ;
22712355 self . push_str ( & body) ;
22722356 self . push_str ( "\n }\n " ) ;
0 commit comments