@@ -300,13 +300,6 @@ fn place_root_mono_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
300300 let is_incremental_build = tcx. sess . opts . incremental . is_some ( ) ;
301301 let mut internalization_candidates = FxHashSet ( ) ;
302302
303- // Determine if monomorphizations instantiated in this crate will be made
304- // available to downstream crates. This depends on whether we are in
305- // share-generics mode and whether the current crate can even have
306- // downstream crates.
307- let export_generics = tcx. sess . opts . share_generics ( ) &&
308- tcx. local_crate_exports_generics ( ) ;
309-
310303 for mono_item in mono_items {
311304 match mono_item. instantiation_mode ( tcx) {
312305 InstantiationMode :: GloballyShared { .. } => { }
@@ -322,146 +315,38 @@ fn place_root_mono_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
322315 None => fallback_cgu_name ( tcx) ,
323316 } ;
324317
325- let make_codegen_unit = || {
326- CodegenUnit :: new ( codegen_unit_name. clone ( ) )
327- } ;
328-
329318 let codegen_unit = codegen_units. entry ( codegen_unit_name. clone ( ) )
330- . or_insert_with ( make_codegen_unit ) ;
319+ . or_insert_with ( || CodegenUnit :: new ( codegen_unit_name . clone ( ) ) ) ;
331320
332321 let mut can_be_internalized = true ;
333- let default_visibility = |id : DefId , is_generic : bool | {
334- if !tcx. sess . target . target . options . default_hidden_visibility {
335- return Visibility :: Default
336- }
322+ let ( linkage, visibility) = mono_item_linkage_and_visibility (
323+ tcx,
324+ & mono_item,
325+ & mut can_be_internalized,
326+ & |id, is_generic| {
327+ if !tcx. sess . target . target . options . default_hidden_visibility {
328+ return Visibility :: Default
329+ }
337330
338- // Generic functions never have export level C
339- if is_generic {
340- return Visibility :: Hidden
341- }
331+ // Generic functions never have export level C
332+ if is_generic {
333+ return Visibility :: Hidden
334+ }
342335
343- // Things with export level C don't get instantiated in downstream
344- // crates
345- if !id. is_local ( ) {
346- return Visibility :: Hidden
347- }
336+ // Things with export level C don't get instantiated in
337+ // downstream crates
338+ if !id. is_local ( ) {
339+ return Visibility :: Hidden
340+ }
348341
349- if let Some ( & SymbolExportLevel :: C ) = tcx. reachable_non_generics ( id. krate )
350- . get ( & id) {
351- Visibility :: Default
352- } else {
353- Visibility :: Hidden
354- }
355- } ;
356- let ( linkage, visibility) = match mono_item. explicit_linkage ( tcx) {
357- Some ( explicit_linkage) => ( explicit_linkage, Visibility :: Default ) ,
358- None => {
359- match mono_item {
360- MonoItem :: Fn ( ref instance) => {
361- let visibility = match instance. def {
362- InstanceDef :: Item ( def_id) => {
363- let is_generic = instance. substs
364- . types ( )
365- . next ( )
366- . is_some ( ) ;
367-
368- // The `start_fn` lang item is actually a
369- // monomorphized instance of a function in the
370- // standard library, used for the `main`
371- // function. We don't want to export it so we
372- // tag it with `Hidden` visibility but this
373- // symbol is only referenced from the actual
374- // `main` symbol which we unfortunately don't
375- // know anything about during
376- // partitioning/collection. As a result we
377- // forcibly keep this symbol out of the
378- // `internalization_candidates` set.
379- //
380- // FIXME: eventually we don't want to always
381- // force this symbol to have hidden
382- // visibility, it should indeed be a candidate
383- // for internalization, but we have to
384- // understand that it's referenced from the
385- // `main` symbol we'll generate later.
386- if tcx. lang_items ( ) . start_fn ( ) == Some ( def_id) {
387- can_be_internalized = false ;
388- Visibility :: Hidden
389- } else if def_id. is_local ( ) {
390- if is_generic {
391- if export_generics {
392- if tcx. is_unreachable_local_definition ( def_id) {
393- // This instance cannot be used
394- // from another crate.
395- Visibility :: Hidden
396- } else {
397- // This instance might be useful in
398- // a downstream crate.
399- can_be_internalized = false ;
400- default_visibility ( def_id, true )
401- }
402- } else {
403- // We are not exporting generics or
404- // the definition is not reachable
405- // for downstream crates, we can
406- // internalize its instantiations.
407- Visibility :: Hidden
408- }
409- } else {
410- // This isn't a generic function.
411- if tcx. is_reachable_non_generic ( def_id) {
412- can_be_internalized = false ;
413- debug_assert ! ( !is_generic) ;
414- default_visibility ( def_id, false )
415- } else {
416- Visibility :: Hidden
417- }
418- }
419- } else {
420- // This is an upstream DefId.
421- if export_generics && is_generic {
422- // If it is a upstream monomorphization
423- // and we export generics, we must make
424- // it available to downstream crates.
425- can_be_internalized = false ;
426- default_visibility ( def_id, true )
427- } else {
428- Visibility :: Hidden
429- }
430- }
431- }
432- InstanceDef :: FnPtrShim ( ..) |
433- InstanceDef :: Virtual ( ..) |
434- InstanceDef :: Intrinsic ( ..) |
435- InstanceDef :: ClosureOnceShim { .. } |
436- InstanceDef :: DropGlue ( ..) |
437- InstanceDef :: CloneShim ( ..) => {
438- Visibility :: Hidden
439- }
440- } ;
441- ( Linkage :: External , visibility)
442- }
443- MonoItem :: Static ( def_id) => {
444- let visibility = if tcx. is_reachable_non_generic ( def_id) {
445- can_be_internalized = false ;
446- default_visibility ( def_id, false )
447- } else {
448- Visibility :: Hidden
449- } ;
450- ( Linkage :: External , visibility)
451- }
452- MonoItem :: GlobalAsm ( node_id) => {
453- let def_id = tcx. hir . local_def_id ( node_id) ;
454- let visibility = if tcx. is_reachable_non_generic ( def_id) {
455- can_be_internalized = false ;
456- default_visibility ( def_id, false )
457- } else {
458- Visibility :: Hidden
459- } ;
460- ( Linkage :: External , visibility)
461- }
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 ,
462347 }
463- }
464- } ;
348+ } ,
349+ ) ;
465350 if visibility == Visibility :: Hidden && can_be_internalized {
466351 internalization_candidates. insert ( mono_item) ;
467352 }
@@ -487,6 +372,132 @@ fn place_root_mono_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
487372 }
488373}
489374
375+ fn mono_item_linkage_and_visibility (
376+ tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
377+ mono_item : & MonoItem < ' tcx > ,
378+ can_be_internalized : & mut bool ,
379+ default : & dyn Fn ( DefId , bool ) -> Visibility ,
380+ ) -> ( Linkage , Visibility ) {
381+ if let Some ( explicit_linkage) = mono_item. explicit_linkage ( tcx) {
382+ return ( explicit_linkage, Visibility :: Default )
383+ }
384+ let vis = mono_item_visibility ( tcx, mono_item, can_be_internalized, default) ;
385+ ( Linkage :: External , vis)
386+ }
387+
388+ fn mono_item_visibility (
389+ tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
390+ mono_item : & MonoItem < ' tcx > ,
391+ can_be_internalized : & mut bool ,
392+ default_visibility : & dyn Fn ( DefId , bool ) -> Visibility ,
393+ ) -> Visibility {
394+ let instance = match mono_item {
395+ // This is pretty complicated, go below
396+ MonoItem :: Fn ( instance) => instance,
397+
398+ // Misc handling for generics and such, but otherwise
399+ MonoItem :: Static ( def_id) => {
400+ return if tcx. is_reachable_non_generic ( * def_id) {
401+ * can_be_internalized = false ;
402+ default_visibility ( * def_id, false )
403+ } else {
404+ Visibility :: Hidden
405+ } ;
406+ }
407+ MonoItem :: GlobalAsm ( node_id) => {
408+ let def_id = tcx. hir . local_def_id ( * node_id) ;
409+ return if tcx. is_reachable_non_generic ( def_id) {
410+ * can_be_internalized = false ;
411+ default_visibility ( def_id, false )
412+ } else {
413+ Visibility :: Hidden
414+ } ;
415+ }
416+ } ;
417+
418+ let def_id = match instance. def {
419+ InstanceDef :: Item ( def_id) => def_id,
420+
421+ // These are all compiler glue and such, never exported, always hidden.
422+ InstanceDef :: FnPtrShim ( ..) |
423+ InstanceDef :: Virtual ( ..) |
424+ InstanceDef :: Intrinsic ( ..) |
425+ InstanceDef :: ClosureOnceShim { .. } |
426+ InstanceDef :: DropGlue ( ..) |
427+ InstanceDef :: CloneShim ( ..) => {
428+ return Visibility :: Hidden
429+ }
430+ } ;
431+
432+ // The `start_fn` lang item is actually a monomorphized instance of a
433+ // function in the standard library, used for the `main` function. We don't
434+ // want to export it so we tag it with `Hidden` visibility but this symbol
435+ // is only referenced from the actual `main` symbol which we unfortunately
436+ // don't know anything about during partitioning/collection. As a result we
437+ // forcibly keep this symbol out of the `internalization_candidates` set.
438+ //
439+ // FIXME: eventually we don't want to always force this symbol to have
440+ // hidden visibility, it should indeed be a candidate for
441+ // internalization, but we have to understand that it's referenced
442+ // from the `main` symbol we'll generate later.
443+ if tcx. lang_items ( ) . start_fn ( ) == Some ( def_id) {
444+ * can_be_internalized = false ;
445+ return Visibility :: Hidden
446+ }
447+
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+ let is_generic = instance. substs . types ( ) . next ( ) . is_some ( ) ;
456+
457+ // Upstream `DefId` instances get different handling than local ones
458+ if !def_id. is_local ( ) {
459+ return if export_generics && is_generic {
460+ // If it is a upstream monomorphization
461+ // and we export generics, we must make
462+ // it available to downstream crates.
463+ * can_be_internalized = false ;
464+ default_visibility ( def_id, true )
465+ } else {
466+ Visibility :: Hidden
467+ }
468+ }
469+
470+ if is_generic {
471+ if export_generics {
472+ if tcx. is_unreachable_local_definition ( def_id) {
473+ // This instance cannot be used
474+ // from another crate.
475+ Visibility :: Hidden
476+ } else {
477+ // This instance might be useful in
478+ // a downstream crate.
479+ * can_be_internalized = false ;
480+ default_visibility ( def_id, true )
481+ }
482+ } else {
483+ // We are not exporting generics or
484+ // the definition is not reachable
485+ // for downstream crates, we can
486+ // internalize its instantiations.
487+ Visibility :: Hidden
488+ }
489+ } else {
490+ // This isn't a generic function.
491+ if tcx. is_reachable_non_generic ( def_id) {
492+ * can_be_internalized = false ;
493+ debug_assert ! ( !is_generic) ;
494+ default_visibility ( def_id, false )
495+ } else {
496+ Visibility :: Hidden
497+ }
498+ }
499+ }
500+
490501fn merge_codegen_units < ' tcx > ( initial_partitioning : & mut PreInliningPartitioning < ' tcx > ,
491502 target_cgu_count : usize ,
492503 crate_name : & str ) {
0 commit comments