Skip to content

Commit 2c5cd9c

Browse files
Clean up CodegenUnit name generation.
1 parent 8dc7ddb commit 2c5cd9c

File tree

5 files changed

+154
-57
lines changed

5 files changed

+154
-57
lines changed

src/librustc/mir/mono.rs

+77-2
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,16 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use hir::def_id::DefId;
11+
use hir::def_id::{DefId, CrateNum};
1212
use syntax::ast::NodeId;
13-
use syntax::symbol::InternedString;
13+
use syntax::symbol::{Symbol, InternedString};
1414
use ty::{Instance, TyCtxt};
1515
use util::nodemap::FxHashMap;
1616
use rustc_data_structures::base_n;
1717
use rustc_data_structures::stable_hasher::{HashStable, StableHasherResult,
1818
StableHasher};
1919
use ich::{Fingerprint, StableHashingContext, NodeIdHashingMode};
20+
use std::fmt;
2021
use std::hash::Hash;
2122

2223
#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
@@ -173,6 +174,80 @@ impl<'tcx> CodegenUnit<'tcx> {
173174
self.size_estimate = Some(size_estimate + delta);
174175
}
175176
}
177+
178+
/// CGU names should fulfill the following requirements:
179+
/// - They should be able to act as a file name on any kind of file system
180+
/// - They should not collide with other CGU names, even for different versions
181+
/// of the same crate.
182+
///
183+
/// Consequently, we don't use special characters except for '.' and '-' and we
184+
/// prefix each name with the crate-name and crate-disambiguator.
185+
///
186+
/// This function will build CGU names of the form:
187+
///
188+
/// ```
189+
/// <crate-name>.<crate-disambiguator>(-<component>)*[.<special-suffix>]
190+
/// ```
191+
///
192+
/// The '.' before `<special-suffix>` makes sure that names with a special
193+
/// suffix can never collide with a name built out of regular Rust
194+
/// identifiers (e.g. module paths).
195+
pub fn build_cgu_name<I, C, S>(tcx: TyCtxt,
196+
cnum: CrateNum,
197+
components: I,
198+
special_suffix: Option<S>)
199+
-> InternedString
200+
where I: IntoIterator<Item=C>,
201+
C: fmt::Display,
202+
S: fmt::Display,
203+
{
204+
let cgu_name = CodegenUnit::build_cgu_name_no_mangle(tcx,
205+
cnum,
206+
components,
207+
special_suffix);
208+
209+
if tcx.sess.opts.debugging_opts.human_readable_cgu_names {
210+
cgu_name
211+
} else {
212+
let cgu_name = &cgu_name.as_str()[..];
213+
Symbol::intern(&CodegenUnit::mangle_name(cgu_name)).as_interned_str()
214+
}
215+
}
216+
217+
/// Same as `CodegenUnit::build_cgu_name()` but will never mangle the
218+
/// resulting name.
219+
pub fn build_cgu_name_no_mangle<I, C, S>(tcx: TyCtxt,
220+
cnum: CrateNum,
221+
components: I,
222+
special_suffix: Option<S>)
223+
-> InternedString
224+
where I: IntoIterator<Item=C>,
225+
C: fmt::Display,
226+
S: fmt::Display,
227+
{
228+
use std::fmt::Write;
229+
230+
let mut cgu_name = String::with_capacity(64);
231+
232+
// Start out with the crate name and disambiguator
233+
write!(cgu_name,
234+
"{}.{}",
235+
tcx.crate_name(cnum),
236+
tcx.crate_disambiguator(cnum)).unwrap();
237+
238+
// Add the components
239+
for component in components {
240+
write!(cgu_name, "-{}", component).unwrap();
241+
}
242+
243+
if let Some(special_suffix) = special_suffix {
244+
// We add a dot in here so it cannot clash with anything in a regular
245+
// Rust identifier
246+
write!(cgu_name, ".{}", special_suffix).unwrap();
247+
}
248+
249+
Symbol::intern(&cgu_name[..]).as_interned_str()
250+
}
176251
}
177252

178253
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for CodegenUnit<'tcx> {

src/librustc/session/mod.rs

+9
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use util::nodemap::{FxHashMap, FxHashSet};
2626
use util::common::{duration_to_secs_str, ErrorReported};
2727
use util::common::ProfileQueriesMsg;
2828

29+
use rustc_data_structures::base_n;
2930
use rustc_data_structures::sync::{self, Lrc, Lock, LockCell, OneThread, Once, RwLock};
3031

3132
use syntax::ast::NodeId;
@@ -1185,6 +1186,14 @@ impl CrateDisambiguator {
11851186
}
11861187
}
11871188

1189+
impl fmt::Display for CrateDisambiguator {
1190+
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
1191+
let (a, b) = self.0.as_value();
1192+
let as_u128 = a as u128 | ((b as u128) << 64);
1193+
f.write_str(&base_n::encode(as_u128, base_n::CASE_INSENSITIVE))
1194+
}
1195+
}
1196+
11881197
impl From<Fingerprint> for CrateDisambiguator {
11891198
fn from(fingerprint: Fingerprint) -> CrateDisambiguator {
11901199
CrateDisambiguator(fingerprint)

src/librustc_incremental/assert_module_sources.rs

+45-8
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@
2727
//! the HIR doesn't change as a result of the annotations, which might
2828
//! perturb the reuse results.
2929
30+
use rustc::hir::def_id::LOCAL_CRATE;
3031
use rustc::dep_graph::{DepNode, DepConstructor};
3132
use rustc::mir::mono::CodegenUnit;
3233
use rustc::ty::TyCtxt;
3334
use syntax::ast;
34-
use syntax_pos::symbol::Symbol;
3535
use rustc::ich::{ATTR_PARTITION_REUSED, ATTR_PARTITION_CODEGENED};
3636

3737
const MODULE: &'static str = "module";
@@ -72,34 +72,71 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> {
7272
return;
7373
}
7474

75-
let mname = self.field(attr, MODULE);
76-
let mangled_cgu_name = CodegenUnit::mangle_name(&mname.as_str());
77-
let mangled_cgu_name = Symbol::intern(&mangled_cgu_name).as_interned_str();
75+
let user_path = self.field(attr, MODULE).as_str().to_string();
76+
let crate_name = self.tcx.crate_name(LOCAL_CRATE).as_str().to_string();
77+
78+
if !user_path.starts_with(&crate_name) {
79+
let msg = format!("Found malformed codegen unit name `{}`. \
80+
Codegen units names must always start with the name of the \
81+
crate (`{}` in this case).", user_path, crate_name);
82+
self.tcx.sess.span_fatal(attr.span, &msg);
83+
}
84+
85+
// Split of the "special suffix" if there is one.
86+
let (user_path, cgu_special_suffix) = if let Some(index) = user_path.rfind(".") {
87+
(&user_path[..index], Some(&user_path[index + 1 ..]))
88+
} else {
89+
(&user_path[..], None)
90+
};
91+
92+
let mut cgu_path_components = user_path.split("-").collect::<Vec<_>>();
93+
94+
// Remove the crate name
95+
assert_eq!(cgu_path_components.remove(0), crate_name);
96+
97+
let cgu_name = CodegenUnit::build_cgu_name(self.tcx,
98+
LOCAL_CRATE,
99+
cgu_path_components,
100+
cgu_special_suffix);
101+
102+
debug!("mapping '{}' to cgu name '{}'", self.field(attr, MODULE), cgu_name);
78103

79104
let dep_node = DepNode::new(self.tcx,
80-
DepConstructor::CompileCodegenUnit(mangled_cgu_name));
105+
DepConstructor::CompileCodegenUnit(cgu_name));
81106

82107
if let Some(loaded_from_cache) = self.tcx.dep_graph.was_loaded_from_cache(&dep_node) {
83108
match (disposition, loaded_from_cache) {
84109
(Disposition::Reused, false) => {
85110
self.tcx.sess.span_err(
86111
attr.span,
87112
&format!("expected module named `{}` to be Reused but is Codegened",
88-
mname));
113+
user_path));
89114
}
90115
(Disposition::Codegened, true) => {
91116
self.tcx.sess.span_err(
92117
attr.span,
93118
&format!("expected module named `{}` to be Codegened but is Reused",
94-
mname));
119+
user_path));
95120
}
96121
(Disposition::Reused, true) |
97122
(Disposition::Codegened, false) => {
98123
// These are what we would expect.
99124
}
100125
}
101126
} else {
102-
self.tcx.sess.span_err(attr.span, &format!("no module named `{}`", mname));
127+
let available_cgus = self.tcx
128+
.collect_and_partition_mono_items(LOCAL_CRATE)
129+
.1
130+
.iter()
131+
.map(|cgu| format!("{}", cgu.name()))
132+
.collect::<Vec<String>>()
133+
.join(", ");
134+
135+
self.tcx.sess.span_err(attr.span,
136+
&format!("no module named `{}` (mangled: {}).\nAvailable modules: {}",
137+
user_path,
138+
cgu_name,
139+
available_cgus));
103140
}
104141
}
105142

src/librustc_mir/monomorphize/partitioning.rs

+22-46
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@
104104
105105
use monomorphize::collector::InliningMap;
106106
use rustc::dep_graph::WorkProductId;
107-
use rustc::hir::def_id::DefId;
107+
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
108108
use rustc::hir::map::DefPathData;
109109
use rustc::mir::mono::{Linkage, Visibility};
110110
use rustc::middle::exported_symbols::SymbolExportLevel;
@@ -114,7 +114,7 @@ use rustc::util::nodemap::{FxHashMap, FxHashSet};
114114
use std::collections::hash_map::Entry;
115115
use std::cmp;
116116
use syntax::ast::NodeId;
117-
use syntax::symbol::{Symbol, InternedString};
117+
use syntax::symbol::InternedString;
118118
use rustc::mir::mono::MonoItem;
119119
use monomorphize::item::{MonoItemExt, InstantiationMode};
120120

@@ -204,16 +204,9 @@ impl<'tcx> CodegenUnitExt<'tcx> for CodegenUnit<'tcx> {
204204

205205
// Anything we can't find a proper codegen unit for goes into this.
206206
fn fallback_cgu_name(tcx: TyCtxt) -> InternedString {
207-
const FALLBACK_CODEGEN_UNIT: &'static str = "__rustc_fallback_codegen_unit";
208-
209-
if tcx.sess.opts.debugging_opts.human_readable_cgu_names {
210-
Symbol::intern(FALLBACK_CODEGEN_UNIT).as_interned_str()
211-
} else {
212-
Symbol::intern(&CodegenUnit::mangle_name(FALLBACK_CODEGEN_UNIT)).as_interned_str()
213-
}
207+
CodegenUnit::build_cgu_name(tcx, LOCAL_CRATE, &["fallback"], Some("cgu"))
214208
}
215209

216-
217210
pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
218211
mono_items: I,
219212
strategy: PartitioningStrategy,
@@ -224,8 +217,7 @@ pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
224217
// In the first step, we place all regular monomorphizations into their
225218
// respective 'home' codegen unit. Regular monomorphizations are all
226219
// functions and statics defined in the local crate.
227-
let mut initial_partitioning = place_root_mono_items(tcx,
228-
mono_items);
220+
let mut initial_partitioning = place_root_mono_items(tcx, mono_items);
229221

230222
initial_partitioning.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(&tcx));
231223

@@ -234,7 +226,7 @@ pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
234226
// If the partitioning should produce a fixed count of codegen units, merge
235227
// until that count is reached.
236228
if let PartitioningStrategy::FixedUnitCount(count) = strategy {
237-
merge_codegen_units(&mut initial_partitioning, count, &tcx.crate_name.as_str());
229+
merge_codegen_units(tcx, &mut initial_partitioning, count);
238230

239231
debug_dump(tcx, "POST MERGING:", initial_partitioning.codegen_units.iter());
240232
}
@@ -328,7 +320,7 @@ fn place_root_mono_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
328320
};
329321

330322
let codegen_unit = codegen_units.entry(codegen_unit_name.clone())
331-
.or_insert_with(make_codegen_unit);
323+
.or_insert_with(make_codegen_unit);
332324

333325
let mut can_be_internalized = true;
334326
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>,
491483
}
492484
}
493485

494-
fn merge_codegen_units<'tcx>(initial_partitioning: &mut PreInliningPartitioning<'tcx>,
495-
target_cgu_count: usize,
496-
crate_name: &str) {
486+
fn merge_codegen_units<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>,
487+
initial_partitioning: &mut PreInliningPartitioning<'tcx>,
488+
target_cgu_count: usize) {
497489
assert!(target_cgu_count >= 1);
498490
let codegen_units = &mut initial_partitioning.codegen_units;
499491

@@ -522,7 +514,7 @@ fn merge_codegen_units<'tcx>(initial_partitioning: &mut PreInliningPartitioning<
522514
}
523515

524516
for (index, cgu) in codegen_units.iter_mut().enumerate() {
525-
cgu.set_name(numbered_codegen_unit_name(crate_name, index));
517+
cgu.set_name(numbered_codegen_unit_name(tcx, index));
526518
}
527519
}
528520

@@ -727,42 +719,26 @@ fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
727719
def_id: DefId,
728720
volatile: bool)
729721
-> InternedString {
730-
// Unfortunately we cannot just use the `ty::item_path` infrastructure here
731-
// because we need paths to modules and the DefIds of those are not
732-
// available anymore for external items.
733-
let mut cgu_name = String::with_capacity(64);
734-
735722
let def_path = tcx.def_path(def_id);
736-
cgu_name.push_str(&tcx.crate_name(def_path.krate).as_str());
737-
738-
for part in tcx.def_path(def_id)
739-
.data
740-
.iter()
741-
.take_while(|part| {
742-
match part.data {
743-
DefPathData::Module(..) => true,
744-
_ => false,
745-
}
746-
}) {
747-
cgu_name.push_str("-");
748-
cgu_name.push_str(&part.data.as_interned_str().as_str());
749-
}
750723

751-
if volatile {
752-
cgu_name.push_str(".volatile");
753-
}
724+
let components = def_path.data.iter().take_while(|part| {
725+
match part.data {
726+
DefPathData::Module(..) => true,
727+
_ => false,
728+
}
729+
}).map(|part| part.data.as_interned_str());
754730

755-
let cgu_name = if tcx.sess.opts.debugging_opts.human_readable_cgu_names {
756-
cgu_name
731+
let volatile_suffix = if volatile {
732+
Some("volatile")
757733
} else {
758-
CodegenUnit::mangle_name(&cgu_name)
734+
None
759735
};
760736

761-
Symbol::intern(&cgu_name[..]).as_interned_str()
737+
CodegenUnit::build_cgu_name(tcx, def_path.krate, components, volatile_suffix)
762738
}
763739

764-
fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString {
765-
Symbol::intern(&format!("{}{}", crate_name, index)).as_interned_str()
740+
fn numbered_codegen_unit_name(tcx: TyCtxt, index: usize) -> InternedString {
741+
CodegenUnit::build_cgu_name_no_mangle(tcx, LOCAL_CRATE, &["cgu"], Some(index))
766742
}
767743

768744
fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,

src/test/incremental/issue-39828/auxiliary/generic.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
// revisions:rpass1 rpass2
1212
// compile-flags: -Z query-dep-graph
1313

14-
#![rustc_partition_reused(module="__rustc_fallback_codegen_unit", cfg="rpass2")]
14+
#![rustc_partition_reused(module="generic-fallback.cgu", cfg="rpass2")]
1515
#![feature(rustc_attrs)]
1616

1717
#![crate_type="rlib"]

0 commit comments

Comments
 (0)