diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs index f0d6b8170eb64..9d2f62bd03046 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)] @@ -239,3 +240,95 @@ impl Stats { self.fn_stats.extend(stats.fn_stats); } } + +pub struct CodegenUnitNameBuilder<'a, 'gcx: 'tcx, 'tcx: 'a> { + tcx: TyCtxt<'a, 'gcx, 'tcx>, + cache: FxHashMap, +} + +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: + /// + /// ``` + /// .(-)*[.] + /// ``` + /// + /// The '.' before `` 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(&mut self, + cnum: CrateNum, + components: I, + special_suffix: Option) + -> InternedString + where I: IntoIterator, + 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(&mut self, + cnum: CrateNum, + components: I, + special_suffix: Option) + -> InternedString + where I: IntoIterator, + 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() + } +} diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index f474f21430544..3dc697e6adb5b 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -24,6 +24,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; @@ -48,6 +49,7 @@ use std; use std::cell::{self, Cell, RefCell}; use std::collections::HashMap; use std::env; +use std::fmt; use std::io::Write; use std::path::{Path, PathBuf}; use std::time::Duration; @@ -1221,6 +1223,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 for CrateDisambiguator { fn from(fingerprint: Fingerprint) -> CrateDisambiguator { CrateDisambiguator(fingerprint) diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs index bbe1ccf3696f4..37c99932f565c 100644 --- a/src/librustc_codegen_llvm/back/link.rs +++ b/src/librustc_codegen_llvm/back/link.rs @@ -46,13 +46,6 @@ use std::process::{Output, Stdio}; use std::str; 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, invalid_output_for_target, build_link_meta, out_filename, check_file_is_writeable}; diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index d7741230327bb..56858a31efd25 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -242,7 +242,7 @@ fn fat_lto(cgcx: &CodegenContext, let llvm = module.llvm().expect("can't lto pre-codegened modules"); (&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 // 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 { let llvm = module.llvm().expect("can't lto pre-codegened modules"); 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)); } @@ -384,9 +384,9 @@ fn thin_lto(diag_handler: &Handler, // the most expensive portion of this small bit of global // analysis! 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 name = CString::new(module.llmod_id.clone()).unwrap(); + let name = CString::new(module.name.clone()).unwrap(); let buffer = ThinBuffer::new(llvm.llmod()); thin_modules.push(llvm::ThinLTOModule { identifier: name.as_ptr(), @@ -395,7 +395,7 @@ fn thin_lto(diag_handler: &Handler, }); thin_buffers.push(buffer); module_names.push(name); - timeline.record(&module.llmod_id); + timeline.record(&module.name); } // FIXME: All upstream crates are deserialized internally in the @@ -668,7 +668,6 @@ impl ThinModule { llcx, tm, }), - llmod_id: self.name().to_string(), name: self.name().to_string(), kind: ModuleKind::Regular, }; diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index d60983d7697b7..b62836ec255d4 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -728,7 +728,7 @@ unsafe fn codegen(cgcx: &CodegenContext, if config.emit_bc_compressed { 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) { 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); Ok(WorkItemResult::Compiled(CompiledModule { - llmod_id: module.llmod_id.clone(), name: module_name, kind: ModuleKind::Regular, pre_existing: true, diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 7ca6a89dd9b57..e626cc3870fe9 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -36,7 +36,7 @@ use metadata; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::middle::lang_items::StartFnLangItem; 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::ty::{self, Ty, TyCtxt}; 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 link_meta = link::build_link_meta(crate_hash); + let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx); // Codegen the metadata. 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", || { write_metadata(tcx, &metadata_llvm_module, &link_meta) }); tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen)); let metadata_module = ModuleCodegen { - name: link::METADATA_MODULE_NAME.to_string(), - llmod_id: llmod_id.to_string(), + name: metadata_cgu_name, source: ModuleSource::Codegened(metadata_llvm_module), 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 { None } else if let Some(kind) = *tcx.sess.allocator_kind.get() { - unsafe { - let llmod_id = "allocator"; - let modules = ModuleLlvm::new(tcx.sess, llmod_id); - time(tcx.sess, "write allocator module", || { + let llmod_id = cgu_name_builder.build_cgu_name(LOCAL_CRATE, + &["crate"], + Some("allocator")).as_str() + .to_string(); + let modules = ModuleLlvm::new(tcx.sess, &llmod_id); + time(tcx.sess, "write allocator module", || { + unsafe { allocator::codegen(tcx, &modules, kind) - }); + } + }); - Some(ModuleCodegen { - name: link::ALLOCATOR_MODULE_NAME.to_string(), - llmod_id: llmod_id.to_string(), - source: ModuleSource::Codegened(modules), - kind: ModuleKind::Allocator, - }) - } + Some(ModuleCodegen { + name: llmod_id, + source: ModuleSource::Codegened(modules), + kind: ModuleKind::Allocator, + }) } else { 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 // and we can safely re-use. 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 { name: cgu.name().to_string(), source: ModuleSource::Preexisting(buf), kind: ModuleKind::Regular, - llmod_id, }; tcx.dep_graph.mark_loaded_from_cache(dep_node_index, true); 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(); - // 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... - let llvm_module = ModuleLlvm::new(tcx.sess, &llmod_id); + let llvm_module = ModuleLlvm::new(tcx.sess, &cgu_name); let stats = { let cx = CodegenCx::new(tcx, cgu, &llvm_module); let mono_items = cx.codegen_unit @@ -1282,7 +1264,6 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, name: cgu_name, source: ModuleSource::Codegened(llvm_module), kind: ModuleKind::Regular, - llmod_id, }) } } diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 390a1df02b88e..a65511a24af72 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -269,8 +269,8 @@ struct ModuleCodegen { /// unique amongst **all** crates. Therefore, it should contain /// something unique to this crate (e.g., a module path) as well /// as the crate name and disambiguator. + /// We currently generate these names via CodegenUnit::build_cgu_name(). name: String, - llmod_id: String, source: ModuleSource, kind: ModuleKind, } @@ -317,7 +317,6 @@ impl ModuleCodegen { }; CompiledModule { - llmod_id: self.llmod_id, name: self.name.clone(), kind: self.kind, pre_existing, @@ -331,7 +330,6 @@ impl ModuleCodegen { #[derive(Debug)] struct CompiledModule { name: String, - llmod_id: String, kind: ModuleKind, pre_existing: bool, object: Option, diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs index df8e0f056afc9..9b8e2c450d5f8 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::mir::mono::CodegenUnitNameBuilder; 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::>(); + + // Remove the crate name + assert_eq!(cgu_path_components.remove(0), crate_name); + + let cgu_name_builder = &mut CodegenUnitNameBuilder::new(self.tcx); + let cgu_name = cgu_name_builder.build_cgu_name(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::>() + .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 4e32ca483a125..73d5d1d0948bf 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -105,9 +105,9 @@ use monomorphize::collector::InliningMap; use rustc::dep_graph::WorkProductId; use rustc::hir::CodegenFnAttrFlags; -use rustc::hir::def_id::DefId; +use rustc::hir::def_id::{DefId, LOCAL_CRATE, CRATE_DEF_INDEX}; 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::ty::{self, TyCtxt, InstanceDef}; use rustc::ty::item_path::characteristic_def_id_of_type; @@ -115,7 +115,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}; @@ -203,17 +203,10 @@ 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() - } +fn fallback_cgu_name(name_builder: &mut CodegenUnitNameBuilder) -> InternedString { + name_builder.build_cgu_name(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()); } @@ -308,6 +300,9 @@ fn place_root_mono_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let export_generics = tcx.sess.opts.share_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 { match mono_item.instantiation_mode(tcx) { InstantiationMode::GloballyShared { .. } => {} @@ -319,8 +314,12 @@ fn place_root_mono_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mono_item.is_generic_fn(); let codegen_unit_name = match characteristic_def_id { - Some(def_id) => compute_codegen_unit_name(tcx, def_id, is_volatile), - None => fallback_cgu_name(tcx), + Some(def_id) => compute_codegen_unit_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()) @@ -344,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 // crate with just types (for example), we could wind up with no CGU 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(), CodegenUnit::new(codegen_unit_name.clone())); } @@ -552,9 +551,9 @@ fn default_visibility(tcx: TyCtxt, id: DefId, is_generic: bool) -> Visibility { } } -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; @@ -582,14 +581,15 @@ fn merge_codegen_units<'tcx>(initial_partitioning: &mut PreInliningPartitioning< } } + let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx); 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(cgu_name_builder, index)); } } fn place_inlined_mono_items<'tcx>(initial_partitioning: PreInliningPartitioning<'tcx>, - inlining_map: &InliningMap<'tcx>) - -> PostInliningPartitioning<'tcx> { + inlining_map: &InliningMap<'tcx>) + -> PostInliningPartitioning<'tcx> { let mut new_partitioning = Vec::new(); let mut mono_item_placements = FxHashMap(); @@ -783,46 +783,72 @@ 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>, - 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()); - } +type CguNameCache = FxHashMap<(DefId, bool), InternedString>; + +fn compute_codegen_unit_name(tcx: TyCtxt, + name_builder: &mut CodegenUnitNameBuilder, + def_id: DefId, + 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); + } + } + 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; + } + } - if volatile { - cgu_name.push_str(".volatile"); + current_def_id.index = def_key.parent.unwrap(); } - let cgu_name = if tcx.sess.opts.debugging_opts.human_readable_cgu_names { - cgu_name - } else { - CodegenUnit::mangle_name(&cgu_name) - }; + 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 { + Some("volatile") + } else { + None + }; - Symbol::intern(&cgu_name[..]).as_interned_str() + name_builder.build_cgu_name(def_path.krate, components, volatile_suffix) + }).clone() } -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(name_builder: &mut CodegenUnitNameBuilder, + 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>, diff --git a/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs index 49e4b8d43c19c..cec88f1c6a245 100644 --- a/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs +++ b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs @@ -14,7 +14,7 @@ #![feature(start)] -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ drop_in_place_intrinsic0[Internal] +//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ drop_in_place_intrinsic-cgu.0[Internal] struct StructWithDtor(u32); impl Drop for StructWithDtor { @@ -26,7 +26,7 @@ impl Drop for StructWithDtor { #[start] fn start(_: isize, _: *const *const u8) -> isize { - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]; 2]> @@ drop_in_place_intrinsic0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]; 2]> @@ drop_in_place_intrinsic-cgu.0[Internal] let x = [StructWithDtor(0), StructWithDtor(1)]; drop_slice_in_place(&x); @@ -40,7 +40,7 @@ fn drop_slice_in_place(x: &[StructWithDtor]) { // This is the interesting thing in this test case: Normally we would // not have drop-glue for the unsized [StructWithDtor]. This has to be // generated though when the drop_in_place() intrinsic is used. - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]]> @@ drop_in_place_intrinsic0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]]> @@ drop_in_place_intrinsic-cgu.0[Internal] ::std::ptr::drop_in_place(x as *const _ as *mut [StructWithDtor]); } } diff --git a/src/test/codegen-units/item-collection/generic-drop-glue.rs b/src/test/codegen-units/item-collection/generic-drop-glue.rs index aad32d1eb7c06..5afa519bc5902 100644 --- a/src/test/codegen-units/item-collection/generic-drop-glue.rs +++ b/src/test/codegen-units/item-collection/generic-drop-glue.rs @@ -47,7 +47,7 @@ enum EnumNoDrop { struct NonGenericNoDrop(i32); struct NonGenericWithDrop(i32); -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ generic_drop_glue0[Internal] +//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ generic_drop_glue-cgu.0[Internal] impl Drop for NonGenericWithDrop { //~ MONO_ITEM fn generic_drop_glue::{{impl}}[2]::drop[0] @@ -57,11 +57,11 @@ impl Drop for NonGenericWithDrop { //~ MONO_ITEM fn generic_drop_glue::start[0] #[start] fn start(_: isize, _: *const *const u8) -> isize { - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn generic_drop_glue::{{impl}}[0]::drop[0] let _ = StructWithDrop { x: 0i8, y: 'a' }.x; - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn generic_drop_glue::{{impl}}[0]::drop[0]<&str, generic_drop_glue::NonGenericNoDrop[0]> let _ = StructWithDrop { x: "&str", y: NonGenericNoDrop(0) }.y; @@ -70,17 +70,17 @@ fn start(_: isize, _: *const *const u8) -> isize { // This is supposed to generate drop-glue because it contains a field that // needs to be dropped. - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue-cgu.0[Internal] let _ = StructNoDrop { x: NonGenericWithDrop(0), y: 0f64 }.y; - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn generic_drop_glue::{{impl}}[1]::drop[0] let _ = match EnumWithDrop::A::(0) { EnumWithDrop::A(x) => x, EnumWithDrop::B(x) => x as i32 }; - //~MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue0[Internal] + //~MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ generic_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn generic_drop_glue::{{impl}}[1]::drop[0] let _ = match EnumWithDrop::B::(1.0) { EnumWithDrop::A(x) => x, diff --git a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs index 5c6201da252be..d09d343a8458e 100644 --- a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs +++ b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs @@ -34,13 +34,13 @@ impl Trait for Struct { fn start(_: isize, _: *const *const u8) -> isize { let s1 = Struct { _a: 0u32 }; - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ instantiation_through_vtable0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ instantiation_through_vtable-cgu.0[Internal] //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::foo[0] //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::bar[0] let _ = &s1 as &Trait; let s1 = Struct { _a: 0u64 }; - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ instantiation_through_vtable0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ instantiation_through_vtable-cgu.0[Internal] //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::foo[0] //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::bar[0] let _ = &s1 as &Trait; diff --git a/src/test/codegen-units/item-collection/non-generic-drop-glue.rs b/src/test/codegen-units/item-collection/non-generic-drop-glue.rs index 6ca24aa5b4b89..a939dd56cda5b 100644 --- a/src/test/codegen-units/item-collection/non-generic-drop-glue.rs +++ b/src/test/codegen-units/item-collection/non-generic-drop-glue.rs @@ -15,7 +15,7 @@ #![deny(dead_code)] #![feature(start)] -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ non_generic_drop_glue0[Internal] +//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ non_generic_drop_glue-cgu.0[Internal] struct StructWithDrop { x: i32 } @@ -29,7 +29,7 @@ struct StructNoDrop { x: i32 } -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ non_generic_drop_glue0[Internal] +//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ non_generic_drop_glue-cgu.0[Internal] enum EnumWithDrop { A(i32) } diff --git a/src/test/codegen-units/item-collection/transitive-drop-glue.rs b/src/test/codegen-units/item-collection/transitive-drop-glue.rs index d20213c109bdb..7bbc9b6d0fbc9 100644 --- a/src/test/codegen-units/item-collection/transitive-drop-glue.rs +++ b/src/test/codegen-units/item-collection/transitive-drop-glue.rs @@ -15,11 +15,11 @@ #![deny(dead_code)] #![feature(start)] -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ transitive_drop_glue0[Internal] +//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ transitive_drop_glue-cgu.0[Internal] struct Root(Intermediate); -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ transitive_drop_glue0[Internal] +//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ transitive_drop_glue-cgu.0[Internal] struct Intermediate(Leaf); -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ transitive_drop_glue0[Internal] +//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ transitive_drop_glue-cgu.0[Internal] struct Leaf; impl Drop for Leaf { @@ -40,15 +40,15 @@ impl Drop for LeafGen { fn start(_: isize, _: *const *const u8) -> isize { let _ = Root(Intermediate(Leaf)); - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue0[Internal] - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue0[Internal] - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn transitive_drop_glue::{{impl}}[1]::drop[0] let _ = RootGen(IntermediateGen(LeafGen(0u32))); - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue0[Internal] - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue0[Internal] - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]> @@ transitive_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn transitive_drop_glue::{{impl}}[1]::drop[0] let _ = RootGen(IntermediateGen(LeafGen(0i16))); diff --git a/src/test/codegen-units/item-collection/tuple-drop-glue.rs b/src/test/codegen-units/item-collection/tuple-drop-glue.rs index 9e4cc6ea6f08e..865570ccfa55a 100644 --- a/src/test/codegen-units/item-collection/tuple-drop-glue.rs +++ b/src/test/codegen-units/item-collection/tuple-drop-glue.rs @@ -15,7 +15,7 @@ #![deny(dead_code)] #![feature(start)] -//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ tuple_drop_glue0[Internal] +//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ tuple_drop_glue-cgu.0[Internal] struct Dropped; impl Drop for Dropped { @@ -26,11 +26,11 @@ impl Drop for Dropped { //~ MONO_ITEM fn tuple_drop_glue::start[0] #[start] fn start(_: isize, _: *const *const u8) -> isize { - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, tuple_drop_glue::Dropped[0])> @@ tuple_drop_glue0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, tuple_drop_glue::Dropped[0])> @@ tuple_drop_glue-cgu.0[Internal] let x = (0u32, Dropped); - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(i16, (tuple_drop_glue::Dropped[0], bool))> @@ tuple_drop_glue0[Internal] - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(tuple_drop_glue::Dropped[0], bool)> @@ tuple_drop_glue0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(i16, (tuple_drop_glue::Dropped[0], bool))> @@ tuple_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(tuple_drop_glue::Dropped[0], bool)> @@ tuple_drop_glue-cgu.0[Internal] let x = (0i16, (Dropped, true)); 0 diff --git a/src/test/codegen-units/item-collection/unsizing.rs b/src/test/codegen-units/item-collection/unsizing.rs index adc0eb6c70915..5e9a3258c7adf 100644 --- a/src/test/codegen-units/item-collection/unsizing.rs +++ b/src/test/codegen-units/item-collection/unsizing.rs @@ -59,13 +59,13 @@ impl, U: ?Sized> CoerceUnsized> for Wrapper fn start(_: isize, _: *const *const u8) -> isize { // simple case let bool_sized = &true; - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ unsizing0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ unsizing-cgu.0[Internal] //~ MONO_ITEM fn unsizing::{{impl}}[0]::foo[0] let _bool_unsized = bool_sized as &Trait; let char_sized = &'a'; - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ unsizing0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ unsizing-cgu.0[Internal] //~ MONO_ITEM fn unsizing::{{impl}}[1]::foo[0] let _char_unsized = char_sized as &Trait; @@ -75,13 +75,13 @@ fn start(_: isize, _: *const *const u8) -> isize { _b: 2, _c: 3.0f64 }; - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ unsizing0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ unsizing-cgu.0[Internal] //~ MONO_ITEM fn unsizing::{{impl}}[2]::foo[0] let _struct_unsized = struct_sized as &Struct; // custom coercion let wrapper_sized = Wrapper(&0u32); - //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ unsizing0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0] @@ unsizing-cgu.0[Internal] //~ MONO_ITEM fn unsizing::{{impl}}[3]::foo[0] let _wrapper_sized = wrapper_sized as Wrapper; diff --git a/src/test/incremental/issue-39828/auxiliary/generic.rs b/src/test/incremental/issue-39828/auxiliary/generic.rs index a562eab1768f3..5491827af8a35 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"] diff --git a/src/test/run-make-fulldeps/cross-lang-lto/Makefile b/src/test/run-make-fulldeps/cross-lang-lto/Makefile index 6d06fade35296..1d072e03de307 100644 --- a/src/test/run-make-fulldeps/cross-lang-lto/Makefile +++ b/src/test/run-make-fulldeps/cross-lang-lto/Makefile @@ -16,22 +16,22 @@ all: staticlib staticlib-fat-lto staticlib-thin-lto rlib exe cdylib rdylib staticlib: lib.rs $(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib.a $(call EXTRACT_OBJS, liblib.a) - $(ASSERT_IS_BITCODE_OBJ) $(TMPDIR)/liblib.lib0.rcgu.o + for file in $(TMPDIR)/liblib.*.rcgu.o; do $(ASSERT_IS_BITCODE_OBJ) $$file; done staticlib-fat-lto: lib.rs $(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib-fat-lto.a -Clto=fat $(call EXTRACT_OBJS, liblib-fat-lto.a) - $(ASSERT_IS_BITCODE_OBJ) $(TMPDIR)/liblib-fat-lto.lib0.rcgu.o + for file in $(TMPDIR)/liblib-fat-lto.*.rcgu.o; do $(ASSERT_IS_BITCODE_OBJ) $$file; done staticlib-thin-lto: lib.rs $(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib-thin-lto.a -Clto=thin $(call EXTRACT_OBJS, liblib-thin-lto.a) - $(ASSERT_IS_BITCODE_OBJ) $(TMPDIR)/liblib-thin-lto.lib0.rcgu.o + for file in $(TMPDIR)/liblib-thin-lto.*.rcgu.o; do $(ASSERT_IS_BITCODE_OBJ) $$file; done rlib: lib.rs $(BUILD_LIB) --crate-type=rlib -o $(TMPDIR)/liblib.rlib $(call EXTRACT_OBJS, liblib.rlib) - $(ASSERT_IS_BITCODE_OBJ) $(TMPDIR)/liblib.lib0.rcgu.o + for file in $(TMPDIR)/liblib.*.rcgu.o; do $(ASSERT_IS_BITCODE_OBJ) $$file; done cdylib: lib.rs $(BUILD_LIB) --crate-type=cdylib --emit=obj -o $(TMPDIR)/cdylib.o diff --git a/src/test/run-make-fulldeps/extra-filename-with-temp-outputs/Makefile b/src/test/run-make-fulldeps/extra-filename-with-temp-outputs/Makefile index 6de4f97df0c16..e46390a9d0cd7 100644 --- a/src/test/run-make-fulldeps/extra-filename-with-temp-outputs/Makefile +++ b/src/test/run-make-fulldeps/extra-filename-with-temp-outputs/Makefile @@ -2,5 +2,5 @@ all: $(RUSTC) -C extra-filename=bar foo.rs -C save-temps - rm $(TMPDIR)/foobar.foo0.rcgu.o + rm $(TMPDIR)/foobar.foo*0.rcgu.o rm $(TMPDIR)/$(call BIN,foobar) diff --git a/src/test/ui/lto-duplicate-symbols.stderr b/src/test/ui/lto-duplicate-symbols.stderr index 2f0e57199bbc2..5760cb9a8fdb6 100644 --- a/src/test/ui/lto-duplicate-symbols.stderr +++ b/src/test/ui/lto-duplicate-symbols.stderr @@ -1,6 +1,6 @@ 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 diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 4b246ab674522..b136173082600 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2209,12 +2209,12 @@ impl<'test> TestCx<'test> { .stdout .lines() .filter(|line| line.starts_with(PREFIX)) - .map(str_to_mono_item) + .map(|line| str_to_mono_item(line, true)) .collect(); let expected: Vec = errors::load_errors(&self.testpaths.file, None) .iter() - .map(|e| str_to_mono_item(&e.msg[..])) + .map(|e| str_to_mono_item(&e.msg[..], false)) .collect(); let mut missing = Vec::new(); @@ -2299,14 +2299,14 @@ impl<'test> TestCx<'test> { } // [MONO_ITEM] name [@@ (cgu)+] - fn str_to_mono_item(s: &str) -> MonoItem { + fn str_to_mono_item(s: &str, cgu_has_crate_disambiguator: bool) -> MonoItem { let s = if s.starts_with(PREFIX) { (&s[PREFIX.len()..]).trim() } else { s.trim() }; - let full_string = format!("{}{}", PREFIX, s.trim().to_owned()); + let full_string = format!("{}{}", PREFIX, s); let parts: Vec<&str> = s .split(CGU_MARKER) @@ -2323,7 +2323,13 @@ impl<'test> TestCx<'test> { .split(' ') .map(str::trim) .filter(|s| !s.is_empty()) - .map(str::to_owned) + .map(|s| { + if cgu_has_crate_disambiguator { + remove_crate_disambiguator_from_cgu(s) + } else { + s.to_string() + } + }) .collect() } else { HashSet::new() @@ -2348,6 +2354,23 @@ impl<'test> TestCx<'test> { string } + + fn remove_crate_disambiguator_from_cgu(cgu: &str) -> String { + // The first '.' is the start of the crate disambiguator + let disambiguator_start = cgu.find('.') + .expect("Could not find start of crate disambiguator in CGU spec"); + + // The first non-alphanumeric character is the end of the disambiguator + let disambiguator_end = cgu[disambiguator_start + 1 ..] + .find(|c| !char::is_alphanumeric(c)) + .expect("Could not find end of crate disambiguator in CGU spec") + + disambiguator_start + 1; + + let mut result = cgu[0 .. disambiguator_start].to_string(); + result.push_str(&cgu[disambiguator_end ..]); + + result + } } fn init_incremental_test(&self) {