@@ -265,15 +265,11 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
265265 let mut codegen_units = FnvHashMap ( ) ;
266266
267267 for trans_item in trans_items {
268- let is_root = match trans_item {
269- TransItem :: Static ( ..) => true ,
270- TransItem :: DropGlue ( ..) => false ,
271- TransItem :: Fn ( _) => !trans_item. is_from_extern_crate ( ) ,
272- } ;
268+ let is_root = !trans_item. is_instantiated_only_on_demand ( ) ;
273269
274270 if is_root {
275271 let characteristic_def_id = characteristic_def_id_of_trans_item ( tcx, trans_item) ;
276- let is_volatile = trans_item. is_lazily_instantiated ( ) ;
272+ let is_volatile = trans_item. is_generic_fn ( ) ;
277273
278274 let codegen_unit_name = match characteristic_def_id {
279275 Some ( def_id) => compute_codegen_unit_name ( tcx, def_id, is_volatile) ,
@@ -304,9 +300,9 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
304300 // it might be used in another codegen unit.
305301 llvm:: ExternalLinkage
306302 } else {
307- // Monomorphizations of generic functions are
308- // always weak-odr
309- llvm :: WeakODRLinkage
303+ // In the current setup, generic functions cannot
304+ // be roots.
305+ unreachable ! ( )
310306 }
311307 }
312308 }
@@ -395,25 +391,30 @@ fn place_inlined_translation_items<'tcx>(initial_partitioning: PreInliningPartit
395391 if let Some ( linkage) = codegen_unit. items . get ( & trans_item) {
396392 // This is a root, just copy it over
397393 new_codegen_unit. items . insert ( trans_item, * linkage) ;
394+ } else if initial_partitioning. roots . contains ( & trans_item) {
395+ // This item will be instantiated in some other codegen unit,
396+ // so we just add it here with AvailableExternallyLinkage
397+ // FIXME(mw): I have not seen it happening yet but having
398+ // available_externally here could potentially lead
399+ // to the same problem with exception handling tables
400+ // as in the case below.
401+ new_codegen_unit. items . insert ( trans_item,
402+ llvm:: AvailableExternallyLinkage ) ;
403+ } else if trans_item. is_from_extern_crate ( ) && !trans_item. is_generic_fn ( ) {
404+ // FIXME(mw): It would be nice if we could mark these as
405+ // `AvailableExternallyLinkage`, since they should have
406+ // been instantiated in the extern crate. But this
407+ // sometimes leads to crashes on Windows because LLVM
408+ // does not handle exception handling table instantiation
409+ // reliably in that case.
410+ new_codegen_unit. items . insert ( trans_item, llvm:: InternalLinkage ) ;
398411 } else {
399- if initial_partitioning. roots . contains ( & trans_item) {
400- // This item will be instantiated in some other codegen unit,
401- // so we just add it here with AvailableExternallyLinkage
402- new_codegen_unit. items . insert ( trans_item,
403- llvm:: AvailableExternallyLinkage ) ;
404- } else if trans_item. is_from_extern_crate ( ) && !trans_item. is_generic_fn ( ) {
405- // An instantiation of this item is always available in the
406- // crate it was imported from.
407- new_codegen_unit. items . insert ( trans_item,
408- llvm:: AvailableExternallyLinkage ) ;
409- } else {
410- // We can't be sure if this will also be instantiated
411- // somewhere else, so we add an instance here with
412- // LinkOnceODRLinkage. That way the item can be discarded if
413- // it's not needed (inlined) after all.
414- new_codegen_unit. items . insert ( trans_item,
415- llvm:: LinkOnceODRLinkage ) ;
416- }
412+ assert ! ( trans_item. is_instantiated_only_on_demand( ) ) ;
413+ // We can't be sure if this will also be instantiated
414+ // somewhere else, so we add an instance here with
415+ // InternalLinkage so we don't get any conflicts.
416+ new_codegen_unit. items . insert ( trans_item,
417+ llvm:: InternalLinkage ) ;
417418 }
418419 }
419420
@@ -521,17 +522,36 @@ fn single_codegen_unit<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
521522 }
522523 }
523524 TransItem :: DropGlue ( _) => {
524- llvm:: PrivateLinkage
525+ llvm:: InternalLinkage
525526 }
526527 TransItem :: Fn ( instance) => {
527- if trans_item. is_generic_fn ( ) ||
528- trans_item. is_from_extern_crate ( ) ||
529- !reachable. contains ( & tcx. map
530- . as_local_node_id ( instance. def )
531- . unwrap ( ) ) {
528+ if trans_item. is_generic_fn ( ) {
529+ // FIXME(mw): Assigning internal linkage to all
530+ // monomorphizations is potentially a waste of space
531+ // since monomorphizations could be shared between
532+ // crates. The main reason for making them internal is
533+ // a limitation in MingW's binutils that cannot deal
534+ // with COFF object that have more than 2^15 sections,
535+ // which is something that can happen for large programs
536+ // when every function gets put into its own COMDAT
537+ // section.
532538 llvm:: InternalLinkage
533- } else {
539+ } else if trans_item. is_from_extern_crate ( ) {
540+ // FIXME(mw): It would be nice if we could mark these as
541+ // `AvailableExternallyLinkage`, since they should have
542+ // been instantiated in the extern crate. But this
543+ // sometimes leads to crashes on Windows because LLVM
544+ // does not handle exception handling table instantiation
545+ // reliably in that case.
546+ llvm:: InternalLinkage
547+ } else if reachable. contains ( & tcx. map
548+ . as_local_node_id ( instance. def )
549+ . unwrap ( ) ) {
534550 llvm:: ExternalLinkage
551+ } else {
552+ // Functions that are not visible outside this crate can
553+ // be marked as internal.
554+ llvm:: InternalLinkage
535555 }
536556 }
537557 }
0 commit comments