@@ -189,6 +189,81 @@ pub mod rustc_trans {
189189 pub fn print_passes ( ) { }
190190}
191191
192+ fn load_backend_from_dylib ( sess : & Session , backend_name : & str ) -> Box < TransCrate > {
193+ use std:: sync:: mpsc;
194+ use std:: path:: Path ;
195+ use syntax:: symbol:: Symbol ;
196+ use rustc:: session:: config:: OutputFilenames ;
197+ use rustc:: ty:: TyCtxt ;
198+ use rustc:: ty:: maps:: Providers ;
199+ use rustc:: middle:: cstore:: MetadataLoader ;
200+ use rustc:: dep_graph:: DepGraph ;
201+ use rustc_metadata:: dynamic_lib:: DynamicLibrary ;
202+ /// This prevents the dylib from being unloaded when there is still a TransCrate open
203+ struct ExternTransCrate {
204+ _lib : DynamicLibrary ,
205+ trans : Box < TransCrate > ,
206+ }
207+ impl TransCrate for ExternTransCrate {
208+ fn print ( & self , req : PrintRequest , sess : & Session ) {
209+ self . trans . print ( req, sess) ;
210+ }
211+ fn target_features ( & self , sess : & Session ) -> Vec < Symbol > {
212+ self . trans . target_features ( ( sess) )
213+ }
214+
215+ fn metadata_loader ( & self ) -> Box < MetadataLoader > {
216+ self . trans . metadata_loader ( )
217+ }
218+ fn provide ( & self , providers : & mut Providers ) {
219+ self . trans . provide ( providers)
220+ }
221+ fn provide_extern ( & self , providers : & mut Providers ) {
222+ self . trans . provide_extern ( providers)
223+ }
224+ fn trans_crate < ' a , ' tcx > (
225+ & self ,
226+ tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
227+ rx : mpsc:: Receiver < Box < Any + Send > >
228+ ) -> Box < Any > {
229+ self . trans . trans_crate ( tcx, rx)
230+ }
231+
232+ fn join_trans_and_link (
233+ & self ,
234+ trans : Box < Any > ,
235+ sess : & Session ,
236+ dep_graph : & DepGraph ,
237+ outputs : & OutputFilenames ,
238+ ) -> Result < ( ) , CompileIncomplete > {
239+ self . trans . join_trans_and_link ( trans, sess, dep_graph, outputs)
240+ }
241+ }
242+
243+ match DynamicLibrary :: open ( Some ( Path :: new ( backend_name) ) ) {
244+ Ok ( lib) => {
245+ unsafe {
246+ let trans = {
247+ let __rustc_codegen_backend: unsafe fn ( & Session ) -> Box < TransCrate > ;
248+ __rustc_codegen_backend = match lib. symbol ( "__rustc_codegen_backend" ) {
249+ Ok ( f) => :: std:: mem:: transmute :: < * mut u8 , _ > ( f) ,
250+ Err ( e) => sess. fatal ( & format ! ( "Couldnt load codegen backend as it\
251+ doesn't export the __rustc_backend_new symbol: {:?}", e) ) ,
252+ } ;
253+ __rustc_codegen_backend ( sess)
254+ } ;
255+ Box :: new ( ExternTransCrate {
256+ _lib : lib,
257+ trans
258+ } )
259+ }
260+ }
261+ Err ( err) => {
262+ sess. fatal ( & format ! ( "Couldnt load codegen backend {:?}: {:?}" , backend_name, err) ) ;
263+ }
264+ }
265+ }
266+
192267pub fn get_trans ( sess : & Session ) -> Box < TransCrate > {
193268 let trans_name = sess. opts . debugging_opts . codegen_backend . clone ( ) ;
194269 match trans_name. as_ref ( ) . map ( |s|& * * s) {
@@ -197,10 +272,10 @@ pub fn get_trans(sess: &Session) -> Box<TransCrate> {
197272 Some ( "metadata_only" ) => {
198273 rustc_trans_utils:: trans_crate:: MetadataOnlyTransCrate :: new ( & sess)
199274 }
200- Some ( filename) if filename. starts_with ( "/ ") => {
201- rustc_trans_utils :: trans_crate :: link_extern_backend ( & sess, filename)
275+ Some ( filename) if filename. contains ( ". ") => {
276+ load_backend_from_dylib ( & sess, & filename)
202277 }
203- Some ( trans_name) => sess. fatal ( & format ! ( "Invalid trans {}" , trans_name) ) ,
278+ Some ( trans_name) => sess. fatal ( & format ! ( "Unknown codegen backend {}" , trans_name) ) ,
204279 }
205280}
206281
0 commit comments