@@ -4,6 +4,7 @@ use std::collections::BTreeMap;
44use std:: error:: Error ;
55use std:: path:: Path ;
66use std:: str:: FromStr ;
7+ use std:: sync:: Arc ;
78use std:: time:: Duration ;
89use std:: { cmp, env, iter} ;
910
@@ -996,18 +997,177 @@ impl CStore {
996997 . map ( |proc_macro| IntoDynSyncSend ( proc_macro. into_dyn_client ( ) ) )
997998 . collect ( ) )
998999 }
999- Err ( err) => {
1000- debug ! (
1001- "failed to dlsym proc_macros {} for symbol `{}`" ,
1002- path. display( ) ,
1003- sym_name
1004- ) ;
1005- Err ( err. into ( ) )
1000+ Err ( _err) => {
1001+ let engine = wasmi:: Engine :: default ( ) ;
1002+ let module = wasmi:: Module :: new ( & engine, std:: fs:: read ( path) . unwrap ( ) ) . unwrap ( ) ;
1003+
1004+ let mut store = wasmi:: Store :: new ( & engine, ( ) ) ;
1005+ let mut linker = wasmi:: Linker :: new ( & engine) ;
1006+ linker
1007+ . func_wrap ( "env" , "__rustc_proc_macro_dispatch" , |_: u32 , _: u32 | -> ( ) {
1008+ unreachable ! ( )
1009+ } )
1010+ . unwrap ( ) ;
1011+ let instance = linker. instantiate_and_start ( & mut store, & module) . unwrap ( ) ;
1012+
1013+ let memory =
1014+ instance. get_export ( & store, "memory" ) . unwrap ( ) . into_memory ( ) . unwrap ( ) ;
1015+
1016+ let sym = instance
1017+ . get_export ( & store, & sym_name)
1018+ . unwrap ( )
1019+ . into_global ( )
1020+ . unwrap ( )
1021+ . get ( & store)
1022+ . i32 ( )
1023+ . unwrap ( ) ;
1024+
1025+ let mut data = [ 0 ; 8 ] ;
1026+ memory. read ( & store, sym as usize , & mut data) . unwrap ( ) ;
1027+ let ptr = u32:: from_le_bytes ( data[ ..4 ] . try_into ( ) . unwrap ( ) ) ;
1028+ let len = u32:: from_le_bytes ( data[ 4 ..8 ] . try_into ( ) . unwrap ( ) ) ;
1029+
1030+ Ok ( ( 0 ..len)
1031+ . map ( |i| {
1032+ let mut data = [ 0 ; 4 ] ;
1033+ memory. read ( & store, ( ptr + 4 * i) as usize , & mut data) . unwrap ( ) ;
1034+ let func_ptr = u32:: from_le_bytes ( data) ;
1035+
1036+ IntoDynSyncSend ( Self :: wasm_macro_client (
1037+ engine. clone ( ) ,
1038+ module. clone ( ) ,
1039+ func_ptr,
1040+ ) )
1041+ } )
1042+ . collect :: < Vec < _ > > ( ) )
10061043 }
10071044 }
10081045 }
10091046 }
10101047
1048+ fn wasm_macro_client ( engine : wasmi:: Engine , module : wasmi:: Module , func_ptr : u32 ) -> DynClient {
1049+ DynClient {
1050+ run : Arc :: new ( move |config| {
1051+ struct Ctx < ' a > {
1052+ dispatch : rustc_proc_macro:: bridge:: Closure < ' a > ,
1053+ client_refs : Option < ClientRefs > ,
1054+ }
1055+
1056+ #[ derive( Clone ) ]
1057+ struct ClientRefs {
1058+ memory : wasmi:: Memory ,
1059+ buffer_replace : wasmi:: TypedFunc < ( u32 , u32 ) , ( ) > ,
1060+ buffer_ptr : wasmi:: TypedFunc < ( u32 , ) , ( u32 , ) > ,
1061+ buffer_len : wasmi:: TypedFunc < ( u32 , ) , ( u32 , ) > ,
1062+ }
1063+
1064+ impl ClientRefs {
1065+ fn read (
1066+ & self ,
1067+ store : & mut impl wasmi:: AsContextMut ,
1068+ buffer : u32 ,
1069+ ) -> Result < Vec < u8 > , wasmi:: Error > {
1070+ let ( buffer_ptr, ) = self . buffer_ptr . call ( & mut * store, ( buffer, ) ) ?;
1071+ let ( buffer_len, ) = self . buffer_len . call ( & mut * store, ( buffer, ) ) ?;
1072+ let mut data = vec ! [ 0 ; buffer_len as usize ] ;
1073+ self . memory . read ( store, buffer_ptr as usize , & mut data) ?;
1074+ Ok ( data)
1075+ }
1076+ }
1077+
1078+ let mut store = wasmi:: Store :: new (
1079+ & engine,
1080+ Ctx { dispatch : config. dispatch , client_refs : None } ,
1081+ ) ;
1082+ let mut linker: wasmi:: Linker < Ctx < ' _ > > = wasmi:: Linker :: new ( & engine) ;
1083+ linker
1084+ . func_new (
1085+ "env" ,
1086+ "__rustc_proc_macro_dispatch" ,
1087+ wasmi:: FuncType :: new ( [ wasmi:: ValType :: I32 , wasmi:: ValType :: I32 ] , [ ] ) ,
1088+ |mut caller, inputs, _outputs| {
1089+ let client_refs = caller. data ( ) . client_refs . clone ( ) . unwrap ( ) ;
1090+ let input_buffer = inputs[ 0 ] . i32 ( ) . unwrap ( ) . cast_unsigned ( ) ;
1091+ let output_buffer = inputs[ 1 ] . i32 ( ) . unwrap ( ) . cast_unsigned ( ) ;
1092+
1093+ let input_buffer_data = client_refs. read ( & mut caller, input_buffer) ?;
1094+
1095+ let output_buffer_data =
1096+ caller. data_mut ( ) . dispatch . call ( input_buffer_data. into ( ) ) ;
1097+
1098+ client_refs. buffer_replace . call (
1099+ & mut caller,
1100+ ( output_buffer, output_buffer_data. len ( ) . try_into ( ) . unwrap ( ) ) ,
1101+ ) ?;
1102+ let ( output_buffer_ptr, ) =
1103+ client_refs. buffer_ptr . call ( & mut caller, ( output_buffer, ) ) ?;
1104+ client_refs. memory . write (
1105+ & mut caller,
1106+ output_buffer_ptr as usize ,
1107+ & output_buffer_data,
1108+ ) ?;
1109+
1110+ Ok ( ( ) )
1111+ } ,
1112+ )
1113+ . unwrap ( ) ;
1114+ let instance = linker. instantiate_and_start ( & mut store, & module) . unwrap ( ) ;
1115+
1116+ fn get_func < T : wasmi:: WasmParams , U : wasmi:: WasmResults > (
1117+ instance : & wasmi:: Instance ,
1118+ store : & impl wasmi:: AsContext ,
1119+ name : & str ,
1120+ ) -> wasmi:: TypedFunc < T , U > {
1121+ instance
1122+ . get_export ( store, name)
1123+ . unwrap ( )
1124+ . into_func ( )
1125+ . unwrap ( )
1126+ . typed ( store)
1127+ . unwrap ( )
1128+ }
1129+
1130+ let client_refs = ClientRefs {
1131+ memory : instance. get_export ( & store, "memory" ) . unwrap ( ) . into_memory ( ) . unwrap ( ) ,
1132+ buffer_replace : get_func (
1133+ & instance,
1134+ & store,
1135+ "__rustc_proc_macro_buffer_replace" ,
1136+ ) ,
1137+ buffer_ptr : get_func ( & instance, & store, "__rustc_proc_macro_buffer_ptr" ) ,
1138+ buffer_len : get_func ( & instance, & store, "__rustc_proc_macro_buffer_len" ) ,
1139+ } ;
1140+ store. data_mut ( ) . client_refs = Some ( client_refs. clone ( ) ) ;
1141+
1142+ let alloc_buffer: wasmi:: TypedFunc < ( u32 , ) , ( u32 , ) > =
1143+ get_func ( & instance, & store, "__rustc_proc_macro_alloc_buffer" ) ;
1144+
1145+ let call_client: wasmi:: TypedFunc < ( u32 , u32 ) , ( u32 , ) > =
1146+ get_func ( & instance, & store, "__rustc_proc_macro_call_client" ) ;
1147+
1148+ let ( input_buffer, ) = alloc_buffer
1149+ . call ( & mut store, ( config. input . len ( ) . try_into ( ) . unwrap ( ) , ) )
1150+ . unwrap ( ) ;
1151+ let input_buffer_ptr =
1152+ client_refs. buffer_ptr . call ( & mut store, ( input_buffer, ) ) . unwrap ( ) . 0 ;
1153+ instance
1154+ . get_export ( & store, "memory" )
1155+ . unwrap ( )
1156+ . into_memory ( )
1157+ . unwrap ( )
1158+ . write ( & mut store, input_buffer_ptr as usize , & config. input )
1159+ . unwrap ( ) ;
1160+
1161+ let ( output_buffer, ) =
1162+ call_client. call ( & mut store, ( input_buffer, func_ptr) ) . unwrap ( ) ;
1163+
1164+ let output_buffer_data = client_refs. read ( & mut store, output_buffer) . unwrap ( ) ;
1165+
1166+ output_buffer_data. into ( )
1167+ } ) ,
1168+ }
1169+ }
1170+
10111171 fn inject_panic_runtime ( & mut self , tcx : TyCtxt < ' _ > , krate : & ast:: Crate ) {
10121172 // If we're only compiling an rlib, then there's no need to select a
10131173 // panic runtime, so we just skip this section entirely.
0 commit comments