@@ -265,15 +265,11 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
265
265
let mut codegen_units = FnvHashMap ( ) ;
266
266
267
267
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 ( ) ;
273
269
274
270
if is_root {
275
271
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 ( ) ;
277
273
278
274
let codegen_unit_name = match characteristic_def_id {
279
275
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>,
304
300
// it might be used in another codegen unit.
305
301
llvm:: ExternalLinkage
306
302
} 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 ! ( )
310
306
}
311
307
}
312
308
}
@@ -395,25 +391,30 @@ fn place_inlined_translation_items<'tcx>(initial_partitioning: PreInliningPartit
395
391
if let Some ( linkage) = codegen_unit. items . get ( & trans_item) {
396
392
// This is a root, just copy it over
397
393
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 ) ;
398
411
} 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 ) ;
417
418
}
418
419
}
419
420
@@ -521,17 +522,36 @@ fn single_codegen_unit<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
521
522
}
522
523
}
523
524
TransItem :: DropGlue ( _) => {
524
- llvm:: PrivateLinkage
525
+ llvm:: InternalLinkage
525
526
}
526
527
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.
532
538
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 ( ) ) {
534
550
llvm:: ExternalLinkage
551
+ } else {
552
+ // Functions that are not visible outside this crate can
553
+ // be marked as internal.
554
+ llvm:: InternalLinkage
535
555
}
536
556
}
537
557
}
0 commit comments