Skip to content

Commit

Permalink
Auto merge of #33473 - michaelwoerister:split-cratecontext, r=nikomat…
Browse files Browse the repository at this point in the history
…sakis

Preparatory refactorings for collector-driven trans.

This is a set of refactorings that allows to do translation item collection and partitioning before LocalCrateContext instances or LLVM modules are generated. As a consequence we can now create LocalCrateContexts already with knowledge of the codegen unit it will be used for. This is a preparation step for driving trans by the results of codegen unit partitioning.
  • Loading branch information
bors committed May 10, 2016
2 parents a4d2424 + 118cc9e commit 1939b76
Show file tree
Hide file tree
Showing 13 changed files with 541 additions and 495 deletions.
3 changes: 2 additions & 1 deletion src/librustc_trans/back/write.rs
Original file line number Diff line number Diff line change
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
91 changes: 49 additions & 42 deletions src/librustc_trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ use common::{node_id_type, fulfill_obligation};
use common::{type_is_immediate, type_is_zero_size, val_ty};
use common;
use consts;
use context::SharedCrateContext;
use context::{SharedCrateContext, CrateContextList};
use controlflow;
use datum;
use debuginfo::{self, DebugLoc, ToDebugLoc};
Expand All @@ -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 @@ -664,7 +664,7 @@ pub fn coerce_unsized_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
}
}

pub fn custom_coerce_unsize_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
pub fn custom_coerce_unsize_info<'scx, 'tcx>(scx: &SharedCrateContext<'scx, 'tcx>,
source_ty: Ty<'tcx>,
target_ty: Ty<'tcx>)
-> CustomCoerceUnsized {
Expand All @@ -674,13 +674,13 @@ pub fn custom_coerce_unsize_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
subst::VecPerParamSpace::empty());

let trait_ref = ty::Binder(ty::TraitRef {
def_id: ccx.tcx().lang_items.coerce_unsized_trait().unwrap(),
substs: ccx.tcx().mk_substs(trait_substs)
def_id: scx.tcx().lang_items.coerce_unsized_trait().unwrap(),
substs: scx.tcx().mk_substs(trait_substs)
});

match fulfill_obligation(ccx, DUMMY_SP, trait_ref) {
match fulfill_obligation(scx, DUMMY_SP, trait_ref) {
traits::VtableImpl(traits::VtableImplData { impl_def_id, .. }) => {
ccx.tcx().custom_coerce_unsized_kind(impl_def_id)
scx.tcx().custom_coerce_unsized_kind(impl_def_id)
}
vtable => {
bug!("invalid CoerceUnsized vtable: {:?}", vtable);
Expand Down Expand Up @@ -1824,7 +1824,7 @@ pub fn trans_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
closure_env: closure::ClosureEnv) {
ccx.stats().n_closures.set(ccx.stats().n_closures.get() + 1);

if collector::collecting_debug_information(ccx) {
if collector::collecting_debug_information(ccx.shared()) {
ccx.record_translation_item_as_generated(TransItem::Fn(instance));
}

Expand Down Expand Up @@ -2188,7 +2188,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 @@ -2524,7 +2525,7 @@ pub fn write_metadata<'a, 'tcx>(cx: &SharedCrateContext<'a, 'tcx>,

/// Find any symbols that are defined in one compilation unit, but not declared
/// in any other compilation unit. Give these symbols internal linkage.
fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<&str>) {
fn internalize_symbols(cx: &CrateContextList, reachable: &HashSet<&str>) {
unsafe {
let mut declared = HashSet::new();

Expand Down Expand Up @@ -2579,12 +2580,12 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<&str>) {
// when using MSVC linker. We do this only for data, as linker can fix up
// code references on its own.
// See #26591, #27438
fn create_imps(cx: &SharedCrateContext) {
fn create_imps(cx: &CrateContextList) {
// The x86 ABI seems to require that leading underscores are added to symbol
// names, so we need an extra underscore on 32-bit. There's also a leading
// '\x01' here which disables LLVM's symbol mangling (e.g. no extra
// underscores added in front).
let prefix = if cx.sess().target.target.target_pointer_width == "32" {
let prefix = if cx.shared().sess().target.target.target_pointer_width == "32" {
"\x01__imp__"
} else {
"\x01__imp_"
Expand Down Expand Up @@ -2661,10 +2662,10 @@ fn iter_functions(llmod: llvm::ModuleRef) -> ValueIter {
///
/// This list is later used by linkers to determine the set of symbols needed to
/// be exposed from a dynamic library and it's also encoded into the metadata.
pub fn filter_reachable_ids(ccx: &SharedCrateContext) -> NodeSet {
ccx.reachable().iter().map(|x| *x).filter(|id| {
pub fn filter_reachable_ids(scx: &SharedCrateContext) -> NodeSet {
scx.reachable().iter().map(|x| *x).filter(|id| {
// First, only worry about nodes which have a symbol name
ccx.item_symbols().borrow().contains_key(id)
scx.item_symbols().borrow().contains_key(id)
}).filter(|&id| {
// Next, we want to ignore some FFI functions that are not exposed from
// this crate. Reachable FFI functions can be lumped into two
Expand All @@ -2679,9 +2680,9 @@ pub fn filter_reachable_ids(ccx: &SharedCrateContext) -> NodeSet {
//
// As a result, if this id is an FFI item (foreign item) then we only
// let it through if it's included statically.
match ccx.tcx().map.get(id) {
match scx.tcx().map.get(id) {
hir_map::NodeForeignItem(..) => {
ccx.sess().cstore.is_statically_included_foreign_item(id)
scx.sess().cstore.is_statically_included_foreign_item(id)
}
_ => true,
}
Expand Down Expand Up @@ -2716,10 +2717,7 @@ pub fn trans_crate<'tcx>(tcx: &TyCtxt<'tcx>,

let link_meta = link::build_link_meta(&tcx, name);

let codegen_units = tcx.sess.opts.cg.codegen_units;
let shared_ccx = SharedCrateContext::new(&link_meta.crate_name,
codegen_units,
tcx,
let shared_ccx = SharedCrateContext::new(tcx,
&mir_map,
export_map,
Sha256::new(),
Expand All @@ -2728,9 +2726,15 @@ pub fn trans_crate<'tcx>(tcx: &TyCtxt<'tcx>,
check_overflow,
check_dropflag);

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 = shared_ccx.get_ccx(0);
collect_translation_items(&ccx);
let ccx = crate_context_list.get_ccx(0);

// Translate all items. See `TransModVisitor` for
// details on why we walk in this particular way.
Expand All @@ -2740,12 +2744,12 @@ pub fn trans_crate<'tcx>(tcx: &TyCtxt<'tcx>,
krate.visit_all_items(&mut TransModVisitor { ccx: &ccx });
}

collector::print_collection_results(&ccx);
collector::print_collection_results(ccx.shared());

symbol_names_test::report_symbol_names(&ccx);
}

for ccx in shared_ccx.iter() {
for ccx in crate_context_list.iter() {
if ccx.sess().opts.debuginfo != NoDebugInfo {
debuginfo::finalize(&ccx);
}
Expand Down Expand Up @@ -2794,7 +2798,7 @@ pub fn trans_crate<'tcx>(tcx: &TyCtxt<'tcx>,
}
}

let modules = shared_ccx.iter()
let modules = crate_context_list.iter()
.map(|ccx| ModuleTranslation { llcx: ccx.llcx(), llmod: ccx.llmod() })
.collect();

Expand All @@ -2820,14 +2824,14 @@ pub fn trans_crate<'tcx>(tcx: &TyCtxt<'tcx>,
}
}

if codegen_units > 1 {
internalize_symbols(&shared_ccx,
if codegen_unit_count > 1 {
internalize_symbols(&crate_context_list,
&reachable_symbols.iter().map(|x| &x[..]).collect());
}

if sess.target.target.options.is_like_msvc &&
sess.crate_types.borrow().iter().any(|ct| *ct == config::CrateTypeRlib) {
create_imps(&shared_ccx);
create_imps(&crate_context_list);
}

let metadata_module = ModuleTranslation {
Expand Down Expand Up @@ -2912,10 +2916,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 @@ -2926,7 +2931,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 @@ -2936,27 +2941,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, 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 @@ -2966,7 +2971,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);
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 @@ -3005,10 +3010,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
}
2 changes: 1 addition & 1 deletion src/librustc_trans/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ impl<'tcx> Callee<'tcx> {
let trait_id = method_item.container().id();
let trait_ref = ty::Binder(substs.to_trait_ref(tcx, trait_id));
let trait_ref = infer::normalize_associated_type(tcx, &trait_ref);
match common::fulfill_obligation(ccx, DUMMY_SP, trait_ref) {
match common::fulfill_obligation(ccx.shared(), DUMMY_SP, trait_ref) {
traits::VtableImpl(vtable_impl) => {
let impl_did = vtable_impl.impl_def_id;
let mname = tcx.item_name(def_id);
Expand Down
Loading

0 comments on commit 1939b76

Please sign in to comment.