@@ -16,11 +16,10 @@ use back::svh::Svh;
1616use session:: { config, Session } ;
1717use session:: search_paths:: PathKind ;
1818use metadata:: cstore;
19- use metadata:: cstore:: { CStore , CrateSource } ;
19+ use metadata:: cstore:: { CStore , CrateSource , MetadataBlob } ;
2020use metadata:: decoder;
2121use metadata:: loader;
2222use metadata:: loader:: CratePaths ;
23- use plugin:: load:: PluginMetadata ;
2423use util:: nodemap:: FnvHashMap ;
2524
2625use std:: rc:: Rc ;
@@ -154,6 +153,29 @@ fn register_native_lib(sess: &Session,
154153 sess. cstore . add_used_library ( name, kind) ;
155154}
156155
156+ pub struct PluginMetadata < ' a > {
157+ sess : & ' a Session ,
158+ metadata : PMDSource ,
159+ dylib : Option < Path > ,
160+ info : CrateInfo ,
161+ vi_span : Span ,
162+ target_only : bool ,
163+ }
164+
165+ enum PMDSource {
166+ Registered ( Rc < cstore:: crate_metadata > ) ,
167+ Owned ( MetadataBlob ) ,
168+ }
169+
170+ impl PMDSource {
171+ pub fn as_slice < ' a > ( & ' a self ) -> & ' a [ u8 ] {
172+ match * self {
173+ PMDSource :: Registered ( ref cmd) => cmd. data ( ) ,
174+ PMDSource :: Owned ( ref mdb) => mdb. as_slice ( ) ,
175+ }
176+ }
177+ }
178+
157179impl < ' a > CrateReader < ' a > {
158180 pub fn new ( sess : & ' a Session ) -> CrateReader < ' a > {
159181 CrateReader {
@@ -450,17 +472,20 @@ impl<'a> CrateReader<'a> {
450472 } ) . collect ( )
451473 }
452474
453- pub fn read_plugin_metadata ( & mut self ,
454- krate : & ast:: ViewItem ) -> PluginMetadata {
455- let info = self . extract_crate_info ( krate ) . unwrap ( ) ;
475+ pub fn read_plugin_metadata < ' b > ( & ' b mut self ,
476+ vi : & ' b ast:: ViewItem ) -> PluginMetadata < ' b > {
477+ let info = self . extract_crate_info ( vi ) . unwrap ( ) ;
456478 let target_triple = self . sess . opts . target_triple [ ] ;
457479 let is_cross = target_triple != config:: host_triple ( ) ;
458480 let mut should_link = info. should_link && !is_cross;
481+ let mut target_only = false ;
482+ let ident = info. ident . clone ( ) ;
483+ let name = info. name . clone ( ) ;
459484 let mut load_ctxt = loader:: Context {
460485 sess : self . sess ,
461- span : krate . span ,
462- ident : info . ident [ ] ,
463- crate_name : info . name [ ] ,
486+ span : vi . span ,
487+ ident : ident[ ] ,
488+ crate_name : name[ ] ,
464489 hash : None ,
465490 filesearch : self . sess . host_filesearch ( PathKind :: Crate ) ,
466491 triple : config:: host_triple ( ) ,
@@ -472,32 +497,49 @@ impl<'a> CrateReader<'a> {
472497 let library = match load_ctxt. maybe_load_library_crate ( ) {
473498 Some ( l) => l,
474499 None if is_cross => {
475- // try loading from target crates (only valid if there are
476- // no syntax extensions)
500+ // Try loading from target crates. This will abort later if we try to
501+ // load a plugin registrar function,
502+ target_only = true ;
503+ should_link = info. should_link ;
504+
477505 load_ctxt. triple = target_triple;
478506 load_ctxt. filesearch = self . sess . target_filesearch ( PathKind :: Crate ) ;
479- let lib = load_ctxt. load_library_crate ( ) ;
480- if decoder:: get_plugin_registrar_fn ( lib. metadata . as_slice ( ) ) . is_some ( ) {
481- let message = format ! ( "crate `{}` contains a plugin_registrar fn but \
482- only a version for triple `{}` could be found (need {})",
483- info. ident, target_triple, config:: host_triple( ) ) ;
484- self . sess . span_err ( krate. span , message[ ] ) ;
485- // need to abort now because the syntax expansion
486- // code will shortly attempt to load and execute
487- // code from the found library.
488- self . sess . abort_if_errors ( ) ;
489- }
490- should_link = info. should_link ;
491- lib
507+ load_ctxt. load_library_crate ( )
492508 }
493509 None => { load_ctxt. report_load_errs ( ) ; unreachable ! ( ) } ,
494510 } ;
495511
496- // Read exported macros
497- let imported_from = Some ( token:: intern ( info. ident [ ] ) . ident ( ) ) ;
498- let source_name = format ! ( "<{} macros>" , info. ident[ ] ) ;
512+ let dylib = library. dylib . clone ( ) ;
513+ let register = should_link && self . existing_match ( info. name [ ] , None ) . is_none ( ) ;
514+ let metadata = if register {
515+ // Register crate now to avoid double-reading metadata
516+ let ( _, cmd, _) = self . register_crate ( & None , info. ident [ ] ,
517+ info. name [ ] , vi. span , library) ;
518+ PMDSource :: Registered ( cmd)
519+ } else {
520+ // Not registering the crate; just hold on to the metadata
521+ PMDSource :: Owned ( library. metadata )
522+ } ;
523+
524+ PluginMetadata {
525+ sess : self . sess ,
526+ metadata : metadata,
527+ dylib : dylib,
528+ info : info,
529+ vi_span : vi. span ,
530+ target_only : target_only,
531+ }
532+ }
533+ }
534+
535+ impl < ' a > PluginMetadata < ' a > {
536+ /// Read exported macros
537+ pub fn exported_macros ( & self ) -> Vec < ast:: MacroDef > {
538+ let imported_from = Some ( token:: intern ( self . info . ident [ ] ) . ident ( ) ) ;
539+ let source_name = format ! ( "<{} macros>" , self . info. ident[ ] ) ;
499540 let mut macros = vec ! [ ] ;
500- decoder:: each_exported_macro ( library. metadata . as_slice ( ) , & * self . sess . cstore . intr ,
541+ decoder:: each_exported_macro ( self . metadata . as_slice ( ) ,
542+ & * self . sess . cstore . intr ,
501543 |name, attrs, body| {
502544 // NB: Don't use parse::parse_tts_from_source_str because it parses with
503545 // quote_depth > 0.
@@ -520,31 +562,37 @@ impl<'a> CrateReader<'a> {
520562 true
521563 }
522564 ) ;
565+ macros
566+ }
523567
524- // Look for a plugin registrar
525- let registrar = decoder :: get_plugin_registrar_fn ( library . metadata . as_slice ( ) ) . map ( |id| {
526- decoder :: get_symbol ( library . metadata . as_slice ( ) , id )
527- } ) ;
528- if library . dylib . is_none ( ) && registrar . is_some ( ) {
529- let message = format ! ( "plugin crate `{}` only found in rlib format, \
530- but must be available in dylib format" ,
531- info . ident ) ;
532- self . sess . span_err ( krate . span , message [ ] ) ;
533- // No need to abort because the loading code will just ignore this
534- // empty dylib.
568+ /// Look for a plugin registrar. Returns library path and symbol name.
569+ pub fn plugin_registrar ( & self ) -> Option < ( Path , String ) > {
570+ if self . target_only {
571+ // Need to abort before syntax expansion.
572+ let message = format ! ( "plugin crate `{}` is not available for triple `{}` \
573+ (only found {})" ,
574+ self . info . ident ,
575+ config :: host_triple ( ) ,
576+ self . sess. opts . target_triple ) ;
577+ self . sess . span_err ( self . vi_span , message [ ] ) ;
578+ self . sess . abort_if_errors ( ) ;
535579 }
536- let pc = PluginMetadata {
537- macros : macros,
538- registrar : match ( library. dylib . as_ref ( ) , registrar) {
539- ( Some ( dylib) , Some ( reg) ) => Some ( ( dylib. clone ( ) , reg) ) ,
540- _ => None ,
541- } ,
542- } ;
543- if should_link && self . existing_match ( info. name [ ] , None ) . is_none ( ) {
544- // register crate now to avoid double-reading metadata
545- self . register_crate ( & None , info. ident [ ] ,
546- info. name [ ] , krate. span , library) ;
580+
581+ let registrar = decoder:: get_plugin_registrar_fn ( self . metadata . as_slice ( ) )
582+ . map ( |id| decoder:: get_symbol ( self . metadata . as_slice ( ) , id) ) ;
583+
584+ match ( self . dylib . as_ref ( ) , registrar) {
585+ ( Some ( dylib) , Some ( reg) ) => Some ( ( dylib. clone ( ) , reg) ) ,
586+ ( None , Some ( _) ) => {
587+ let message = format ! ( "plugin crate `{}` only found in rlib format, \
588+ but must be available in dylib format",
589+ self . info. ident) ;
590+ self . sess . span_err ( self . vi_span , message[ ] ) ;
591+ // No need to abort because the loading code will just ignore this
592+ // empty dylib.
593+ None
594+ }
595+ _ => None ,
547596 }
548- pc
549597 }
550598}
0 commit comments