]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/monomorphize/partitioning.rs
Don't default on std crate when manipulating browser history
[rust.git] / src / librustc_mir / monomorphize / partitioning.rs
1 //! Partitioning Codegen Units for Incremental Compilation
2 //! ======================================================
3 //!
4 //! The task of this module is to take the complete set of monomorphizations of
5 //! a crate and produce a set of codegen units from it, where a codegen unit
6 //! is a named set of (mono-item, linkage) pairs. That is, this module
7 //! decides which monomorphization appears in which codegen units with which
8 //! linkage. The following paragraphs describe some of the background on the
9 //! partitioning scheme.
10 //!
11 //! The most important opportunity for saving on compilation time with
12 //! incremental compilation is to avoid re-codegenning and re-optimizing code.
13 //! Since the unit of codegen and optimization for LLVM is "modules" or, how
14 //! we call them "codegen units", the particulars of how much time can be saved
15 //! by incremental compilation are tightly linked to how the output program is
16 //! partitioned into these codegen units prior to passing it to LLVM --
17 //! especially because we have to treat codegen units as opaque entities once
18 //! they are created: There is no way for us to incrementally update an existing
19 //! LLVM module and so we have to build any such module from scratch if it was
20 //! affected by some change in the source code.
21 //!
22 //! From that point of view it would make sense to maximize the number of
23 //! codegen units by, for example, putting each function into its own module.
24 //! That way only those modules would have to be re-compiled that were actually
25 //! affected by some change, minimizing the number of functions that could have
26 //! been re-used but just happened to be located in a module that is
27 //! re-compiled.
28 //!
29 //! However, since LLVM optimization does not work across module boundaries,
30 //! using such a highly granular partitioning would lead to very slow runtime
31 //! code since it would effectively prohibit inlining and other inter-procedure
32 //! optimizations. We want to avoid that as much as possible.
33 //!
34 //! Thus we end up with a trade-off: The bigger the codegen units, the better
35 //! LLVM's optimizer can do its work, but also the smaller the compilation time
36 //! reduction we get from incremental compilation.
37 //!
38 //! Ideally, we would create a partitioning such that there are few big codegen
39 //! units with few interdependencies between them. For now though, we use the
40 //! following heuristic to determine the partitioning:
41 //!
42 //! - There are two codegen units for every source-level module:
43 //! - One for "stable", that is non-generic, code
44 //! - One for more "volatile" code, i.e., monomorphized instances of functions
45 //!   defined in that module
46 //!
47 //! In order to see why this heuristic makes sense, let's take a look at when a
48 //! codegen unit can get invalidated:
49 //!
50 //! 1. The most straightforward case is when the BODY of a function or global
51 //! changes. Then any codegen unit containing the code for that item has to be
52 //! re-compiled. Note that this includes all codegen units where the function
53 //! has been inlined.
54 //!
55 //! 2. The next case is when the SIGNATURE of a function or global changes. In
56 //! this case, all codegen units containing a REFERENCE to that item have to be
57 //! re-compiled. This is a superset of case 1.
58 //!
59 //! 3. The final and most subtle case is when a REFERENCE to a generic function
60 //! is added or removed somewhere. Even though the definition of the function
61 //! might be unchanged, a new REFERENCE might introduce a new monomorphized
62 //! instance of this function which has to be placed and compiled somewhere.
63 //! Conversely, when removing a REFERENCE, it might have been the last one with
64 //! that particular set of generic arguments and thus we have to remove it.
65 //!
66 //! From the above we see that just using one codegen unit per source-level
67 //! module is not such a good idea, since just adding a REFERENCE to some
68 //! generic item somewhere else would invalidate everything within the module
69 //! containing the generic item. The heuristic above reduces this detrimental
70 //! side-effect of references a little by at least not touching the non-generic
71 //! code of the module.
72 //!
73 //! A Note on Inlining
74 //! ------------------
75 //! As briefly mentioned above, in order for LLVM to be able to inline a
76 //! function call, the body of the function has to be available in the LLVM
77 //! module where the call is made. This has a few consequences for partitioning:
78 //!
79 //! - The partitioning algorithm has to take care of placing functions into all
80 //!   codegen units where they should be available for inlining. It also has to
81 //!   decide on the correct linkage for these functions.
82 //!
83 //! - The partitioning algorithm has to know which functions are likely to get
84 //!   inlined, so it can distribute function instantiations accordingly. Since
85 //!   there is no way of knowing for sure which functions LLVM will decide to
86 //!   inline in the end, we apply a heuristic here: Only functions marked with
87 //!   `#[inline]` are considered for inlining by the partitioner. The current
88 //!   implementation will not try to determine if a function is likely to be
89 //!   inlined by looking at the functions definition.
90 //!
91 //! Note though that as a side-effect of creating a codegen units per
92 //! source-level module, functions from the same module will be available for
93 //! inlining, even when they are not marked #[inline].
94
95 use std::collections::hash_map::Entry;
96 use std::cmp;
97 use std::sync::Arc;
98
99 use syntax::ast::NodeId;
100 use syntax::symbol::InternedString;
101 use rustc::dep_graph::{WorkProductId, WorkProduct, DepNode, DepConstructor};
102 use rustc::hir::CodegenFnAttrFlags;
103 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX};
104 use rustc::hir::map::DefPathData;
105 use rustc::mir::mono::{Linkage, Visibility, CodegenUnitNameBuilder};
106 use rustc::middle::exported_symbols::SymbolExportLevel;
107 use rustc::ty::{self, TyCtxt, InstanceDef};
108 use rustc::ty::item_path::characteristic_def_id_of_type;
109 use rustc::ty::query::Providers;
110 use rustc::util::common::time;
111 use rustc::util::nodemap::{DefIdSet, FxHashMap, FxHashSet};
112 use rustc::mir::mono::MonoItem;
113
114 use monomorphize::collector::InliningMap;
115 use monomorphize::collector::{self, MonoItemCollectionMode};
116 use monomorphize::item::{MonoItemExt, InstantiationMode};
117
118 pub use rustc::mir::mono::CodegenUnit;
119
120 pub enum PartitioningStrategy {
121     /// Generate one codegen unit per source-level module.
122     PerModule,
123
124     /// Partition the whole crate into a fixed number of codegen units.
125     FixedUnitCount(usize)
126 }
127
128 pub trait CodegenUnitExt<'tcx> {
129     fn as_codegen_unit(&self) -> &CodegenUnit<'tcx>;
130
131     fn contains_item(&self, item: &MonoItem<'tcx>) -> bool {
132         self.items().contains_key(item)
133     }
134
135     fn name<'a>(&'a self) -> &'a InternedString
136         where 'tcx: 'a,
137     {
138         &self.as_codegen_unit().name()
139     }
140
141     fn items(&self) -> &FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)> {
142         &self.as_codegen_unit().items()
143     }
144
145     fn work_product_id(&self) -> WorkProductId {
146         WorkProductId::from_cgu_name(&self.name().as_str())
147     }
148
149     fn work_product(&self, tcx: TyCtxt) -> WorkProduct {
150         let work_product_id = self.work_product_id();
151         tcx.dep_graph
152            .previous_work_product(&work_product_id)
153            .unwrap_or_else(|| {
154                 panic!("Could not find work-product for CGU `{}`", self.name())
155             })
156     }
157
158     fn items_in_deterministic_order<'a>(&self,
159                                         tcx: TyCtxt<'a, 'tcx, 'tcx>)
160                                         -> Vec<(MonoItem<'tcx>,
161                                                 (Linkage, Visibility))> {
162         // The codegen tests rely on items being process in the same order as
163         // they appear in the file, so for local items, we sort by node_id first
164         #[derive(PartialEq, Eq, PartialOrd, Ord)]
165         pub struct ItemSortKey(Option<NodeId>, ty::SymbolName);
166
167         fn item_sort_key<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
168                                    item: MonoItem<'tcx>) -> ItemSortKey {
169             ItemSortKey(match item {
170                 MonoItem::Fn(ref instance) => {
171                     match instance.def {
172                         // We only want to take NodeIds of user-defined
173                         // instances into account. The others don't matter for
174                         // the codegen tests and can even make item order
175                         // unstable.
176                         InstanceDef::Item(def_id) => {
177                             tcx.hir().as_local_node_id(def_id)
178                         }
179                         InstanceDef::VtableShim(..) |
180                         InstanceDef::Intrinsic(..) |
181                         InstanceDef::FnPtrShim(..) |
182                         InstanceDef::Virtual(..) |
183                         InstanceDef::ClosureOnceShim { .. } |
184                         InstanceDef::DropGlue(..) |
185                         InstanceDef::CloneShim(..) => {
186                             None
187                         }
188                     }
189                 }
190                 MonoItem::Static(def_id) => {
191                     tcx.hir().as_local_node_id(def_id)
192                 }
193                 MonoItem::GlobalAsm(node_id) => {
194                     Some(node_id)
195                 }
196             }, item.symbol_name(tcx))
197         }
198
199         let mut items: Vec<_> = self.items().iter().map(|(&i, &l)| (i, l)).collect();
200         items.sort_by_cached_key(|&(i, _)| item_sort_key(tcx, i));
201         items
202     }
203
204     fn codegen_dep_node(&self, tcx: TyCtxt<'_, 'tcx, 'tcx>) -> DepNode {
205         DepNode::new(tcx, DepConstructor::CompileCodegenUnit(self.name().clone()))
206     }
207 }
208
209 impl<'tcx> CodegenUnitExt<'tcx> for CodegenUnit<'tcx> {
210     fn as_codegen_unit(&self) -> &CodegenUnit<'tcx> {
211         self
212     }
213 }
214
215 // Anything we can't find a proper codegen unit for goes into this.
216 fn fallback_cgu_name(name_builder: &mut CodegenUnitNameBuilder) -> InternedString {
217     name_builder.build_cgu_name(LOCAL_CRATE, &["fallback"], Some("cgu"))
218 }
219
220 pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
221                               mono_items: I,
222                               strategy: PartitioningStrategy,
223                               inlining_map: &InliningMap<'tcx>)
224                               -> Vec<CodegenUnit<'tcx>>
225     where I: Iterator<Item = MonoItem<'tcx>>
226 {
227     // In the first step, we place all regular monomorphizations into their
228     // respective 'home' codegen unit. Regular monomorphizations are all
229     // functions and statics defined in the local crate.
230     let mut initial_partitioning = place_root_mono_items(tcx, mono_items);
231
232     initial_partitioning.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(&tcx));
233
234     debug_dump(tcx, "INITIAL PARTITIONING:", initial_partitioning.codegen_units.iter());
235
236     // If the partitioning should produce a fixed count of codegen units, merge
237     // until that count is reached.
238     if let PartitioningStrategy::FixedUnitCount(count) = strategy {
239         merge_codegen_units(tcx, &mut initial_partitioning, count);
240
241         debug_dump(tcx, "POST MERGING:", initial_partitioning.codegen_units.iter());
242     }
243
244     // In the next step, we use the inlining map to determine which additional
245     // monomorphizations have to go into each codegen unit. These additional
246     // monomorphizations can be drop-glue, functions from external crates, and
247     // local functions the definition of which is marked with #[inline].
248     let mut post_inlining = place_inlined_mono_items(initial_partitioning,
249                                                             inlining_map);
250
251     post_inlining.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(&tcx));
252
253     debug_dump(tcx, "POST INLINING:", post_inlining.codegen_units.iter());
254
255     // Next we try to make as many symbols "internal" as possible, so LLVM has
256     // more freedom to optimize.
257     if !tcx.sess.opts.cg.link_dead_code {
258         internalize_symbols(tcx, &mut post_inlining, inlining_map);
259     }
260
261     // Finally, sort by codegen unit name, so that we get deterministic results
262     let PostInliningPartitioning {
263         codegen_units: mut result,
264         mono_item_placements: _,
265         internalization_candidates: _,
266     } = post_inlining;
267
268     result.sort_by(|cgu1, cgu2| {
269         cgu1.name().cmp(cgu2.name())
270     });
271
272     result
273 }
274
275 struct PreInliningPartitioning<'tcx> {
276     codegen_units: Vec<CodegenUnit<'tcx>>,
277     roots: FxHashSet<MonoItem<'tcx>>,
278     internalization_candidates: FxHashSet<MonoItem<'tcx>>,
279 }
280
281 /// For symbol internalization, we need to know whether a symbol/mono-item is
282 /// accessed from outside the codegen unit it is defined in. This type is used
283 /// to keep track of that.
284 #[derive(Clone, PartialEq, Eq, Debug)]
285 enum MonoItemPlacement {
286     SingleCgu { cgu_name: InternedString },
287     MultipleCgus,
288 }
289
290 struct PostInliningPartitioning<'tcx> {
291     codegen_units: Vec<CodegenUnit<'tcx>>,
292     mono_item_placements: FxHashMap<MonoItem<'tcx>, MonoItemPlacement>,
293     internalization_candidates: FxHashSet<MonoItem<'tcx>>,
294 }
295
296 fn place_root_mono_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
297                                              mono_items: I)
298                                              -> PreInliningPartitioning<'tcx>
299     where I: Iterator<Item = MonoItem<'tcx>>
300 {
301     let mut roots = FxHashSet::default();
302     let mut codegen_units = FxHashMap::default();
303     let is_incremental_build = tcx.sess.opts.incremental.is_some();
304     let mut internalization_candidates = FxHashSet::default();
305
306     // Determine if monomorphizations instantiated in this crate will be made
307     // available to downstream crates. This depends on whether we are in
308     // share-generics mode and whether the current crate can even have
309     // downstream crates.
310     let export_generics = tcx.sess.opts.share_generics() &&
311                           tcx.local_crate_exports_generics();
312
313     let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
314     let cgu_name_cache = &mut FxHashMap::default();
315
316     for mono_item in mono_items {
317         match mono_item.instantiation_mode(tcx) {
318             InstantiationMode::GloballyShared { .. } => {}
319             InstantiationMode::LocalCopy => continue,
320         }
321
322         let characteristic_def_id = characteristic_def_id_of_mono_item(tcx, mono_item);
323         let is_volatile = is_incremental_build &&
324                           mono_item.is_generic_fn();
325
326         let codegen_unit_name = match characteristic_def_id {
327             Some(def_id) => compute_codegen_unit_name(tcx,
328                                                       cgu_name_builder,
329                                                       def_id,
330                                                       is_volatile,
331                                                       cgu_name_cache),
332             None => fallback_cgu_name(cgu_name_builder),
333         };
334
335         let codegen_unit = codegen_units.entry(codegen_unit_name.clone())
336             .or_insert_with(|| CodegenUnit::new(codegen_unit_name.clone()));
337
338         let mut can_be_internalized = true;
339         let (linkage, visibility) = mono_item_linkage_and_visibility(
340             tcx,
341             &mono_item,
342             &mut can_be_internalized,
343             export_generics,
344         );
345         if visibility == Visibility::Hidden && can_be_internalized {
346             internalization_candidates.insert(mono_item);
347         }
348
349         codegen_unit.items_mut().insert(mono_item, (linkage, visibility));
350         roots.insert(mono_item);
351     }
352
353     // always ensure we have at least one CGU; otherwise, if we have a
354     // crate with just types (for example), we could wind up with no CGU
355     if codegen_units.is_empty() {
356         let codegen_unit_name = fallback_cgu_name(cgu_name_builder);
357         codegen_units.insert(codegen_unit_name.clone(),
358                              CodegenUnit::new(codegen_unit_name.clone()));
359     }
360
361     PreInliningPartitioning {
362         codegen_units: codegen_units.into_iter()
363                                     .map(|(_, codegen_unit)| codegen_unit)
364                                     .collect(),
365         roots,
366         internalization_candidates,
367     }
368 }
369
370 fn mono_item_linkage_and_visibility(
371     tcx: TyCtxt<'a, 'tcx, 'tcx>,
372     mono_item: &MonoItem<'tcx>,
373     can_be_internalized: &mut bool,
374     export_generics: bool,
375 ) -> (Linkage, Visibility) {
376     if let Some(explicit_linkage) = mono_item.explicit_linkage(tcx) {
377         return (explicit_linkage, Visibility::Default)
378     }
379     let vis = mono_item_visibility(
380         tcx,
381         mono_item,
382         can_be_internalized,
383         export_generics,
384     );
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     export_generics: bool,
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(tcx, *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(tcx, 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::VtableShim(..) |
423         InstanceDef::FnPtrShim(..) |
424         InstanceDef::Virtual(..) |
425         InstanceDef::Intrinsic(..) |
426         InstanceDef::ClosureOnceShim { .. } |
427         InstanceDef::DropGlue(..) |
428         InstanceDef::CloneShim(..) => {
429             return Visibility::Hidden
430         }
431     };
432
433     // The `start_fn` lang item is actually a monomorphized instance of a
434     // function in the standard library, used for the `main` function. We don't
435     // want to export it so we tag it with `Hidden` visibility but this symbol
436     // is only referenced from the actual `main` symbol which we unfortunately
437     // don't know anything about during partitioning/collection. As a result we
438     // forcibly keep this symbol out of the `internalization_candidates` set.
439     //
440     // FIXME: eventually we don't want to always force this symbol to have
441     //        hidden visibility, it should indeed be a candidate for
442     //        internalization, but we have to understand that it's referenced
443     //        from the `main` symbol we'll generate later.
444     //
445     //        This may be fixable with a new `InstanceDef` perhaps? Unsure!
446     if tcx.lang_items().start_fn() == Some(def_id) {
447         *can_be_internalized = false;
448         return Visibility::Hidden
449     }
450
451     let is_generic = instance.substs.types().next().is_some();
452
453     // Upstream `DefId` instances get different handling than local ones
454     if !def_id.is_local() {
455         return if export_generics && is_generic {
456             // If it is a upstream monomorphization
457             // and we export generics, we must make
458             // it available to downstream crates.
459             *can_be_internalized = false;
460             default_visibility(tcx, def_id, true)
461         } else {
462             Visibility::Hidden
463         }
464     }
465
466     if is_generic {
467         if export_generics {
468             if tcx.is_unreachable_local_definition(def_id) {
469                 // This instance cannot be used
470                 // from another crate.
471                 Visibility::Hidden
472             } else {
473                 // This instance might be useful in
474                 // a downstream crate.
475                 *can_be_internalized = false;
476                 default_visibility(tcx, def_id, true)
477             }
478         } else {
479             // We are not exporting generics or
480             // the definition is not reachable
481             // for downstream crates, we can
482             // internalize its instantiations.
483             Visibility::Hidden
484         }
485     } else {
486
487         // If this isn't a generic function then we mark this a `Default` if
488         // this is a reachable item, meaning that it's a symbol other crates may
489         // access when they link to us.
490         if tcx.is_reachable_non_generic(def_id) {
491             *can_be_internalized = false;
492             debug_assert!(!is_generic);
493             return default_visibility(tcx, def_id, false)
494         }
495
496         // If this isn't reachable then we're gonna tag this with `Hidden`
497         // visibility. In some situations though we'll want to prevent this
498         // symbol from being internalized.
499         //
500         // There's two categories of items here:
501         //
502         // * First is weak lang items. These are basically mechanisms for
503         //   libcore to forward-reference symbols defined later in crates like
504         //   the standard library or `#[panic_handler]` definitions. The
505         //   definition of these weak lang items needs to be referenceable by
506         //   libcore, so we're no longer a candidate for internalization.
507         //   Removal of these functions can't be done by LLVM but rather must be
508         //   done by the linker as it's a non-local decision.
509         //
510         // * Second is "std internal symbols". Currently this is primarily used
511         //   for allocator symbols. Allocators are a little weird in their
512         //   implementation, but the idea is that the compiler, at the last
513         //   minute, defines an allocator with an injected object file. The
514         //   `alloc` crate references these symbols (`__rust_alloc`) and the
515         //   definition doesn't get hooked up until a linked crate artifact is
516         //   generated.
517         //
518         //   The symbols synthesized by the compiler (`__rust_alloc`) are thin
519         //   veneers around the actual implementation, some other symbol which
520         //   implements the same ABI. These symbols (things like `__rg_alloc`,
521         //   `__rdl_alloc`, `__rde_alloc`, etc), are all tagged with "std
522         //   internal symbols".
523         //
524         //   The std-internal symbols here **should not show up in a dll as an
525         //   exported interface**, so they return `false` from
526         //   `is_reachable_non_generic` above and we'll give them `Hidden`
527         //   visibility below. Like the weak lang items, though, we can't let
528         //   LLVM internalize them as this decision is left up to the linker to
529         //   omit them, so prevent them from being internalized.
530         let attrs = tcx.codegen_fn_attrs(def_id);
531         if attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
532             *can_be_internalized = false;
533         }
534
535         Visibility::Hidden
536     }
537 }
538
539 fn default_visibility(tcx: TyCtxt, id: DefId, is_generic: bool) -> Visibility {
540     if !tcx.sess.target.target.options.default_hidden_visibility {
541         return Visibility::Default
542     }
543
544     // Generic functions never have export level C
545     if is_generic {
546         return Visibility::Hidden
547     }
548
549     // Things with export level C don't get instantiated in
550     // downstream crates
551     if !id.is_local() {
552         return Visibility::Hidden
553     }
554
555     // C-export level items remain at `Default`, all other internal
556     // items become `Hidden`
557     match tcx.reachable_non_generics(id.krate).get(&id) {
558         Some(SymbolExportLevel::C) => Visibility::Default,
559         _ => Visibility::Hidden,
560     }
561 }
562
563 fn merge_codegen_units<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>,
564                              initial_partitioning: &mut PreInliningPartitioning<'tcx>,
565                              target_cgu_count: usize) {
566     assert!(target_cgu_count >= 1);
567     let codegen_units = &mut initial_partitioning.codegen_units;
568
569     // Note that at this point in time the `codegen_units` here may not be in a
570     // deterministic order (but we know they're deterministically the same set).
571     // We want this merging to produce a deterministic ordering of codegen units
572     // from the input.
573     //
574     // Due to basically how we've implemented the merging below (merge the two
575     // smallest into each other) we're sure to start off with a deterministic
576     // order (sorted by name). This'll mean that if two cgus have the same size
577     // the stable sort below will keep everything nice and deterministic.
578     codegen_units.sort_by_key(|cgu| *cgu.name());
579
580     // Merge the two smallest codegen units until the target size is reached.
581     while codegen_units.len() > target_cgu_count {
582         // Sort small cgus to the back
583         codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate()));
584         let mut smallest = codegen_units.pop().unwrap();
585         let second_smallest = codegen_units.last_mut().unwrap();
586
587         second_smallest.modify_size_estimate(smallest.size_estimate());
588         for (k, v) in smallest.items_mut().drain() {
589             second_smallest.items_mut().insert(k, v);
590         }
591     }
592
593     let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
594     for (index, cgu) in codegen_units.iter_mut().enumerate() {
595         cgu.set_name(numbered_codegen_unit_name(cgu_name_builder, index));
596     }
597 }
598
599 fn place_inlined_mono_items<'tcx>(initial_partitioning: PreInliningPartitioning<'tcx>,
600                                   inlining_map: &InliningMap<'tcx>)
601                                   -> PostInliningPartitioning<'tcx> {
602     let mut new_partitioning = Vec::new();
603     let mut mono_item_placements = FxHashMap::default();
604
605     let PreInliningPartitioning {
606         codegen_units: initial_cgus,
607         roots,
608         internalization_candidates,
609     } = initial_partitioning;
610
611     let single_codegen_unit = initial_cgus.len() == 1;
612
613     for old_codegen_unit in initial_cgus {
614         // Collect all items that need to be available in this codegen unit
615         let mut reachable = FxHashSet::default();
616         for root in old_codegen_unit.items().keys() {
617             follow_inlining(*root, inlining_map, &mut reachable);
618         }
619
620         let mut new_codegen_unit = CodegenUnit::new(old_codegen_unit.name().clone());
621
622         // Add all monomorphizations that are not already there
623         for mono_item in reachable {
624             if let Some(linkage) = old_codegen_unit.items().get(&mono_item) {
625                 // This is a root, just copy it over
626                 new_codegen_unit.items_mut().insert(mono_item, *linkage);
627             } else {
628                 if roots.contains(&mono_item) {
629                     bug!("GloballyShared mono-item inlined into other CGU: \
630                           {:?}", mono_item);
631                 }
632
633                 // This is a cgu-private copy
634                 new_codegen_unit.items_mut().insert(
635                     mono_item,
636                     (Linkage::Internal, Visibility::Default),
637                 );
638             }
639
640             if !single_codegen_unit {
641                 // If there is more than one codegen unit, we need to keep track
642                 // in which codegen units each monomorphization is placed:
643                 match mono_item_placements.entry(mono_item) {
644                     Entry::Occupied(e) => {
645                         let placement = e.into_mut();
646                         debug_assert!(match *placement {
647                             MonoItemPlacement::SingleCgu { ref cgu_name } => {
648                                 *cgu_name != *new_codegen_unit.name()
649                             }
650                             MonoItemPlacement::MultipleCgus => true,
651                         });
652                         *placement = MonoItemPlacement::MultipleCgus;
653                     }
654                     Entry::Vacant(e) => {
655                         e.insert(MonoItemPlacement::SingleCgu {
656                             cgu_name: new_codegen_unit.name().clone()
657                         });
658                     }
659                 }
660             }
661         }
662
663         new_partitioning.push(new_codegen_unit);
664     }
665
666     return PostInliningPartitioning {
667         codegen_units: new_partitioning,
668         mono_item_placements,
669         internalization_candidates,
670     };
671
672     fn follow_inlining<'tcx>(mono_item: MonoItem<'tcx>,
673                              inlining_map: &InliningMap<'tcx>,
674                              visited: &mut FxHashSet<MonoItem<'tcx>>) {
675         if !visited.insert(mono_item) {
676             return;
677         }
678
679         inlining_map.with_inlining_candidates(mono_item, |target| {
680             follow_inlining(target, inlining_map, visited);
681         });
682     }
683 }
684
685 fn internalize_symbols<'a, 'tcx>(_tcx: TyCtxt<'a, 'tcx, 'tcx>,
686                                  partitioning: &mut PostInliningPartitioning<'tcx>,
687                                  inlining_map: &InliningMap<'tcx>) {
688     if partitioning.codegen_units.len() == 1 {
689         // Fast path for when there is only one codegen unit. In this case we
690         // can internalize all candidates, since there is nowhere else they
691         // could be accessed from.
692         for cgu in &mut partitioning.codegen_units {
693             for candidate in &partitioning.internalization_candidates {
694                 cgu.items_mut().insert(*candidate,
695                                        (Linkage::Internal, Visibility::Default));
696             }
697         }
698
699         return;
700     }
701
702     // Build a map from every monomorphization to all the monomorphizations that
703     // reference it.
704     let mut accessor_map: FxHashMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>> = Default::default();
705     inlining_map.iter_accesses(|accessor, accessees| {
706         for accessee in accessees {
707             accessor_map.entry(*accessee)
708                         .or_default()
709                         .push(accessor);
710         }
711     });
712
713     let mono_item_placements = &partitioning.mono_item_placements;
714
715     // For each internalization candidates in each codegen unit, check if it is
716     // accessed from outside its defining codegen unit.
717     for cgu in &mut partitioning.codegen_units {
718         let home_cgu = MonoItemPlacement::SingleCgu {
719             cgu_name: cgu.name().clone()
720         };
721
722         for (accessee, linkage_and_visibility) in cgu.items_mut() {
723             if !partitioning.internalization_candidates.contains(accessee) {
724                 // This item is no candidate for internalizing, so skip it.
725                 continue
726             }
727             debug_assert_eq!(mono_item_placements[accessee], home_cgu);
728
729             if let Some(accessors) = accessor_map.get(accessee) {
730                 if accessors.iter()
731                             .filter_map(|accessor| {
732                                 // Some accessors might not have been
733                                 // instantiated. We can safely ignore those.
734                                 mono_item_placements.get(accessor)
735                             })
736                             .any(|placement| *placement != home_cgu) {
737                     // Found an accessor from another CGU, so skip to the next
738                     // item without marking this one as internal.
739                     continue
740                 }
741             }
742
743             // If we got here, we did not find any accesses from other CGUs,
744             // so it's fine to make this monomorphization internal.
745             *linkage_and_visibility = (Linkage::Internal, Visibility::Default);
746         }
747     }
748 }
749
750 fn characteristic_def_id_of_mono_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
751                                                  mono_item: MonoItem<'tcx>)
752                                                  -> Option<DefId> {
753     match mono_item {
754         MonoItem::Fn(instance) => {
755             let def_id = match instance.def {
756                 ty::InstanceDef::Item(def_id) => def_id,
757                 ty::InstanceDef::VtableShim(..) |
758                 ty::InstanceDef::FnPtrShim(..) |
759                 ty::InstanceDef::ClosureOnceShim { .. } |
760                 ty::InstanceDef::Intrinsic(..) |
761                 ty::InstanceDef::DropGlue(..) |
762                 ty::InstanceDef::Virtual(..) |
763                 ty::InstanceDef::CloneShim(..) => return None
764             };
765
766             // If this is a method, we want to put it into the same module as
767             // its self-type. If the self-type does not provide a characteristic
768             // DefId, we use the location of the impl after all.
769
770             if tcx.trait_of_item(def_id).is_some() {
771                 let self_ty = instance.substs.type_at(0);
772                 // This is an implementation of a trait method.
773                 return characteristic_def_id_of_type(self_ty).or(Some(def_id));
774             }
775
776             if let Some(impl_def_id) = tcx.impl_of_method(def_id) {
777                 // This is a method within an inherent impl, find out what the
778                 // self-type is:
779                 let impl_self_ty = tcx.subst_and_normalize_erasing_regions(
780                     instance.substs,
781                     ty::ParamEnv::reveal_all(),
782                     &tcx.type_of(impl_def_id),
783                 );
784                 if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) {
785                     return Some(def_id);
786                 }
787             }
788
789             Some(def_id)
790         }
791         MonoItem::Static(def_id) => Some(def_id),
792         MonoItem::GlobalAsm(node_id) => Some(tcx.hir().local_def_id(node_id)),
793     }
794 }
795
796 type CguNameCache = FxHashMap<(DefId, bool), InternedString>;
797
798 fn compute_codegen_unit_name(tcx: TyCtxt,
799                              name_builder: &mut CodegenUnitNameBuilder,
800                              def_id: DefId,
801                              volatile: bool,
802                              cache: &mut CguNameCache)
803                              -> InternedString {
804     // Find the innermost module that is not nested within a function
805     let mut current_def_id = def_id;
806     let mut cgu_def_id = None;
807     // Walk backwards from the item we want to find the module for:
808     loop {
809         let def_key = tcx.def_key(current_def_id);
810
811         match def_key.disambiguated_data.data {
812             DefPathData::Module(..) => {
813                 if cgu_def_id.is_none() {
814                     cgu_def_id = Some(current_def_id);
815                 }
816             }
817             DefPathData::CrateRoot { .. } => {
818                 if cgu_def_id.is_none() {
819                     // If we have not found a module yet, take the crate root.
820                     cgu_def_id = Some(DefId {
821                         krate: def_id.krate,
822                         index: CRATE_DEF_INDEX,
823                     });
824                 }
825                 break
826             }
827             _ => {
828                 // If we encounter something that is not a module, throw away
829                 // any module that we've found so far because we now know that
830                 // it is nested within something else.
831                 cgu_def_id = None;
832             }
833         }
834
835         current_def_id.index = def_key.parent.unwrap();
836     }
837
838     let cgu_def_id = cgu_def_id.unwrap();
839
840     cache.entry((cgu_def_id, volatile)).or_insert_with(|| {
841         let def_path = tcx.def_path(cgu_def_id);
842
843         let components = def_path
844             .data
845             .iter()
846             .map(|part| part.data.as_interned_str());
847
848         let volatile_suffix = if volatile {
849             Some("volatile")
850         } else {
851             None
852         };
853
854         name_builder.build_cgu_name(def_path.krate, components, volatile_suffix)
855     }).clone()
856 }
857
858 fn numbered_codegen_unit_name(name_builder: &mut CodegenUnitNameBuilder,
859                               index: usize)
860                               -> InternedString {
861     name_builder.build_cgu_name_no_mangle(LOCAL_CRATE, &["cgu"], Some(index))
862 }
863
864 fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
865                                label: &str,
866                                cgus: I)
867     where I: Iterator<Item=&'b CodegenUnit<'tcx>>,
868           'tcx: 'a + 'b
869 {
870     if cfg!(debug_assertions) {
871         debug!("{}", label);
872         for cgu in cgus {
873             debug!("CodegenUnit {}:", cgu.name());
874
875             for (mono_item, linkage) in cgu.items() {
876                 let symbol_name = mono_item.symbol_name(tcx).as_str();
877                 let symbol_hash_start = symbol_name.rfind('h');
878                 let symbol_hash = symbol_hash_start.map(|i| &symbol_name[i ..])
879                                                    .unwrap_or("<no hash>");
880
881                 debug!(" - {} [{:?}] [{}]",
882                        mono_item.to_string(tcx, true),
883                        linkage,
884                        symbol_hash);
885             }
886
887             debug!("");
888         }
889     }
890 }
891
892 fn collect_and_partition_mono_items<'a, 'tcx>(
893     tcx: TyCtxt<'a, 'tcx, 'tcx>,
894     cnum: CrateNum,
895 ) -> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>)
896 {
897     assert_eq!(cnum, LOCAL_CRATE);
898
899     let collection_mode = match tcx.sess.opts.debugging_opts.print_mono_items {
900         Some(ref s) => {
901             let mode_string = s.to_lowercase();
902             let mode_string = mode_string.trim();
903             if mode_string == "eager" {
904                 MonoItemCollectionMode::Eager
905             } else {
906                 if mode_string != "lazy" {
907                     let message = format!("Unknown codegen-item collection mode '{}'. \
908                                            Falling back to 'lazy' mode.",
909                                           mode_string);
910                     tcx.sess.warn(&message);
911                 }
912
913                 MonoItemCollectionMode::Lazy
914             }
915         }
916         None => {
917             if tcx.sess.opts.cg.link_dead_code {
918                 MonoItemCollectionMode::Eager
919             } else {
920                 MonoItemCollectionMode::Lazy
921             }
922         }
923     };
924
925     let (items, inlining_map) =
926         time(tcx.sess, "monomorphization collection", || {
927             collector::collect_crate_mono_items(tcx, collection_mode)
928     });
929
930     tcx.sess.abort_if_errors();
931
932     ::monomorphize::assert_symbols_are_distinct(tcx, items.iter());
933
934     let strategy = if tcx.sess.opts.incremental.is_some() {
935         PartitioningStrategy::PerModule
936     } else {
937         PartitioningStrategy::FixedUnitCount(tcx.sess.codegen_units())
938     };
939
940     let codegen_units = time(tcx.sess, "codegen unit partitioning", || {
941         partition(
942             tcx,
943             items.iter().cloned(),
944             strategy,
945             &inlining_map
946         )
947             .into_iter()
948             .map(Arc::new)
949             .collect::<Vec<_>>()
950     });
951
952     let mono_items: DefIdSet = items.iter().filter_map(|mono_item| {
953         match *mono_item {
954             MonoItem::Fn(ref instance) => Some(instance.def_id()),
955             MonoItem::Static(def_id) => Some(def_id),
956             _ => None,
957         }
958     }).collect();
959
960     if tcx.sess.opts.debugging_opts.print_mono_items.is_some() {
961         let mut item_to_cgus: FxHashMap<_, Vec<_>> = Default::default();
962
963         for cgu in &codegen_units {
964             for (&mono_item, &linkage) in cgu.items() {
965                 item_to_cgus.entry(mono_item)
966                             .or_default()
967                             .push((cgu.name().clone(), linkage));
968             }
969         }
970
971         let mut item_keys: Vec<_> = items
972             .iter()
973             .map(|i| {
974                 let mut output = i.to_string(tcx, false);
975                 output.push_str(" @@");
976                 let mut empty = Vec::new();
977                 let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);
978                 cgus.sort_by_key(|(name, _)| *name);
979                 cgus.dedup();
980                 for &(ref cgu_name, (linkage, _)) in cgus.iter() {
981                     output.push_str(" ");
982                     output.push_str(&cgu_name.as_str());
983
984                     let linkage_abbrev = match linkage {
985                         Linkage::External => "External",
986                         Linkage::AvailableExternally => "Available",
987                         Linkage::LinkOnceAny => "OnceAny",
988                         Linkage::LinkOnceODR => "OnceODR",
989                         Linkage::WeakAny => "WeakAny",
990                         Linkage::WeakODR => "WeakODR",
991                         Linkage::Appending => "Appending",
992                         Linkage::Internal => "Internal",
993                         Linkage::Private => "Private",
994                         Linkage::ExternalWeak => "ExternalWeak",
995                         Linkage::Common => "Common",
996                     };
997
998                     output.push_str("[");
999                     output.push_str(linkage_abbrev);
1000                     output.push_str("]");
1001                 }
1002                 output
1003             })
1004             .collect();
1005
1006         item_keys.sort();
1007
1008         for item in item_keys {
1009             println!("MONO_ITEM {}", item);
1010         }
1011     }
1012
1013     (Arc::new(mono_items), Arc::new(codegen_units))
1014 }
1015
1016 pub fn provide(providers: &mut Providers) {
1017     providers.collect_and_partition_mono_items =
1018         collect_and_partition_mono_items;
1019
1020     providers.is_codegened_item = |tcx, def_id| {
1021         let (all_mono_items, _) =
1022             tcx.collect_and_partition_mono_items(LOCAL_CRATE);
1023         all_mono_items.contains(&def_id)
1024     };
1025
1026     providers.codegen_unit = |tcx, name| {
1027         let (_, all) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
1028         all.iter()
1029             .find(|cgu| *cgu.name() == name)
1030             .cloned()
1031             .unwrap_or_else(|| panic!("failed to find cgu with name {:?}", name))
1032     };
1033 }