@@ -16,11 +16,10 @@ use back::svh::Svh;
16
16
use session:: { config, Session } ;
17
17
use session:: search_paths:: PathKind ;
18
18
use metadata:: cstore;
19
- use metadata:: cstore:: { CStore , CrateSource } ;
19
+ use metadata:: cstore:: { CStore , CrateSource , MetadataBlob } ;
20
20
use metadata:: decoder;
21
21
use metadata:: loader;
22
22
use metadata:: loader:: CratePaths ;
23
- use plugin:: load:: PluginMetadata ;
24
23
use util:: nodemap:: FnvHashMap ;
25
24
26
25
use std:: rc:: Rc ;
@@ -154,6 +153,29 @@ fn register_native_lib(sess: &Session,
154
153
sess. cstore . add_used_library ( name, kind) ;
155
154
}
156
155
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
+
157
179
impl < ' a > CrateReader < ' a > {
158
180
pub fn new ( sess : & ' a Session ) -> CrateReader < ' a > {
159
181
CrateReader {
@@ -450,17 +472,20 @@ impl<'a> CrateReader<'a> {
450
472
} ) . collect ( )
451
473
}
452
474
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 ( ) ;
456
478
let target_triple = self . sess . opts . target_triple [ ] ;
457
479
let is_cross = target_triple != config:: host_triple ( ) ;
458
480
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 ( ) ;
459
484
let mut load_ctxt = loader:: Context {
460
485
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[ ] ,
464
489
hash : None ,
465
490
filesearch : self . sess . host_filesearch ( PathKind :: Crate ) ,
466
491
triple : config:: host_triple ( ) ,
@@ -472,32 +497,49 @@ impl<'a> CrateReader<'a> {
472
497
let library = match load_ctxt. maybe_load_library_crate ( ) {
473
498
Some ( l) => l,
474
499
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
+
477
505
load_ctxt. triple = target_triple;
478
506
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 ( )
492
508
}
493
509
None => { load_ctxt. report_load_errs ( ) ; unreachable ! ( ) } ,
494
510
} ;
495
511
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[ ] ) ;
499
540
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 ,
501
543
|name, attrs, body| {
502
544
// NB: Don't use parse::parse_tts_from_source_str because it parses with
503
545
// quote_depth > 0.
@@ -520,31 +562,37 @@ impl<'a> CrateReader<'a> {
520
562
true
521
563
}
522
564
) ;
565
+ macros
566
+ }
523
567
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 ( ) ;
535
579
}
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 ,
547
596
}
548
- pc
549
597
}
550
598
}
0 commit comments