From bebcb285ad187153a71296c42a02e4bb9c2297f5 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 6 May 2016 14:27:34 -0400 Subject: [PATCH] Restructure trans_crate() so that codegen unit partitioning happens before creating LocalCrateContexts. --- src/librustc_trans/back/write.rs | 3 ++- src/librustc_trans/base.rs | 43 +++++++++++++++++------------- src/librustc_trans/context.rs | 8 +++--- src/librustc_trans/partitioning.rs | 14 +++++++++- 4 files changed, 45 insertions(+), 23 deletions(-) diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 9f7a794185ad..cf81777be261 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -639,7 +639,8 @@ pub fn run_passes(sess: &Session, } // Sanity check - assert!(trans.modules.len() == sess.opts.cg.codegen_units); + assert!(trans.modules.len() == sess.opts.cg.codegen_units || + sess.opts.debugging_opts.incremental.is_some()); let tm = create_target_machine(sess); diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index c89a8a930f72..a8aff88dfc7c 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -81,7 +81,7 @@ use machine::{llalign_of_min, llsize_of, llsize_of_real}; use meth; use mir; use monomorphize::{self, Instance}; -use partitioning::{self, PartitioningStrategy, InstantiationMode}; +use partitioning::{self, PartitioningStrategy, InstantiationMode, CodegenUnit}; use symbol_names_test; use tvec; use type_::Type; @@ -2186,7 +2186,8 @@ pub fn update_linkage(ccx: &CrateContext, // `llval` is a translation of an item defined in a separate // compilation unit. This only makes sense if there are at least // two compilation units. - assert!(ccx.sess().opts.cg.codegen_units > 1); + assert!(ccx.sess().opts.cg.codegen_units > 1 || + ccx.sess().opts.debugging_opts.incremental.is_some()); // `llval` is a copy of something defined elsewhere, so use // `AvailableExternallyLinkage` to avoid duplicating code in the // output. @@ -2723,12 +2724,15 @@ pub fn trans_crate<'tcx>(tcx: &TyCtxt<'tcx>, check_overflow, check_dropflag); - let codegen_units = tcx.sess.opts.cg.codegen_units; + let codegen_units = collect_and_partition_translation_items(&shared_ccx); + let codegen_unit_count = codegen_units.len(); + assert!(tcx.sess.opts.cg.codegen_units == codegen_unit_count || + tcx.sess.opts.debugging_opts.incremental.is_some()); + let crate_context_list = CrateContextList::new(&shared_ccx, codegen_units); { let ccx = crate_context_list.get_ccx(0); - collect_translation_items(&ccx); // Translate all items. See `TransModVisitor` for // details on why we walk in this particular way. @@ -2818,7 +2822,7 @@ pub fn trans_crate<'tcx>(tcx: &TyCtxt<'tcx>, } } - if codegen_units > 1 { + if codegen_unit_count > 1 { internalize_symbols(&crate_context_list, &reachable_symbols.iter().map(|x| &x[..]).collect()); } @@ -2910,10 +2914,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TransItemsWithinModVisitor<'a, 'tcx> { } } -fn collect_translation_items<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>) { - let time_passes = ccx.sess().time_passes(); +fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>) + -> Vec> { + let time_passes = scx.sess().time_passes(); - let collection_mode = match ccx.sess().opts.debugging_opts.print_trans_items { + let collection_mode = match scx.sess().opts.debugging_opts.print_trans_items { Some(ref s) => { let mode_string = s.to_lowercase(); let mode_string = mode_string.trim(); @@ -2924,7 +2929,7 @@ fn collect_translation_items<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>) { let message = format!("Unknown codegen-item collection mode '{}'. \ Falling back to 'lazy' mode.", mode_string); - ccx.sess().warn(&message); + scx.sess().warn(&message); } TransItemCollectionMode::Lazy @@ -2934,27 +2939,27 @@ fn collect_translation_items<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>) { }; let (items, reference_map) = time(time_passes, "translation item collection", || { - collector::collect_crate_translation_items(ccx.shared(), collection_mode) + collector::collect_crate_translation_items(scx, collection_mode) }); - let strategy = if ccx.sess().opts.debugging_opts.incremental.is_some() { + let strategy = if scx.sess().opts.debugging_opts.incremental.is_some() { PartitioningStrategy::PerModule } else { - PartitioningStrategy::FixedUnitCount(ccx.sess().opts.cg.codegen_units) + PartitioningStrategy::FixedUnitCount(scx.sess().opts.cg.codegen_units) }; let codegen_units = time(time_passes, "codegen unit partitioning", || { - partitioning::partition(ccx.tcx(), + partitioning::partition(scx.tcx(), items.iter().cloned(), strategy, &reference_map) }); - if ccx.sess().opts.debugging_opts.print_trans_items.is_some() { + if scx.sess().opts.debugging_opts.print_trans_items.is_some() { let mut item_to_cgus = HashMap::new(); - for cgu in codegen_units { - for (trans_item, linkage) in cgu.items { + for cgu in &codegen_units { + for (&trans_item, &linkage) in &cgu.items { item_to_cgus.entry(trans_item) .or_insert(Vec::new()) .push((cgu.name.clone(), linkage)); @@ -2964,7 +2969,7 @@ fn collect_translation_items<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>) { let mut item_keys: Vec<_> = items .iter() .map(|i| { - let mut output = i.to_string(ccx.tcx()); + let mut output = i.to_string(scx.tcx()); output.push_str(" @@"); let mut empty = Vec::new(); let mut cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty); @@ -3003,10 +3008,12 @@ fn collect_translation_items<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>) { println!("TRANS_ITEM {}", item); } - let mut ccx_map = ccx.translation_items().borrow_mut(); + let mut ccx_map = scx.translation_items().borrow_mut(); for cgi in items { ccx_map.insert(cgi, TransItemState::PredictedButNotGenerated); } } + + codegen_units } diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 323bc338245d..9f5fe28ee821 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -28,6 +28,7 @@ use mir::CachedMir; use monomorphize::Instance; use collector::{TransItem, TransItemState}; +use partitioning::CodegenUnit; use type_::{Type, TypeNames}; use rustc::ty::subst::{Substs, VecPerParamSpace}; use rustc::ty::{self, Ty, TyCtxt}; @@ -196,11 +197,12 @@ pub struct CrateContextList<'a, 'tcx: 'a> { impl<'a, 'tcx: 'a> CrateContextList<'a, 'tcx> { pub fn new(shared_ccx: &'a SharedCrateContext<'a, 'tcx>, - local_count: usize) + codegen_units: Vec>) -> CrateContextList<'a, 'tcx> { CrateContextList { shared: shared_ccx, - local_ccxs: (0..local_count).map(|index| { + // FIXME: We don't actually use the codegen unit partitioning yet. + local_ccxs: codegen_units.iter().map(|cgu| { // Append ".rs" to crate name as LLVM module identifier. // // LLVM code generator emits a ".file filename" directive @@ -209,7 +211,7 @@ impl<'a, 'tcx: 'a> CrateContextList<'a, 'tcx> { // 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", shared_ccx.link_meta.crate_name, index); + let llmod_id = format!("{}.rs", cgu.name); LocalCrateContext::new(shared_ccx, &llmod_id[..]) }).collect() } diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index 250292ee684d..6e50292a91a5 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -182,7 +182,19 @@ pub fn partition<'tcx, I>(tcx: &TyCtxt<'tcx>, // easily determine which declarations need to be placed within each one. let post_declarations = place_declarations(post_inlining, reference_map); - post_declarations.0 + let mut final_partitioning = post_declarations.0; + + if final_partitioning.len() == 0 { + // Some crates don't contain anything that will result in a translation + // item. We still want to have at least one (empty) codegen unit in that + // case. + final_partitioning.push(CodegenUnit { + name: token::intern_and_get_ident(&format!("{}.0", tcx.crate_name)[..]), + items: FnvHashMap() + }); + } + + final_partitioning } struct PreInliningPartitioning<'tcx> {