2626 crate :: encoding:: { ComponentEncoder , Instance , Item , LibraryInfo , MainOrAdapter } ,
2727 anyhow:: { anyhow, bail, Context , Result } ,
2828 indexmap:: IndexSet ,
29- metadata:: { Export , FunctionType , GlobalType , Metadata , Type , ValueType } ,
29+ metadata:: { Export , ExportKey , FunctionType , GlobalType , Metadata , Type , ValueType } ,
3030 std:: {
3131 collections:: { hash_map:: Entry , BTreeMap , HashMap , HashSet } ,
3232 iter,
3737 Instruction as Ins , MemArg , MemorySection , MemoryType , Module , RawCustomSection , RefType ,
3838 StartSection , TableSection , TableType , TypeSection , ValType ,
3939 } ,
40+ wasmparser:: WASM_SYM_BINDING_WEAK ,
4041} ;
4142
4243mod metadata;
@@ -101,17 +102,17 @@ impl<'a> DlOpenables<'a> {
101102 . iter ( )
102103 . map ( |export| {
103104 let name_address = memory_base + u32:: try_from ( buffer. len ( ) ) . unwrap ( ) ;
104- write_bytes_padded ( & mut buffer, export. name . as_bytes ( ) ) ;
105+ write_bytes_padded ( & mut buffer, export. key . name . as_bytes ( ) ) ;
105106
106- let address = if let Type :: Function ( _) = & export. ty {
107+ let address = if let Type :: Function ( _) = & export. key . ty {
107108 Address :: Function (
108109 table_base + get_and_increment ( & mut function_count) ,
109110 )
110111 } else {
111- Address :: Global ( export. name )
112+ Address :: Global ( export. key . name )
112113 } ;
113114
114- ( export. name , name_address, address)
115+ ( export. key . name , name_address, address)
115116 } )
116117 . collect :: < Vec < _ > > ( ) ;
117118
@@ -405,7 +406,7 @@ fn make_env_module<'a>(
405406/// This module also contains the data segment for the `dlopen`/`dlsym` lookup table.
406407fn make_init_module (
407408 metadata : & [ Metadata ] ,
408- exporters : & HashMap < & Export , & str > ,
409+ exporters : & HashMap < & ExportKey , ( & str , & Export ) > ,
409410 function_exports : & [ ( & str , & FunctionType , usize ) ] ,
410411 dl_openables : DlOpenables ,
411412 indirection_table_base : u32 ,
@@ -421,7 +422,7 @@ fn make_init_module(
421422 for metadata in metadata {
422423 if metadata. dl_openable {
423424 for export in & metadata. exports {
424- if let Type :: Function ( ty) = & export. ty {
425+ if let Type :: Function ( ty) = & export. key . ty {
425426 types. function (
426427 ty. parameters . iter ( ) . copied ( ) . map ( ValType :: from) ,
427428 ty. results . iter ( ) . copied ( ) . map ( ValType :: from) ,
@@ -552,7 +553,7 @@ fn make_init_module(
552553 }
553554
554555 for import in & metadata. memory_address_imports {
555- let exporter = find_offset_exporter ( import, exporters) ?;
556+ let ( exporter, _ ) = find_offset_exporter ( import, exporters) ?;
556557
557558 memory_address_inits. push ( Ins :: GlobalGet ( add_global_import (
558559 & mut imports,
@@ -580,11 +581,11 @@ fn make_init_module(
580581 for metadata in metadata {
581582 if metadata. dl_openable {
582583 for export in & metadata. exports {
583- if let Type :: Function ( _) = & export. ty {
584+ if let Type :: Function ( _) = & export. key . ty {
584585 dl_openable_functions. push ( add_function_import (
585586 & mut imports,
586587 metadata. name ,
587- export. name ,
588+ export. key . name ,
588589 get_and_increment ( & mut type_offset) ,
589590 ) ) ;
590591 }
@@ -665,8 +666,11 @@ fn make_init_module(
665666}
666667
667668/// Find the library which exports the specified function or global address.
668- fn find_offset_exporter < ' a > ( name : & str , exporters : & HashMap < & Export , & ' a str > ) -> Result < & ' a str > {
669- let export = Export {
669+ fn find_offset_exporter < ' a > (
670+ name : & str ,
671+ exporters : & HashMap < & ExportKey , ( & ' a str , & ' a Export < ' a > ) > ,
672+ ) -> Result < ( & ' a str , & ' a Export < ' a > ) > {
673+ let export = ExportKey {
670674 name,
671675 ty : Type :: Global ( GlobalType {
672676 ty : ValueType :: I32 ,
@@ -684,9 +688,9 @@ fn find_offset_exporter<'a>(name: &str, exporters: &HashMap<&Export, &'a str>) -
684688fn find_function_exporter < ' a > (
685689 name : & str ,
686690 ty : & FunctionType ,
687- exporters : & HashMap < & Export , & ' a str > ,
688- ) -> Result < & ' a str > {
689- let export = Export {
691+ exporters : & HashMap < & ExportKey , ( & ' a str , & ' a Export < ' a > ) > ,
692+ ) -> Result < ( & ' a str , & ' a Export < ' a > ) > {
693+ let export = ExportKey {
690694 name,
691695 ty : Type :: Function ( ty. clone ( ) ) ,
692696 } ;
@@ -700,11 +704,14 @@ fn find_function_exporter<'a>(
700704/// Analyze the specified library metadata, producing a symbol-to-library-name map of exports.
701705fn resolve_exporters < ' a > (
702706 metadata : & ' a [ Metadata < ' a > ] ,
703- ) -> Result < HashMap < & ' a Export < ' a > , Vec < & ' a str > > > {
707+ ) -> Result < HashMap < & ' a ExportKey < ' a > , Vec < ( & ' a str , & ' a Export < ' a > ) > > > {
704708 let mut exporters = HashMap :: < _ , Vec < _ > > :: new ( ) ;
705709 for metadata in metadata {
706710 for export in & metadata. exports {
707- exporters. entry ( export) . or_default ( ) . push ( metadata. name ) ;
711+ exporters
712+ . entry ( & export. key )
713+ . or_default ( )
714+ . push ( ( metadata. name , export) ) ;
708715 }
709716 }
710717 Ok ( exporters)
@@ -713,11 +720,11 @@ fn resolve_exporters<'a>(
713720/// Match up all imported symbols to their corresponding exports, reporting any missing or duplicate symbols.
714721fn resolve_symbols < ' a > (
715722 metadata : & ' a [ Metadata < ' a > ] ,
716- exporters : & ' a HashMap < & ' a Export < ' a > , Vec < & ' a str > > ,
723+ exporters : & ' a HashMap < & ' a ExportKey < ' a > , Vec < ( & ' a str , & ' a Export < ' a > ) > > ,
717724) -> (
718- HashMap < & ' a Export < ' a > , & ' a str > ,
725+ HashMap < & ' a ExportKey < ' a > , ( & ' a str , & ' a Export < ' a > ) > ,
719726 Vec < ( & ' a str , Export < ' a > ) > ,
720- Vec < ( & ' a str , & ' a Export < ' a > , & ' a [ & ' a str ] ) > ,
727+ Vec < ( & ' a str , & ' a ExportKey < ' a > , & ' a [ ( & ' a str , & ' a Export < ' a > ) ] ) > ,
721728) {
722729 // TODO: consider weak symbols when checking for duplicates
723730
@@ -736,8 +743,8 @@ fn resolve_symbols<'a>(
736743 let mut missing = Vec :: new ( ) ;
737744 let mut duplicates = Vec :: new ( ) ;
738745
739- let mut triage = |metadata : & ' a Metadata , export| {
740- if let Some ( ( key, value) ) = exporters. get_key_value ( & export) {
746+ let mut triage = |metadata : & ' a Metadata , export : Export < ' a > | {
747+ if let Some ( ( key, value) ) = exporters. get_key_value ( & export. key ) {
741748 match value. as_slice ( ) {
742749 [ ] => unreachable ! ( ) ,
743750 [ exporter] => {
@@ -753,12 +760,15 @@ fn resolve_symbols<'a>(
753760 } ;
754761
755762 for metadata in metadata {
756- for ( name, ty ) in & metadata. env_imports {
763+ for ( name, ( ty , flags ) ) in & metadata. env_imports {
757764 triage (
758765 metadata,
759766 Export {
760- name,
761- ty : Type :: Function ( ty. clone ( ) ) ,
767+ key : ExportKey {
768+ name,
769+ ty : Type :: Function ( ty. clone ( ) ) ,
770+ } ,
771+ flags : * flags,
762772 } ,
763773 ) ;
764774 }
@@ -767,11 +777,14 @@ fn resolve_symbols<'a>(
767777 triage (
768778 metadata,
769779 Export {
770- name,
771- ty : Type :: Global ( GlobalType {
772- ty : ValueType :: I32 ,
773- mutable : false ,
774- } ) ,
780+ key : ExportKey {
781+ name,
782+ ty : Type :: Global ( GlobalType {
783+ ty : ValueType :: I32 ,
784+ mutable : false ,
785+ } ) ,
786+ } ,
787+ flags : 0 ,
775788 } ,
776789 ) ;
777790 }
@@ -793,11 +806,14 @@ fn resolve_symbols<'a>(
793806 missing. push ( (
794807 metadata. name ,
795808 Export {
796- name,
797- ty : Type :: Function ( FunctionType {
798- parameters : Vec :: new ( ) ,
799- results : Vec :: new ( ) ,
800- } ) ,
809+ key : ExportKey {
810+ name,
811+ ty : Type :: Function ( FunctionType {
812+ parameters : Vec :: new ( ) ,
813+ results : Vec :: new ( ) ,
814+ } ) ,
815+ } ,
816+ flags : 0 ,
801817 } ,
802818 ) ) ;
803819 }
@@ -850,7 +866,7 @@ fn topo_sort(count: usize, dependencies: &HashMap<usize, HashSet<usize>>) -> Res
850866/// represented by its offset in the original metadata slice.
851867fn find_dependencies (
852868 metadata : & [ Metadata ] ,
853- exporters : & HashMap < & Export , & str > ,
869+ exporters : & HashMap < & ExportKey , ( & str , & Export ) > ,
854870) -> Result < HashMap < usize , HashSet < usize > > > {
855871 let mut dependencies = HashMap :: < _ , HashSet < _ > > :: new ( ) ;
856872 let mut indexes = HashMap :: new ( ) ;
@@ -862,11 +878,11 @@ fn find_dependencies(
862878 . or_default ( )
863879 . insert ( needed) ;
864880 }
865- for ( import_name, ty ) in & metadata. env_imports {
881+ for ( import_name, ( ty , _ ) ) in & metadata. env_imports {
866882 dependencies
867883 . entry ( metadata. name )
868884 . or_default ( )
869- . insert ( find_function_exporter ( import_name, ty, exporters) ?) ;
885+ . insert ( find_function_exporter ( import_name, ty, exporters) ?. 0 ) ;
870886 }
871887 }
872888
@@ -909,7 +925,7 @@ fn find_dependencies(
909925/// the original export.
910926fn env_function_exports < ' a > (
911927 metadata : & ' a [ Metadata < ' a > ] ,
912- exporters : & ' a HashMap < & ' a Export , & ' a str > ,
928+ exporters : & ' a HashMap < & ' a ExportKey , ( & ' a str , & Export ) > ,
913929 topo_sorted : & [ usize ] ,
914930) -> Result < Vec < ( & ' a str , & ' a FunctionType , usize ) > > {
915931 let function_exporters = exporters
@@ -938,7 +954,7 @@ fn env_function_exports<'a>(
938954
939955 for name in & metadata. table_address_imports {
940956 if !exported. contains ( name) {
941- let ( ty, exporter) = function_exporters
957+ let ( ty, ( exporter, _ ) ) = function_exporters
942958 . get ( name)
943959 . ok_or_else ( || anyhow ! ( "unable to find {name:?} in any library" ) ) ?;
944960
@@ -947,9 +963,11 @@ fn env_function_exports<'a>(
947963 }
948964 }
949965
950- for ( import_name, ty ) in & metadata. env_imports {
966+ for ( import_name, ( ty , _ ) ) in & metadata. env_imports {
951967 if !exported. contains ( import_name) {
952- let exporter = indexes[ find_function_exporter ( import_name, ty, exporters) . unwrap ( ) ] ;
968+ let exporter = indexes[ find_function_exporter ( import_name, ty, exporters)
969+ . unwrap ( )
970+ . 0 ] ;
953971 if !seen. contains ( & exporter) {
954972 result. push ( ( * import_name, ty, exporter) ) ;
955973 exported. insert ( * import_name) ;
@@ -971,7 +989,7 @@ fn make_stubs_module(missing: &[(&str, Export)]) -> Vec<u8> {
971989 for ( offset, ( _, export) ) in missing. iter ( ) . enumerate ( ) {
972990 let offset = u32:: try_from ( offset) . unwrap ( ) ;
973991
974- let Export { name, ty : Type :: Function ( ty) } = export else {
992+ let Export { key : ExportKey { name, ty : Type :: Function ( ty) } , .. } = export else {
975993 unreachable ! ( ) ;
976994 } ;
977995
@@ -1136,7 +1154,7 @@ impl Linker {
11361154 let mut exporters = resolve_exporters ( & metadata) ?;
11371155
11381156 let cabi_realloc_exporter = exporters
1139- . get_mut ( & Export {
1157+ . get_mut ( & ExportKey {
11401158 name : "cabi_realloc" ,
11411159 ty : Type :: Function ( FunctionType {
11421160 parameters : vec ! [ ValueType :: I32 ; 4 ] ,
@@ -1147,16 +1165,19 @@ impl Linker {
11471165 // TODO: Verify that there is at most one strong exporter
11481166 let first = * exporters. first ( ) . unwrap ( ) ;
11491167 * exporters = vec ! [ first] ;
1150- first
1168+ first. 0
11511169 } ) ;
11521170
11531171 let ( exporters, missing, duplicates) = resolve_symbols ( & metadata, & exporters) ;
11541172
11551173 if !missing. is_empty ( ) {
1156- if self . stub_missing_functions
1157- && missing
1158- . iter ( )
1159- . all ( |( _, export) | matches ! ( & export. ty, Type :: Function ( _) ) )
1174+ if missing
1175+ . iter ( )
1176+ . all ( |( _, export) | matches ! ( & export. key. ty, Type :: Function ( _) ) )
1177+ && ( self . stub_missing_functions
1178+ || missing
1179+ . iter ( )
1180+ . all ( |( _, export) | 0 != ( export. flags & WASM_SYM_BINDING_WEAK ) ) )
11601181 {
11611182 self . stub_missing_functions = false ;
11621183 self . libraries . push ( (
@@ -1166,11 +1187,18 @@ impl Linker {
11661187 ) ) ;
11671188 return self . encode ( ) ;
11681189 } else {
1169- bail ! ( "unresolved symbol(s): {missing:#?}" )
1190+ bail ! (
1191+ "unresolved symbol(s): {:#?}" ,
1192+ missing
1193+ . iter( )
1194+ . filter( |( _, export) | 0 == ( export. flags & WASM_SYM_BINDING_WEAK ) )
1195+ . collect:: <Vec <_>>( )
1196+ ) ;
11701197 }
11711198 }
11721199
11731200 if !duplicates. is_empty ( ) {
1201+ // TODO: Check for weak symbols before giving up here
11741202 bail ! ( "duplicate symbol(s): {duplicates:#?}" ) ;
11751203 }
11761204
@@ -1249,8 +1277,8 @@ impl Linker {
12491277 name : format ! ( "{name}:table_base" ) ,
12501278 } ,
12511279 ] )
1252- . chain ( metadata. env_imports . iter ( ) . map ( |( name, ty ) | {
1253- let exporter = find_function_exporter ( name, ty, & exporters) . unwrap ( ) ;
1280+ . chain ( metadata. env_imports . iter ( ) . map ( |( name, ( ty , _ ) ) | {
1281+ let ( exporter, _ ) = find_function_exporter ( name, ty, & exporters) . unwrap ( ) ;
12541282
12551283 Item {
12561284 alias : ( * name) . into ( ) ,
0 commit comments