104
104
105
105
use monomorphize:: collector:: InliningMap ;
106
106
use rustc:: dep_graph:: WorkProductId ;
107
+ use rustc:: hir:: CodegenFnAttrFlags ;
107
108
use rustc:: hir:: def_id:: DefId ;
108
109
use rustc:: hir:: map:: DefPathData ;
109
110
use rustc:: mir:: mono:: { Linkage , Visibility } ;
@@ -300,6 +301,13 @@ fn place_root_mono_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
300
301
let is_incremental_build = tcx. sess . opts . incremental . is_some ( ) ;
301
302
let mut internalization_candidates = FxHashSet ( ) ;
302
303
304
+ // Determine if monomorphizations instantiated in this crate will be made
305
+ // available to downstream crates. This depends on whether we are in
306
+ // share-generics mode and whether the current crate can even have
307
+ // downstream crates.
308
+ let export_generics = tcx. sess . opts . share_generics ( ) &&
309
+ tcx. local_crate_exports_generics ( ) ;
310
+
303
311
for mono_item in mono_items {
304
312
match mono_item. instantiation_mode ( tcx) {
305
313
InstantiationMode :: GloballyShared { .. } => { }
@@ -323,29 +331,7 @@ fn place_root_mono_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
323
331
tcx,
324
332
& mono_item,
325
333
& mut can_be_internalized,
326
- & |id, is_generic| {
327
- if !tcx. sess . target . target . options . default_hidden_visibility {
328
- return Visibility :: Default
329
- }
330
-
331
- // Generic functions never have export level C
332
- if is_generic {
333
- return Visibility :: Hidden
334
- }
335
-
336
- // Things with export level C don't get instantiated in
337
- // downstream crates
338
- if !id. is_local ( ) {
339
- return Visibility :: Hidden
340
- }
341
-
342
- // C-export level items remain at `Default`, all other internal
343
- // items become `Hidden`
344
- match tcx. reachable_non_generics ( id. krate ) . get ( & id) {
345
- Some ( SymbolExportLevel :: C ) => Visibility :: Default ,
346
- _ => Visibility :: Hidden ,
347
- }
348
- } ,
334
+ export_generics,
349
335
) ;
350
336
if visibility == Visibility :: Hidden && can_be_internalized {
351
337
internalization_candidates. insert ( mono_item) ;
@@ -376,20 +362,25 @@ fn mono_item_linkage_and_visibility(
376
362
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
377
363
mono_item : & MonoItem < ' tcx > ,
378
364
can_be_internalized : & mut bool ,
379
- default : & dyn Fn ( DefId , bool ) -> Visibility ,
365
+ export_generics : bool ,
380
366
) -> ( Linkage , Visibility ) {
381
367
if let Some ( explicit_linkage) = mono_item. explicit_linkage ( tcx) {
382
368
return ( explicit_linkage, Visibility :: Default )
383
369
}
384
- let vis = mono_item_visibility ( tcx, mono_item, can_be_internalized, default) ;
370
+ let vis = mono_item_visibility (
371
+ tcx,
372
+ mono_item,
373
+ can_be_internalized,
374
+ export_generics,
375
+ ) ;
385
376
( Linkage :: External , vis)
386
377
}
387
378
388
379
fn mono_item_visibility (
389
380
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
390
381
mono_item : & MonoItem < ' tcx > ,
391
382
can_be_internalized : & mut bool ,
392
- default_visibility : & dyn Fn ( DefId , bool ) -> Visibility ,
383
+ export_generics : bool ,
393
384
) -> Visibility {
394
385
let instance = match mono_item {
395
386
// This is pretty complicated, go below
@@ -399,7 +390,7 @@ fn mono_item_visibility(
399
390
MonoItem :: Static ( def_id) => {
400
391
return if tcx. is_reachable_non_generic ( * def_id) {
401
392
* can_be_internalized = false ;
402
- default_visibility ( * def_id, false )
393
+ default_visibility ( tcx , * def_id, false )
403
394
} else {
404
395
Visibility :: Hidden
405
396
} ;
@@ -408,7 +399,7 @@ fn mono_item_visibility(
408
399
let def_id = tcx. hir . local_def_id ( * node_id) ;
409
400
return if tcx. is_reachable_non_generic ( def_id) {
410
401
* can_be_internalized = false ;
411
- default_visibility ( def_id, false )
402
+ default_visibility ( tcx , def_id, false )
412
403
} else {
413
404
Visibility :: Hidden
414
405
} ;
@@ -440,18 +431,13 @@ fn mono_item_visibility(
440
431
// hidden visibility, it should indeed be a candidate for
441
432
// internalization, but we have to understand that it's referenced
442
433
// from the `main` symbol we'll generate later.
434
+ //
435
+ // This may be fixable with a new `InstanceDef` perhaps? Unsure!
443
436
if tcx. lang_items ( ) . start_fn ( ) == Some ( def_id) {
444
437
* can_be_internalized = false ;
445
438
return Visibility :: Hidden
446
439
}
447
440
448
- // Determine if monomorphizations instantiated in this crate will be made
449
- // available to downstream crates. This depends on whether we are in
450
- // share-generics mode and whether the current crate can even have
451
- // downstream crates.
452
- let export_generics = tcx. sess . opts . share_generics ( ) &&
453
- tcx. local_crate_exports_generics ( ) ;
454
-
455
441
let is_generic = instance. substs . types ( ) . next ( ) . is_some ( ) ;
456
442
457
443
// Upstream `DefId` instances get different handling than local ones
@@ -461,7 +447,7 @@ fn mono_item_visibility(
461
447
// and we export generics, we must make
462
448
// it available to downstream crates.
463
449
* can_be_internalized = false ;
464
- default_visibility ( def_id, true )
450
+ default_visibility ( tcx , def_id, true )
465
451
} else {
466
452
Visibility :: Hidden
467
453
}
@@ -477,7 +463,7 @@ fn mono_item_visibility(
477
463
// This instance might be useful in
478
464
// a downstream crate.
479
465
* can_be_internalized = false ;
480
- default_visibility ( def_id, true )
466
+ default_visibility ( tcx , def_id, true )
481
467
}
482
468
} else {
483
469
// We are not exporting generics or
@@ -487,14 +473,82 @@ fn mono_item_visibility(
487
473
Visibility :: Hidden
488
474
}
489
475
} else {
490
- // This isn't a generic function.
476
+
477
+ // If this isn't a generic function then we mark this a `Default` if
478
+ // this is a reachable item, meaning that it's a symbol other crates may
479
+ // access when they link to us.
491
480
if tcx. is_reachable_non_generic ( def_id) {
492
481
* can_be_internalized = false ;
493
482
debug_assert ! ( !is_generic) ;
494
- default_visibility ( def_id, false )
495
- } else {
496
- Visibility :: Hidden
483
+ return default_visibility ( tcx, def_id, false )
484
+ }
485
+
486
+ // If this isn't reachable then we're gonna tag this with `Hidden`
487
+ // visibility. In some situations though we'll want to prevent this
488
+ // symbol from being internalized.
489
+ //
490
+ // There's two categories of items here:
491
+ //
492
+ // * First is weak lang items. These are basically mechanisms for
493
+ // libcore to forward-reference symbols defined later in crates like
494
+ // the standard library or `#[panic_implementation]` definitions. The
495
+ // definition of these weak lang items needs to be referenceable by
496
+ // libcore, so we're no longer a candidate for internalization.
497
+ // Removal of these functions can't be done by LLVM but rather must be
498
+ // done by the linker as it's a non-local decision.
499
+ //
500
+ // * Second is "std internal symbols". Currently this is primarily used
501
+ // for allocator symbols. Allocators are a little weird in their
502
+ // implementation, but the idea is that the compiler, at the last
503
+ // minute, defines an allocator with an injected object file. The
504
+ // `alloc` crate references these symbols (`__rust_alloc`) and the
505
+ // definition doesn't get hooked up until a linked crate artifact is
506
+ // generated.
507
+ //
508
+ // The symbols synthesized by the compiler (`__rust_alloc`) are thin
509
+ // veneers around the actual implementation, some other symbol which
510
+ // implements the same ABI. These symbols (things like `__rg_alloc`,
511
+ // `__rdl_alloc`, `__rde_alloc`, etc), are all tagged with "std
512
+ // internal symbols".
513
+ //
514
+ // The std-internal symbols here **should not show up in a dll as an
515
+ // exported interface**, so they return `false` from
516
+ // `is_reachable_non_generic` above and we'll give them `Hidden`
517
+ // visibility below. Like the weak lang items, though, we can't let
518
+ // LLVM internalize them as this decision is left up to the linker to
519
+ // omit them, so prevent them from being internalized.
520
+ let codegen_fn_attrs = tcx. codegen_fn_attrs ( def_id) ;
521
+ let std_internal_symbol = codegen_fn_attrs. flags
522
+ . contains ( CodegenFnAttrFlags :: RUSTC_STD_INTERNAL_SYMBOL ) ;
523
+ if tcx. is_weak_lang_item ( def_id) || std_internal_symbol {
524
+ * can_be_internalized = false ;
497
525
}
526
+
527
+ Visibility :: Hidden
528
+ }
529
+ }
530
+
531
+ fn default_visibility ( tcx : TyCtxt , id : DefId , is_generic : bool ) -> Visibility {
532
+ if !tcx. sess . target . target . options . default_hidden_visibility {
533
+ return Visibility :: Default
534
+ }
535
+
536
+ // Generic functions never have export level C
537
+ if is_generic {
538
+ return Visibility :: Hidden
539
+ }
540
+
541
+ // Things with export level C don't get instantiated in
542
+ // downstream crates
543
+ if !id. is_local ( ) {
544
+ return Visibility :: Hidden
545
+ }
546
+
547
+ // C-export level items remain at `Default`, all other internal
548
+ // items become `Hidden`
549
+ match tcx. reachable_non_generics ( id. krate ) . get ( & id) {
550
+ Some ( SymbolExportLevel :: C ) => Visibility :: Default ,
551
+ _ => Visibility :: Hidden ,
498
552
}
499
553
}
500
554
0 commit comments