about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMichael Woerister <michaelwoerister@posteo>2018-07-10 19:16:22 +0200
committerMichael Woerister <michaelwoerister@posteo>2018-07-11 17:52:57 +0200
commit2c5cd9ce53d2d25041db0cb02b40ba460ffa8908 (patch)
tree6a035b3951c42c1d37d1948bc497704a002b73e2 /src
parent8dc7ddb9763f28b83de7bf3b3025f8042ea9e830 (diff)
downloadrust-2c5cd9ce53d2d25041db0cb02b40ba460ffa8908.tar.gz
rust-2c5cd9ce53d2d25041db0cb02b40ba460ffa8908.zip
Clean up CodegenUnit name generation.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/mir/mono.rs79
-rw-r--r--src/librustc/session/mod.rs9
-rw-r--r--src/librustc_incremental/assert_module_sources.rs53
-rw-r--r--src/librustc_mir/monomorphize/partitioning.rs68
-rw-r--r--src/test/incremental/issue-39828/auxiliary/generic.rs2
5 files changed, 154 insertions, 57 deletions
diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs
index 79566fbbc11..5ca0dda7545 100644
--- a/src/librustc/mir/mono.rs
+++ b/src/librustc/mir/mono.rs
@@ -8,15 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use hir::def_id::DefId;
+use hir::def_id::{DefId, CrateNum};
 use syntax::ast::NodeId;
-use syntax::symbol::InternedString;
+use syntax::symbol::{Symbol, InternedString};
 use ty::{Instance, TyCtxt};
 use util::nodemap::FxHashMap;
 use rustc_data_structures::base_n;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasherResult,
                                            StableHasher};
 use ich::{Fingerprint, StableHashingContext, NodeIdHashingMode};
+use std::fmt;
 use std::hash::Hash;
 
 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
@@ -173,6 +174,80 @@ impl<'tcx> CodegenUnit<'tcx> {
             self.size_estimate = Some(size_estimate + delta);
         }
     }
+
+    /// CGU names should fulfill the following requirements:
+    /// - They should be able to act as a file name on any kind of file system
+    /// - They should not collide with other CGU names, even for different versions
+    ///   of the same crate.
+    ///
+    /// Consequently, we don't use special characters except for '.' and '-' and we
+    /// prefix each name with the crate-name and crate-disambiguator.
+    ///
+    /// This function will build CGU names of the form:
+    ///
+    /// ```
+    /// <crate-name>.<crate-disambiguator>(-<component>)*[.<special-suffix>]
+    /// ```
+    ///
+    /// The '.' before `<special-suffix>` makes sure that names with a special
+    /// suffix can never collide with a name built out of regular Rust
+    /// identifiers (e.g. module paths).
+    pub fn build_cgu_name<I, C, S>(tcx: TyCtxt,
+                                   cnum: CrateNum,
+                                   components: I,
+                                   special_suffix: Option<S>)
+                                   -> InternedString
+        where I: IntoIterator<Item=C>,
+              C: fmt::Display,
+              S: fmt::Display,
+    {
+        let cgu_name = CodegenUnit::build_cgu_name_no_mangle(tcx,
+                                                             cnum,
+                                                             components,
+                                                             special_suffix);
+
+        if tcx.sess.opts.debugging_opts.human_readable_cgu_names {
+            cgu_name
+        } else {
+            let cgu_name = &cgu_name.as_str()[..];
+            Symbol::intern(&CodegenUnit::mangle_name(cgu_name)).as_interned_str()
+        }
+    }
+
+    /// Same as `CodegenUnit::build_cgu_name()` but will never mangle the
+    /// resulting name.
+    pub fn build_cgu_name_no_mangle<I, C, S>(tcx: TyCtxt,
+                                             cnum: CrateNum,
+                                             components: I,
+                                             special_suffix: Option<S>)
+                                             -> InternedString
+        where I: IntoIterator<Item=C>,
+              C: fmt::Display,
+              S: fmt::Display,
+    {
+        use std::fmt::Write;
+
+        let mut cgu_name = String::with_capacity(64);
+
+        // Start out with the crate name and disambiguator
+        write!(cgu_name,
+               "{}.{}",
+               tcx.crate_name(cnum),
+               tcx.crate_disambiguator(cnum)).unwrap();
+
+        // Add the components
+        for component in components {
+            write!(cgu_name, "-{}", component).unwrap();
+        }
+
+        if let Some(special_suffix) = special_suffix {
+            // We add a dot in here so it cannot clash with anything in a regular
+            // Rust identifier
+            write!(cgu_name, ".{}", special_suffix).unwrap();
+        }
+
+        Symbol::intern(&cgu_name[..]).as_interned_str()
+    }
 }
 
 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for CodegenUnit<'tcx> {
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index ad1df0a1348..c28b49756f0 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -26,6 +26,7 @@ use util::nodemap::{FxHashMap, FxHashSet};
 use util::common::{duration_to_secs_str, ErrorReported};
 use util::common::ProfileQueriesMsg;
 
+use rustc_data_structures::base_n;
 use rustc_data_structures::sync::{self, Lrc, Lock, LockCell, OneThread, Once, RwLock};
 
 use syntax::ast::NodeId;
@@ -1185,6 +1186,14 @@ impl CrateDisambiguator {
     }
 }
 
+impl fmt::Display for CrateDisambiguator {
+    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+        let (a, b) = self.0.as_value();
+        let as_u128 = a as u128 | ((b as u128) << 64);
+        f.write_str(&base_n::encode(as_u128, base_n::CASE_INSENSITIVE))
+    }
+}
+
 impl From<Fingerprint> for CrateDisambiguator {
     fn from(fingerprint: Fingerprint) -> CrateDisambiguator {
         CrateDisambiguator(fingerprint)
diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs
index df8e0f056af..f6e9ee7b225 100644
--- a/src/librustc_incremental/assert_module_sources.rs
+++ b/src/librustc_incremental/assert_module_sources.rs
@@ -27,11 +27,11 @@
 //! the HIR doesn't change as a result of the annotations, which might
 //! perturb the reuse results.
 
+use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::dep_graph::{DepNode, DepConstructor};
 use rustc::mir::mono::CodegenUnit;
 use rustc::ty::TyCtxt;
 use syntax::ast;
-use syntax_pos::symbol::Symbol;
 use rustc::ich::{ATTR_PARTITION_REUSED, ATTR_PARTITION_CODEGENED};
 
 const MODULE: &'static str = "module";
@@ -72,12 +72,37 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> {
             return;
         }
 
-        let mname = self.field(attr, MODULE);
-        let mangled_cgu_name = CodegenUnit::mangle_name(&mname.as_str());
-        let mangled_cgu_name = Symbol::intern(&mangled_cgu_name).as_interned_str();
+        let user_path = self.field(attr, MODULE).as_str().to_string();
+        let crate_name = self.tcx.crate_name(LOCAL_CRATE).as_str().to_string();
+
+        if !user_path.starts_with(&crate_name) {
+            let msg = format!("Found malformed codegen unit name `{}`. \
+                Codegen units names must always start with the name of the \
+                crate (`{}` in this case).", user_path, crate_name);
+            self.tcx.sess.span_fatal(attr.span, &msg);
+        }
+
+        // Split of the "special suffix" if there is one.
+        let (user_path, cgu_special_suffix) = if let Some(index) = user_path.rfind(".") {
+            (&user_path[..index], Some(&user_path[index + 1 ..]))
+        } else {
+            (&user_path[..], None)
+        };
+
+        let mut cgu_path_components = user_path.split("-").collect::<Vec<_>>();
+
+        // Remove the crate name
+        assert_eq!(cgu_path_components.remove(0), crate_name);
+
+        let cgu_name = CodegenUnit::build_cgu_name(self.tcx,
+                                                   LOCAL_CRATE,
+                                                   cgu_path_components,
+                                                   cgu_special_suffix);
+
+        debug!("mapping '{}' to cgu name '{}'", self.field(attr, MODULE), cgu_name);
 
         let dep_node = DepNode::new(self.tcx,
-                                    DepConstructor::CompileCodegenUnit(mangled_cgu_name));
+                                    DepConstructor::CompileCodegenUnit(cgu_name));
 
         if let Some(loaded_from_cache) = self.tcx.dep_graph.was_loaded_from_cache(&dep_node) {
             match (disposition, loaded_from_cache) {
@@ -85,13 +110,13 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> {
                     self.tcx.sess.span_err(
                         attr.span,
                         &format!("expected module named `{}` to be Reused but is Codegened",
-                                 mname));
+                                 user_path));
                 }
                 (Disposition::Codegened, true) => {
                     self.tcx.sess.span_err(
                         attr.span,
                         &format!("expected module named `{}` to be Codegened but is Reused",
-                                 mname));
+                                 user_path));
                 }
                 (Disposition::Reused, true) |
                 (Disposition::Codegened, false) => {
@@ -99,7 +124,19 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> {
                 }
             }
         } else {
-            self.tcx.sess.span_err(attr.span, &format!("no module named `{}`", mname));
+            let available_cgus = self.tcx
+                .collect_and_partition_mono_items(LOCAL_CRATE)
+                .1
+                .iter()
+                .map(|cgu| format!("{}", cgu.name()))
+                .collect::<Vec<String>>()
+                .join(", ");
+
+            self.tcx.sess.span_err(attr.span,
+                &format!("no module named `{}` (mangled: {}).\nAvailable modules: {}",
+                    user_path,
+                    cgu_name,
+                    available_cgus));
         }
     }
 
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index 5f15870d6fb..73b430bc041 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -104,7 +104,7 @@
 
 use monomorphize::collector::InliningMap;
 use rustc::dep_graph::WorkProductId;
-use rustc::hir::def_id::DefId;
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::hir::map::DefPathData;
 use rustc::mir::mono::{Linkage, Visibility};
 use rustc::middle::exported_symbols::SymbolExportLevel;
@@ -114,7 +114,7 @@ use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use std::collections::hash_map::Entry;
 use std::cmp;
 use syntax::ast::NodeId;
-use syntax::symbol::{Symbol, InternedString};
+use syntax::symbol::InternedString;
 use rustc::mir::mono::MonoItem;
 use monomorphize::item::{MonoItemExt, InstantiationMode};
 
@@ -204,16 +204,9 @@ impl<'tcx> CodegenUnitExt<'tcx> for CodegenUnit<'tcx> {
 
 // Anything we can't find a proper codegen unit for goes into this.
 fn fallback_cgu_name(tcx: TyCtxt) -> InternedString {
-    const FALLBACK_CODEGEN_UNIT: &'static str = "__rustc_fallback_codegen_unit";
-
-    if tcx.sess.opts.debugging_opts.human_readable_cgu_names {
-        Symbol::intern(FALLBACK_CODEGEN_UNIT).as_interned_str()
-    } else {
-        Symbol::intern(&CodegenUnit::mangle_name(FALLBACK_CODEGEN_UNIT)).as_interned_str()
-    }
+    CodegenUnit::build_cgu_name(tcx, LOCAL_CRATE, &["fallback"], Some("cgu"))
 }
 
-
 pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                               mono_items: I,
                               strategy: PartitioningStrategy,
@@ -224,8 +217,7 @@ pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // In the first step, we place all regular monomorphizations into their
     // respective 'home' codegen unit. Regular monomorphizations are all
     // functions and statics defined in the local crate.
-    let mut initial_partitioning = place_root_mono_items(tcx,
-                                                                mono_items);
+    let mut initial_partitioning = place_root_mono_items(tcx, mono_items);
 
     initial_partitioning.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(&tcx));
 
@@ -234,7 +226,7 @@ pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // If the partitioning should produce a fixed count of codegen units, merge
     // until that count is reached.
     if let PartitioningStrategy::FixedUnitCount(count) = strategy {
-        merge_codegen_units(&mut initial_partitioning, count, &tcx.crate_name.as_str());
+        merge_codegen_units(tcx, &mut initial_partitioning, count);
 
         debug_dump(tcx, "POST MERGING:", initial_partitioning.codegen_units.iter());
     }
@@ -328,7 +320,7 @@ fn place_root_mono_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         };
 
         let codegen_unit = codegen_units.entry(codegen_unit_name.clone())
-                                            .or_insert_with(make_codegen_unit);
+                                        .or_insert_with(make_codegen_unit);
 
         let mut can_be_internalized = true;
         let default_visibility = |id: DefId, is_generic: bool| {
@@ -491,9 +483,9 @@ fn place_root_mono_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
-fn merge_codegen_units<'tcx>(initial_partitioning: &mut PreInliningPartitioning<'tcx>,
-                             target_cgu_count: usize,
-                             crate_name: &str) {
+fn merge_codegen_units<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>,
+                             initial_partitioning: &mut PreInliningPartitioning<'tcx>,
+                             target_cgu_count: usize) {
     assert!(target_cgu_count >= 1);
     let codegen_units = &mut initial_partitioning.codegen_units;
 
@@ -522,7 +514,7 @@ fn merge_codegen_units<'tcx>(initial_partitioning: &mut PreInliningPartitioning<
     }
 
     for (index, cgu) in codegen_units.iter_mut().enumerate() {
-        cgu.set_name(numbered_codegen_unit_name(crate_name, index));
+        cgu.set_name(numbered_codegen_unit_name(tcx, index));
     }
 }
 
@@ -727,42 +719,26 @@ fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                        def_id: DefId,
                                        volatile: bool)
                                        -> InternedString {
-    // Unfortunately we cannot just use the `ty::item_path` infrastructure here
-    // because we need paths to modules and the DefIds of those are not
-    // available anymore for external items.
-    let mut cgu_name = String::with_capacity(64);
-
     let def_path = tcx.def_path(def_id);
-    cgu_name.push_str(&tcx.crate_name(def_path.krate).as_str());
-
-    for part in tcx.def_path(def_id)
-                   .data
-                   .iter()
-                   .take_while(|part| {
-                        match part.data {
-                            DefPathData::Module(..) => true,
-                            _ => false,
-                        }
-                    }) {
-        cgu_name.push_str("-");
-        cgu_name.push_str(&part.data.as_interned_str().as_str());
-    }
 
-    if volatile {
-        cgu_name.push_str(".volatile");
-    }
+    let components = def_path.data.iter().take_while(|part| {
+        match part.data {
+            DefPathData::Module(..) => true,
+            _ => false,
+        }
+    }).map(|part| part.data.as_interned_str());
 
-    let cgu_name = if tcx.sess.opts.debugging_opts.human_readable_cgu_names {
-        cgu_name
+    let volatile_suffix = if volatile {
+        Some("volatile")
     } else {
-        CodegenUnit::mangle_name(&cgu_name)
+        None
     };
 
-    Symbol::intern(&cgu_name[..]).as_interned_str()
+    CodegenUnit::build_cgu_name(tcx, def_path.krate, components, volatile_suffix)
 }
 
-fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString {
-    Symbol::intern(&format!("{}{}", crate_name, index)).as_interned_str()
+fn numbered_codegen_unit_name(tcx: TyCtxt, index: usize) -> InternedString {
+    CodegenUnit::build_cgu_name_no_mangle(tcx, LOCAL_CRATE, &["cgu"], Some(index))
 }
 
 fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
diff --git a/src/test/incremental/issue-39828/auxiliary/generic.rs b/src/test/incremental/issue-39828/auxiliary/generic.rs
index a562eab1768..5491827af8a 100644
--- a/src/test/incremental/issue-39828/auxiliary/generic.rs
+++ b/src/test/incremental/issue-39828/auxiliary/generic.rs
@@ -11,7 +11,7 @@
 // revisions:rpass1 rpass2
 // compile-flags: -Z query-dep-graph
 
-#![rustc_partition_reused(module="__rustc_fallback_codegen_unit", cfg="rpass2")]
+#![rustc_partition_reused(module="generic-fallback.cgu", cfg="rpass2")]
 #![feature(rustc_attrs)]
 
 #![crate_type="rlib"]