104104
105105use monomorphize:: collector:: InliningMap ;
106106use rustc:: dep_graph:: WorkProductId ;
107+ use rustc:: hir:: CodegenFnAttrFlags ;
107108use rustc:: hir:: def_id:: DefId ;
108109use rustc:: hir:: map:: DefPathData ;
109110use rustc:: mir:: mono:: { Linkage , Visibility } ;
@@ -300,6 +301,13 @@ fn place_root_mono_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
300301 let is_incremental_build = tcx. sess . opts . incremental . is_some ( ) ;
301302 let mut internalization_candidates = FxHashSet ( ) ;
302303
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+
303311 for mono_item in mono_items {
304312 match mono_item. instantiation_mode ( tcx) {
305313 InstantiationMode :: GloballyShared { .. } => { }
@@ -323,29 +331,7 @@ fn place_root_mono_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
323331 tcx,
324332 & mono_item,
325333 & 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,
349335 ) ;
350336 if visibility == Visibility :: Hidden && can_be_internalized {
351337 internalization_candidates. insert ( mono_item) ;
@@ -376,20 +362,25 @@ fn mono_item_linkage_and_visibility(
376362 tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
377363 mono_item : & MonoItem < ' tcx > ,
378364 can_be_internalized : & mut bool ,
379- default : & dyn Fn ( DefId , bool ) -> Visibility ,
365+ export_generics : bool ,
380366) -> ( Linkage , Visibility ) {
381367 if let Some ( explicit_linkage) = mono_item. explicit_linkage ( tcx) {
382368 return ( explicit_linkage, Visibility :: Default )
383369 }
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+ ) ;
385376 ( Linkage :: External , vis)
386377}
387378
388379fn mono_item_visibility (
389380 tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
390381 mono_item : & MonoItem < ' tcx > ,
391382 can_be_internalized : & mut bool ,
392- default_visibility : & dyn Fn ( DefId , bool ) -> Visibility ,
383+ export_generics : bool ,
393384) -> Visibility {
394385 let instance = match mono_item {
395386 // This is pretty complicated, go below
@@ -399,7 +390,7 @@ fn mono_item_visibility(
399390 MonoItem :: Static ( def_id) => {
400391 return if tcx. is_reachable_non_generic ( * def_id) {
401392 * can_be_internalized = false ;
402- default_visibility ( * def_id, false )
393+ default_visibility ( tcx , * def_id, false )
403394 } else {
404395 Visibility :: Hidden
405396 } ;
@@ -408,7 +399,7 @@ fn mono_item_visibility(
408399 let def_id = tcx. hir . local_def_id ( * node_id) ;
409400 return if tcx. is_reachable_non_generic ( def_id) {
410401 * can_be_internalized = false ;
411- default_visibility ( def_id, false )
402+ default_visibility ( tcx , def_id, false )
412403 } else {
413404 Visibility :: Hidden
414405 } ;
@@ -440,18 +431,13 @@ fn mono_item_visibility(
440431 // hidden visibility, it should indeed be a candidate for
441432 // internalization, but we have to understand that it's referenced
442433 // from the `main` symbol we'll generate later.
434+ //
435+ // This may be fixable with a new `InstanceDef` perhaps? Unsure!
443436 if tcx. lang_items ( ) . start_fn ( ) == Some ( def_id) {
444437 * can_be_internalized = false ;
445438 return Visibility :: Hidden
446439 }
447440
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-
455441 let is_generic = instance. substs . types ( ) . next ( ) . is_some ( ) ;
456442
457443 // Upstream `DefId` instances get different handling than local ones
@@ -461,7 +447,7 @@ fn mono_item_visibility(
461447 // and we export generics, we must make
462448 // it available to downstream crates.
463449 * can_be_internalized = false ;
464- default_visibility ( def_id, true )
450+ default_visibility ( tcx , def_id, true )
465451 } else {
466452 Visibility :: Hidden
467453 }
@@ -477,7 +463,7 @@ fn mono_item_visibility(
477463 // This instance might be useful in
478464 // a downstream crate.
479465 * can_be_internalized = false ;
480- default_visibility ( def_id, true )
466+ default_visibility ( tcx , def_id, true )
481467 }
482468 } else {
483469 // We are not exporting generics or
@@ -487,14 +473,82 @@ fn mono_item_visibility(
487473 Visibility :: Hidden
488474 }
489475 } 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.
491480 if tcx. is_reachable_non_generic ( def_id) {
492481 * can_be_internalized = false ;
493482 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 ;
497525 }
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 ,
498552 }
499553}
500554
0 commit comments