Skip to content

Commit

Permalink
Restructure trans_crate() so that codegen unit partitioning happens b…
Browse files Browse the repository at this point in the history
…efore creating LocalCrateContexts.
  • Loading branch information
michaelwoerister committed May 9, 2016
1 parent bb8c8c5 commit bebcb28
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 23 deletions.
3 changes: 2 additions & 1 deletion src/librustc_trans/back/write.rs
Expand Up @@ -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);

Expand Down
43 changes: 25 additions & 18 deletions src/librustc_trans/base.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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());
}
Expand Down Expand Up @@ -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<CodegenUnit<'tcx>> {
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();
Expand All @@ -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
Expand All @@ -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));
Expand All @@ -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);
Expand Down Expand Up @@ -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
}
8 changes: 5 additions & 3 deletions src/librustc_trans/context.rs
Expand Up @@ -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};
Expand Down Expand Up @@ -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<CodegenUnit<'tcx>>)
-> 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
Expand All @@ -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()
}
Expand Down
14 changes: 13 additions & 1 deletion src/librustc_trans/partitioning.rs
Expand Up @@ -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> {
Expand Down

0 comments on commit bebcb28

Please sign in to comment.