Use CGU name as LLVM module name and add some caching to CGU name generation.
This commit is contained in:
parent
e192e498ab
commit
d662083a6c
9 changed files with 207 additions and 169 deletions
|
@ -171,80 +171,6 @@ impl<'tcx> CodegenUnit<'tcx> {
|
||||||
self.size_estimate = Some(size_estimate + delta);
|
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> {
|
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for CodegenUnit<'tcx> {
|
||||||
|
@ -314,3 +240,95 @@ impl Stats {
|
||||||
self.fn_stats.extend(stats.fn_stats);
|
self.fn_stats.extend(stats.fn_stats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct CodegenUnitNameBuilder<'a, 'gcx: 'tcx, 'tcx: 'a> {
|
||||||
|
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
cache: FxHashMap<CrateNum, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'gcx: 'tcx, 'tcx: 'a> CodegenUnitNameBuilder<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
|
pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Self {
|
||||||
|
CodegenUnitNameBuilder {
|
||||||
|
tcx,
|
||||||
|
cache: FxHashMap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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>(&mut self,
|
||||||
|
cnum: CrateNum,
|
||||||
|
components: I,
|
||||||
|
special_suffix: Option<S>)
|
||||||
|
-> InternedString
|
||||||
|
where I: IntoIterator<Item=C>,
|
||||||
|
C: fmt::Display,
|
||||||
|
S: fmt::Display,
|
||||||
|
{
|
||||||
|
let cgu_name = self.build_cgu_name_no_mangle(cnum,
|
||||||
|
components,
|
||||||
|
special_suffix);
|
||||||
|
|
||||||
|
if self.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>(&mut self,
|
||||||
|
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
|
||||||
|
let tcx = self.tcx;
|
||||||
|
let crate_prefix = self.cache.entry(cnum).or_insert_with(|| {
|
||||||
|
let crate_disambiguator = format!("{}", tcx.crate_disambiguator(cnum));
|
||||||
|
// Using a shortened disambiguator of about 40 bits
|
||||||
|
format!("{}.{}", tcx.crate_name(cnum), &crate_disambiguator[0 .. 8])
|
||||||
|
});
|
||||||
|
|
||||||
|
write!(cgu_name, "{}", crate_prefix).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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -46,13 +46,6 @@ use std::process::{Output, Stdio};
|
||||||
use std::str;
|
use std::str;
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
|
|
||||||
/// The LLVM module name containing crate-metadata. This includes a `.` on
|
|
||||||
/// purpose, so it cannot clash with the name of a user-defined module.
|
|
||||||
pub const METADATA_MODULE_NAME: &'static str = "crate.metadata";
|
|
||||||
|
|
||||||
// same as for metadata above, but for allocator shim
|
|
||||||
pub const ALLOCATOR_MODULE_NAME: &'static str = "crate.allocator";
|
|
||||||
|
|
||||||
pub use rustc_codegen_utils::link::{find_crate_name, filename_for_input, default_output_for_target,
|
pub use rustc_codegen_utils::link::{find_crate_name, filename_for_input, default_output_for_target,
|
||||||
invalid_output_for_target, build_link_meta, out_filename,
|
invalid_output_for_target, build_link_meta, out_filename,
|
||||||
check_file_is_writeable};
|
check_file_is_writeable};
|
||||||
|
|
|
@ -242,7 +242,7 @@ fn fat_lto(cgcx: &CodegenContext,
|
||||||
let llvm = module.llvm().expect("can't lto pre-codegened modules");
|
let llvm = module.llvm().expect("can't lto pre-codegened modules");
|
||||||
(&llvm.llcx, llvm.llmod())
|
(&llvm.llcx, llvm.llmod())
|
||||||
};
|
};
|
||||||
info!("using {:?} as a base module", module.llmod_id);
|
info!("using {:?} as a base module", module.name);
|
||||||
|
|
||||||
// The linking steps below may produce errors and diagnostics within LLVM
|
// The linking steps below may produce errors and diagnostics within LLVM
|
||||||
// which we'd like to handle and print, so set up our diagnostic handlers
|
// which we'd like to handle and print, so set up our diagnostic handlers
|
||||||
|
@ -257,7 +257,7 @@ fn fat_lto(cgcx: &CodegenContext,
|
||||||
for module in modules {
|
for module in modules {
|
||||||
let llvm = module.llvm().expect("can't lto pre-codegened modules");
|
let llvm = module.llvm().expect("can't lto pre-codegened modules");
|
||||||
let buffer = ModuleBuffer::new(llvm.llmod());
|
let buffer = ModuleBuffer::new(llvm.llmod());
|
||||||
let llmod_id = CString::new(&module.llmod_id[..]).unwrap();
|
let llmod_id = CString::new(&module.name[..]).unwrap();
|
||||||
serialized_modules.push((SerializedModule::Local(buffer), llmod_id));
|
serialized_modules.push((SerializedModule::Local(buffer), llmod_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,9 +384,9 @@ fn thin_lto(diag_handler: &Handler,
|
||||||
// the most expensive portion of this small bit of global
|
// the most expensive portion of this small bit of global
|
||||||
// analysis!
|
// analysis!
|
||||||
for (i, module) in modules.iter().enumerate() {
|
for (i, module) in modules.iter().enumerate() {
|
||||||
info!("local module: {} - {}", i, module.llmod_id);
|
info!("local module: {} - {}", i, module.name);
|
||||||
let llvm = module.llvm().expect("can't lto precodegened module");
|
let llvm = module.llvm().expect("can't lto precodegened module");
|
||||||
let name = CString::new(module.llmod_id.clone()).unwrap();
|
let name = CString::new(module.name.clone()).unwrap();
|
||||||
let buffer = ThinBuffer::new(llvm.llmod());
|
let buffer = ThinBuffer::new(llvm.llmod());
|
||||||
thin_modules.push(llvm::ThinLTOModule {
|
thin_modules.push(llvm::ThinLTOModule {
|
||||||
identifier: name.as_ptr(),
|
identifier: name.as_ptr(),
|
||||||
|
@ -395,7 +395,7 @@ fn thin_lto(diag_handler: &Handler,
|
||||||
});
|
});
|
||||||
thin_buffers.push(buffer);
|
thin_buffers.push(buffer);
|
||||||
module_names.push(name);
|
module_names.push(name);
|
||||||
timeline.record(&module.llmod_id);
|
timeline.record(&module.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: All upstream crates are deserialized internally in the
|
// FIXME: All upstream crates are deserialized internally in the
|
||||||
|
@ -668,7 +668,6 @@ impl ThinModule {
|
||||||
llcx,
|
llcx,
|
||||||
tm,
|
tm,
|
||||||
}),
|
}),
|
||||||
llmod_id: self.name().to_string(),
|
|
||||||
name: self.name().to_string(),
|
name: self.name().to_string(),
|
||||||
kind: ModuleKind::Regular,
|
kind: ModuleKind::Regular,
|
||||||
};
|
};
|
||||||
|
|
|
@ -728,7 +728,7 @@ unsafe fn codegen(cgcx: &CodegenContext,
|
||||||
|
|
||||||
if config.emit_bc_compressed {
|
if config.emit_bc_compressed {
|
||||||
let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION);
|
let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION);
|
||||||
let data = bytecode::encode(&module.llmod_id, data);
|
let data = bytecode::encode(&module.name, data);
|
||||||
if let Err(e) = fs::write(&dst, data) {
|
if let Err(e) = fs::write(&dst, data) {
|
||||||
diag_handler.err(&format!("failed to write bytecode: {}", e));
|
diag_handler.err(&format!("failed to write bytecode: {}", e));
|
||||||
}
|
}
|
||||||
|
@ -1338,7 +1338,6 @@ fn execute_work_item(cgcx: &CodegenContext,
|
||||||
assert_eq!(bytecode_compressed.is_some(), config.emit_bc_compressed);
|
assert_eq!(bytecode_compressed.is_some(), config.emit_bc_compressed);
|
||||||
|
|
||||||
Ok(WorkItemResult::Compiled(CompiledModule {
|
Ok(WorkItemResult::Compiled(CompiledModule {
|
||||||
llmod_id: module.llmod_id.clone(),
|
|
||||||
name: module_name,
|
name: module_name,
|
||||||
kind: ModuleKind::Regular,
|
kind: ModuleKind::Regular,
|
||||||
pre_existing: true,
|
pre_existing: true,
|
||||||
|
|
|
@ -36,7 +36,7 @@ use metadata;
|
||||||
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||||
use rustc::middle::lang_items::StartFnLangItem;
|
use rustc::middle::lang_items::StartFnLangItem;
|
||||||
use rustc::middle::weak_lang_items;
|
use rustc::middle::weak_lang_items;
|
||||||
use rustc::mir::mono::{Linkage, Visibility, Stats};
|
use rustc::mir::mono::{Linkage, Visibility, Stats, CodegenUnitNameBuilder};
|
||||||
use rustc::middle::cstore::{EncodedMetadata};
|
use rustc::middle::cstore::{EncodedMetadata};
|
||||||
use rustc::ty::{self, Ty, TyCtxt};
|
use rustc::ty::{self, Ty, TyCtxt};
|
||||||
use rustc::ty::layout::{self, Align, TyLayout, LayoutOf};
|
use rustc::ty::layout::{self, Align, TyLayout, LayoutOf};
|
||||||
|
@ -742,19 +742,23 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
|
||||||
let crate_hash = tcx.crate_hash(LOCAL_CRATE);
|
let crate_hash = tcx.crate_hash(LOCAL_CRATE);
|
||||||
let link_meta = link::build_link_meta(crate_hash);
|
let link_meta = link::build_link_meta(crate_hash);
|
||||||
|
let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
|
||||||
|
|
||||||
// Codegen the metadata.
|
// Codegen the metadata.
|
||||||
tcx.sess.profiler(|p| p.start_activity(ProfileCategory::Codegen));
|
tcx.sess.profiler(|p| p.start_activity(ProfileCategory::Codegen));
|
||||||
let llmod_id = "metadata";
|
|
||||||
let metadata_llvm_module = ModuleLlvm::new(tcx.sess, llmod_id);
|
let metadata_cgu_name = cgu_name_builder.build_cgu_name(LOCAL_CRATE,
|
||||||
|
&["crate"],
|
||||||
|
Some("metadata")).as_str()
|
||||||
|
.to_string();
|
||||||
|
let metadata_llvm_module = ModuleLlvm::new(tcx.sess, &metadata_cgu_name);
|
||||||
let metadata = time(tcx.sess, "write metadata", || {
|
let metadata = time(tcx.sess, "write metadata", || {
|
||||||
write_metadata(tcx, &metadata_llvm_module, &link_meta)
|
write_metadata(tcx, &metadata_llvm_module, &link_meta)
|
||||||
});
|
});
|
||||||
tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen));
|
tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen));
|
||||||
|
|
||||||
let metadata_module = ModuleCodegen {
|
let metadata_module = ModuleCodegen {
|
||||||
name: link::METADATA_MODULE_NAME.to_string(),
|
name: metadata_cgu_name,
|
||||||
llmod_id: llmod_id.to_string(),
|
|
||||||
source: ModuleSource::Codegened(metadata_llvm_module),
|
source: ModuleSource::Codegened(metadata_llvm_module),
|
||||||
kind: ModuleKind::Metadata,
|
kind: ModuleKind::Metadata,
|
||||||
};
|
};
|
||||||
|
@ -833,20 +837,22 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
let allocator_module = if any_dynamic_crate {
|
let allocator_module = if any_dynamic_crate {
|
||||||
None
|
None
|
||||||
} else if let Some(kind) = *tcx.sess.allocator_kind.get() {
|
} else if let Some(kind) = *tcx.sess.allocator_kind.get() {
|
||||||
unsafe {
|
let llmod_id = cgu_name_builder.build_cgu_name(LOCAL_CRATE,
|
||||||
let llmod_id = "allocator";
|
&["crate"],
|
||||||
let modules = ModuleLlvm::new(tcx.sess, llmod_id);
|
Some("allocator")).as_str()
|
||||||
|
.to_string();
|
||||||
|
let modules = ModuleLlvm::new(tcx.sess, &llmod_id);
|
||||||
time(tcx.sess, "write allocator module", || {
|
time(tcx.sess, "write allocator module", || {
|
||||||
|
unsafe {
|
||||||
allocator::codegen(tcx, &modules, kind)
|
allocator::codegen(tcx, &modules, kind)
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Some(ModuleCodegen {
|
Some(ModuleCodegen {
|
||||||
name: link::ALLOCATOR_MODULE_NAME.to_string(),
|
name: llmod_id,
|
||||||
llmod_id: llmod_id.to_string(),
|
|
||||||
source: ModuleSource::Codegened(modules),
|
source: ModuleSource::Codegened(modules),
|
||||||
kind: ModuleKind::Allocator,
|
kind: ModuleKind::Allocator,
|
||||||
})
|
})
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -889,21 +895,10 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
// succeed it means that none of the dependencies has changed
|
// succeed it means that none of the dependencies has changed
|
||||||
// and we can safely re-use.
|
// and we can safely re-use.
|
||||||
if let Some(dep_node_index) = tcx.dep_graph.try_mark_green(tcx, dep_node) {
|
if let Some(dep_node_index) = tcx.dep_graph.try_mark_green(tcx, dep_node) {
|
||||||
// Append ".rs" to LLVM module identifier.
|
|
||||||
//
|
|
||||||
// LLVM code generator emits a ".file filename" directive
|
|
||||||
// for ELF backends. Value of the "filename" is set as the
|
|
||||||
// LLVM module identifier. Due to a LLVM MC bug[1], LLVM
|
|
||||||
// crashes if the module identifier is same as other symbols
|
|
||||||
// such as a function name in the module.
|
|
||||||
// 1. http://llvm.org/bugs/show_bug.cgi?id=11479
|
|
||||||
let llmod_id = format!("{}.rs", cgu.name());
|
|
||||||
|
|
||||||
let module = ModuleCodegen {
|
let module = ModuleCodegen {
|
||||||
name: cgu.name().to_string(),
|
name: cgu.name().to_string(),
|
||||||
source: ModuleSource::Preexisting(buf),
|
source: ModuleSource::Preexisting(buf),
|
||||||
kind: ModuleKind::Regular,
|
kind: ModuleKind::Regular,
|
||||||
llmod_id,
|
|
||||||
};
|
};
|
||||||
tcx.dep_graph.mark_loaded_from_cache(dep_node_index, true);
|
tcx.dep_graph.mark_loaded_from_cache(dep_node_index, true);
|
||||||
write::submit_codegened_module_to_llvm(tcx, module, 0);
|
write::submit_codegened_module_to_llvm(tcx, module, 0);
|
||||||
|
@ -1212,21 +1207,8 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
{
|
{
|
||||||
let cgu_name = cgu.name().to_string();
|
let cgu_name = cgu.name().to_string();
|
||||||
|
|
||||||
// Append ".rs" to LLVM module identifier.
|
|
||||||
//
|
|
||||||
// LLVM code generator emits a ".file filename" directive
|
|
||||||
// for ELF backends. Value of the "filename" is set as the
|
|
||||||
// LLVM module identifier. Due to a LLVM MC bug[1], LLVM
|
|
||||||
// crashes if the module identifier is same as other symbols
|
|
||||||
// such as a function name in the module.
|
|
||||||
// 1. http://llvm.org/bugs/show_bug.cgi?id=11479
|
|
||||||
let llmod_id = format!("{}-{}.rs",
|
|
||||||
cgu.name(),
|
|
||||||
tcx.crate_disambiguator(LOCAL_CRATE)
|
|
||||||
.to_fingerprint().to_hex());
|
|
||||||
|
|
||||||
// Instantiate monomorphizations without filling out definitions yet...
|
// Instantiate monomorphizations without filling out definitions yet...
|
||||||
let llvm_module = ModuleLlvm::new(tcx.sess, &llmod_id);
|
let llvm_module = ModuleLlvm::new(tcx.sess, &cgu_name);
|
||||||
let stats = {
|
let stats = {
|
||||||
let cx = CodegenCx::new(tcx, cgu, &llvm_module);
|
let cx = CodegenCx::new(tcx, cgu, &llvm_module);
|
||||||
let mono_items = cx.codegen_unit
|
let mono_items = cx.codegen_unit
|
||||||
|
@ -1282,7 +1264,6 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
name: cgu_name,
|
name: cgu_name,
|
||||||
source: ModuleSource::Codegened(llvm_module),
|
source: ModuleSource::Codegened(llvm_module),
|
||||||
kind: ModuleKind::Regular,
|
kind: ModuleKind::Regular,
|
||||||
llmod_id,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -269,8 +269,8 @@ struct ModuleCodegen {
|
||||||
/// unique amongst **all** crates. Therefore, it should contain
|
/// unique amongst **all** crates. Therefore, it should contain
|
||||||
/// something unique to this crate (e.g., a module path) as well
|
/// something unique to this crate (e.g., a module path) as well
|
||||||
/// as the crate name and disambiguator.
|
/// as the crate name and disambiguator.
|
||||||
|
/// We currently generate these names via CodegenUnit::build_cgu_name().
|
||||||
name: String,
|
name: String,
|
||||||
llmod_id: String,
|
|
||||||
source: ModuleSource,
|
source: ModuleSource,
|
||||||
kind: ModuleKind,
|
kind: ModuleKind,
|
||||||
}
|
}
|
||||||
|
@ -317,7 +317,6 @@ impl ModuleCodegen {
|
||||||
};
|
};
|
||||||
|
|
||||||
CompiledModule {
|
CompiledModule {
|
||||||
llmod_id: self.llmod_id,
|
|
||||||
name: self.name.clone(),
|
name: self.name.clone(),
|
||||||
kind: self.kind,
|
kind: self.kind,
|
||||||
pre_existing,
|
pre_existing,
|
||||||
|
@ -331,7 +330,6 @@ impl ModuleCodegen {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct CompiledModule {
|
struct CompiledModule {
|
||||||
name: String,
|
name: String,
|
||||||
llmod_id: String,
|
|
||||||
kind: ModuleKind,
|
kind: ModuleKind,
|
||||||
pre_existing: bool,
|
pre_existing: bool,
|
||||||
object: Option<PathBuf>,
|
object: Option<PathBuf>,
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
use rustc::hir::def_id::LOCAL_CRATE;
|
use rustc::hir::def_id::LOCAL_CRATE;
|
||||||
use rustc::dep_graph::{DepNode, DepConstructor};
|
use rustc::dep_graph::{DepNode, DepConstructor};
|
||||||
use rustc::mir::mono::CodegenUnit;
|
use rustc::mir::mono::CodegenUnitNameBuilder;
|
||||||
use rustc::ty::TyCtxt;
|
use rustc::ty::TyCtxt;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use rustc::ich::{ATTR_PARTITION_REUSED, ATTR_PARTITION_CODEGENED};
|
use rustc::ich::{ATTR_PARTITION_REUSED, ATTR_PARTITION_CODEGENED};
|
||||||
|
@ -94,8 +94,8 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> {
|
||||||
// Remove the crate name
|
// Remove the crate name
|
||||||
assert_eq!(cgu_path_components.remove(0), crate_name);
|
assert_eq!(cgu_path_components.remove(0), crate_name);
|
||||||
|
|
||||||
let cgu_name = CodegenUnit::build_cgu_name(self.tcx,
|
let cgu_name_builder = &mut CodegenUnitNameBuilder::new(self.tcx);
|
||||||
LOCAL_CRATE,
|
let cgu_name = cgu_name_builder.build_cgu_name(LOCAL_CRATE,
|
||||||
cgu_path_components,
|
cgu_path_components,
|
||||||
cgu_special_suffix);
|
cgu_special_suffix);
|
||||||
|
|
||||||
|
|
|
@ -105,9 +105,9 @@
|
||||||
use monomorphize::collector::InliningMap;
|
use monomorphize::collector::InliningMap;
|
||||||
use rustc::dep_graph::WorkProductId;
|
use rustc::dep_graph::WorkProductId;
|
||||||
use rustc::hir::CodegenFnAttrFlags;
|
use rustc::hir::CodegenFnAttrFlags;
|
||||||
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
|
use rustc::hir::def_id::{DefId, LOCAL_CRATE, CRATE_DEF_INDEX};
|
||||||
use rustc::hir::map::DefPathData;
|
use rustc::hir::map::DefPathData;
|
||||||
use rustc::mir::mono::{Linkage, Visibility};
|
use rustc::mir::mono::{Linkage, Visibility, CodegenUnitNameBuilder};
|
||||||
use rustc::middle::exported_symbols::SymbolExportLevel;
|
use rustc::middle::exported_symbols::SymbolExportLevel;
|
||||||
use rustc::ty::{self, TyCtxt, InstanceDef};
|
use rustc::ty::{self, TyCtxt, InstanceDef};
|
||||||
use rustc::ty::item_path::characteristic_def_id_of_type;
|
use rustc::ty::item_path::characteristic_def_id_of_type;
|
||||||
|
@ -203,8 +203,8 @@ impl<'tcx> CodegenUnitExt<'tcx> for CodegenUnit<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Anything we can't find a proper codegen unit for goes into this.
|
// Anything we can't find a proper codegen unit for goes into this.
|
||||||
fn fallback_cgu_name(tcx: TyCtxt) -> InternedString {
|
fn fallback_cgu_name(name_builder: &mut CodegenUnitNameBuilder) -> InternedString {
|
||||||
CodegenUnit::build_cgu_name(tcx, LOCAL_CRATE, &["fallback"], Some("cgu"))
|
name_builder.build_cgu_name(LOCAL_CRATE, &["fallback"], Some("cgu"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
@ -300,6 +300,9 @@ fn place_root_mono_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
let export_generics = tcx.sess.opts.share_generics() &&
|
let export_generics = tcx.sess.opts.share_generics() &&
|
||||||
tcx.local_crate_exports_generics();
|
tcx.local_crate_exports_generics();
|
||||||
|
|
||||||
|
let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
|
||||||
|
let cgu_name_cache = &mut FxHashMap();
|
||||||
|
|
||||||
for mono_item in mono_items {
|
for mono_item in mono_items {
|
||||||
match mono_item.instantiation_mode(tcx) {
|
match mono_item.instantiation_mode(tcx) {
|
||||||
InstantiationMode::GloballyShared { .. } => {}
|
InstantiationMode::GloballyShared { .. } => {}
|
||||||
|
@ -311,8 +314,12 @@ fn place_root_mono_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
mono_item.is_generic_fn();
|
mono_item.is_generic_fn();
|
||||||
|
|
||||||
let codegen_unit_name = match characteristic_def_id {
|
let codegen_unit_name = match characteristic_def_id {
|
||||||
Some(def_id) => compute_codegen_unit_name(tcx, def_id, is_volatile),
|
Some(def_id) => compute_codegen_unit_name(tcx,
|
||||||
None => fallback_cgu_name(tcx),
|
cgu_name_builder,
|
||||||
|
def_id,
|
||||||
|
is_volatile,
|
||||||
|
cgu_name_cache),
|
||||||
|
None => fallback_cgu_name(cgu_name_builder),
|
||||||
};
|
};
|
||||||
|
|
||||||
let codegen_unit = codegen_units.entry(codegen_unit_name.clone())
|
let codegen_unit = codegen_units.entry(codegen_unit_name.clone())
|
||||||
|
@ -336,7 +343,7 @@ fn place_root_mono_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
// always ensure we have at least one CGU; otherwise, if we have a
|
// always ensure we have at least one CGU; otherwise, if we have a
|
||||||
// crate with just types (for example), we could wind up with no CGU
|
// crate with just types (for example), we could wind up with no CGU
|
||||||
if codegen_units.is_empty() {
|
if codegen_units.is_empty() {
|
||||||
let codegen_unit_name = fallback_cgu_name(tcx);
|
let codegen_unit_name = fallback_cgu_name(cgu_name_builder);
|
||||||
codegen_units.insert(codegen_unit_name.clone(),
|
codegen_units.insert(codegen_unit_name.clone(),
|
||||||
CodegenUnit::new(codegen_unit_name.clone()));
|
CodegenUnit::new(codegen_unit_name.clone()));
|
||||||
}
|
}
|
||||||
|
@ -574,8 +581,9 @@ fn merge_codegen_units<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
|
||||||
for (index, cgu) in codegen_units.iter_mut().enumerate() {
|
for (index, cgu) in codegen_units.iter_mut().enumerate() {
|
||||||
cgu.set_name(numbered_codegen_unit_name(tcx, index));
|
cgu.set_name(numbered_codegen_unit_name(cgu_name_builder, index));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -775,18 +783,57 @@ fn characteristic_def_id_of_mono_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
type CguNameCache = FxHashMap<(DefId, bool), InternedString>;
|
||||||
def_id: DefId,
|
|
||||||
volatile: bool)
|
|
||||||
-> InternedString {
|
|
||||||
let def_path = tcx.def_path(def_id);
|
|
||||||
|
|
||||||
let components = def_path.data.iter().take_while(|part| {
|
fn compute_codegen_unit_name(tcx: TyCtxt,
|
||||||
match part.data {
|
name_builder: &mut CodegenUnitNameBuilder,
|
||||||
DefPathData::Module(..) => true,
|
def_id: DefId,
|
||||||
_ => false,
|
volatile: bool,
|
||||||
|
cache: &mut CguNameCache)
|
||||||
|
-> InternedString {
|
||||||
|
// Find the innermost module that is not nested within a function
|
||||||
|
let mut current_def_id = def_id;
|
||||||
|
let mut cgu_def_id = None;
|
||||||
|
// Walk backwards from the item we want to find the module for:
|
||||||
|
loop {
|
||||||
|
let def_key = tcx.def_key(current_def_id);
|
||||||
|
|
||||||
|
match def_key.disambiguated_data.data {
|
||||||
|
DefPathData::Module(..) => {
|
||||||
|
if cgu_def_id.is_none() {
|
||||||
|
cgu_def_id = Some(current_def_id);
|
||||||
}
|
}
|
||||||
}).map(|part| part.data.as_interned_str());
|
}
|
||||||
|
DefPathData::CrateRoot { .. } => {
|
||||||
|
if cgu_def_id.is_none() {
|
||||||
|
// If we have not found a module yet, take the crate root.
|
||||||
|
cgu_def_id = Some(DefId {
|
||||||
|
krate: def_id.krate,
|
||||||
|
index: CRATE_DEF_INDEX,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// If we encounter something that is not a module, throw away
|
||||||
|
// any module that we've found so far because we now know that
|
||||||
|
// it is nested within something else.
|
||||||
|
cgu_def_id = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
current_def_id.index = def_key.parent.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let cgu_def_id = cgu_def_id.unwrap();
|
||||||
|
|
||||||
|
cache.entry((cgu_def_id, volatile)).or_insert_with(|| {
|
||||||
|
let def_path = tcx.def_path(cgu_def_id);
|
||||||
|
|
||||||
|
let components = def_path
|
||||||
|
.data
|
||||||
|
.iter()
|
||||||
|
.map(|part| part.data.as_interned_str());
|
||||||
|
|
||||||
let volatile_suffix = if volatile {
|
let volatile_suffix = if volatile {
|
||||||
Some("volatile")
|
Some("volatile")
|
||||||
|
@ -794,11 +841,14 @@ fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
CodegenUnit::build_cgu_name(tcx, def_path.krate, components, volatile_suffix)
|
name_builder.build_cgu_name(def_path.krate, components, volatile_suffix)
|
||||||
|
}).clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn numbered_codegen_unit_name(tcx: TyCtxt, index: usize) -> InternedString {
|
fn numbered_codegen_unit_name(name_builder: &mut CodegenUnitNameBuilder,
|
||||||
CodegenUnit::build_cgu_name_no_mangle(tcx, LOCAL_CRATE, &["cgu"], Some(index))
|
index: usize)
|
||||||
|
-> InternedString {
|
||||||
|
name_builder.build_cgu_name_no_mangle(LOCAL_CRATE, &["cgu"], Some(index))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
warning: Linking globals named 'foo': symbol multiply defined!
|
warning: Linking globals named 'foo': symbol multiply defined!
|
||||||
|
|
||||||
error: failed to load bc of "lto_duplicate_symbols10-8787f43e282added376259c1adb08b80.rs":
|
error: failed to load bc of "lto_duplicate_symbols1.3a1fbbbh-cgu.0":
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue