@@ -126,7 +126,7 @@ use rustc::ty::TyCtxt;
126126use rustc:: ty:: item_path:: characteristic_def_id_of_type;
127127use syntax:: parse:: token:: { self , InternedString } ;
128128use trans_item:: TransItem ;
129- use util:: nodemap:: { FnvHashMap , FnvHashSet } ;
129+ use util:: nodemap:: { FnvHashMap , FnvHashSet , NodeSet } ;
130130
131131pub struct CodegenUnit < ' tcx > {
132132 pub name : InternedString ,
@@ -147,14 +147,23 @@ const FALLBACK_CODEGEN_UNIT: &'static str = "__rustc_fallback_codegen_unit";
147147pub fn partition < ' a , ' tcx , I > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
148148 trans_items : I ,
149149 strategy : PartitioningStrategy ,
150- inlining_map : & InliningMap < ' tcx > )
150+ inlining_map : & InliningMap < ' tcx > ,
151+ reachable : & NodeSet )
151152 -> Vec < CodegenUnit < ' tcx > >
152153 where I : Iterator < Item = TransItem < ' tcx > >
153154{
155+ if let PartitioningStrategy :: FixedUnitCount ( 1 ) = strategy {
156+ // If there is only a single codegen-unit, we can use a very simple
157+ // scheme and don't have to bother with doing much analysis.
158+ return vec ! [ single_codegen_unit( tcx, trans_items, reachable) ] ;
159+ }
160+
154161 // In the first step, we place all regular translation items into their
155162 // respective 'home' codegen unit. Regular translation items are all
156163 // functions and statics defined in the local crate.
157- let mut initial_partitioning = place_root_translation_items ( tcx, trans_items) ;
164+ let mut initial_partitioning = place_root_translation_items ( tcx,
165+ trans_items,
166+ reachable) ;
158167
159168 // If the partitioning should produce a fixed count of codegen units, merge
160169 // until that count is reached.
@@ -179,7 +188,8 @@ struct PreInliningPartitioning<'tcx> {
179188struct PostInliningPartitioning < ' tcx > ( Vec < CodegenUnit < ' tcx > > ) ;
180189
181190fn place_root_translation_items < ' a , ' tcx , I > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
182- trans_items : I )
191+ trans_items : I ,
192+ _reachable : & NodeSet )
183193 -> PreInliningPartitioning < ' tcx >
184194 where I : Iterator < Item = TransItem < ' tcx > >
185195{
@@ -219,7 +229,18 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
219229 TransItem :: Static ( ..) => llvm:: ExternalLinkage ,
220230 TransItem :: DropGlue ( ..) => unreachable ! ( ) ,
221231 // Is there any benefit to using ExternalLinkage?:
222- TransItem :: Fn ( ..) => llvm:: WeakODRLinkage ,
232+ TransItem :: Fn ( ref instance) => {
233+ if instance. substs . types . is_empty ( ) {
234+ // This is a non-generic functions, we always
235+ // make it visible externally on the chance that
236+ // it might be used in another codegen unit.
237+ llvm:: ExternalLinkage
238+ } else {
239+ // Monomorphizations of generic functions are
240+ // always weak-odr
241+ llvm:: WeakODRLinkage
242+ }
243+ }
223244 }
224245 }
225246 } ;
@@ -282,13 +303,6 @@ fn merge_codegen_units<'tcx>(initial_partitioning: &mut PreInliningPartitioning<
282303 items : FnvHashMap ( )
283304 } ) ;
284305 }
285-
286- fn numbered_codegen_unit_name ( crate_name : & str , index : usize ) -> InternedString {
287- token:: intern_and_get_ident ( & format ! ( "{}{}{}" ,
288- crate_name,
289- NUMBERED_CODEGEN_UNIT_MARKER ,
290- index) [ ..] )
291- }
292306}
293307
294308fn place_inlined_translation_items < ' tcx > ( initial_partitioning : PreInliningPartitioning < ' tcx > ,
@@ -319,6 +333,11 @@ fn place_inlined_translation_items<'tcx>(initial_partitioning: PreInliningPartit
319333 // so we just add it here with AvailableExternallyLinkage
320334 new_codegen_unit. items . insert ( trans_item,
321335 llvm:: AvailableExternallyLinkage ) ;
336+ } else if trans_item. is_from_extern_crate ( ) && !trans_item. is_generic_fn ( ) {
337+ // An instantiation of this item is always available in the
338+ // crate it was imported from.
339+ new_codegen_unit. items . insert ( trans_item,
340+ llvm:: AvailableExternallyLinkage ) ;
322341 } else {
323342 // We can't be sure if this will also be instantiated
324343 // somewhere else, so we add an instance here with
@@ -414,3 +433,54 @@ fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
414433
415434 return token:: intern_and_get_ident ( & mod_path[ ..] ) ;
416435}
436+
437+ fn single_codegen_unit < ' a , ' tcx , I > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
438+ trans_items : I ,
439+ reachable : & NodeSet )
440+ -> CodegenUnit < ' tcx >
441+ where I : Iterator < Item = TransItem < ' tcx > >
442+ {
443+ let mut items = FnvHashMap ( ) ;
444+
445+ for trans_item in trans_items {
446+ let linkage = trans_item. explicit_linkage ( tcx) . unwrap_or_else ( || {
447+ match trans_item {
448+ TransItem :: Static ( node_id) => {
449+ if reachable. contains ( & node_id) {
450+ llvm:: ExternalLinkage
451+ } else {
452+ llvm:: InternalLinkage
453+ }
454+ }
455+ TransItem :: DropGlue ( _) => {
456+ llvm:: InternalLinkage
457+ }
458+ TransItem :: Fn ( instance) => {
459+ if trans_item. is_generic_fn ( ) ||
460+ trans_item. is_from_extern_crate ( ) ||
461+ !reachable. contains ( & tcx. map
462+ . as_local_node_id ( instance. def )
463+ . unwrap ( ) ) {
464+ llvm:: InternalLinkage
465+ } else {
466+ llvm:: ExternalLinkage
467+ }
468+ }
469+ }
470+ } ) ;
471+
472+ items. insert ( trans_item, linkage) ;
473+ }
474+
475+ CodegenUnit {
476+ name : numbered_codegen_unit_name ( & tcx. crate_name [ ..] , 0 ) ,
477+ items : items
478+ }
479+ }
480+
481+ fn numbered_codegen_unit_name ( crate_name : & str , index : usize ) -> InternedString {
482+ token:: intern_and_get_ident ( & format ! ( "{}{}{}" ,
483+ crate_name,
484+ NUMBERED_CODEGEN_UNIT_MARKER ,
485+ index) [ ..] )
486+ }
0 commit comments