1 // Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 use hir::def_id::DefId;
12 use syntax::ast::NodeId;
13 use syntax::symbol::InternedString;
14 use ty::{Instance, TyCtxt};
15 use util::nodemap::FxHashMap;
16 use rustc_data_structures::base_n;
17 use rustc_data_structures::stable_hasher::{HashStable, StableHasherResult,
19 use ich::{Fingerprint, StableHashingContext, NodeIdHashingMode};
22 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
23 pub enum MonoItem<'tcx> {
29 impl<'tcx> MonoItem<'tcx> {
30 pub fn size_estimate<'a>(&self, tcx: &TyCtxt<'a, 'tcx, 'tcx>) -> usize {
32 MonoItem::Fn(instance) => {
33 // Estimate the size of a function based on how many statements
35 tcx.instance_def_size_estimate(instance.def)
37 // Conservatively estimate the size of a static declaration
38 // or assembly to be 1.
39 MonoItem::Static(_) | MonoItem::GlobalAsm(_) => 1,
44 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for MonoItem<'tcx> {
45 fn hash_stable<W: StableHasherResult>(&self,
46 hcx: &mut StableHashingContext<'a>,
47 hasher: &mut StableHasher<W>) {
48 ::std::mem::discriminant(self).hash_stable(hcx, hasher);
51 MonoItem::Fn(ref instance) => {
52 instance.hash_stable(hcx, hasher);
54 MonoItem::Static(def_id) => {
55 def_id.hash_stable(hcx, hasher);
57 MonoItem::GlobalAsm(node_id) => {
58 hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
59 node_id.hash_stable(hcx, hasher);
66 pub struct CodegenUnit<'tcx> {
67 /// A name for this CGU. Incremental compilation requires that
68 /// name be unique amongst **all** crates. Therefore, it should
69 /// contain something unique to this crate (e.g., a module path)
70 /// as well as the crate name and disambiguator.
72 items: FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)>,
73 size_estimate: Option<usize>,
76 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
91 impl_stable_hash_for!(enum self::Linkage {
105 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
106 pub enum Visibility {
112 impl_stable_hash_for!(enum self::Visibility {
118 impl<'tcx> CodegenUnit<'tcx> {
119 pub fn new(name: InternedString) -> CodegenUnit<'tcx> {
127 pub fn name(&self) -> &InternedString {
131 pub fn set_name(&mut self, name: InternedString) {
135 pub fn items(&self) -> &FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)> {
139 pub fn items_mut(&mut self)
140 -> &mut FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)>
145 pub fn mangle_name(human_readable_name: &str) -> String {
146 // We generate a 80 bit hash from the name. This should be enough to
147 // avoid collisions and is still reasonably short for filenames.
148 let mut hasher = StableHasher::new();
149 human_readable_name.hash(&mut hasher);
150 let hash: u128 = hasher.finish();
151 let hash = hash & ((1u128 << 80) - 1);
152 base_n::encode(hash, base_n::CASE_INSENSITIVE)
155 pub fn estimate_size<'a>(&mut self, tcx: &TyCtxt<'a, 'tcx, 'tcx>) {
156 // Estimate the size of a codegen unit as (approximately) the number of MIR
157 // statements it corresponds to.
158 self.size_estimate = Some(self.items.keys().map(|mi| mi.size_estimate(tcx)).sum());
161 pub fn size_estimate(&self) -> usize {
162 // Should only be called if `estimate_size` has previously been called.
163 self.size_estimate.expect("estimate_size must be called before getting a size_estimate")
166 pub fn modify_size_estimate(&mut self, delta: usize) {
167 assert!(self.size_estimate.is_some());
168 if let Some(size_estimate) = self.size_estimate {
169 self.size_estimate = Some(size_estimate + delta);
174 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for CodegenUnit<'tcx> {
175 fn hash_stable<W: StableHasherResult>(&self,
176 hcx: &mut StableHashingContext<'a>,
177 hasher: &mut StableHasher<W>) {
181 // The size estimate is not relevant to the hash
185 name.hash_stable(hcx, hasher);
187 let mut items: Vec<(Fingerprint, _)> = items.iter().map(|(mono_item, &attrs)| {
188 let mut hasher = StableHasher::new();
189 mono_item.hash_stable(hcx, &mut hasher);
190 let mono_item_fingerprint = hasher.finish();
191 (mono_item_fingerprint, attrs)
194 items.sort_unstable_by_key(|i| i.0);
195 items.hash_stable(hcx, hasher);
199 #[derive(Clone, Default)]
201 pub n_glues_created: usize,
202 pub n_null_glues: usize,
203 pub n_real_glues: usize,
205 pub n_inlines: usize,
206 pub n_closures: usize,
207 pub n_llvm_insns: usize,
208 pub llvm_insns: FxHashMap<String, usize>,
209 // (ident, llvm-instructions)
210 pub fn_stats: Vec<(String, usize)>,
213 impl_stable_hash_for!(struct self::Stats {
226 pub fn extend(&mut self, stats: Stats) {
227 self.n_glues_created += stats.n_glues_created;
228 self.n_null_glues += stats.n_null_glues;
229 self.n_real_glues += stats.n_real_glues;
230 self.n_fns += stats.n_fns;
231 self.n_inlines += stats.n_inlines;
232 self.n_closures += stats.n_closures;
233 self.n_llvm_insns += stats.n_llvm_insns;
235 for (k, v) in stats.llvm_insns {
236 *self.llvm_insns.entry(k).or_insert(0) += v;
238 self.fn_stats.extend(stats.fn_stats);