Skip to content

Commit 2d2cd21

Browse files
Clean up CodegenUnit name generation.
1 parent 81cfaad commit 2d2cd21

File tree

5 files changed

+154
-56
lines changed

5 files changed

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

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

src/librustc/session/mod.rs

+10
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use util::nodemap::{FxHashMap, FxHashSet};
2424
use util::common::{duration_to_secs_str, ErrorReported};
2525
use util::common::ProfileQueriesMsg;
2626

27+
use rustc_data_structures::base_n;
2728
use rustc_data_structures::sync::{self, Lrc, Lock, LockCell, OneThread, Once, RwLock};
2829

2930
use syntax::ast::NodeId;
@@ -48,6 +49,7 @@ use std;
4849
use std::cell::{self, Cell, RefCell};
4950
use std::collections::HashMap;
5051
use std::env;
52+
use std::fmt;
5153
use std::io::Write;
5254
use std::path::{Path, PathBuf};
5355
use std::time::Duration;
@@ -1221,6 +1223,14 @@ impl CrateDisambiguator {
12211223
}
12221224
}
12231225

1226+
impl fmt::Display for CrateDisambiguator {
1227+
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
1228+
let (a, b) = self.0.as_value();
1229+
let as_u128 = a as u128 | ((b as u128) << 64);
1230+
f.write_str(&base_n::encode(as_u128, base_n::CASE_INSENSITIVE))
1231+
}
1232+
}
1233+
12241234
impl From<Fingerprint> for CrateDisambiguator {
12251235
fn from(fingerprint: Fingerprint) -> CrateDisambiguator {
12261236
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

+21-45
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@
105105
use monomorphize::collector::InliningMap;
106106
use rustc::dep_graph::WorkProductId;
107107
use rustc::hir::CodegenFnAttrFlags;
108-
use rustc::hir::def_id::DefId;
108+
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
109109
use rustc::hir::map::DefPathData;
110110
use rustc::mir::mono::{Linkage, Visibility};
111111
use rustc::middle::exported_symbols::SymbolExportLevel;
@@ -115,7 +115,7 @@ use rustc::util::nodemap::{FxHashMap, FxHashSet};
115115
use std::collections::hash_map::Entry;
116116
use std::cmp;
117117
use syntax::ast::NodeId;
118-
use syntax::symbol::{Symbol, InternedString};
118+
use syntax::symbol::InternedString;
119119
use rustc::mir::mono::MonoItem;
120120
use monomorphize::item::{MonoItemExt, InstantiationMode};
121121

@@ -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
}
@@ -552,9 +544,9 @@ fn default_visibility(tcx: TyCtxt, id: DefId, is_generic: bool) -> Visibility {
552544
}
553545
}
554546

555-
fn merge_codegen_units<'tcx>(initial_partitioning: &mut PreInliningPartitioning<'tcx>,
556-
target_cgu_count: usize,
557-
crate_name: &str) {
547+
fn merge_codegen_units<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>,
548+
initial_partitioning: &mut PreInliningPartitioning<'tcx>,
549+
target_cgu_count: usize) {
558550
assert!(target_cgu_count >= 1);
559551
let codegen_units = &mut initial_partitioning.codegen_units;
560552

@@ -583,7 +575,7 @@ fn merge_codegen_units<'tcx>(initial_partitioning: &mut PreInliningPartitioning<
583575
}
584576

585577
for (index, cgu) in codegen_units.iter_mut().enumerate() {
586-
cgu.set_name(numbered_codegen_unit_name(crate_name, index));
578+
cgu.set_name(numbered_codegen_unit_name(tcx, index));
587579
}
588580
}
589581

@@ -787,42 +779,26 @@ fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
787779
def_id: DefId,
788780
volatile: bool)
789781
-> InternedString {
790-
// Unfortunately we cannot just use the `ty::item_path` infrastructure here
791-
// because we need paths to modules and the DefIds of those are not
792-
// available anymore for external items.
793-
let mut cgu_name = String::with_capacity(64);
794-
795782
let def_path = tcx.def_path(def_id);
796-
cgu_name.push_str(&tcx.crate_name(def_path.krate).as_str());
797-
798-
for part in tcx.def_path(def_id)
799-
.data
800-
.iter()
801-
.take_while(|part| {
802-
match part.data {
803-
DefPathData::Module(..) => true,
804-
_ => false,
805-
}
806-
}) {
807-
cgu_name.push_str("-");
808-
cgu_name.push_str(&part.data.as_interned_str().as_str());
809-
}
810783

811-
if volatile {
812-
cgu_name.push_str(".volatile");
813-
}
784+
let components = def_path.data.iter().take_while(|part| {
785+
match part.data {
786+
DefPathData::Module(..) => true,
787+
_ => false,
788+
}
789+
}).map(|part| part.data.as_interned_str());
814790

815-
let cgu_name = if tcx.sess.opts.debugging_opts.human_readable_cgu_names {
816-
cgu_name
791+
let volatile_suffix = if volatile {
792+
Some("volatile")
817793
} else {
818-
CodegenUnit::mangle_name(&cgu_name)
794+
None
819795
};
820796

821-
Symbol::intern(&cgu_name[..]).as_interned_str()
797+
CodegenUnit::build_cgu_name(tcx, def_path.krate, components, volatile_suffix)
822798
}
823799

824-
fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString {
825-
Symbol::intern(&format!("{}{}", crate_name, index)).as_interned_str()
800+
fn numbered_codegen_unit_name(tcx: TyCtxt, index: usize) -> InternedString {
801+
CodegenUnit::build_cgu_name_no_mangle(tcx, LOCAL_CRATE, &["cgu"], Some(index))
826802
}
827803

828804
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)