use middle::lang_items::StartFnLangItem;
use middle::cstore::EncodedMetadata;
use rustc::ty::{self, Ty, TyCtxt};
-use rustc::dep_graph::{AssertDepGraphSafe, DepNode, WorkProduct};
+use rustc::dep_graph::{AssertDepGraphSafe, DepNode};
use rustc::hir::map as hir_map;
use rustc::util::common::time;
use session::config::{self, NoDebugInfo};
use common::{type_is_zero_size, val_ty};
use common;
use consts;
-use context::{self, SharedCrateContext, CrateContextList};
+use context::{self, LocalCrateContext, SharedCrateContext};
use debuginfo;
use declare;
use machine;
let symbol_map = Rc::new(symbol_map);
- let previous_work_products = trans_reuse_previous_work_products(&shared_ccx,
- &codegen_units,
- &symbol_map);
-
- let crate_context_list = CrateContextList::new(&shared_ccx,
- codegen_units,
- previous_work_products,
- symbol_map.clone());
-
- let modules: Vec<ModuleTranslation> = crate_context_list
- .iter_all()
- .map(|ccx| {
- let dep_node = ccx.codegen_unit().work_product_dep_node();
+ let modules: Vec<ModuleTranslation> = codegen_units
+ .into_iter()
+ .map(|cgu| {
+ let dep_node = cgu.work_product_dep_node();
tcx.dep_graph.with_task(dep_node,
- ccx,
- AssertDepGraphSafe(symbol_map.clone()),
+ AssertDepGraphSafe(&shared_ccx),
+ AssertDepGraphSafe((cgu, symbol_map.clone())),
module_translation)
})
.collect();
- fn module_translation<'a, 'tcx>(ccx: CrateContext<'a, 'tcx>,
- symbol_map: AssertDepGraphSafe<Rc<SymbolMap<'tcx>>>)
- -> ModuleTranslation {
- // FIXME(#40304): Instead of this, the symbol-map should be an
- // on-demand thing that we compute.
- let AssertDepGraphSafe(symbol_map) = symbol_map;
+ fn module_translation<'a, 'tcx>(
+ scx: AssertDepGraphSafe<&SharedCrateContext<'a, 'tcx>>,
+ args: AssertDepGraphSafe<(CodegenUnit<'tcx>, Rc<SymbolMap<'tcx>>)>)
+ -> ModuleTranslation
+ {
+ // FIXME(#40304): We ought to be using the id as a key and some queries, I think.
+ let AssertDepGraphSafe(scx) = scx;
+ let AssertDepGraphSafe((cgu, symbol_map)) = args;
+
+ let cgu_name = String::from(cgu.name());
+ let cgu_id = cgu.work_product_id();
+ let symbol_name_hash = cgu.compute_symbol_name_hash(scx, &symbol_map);
+
+ // Check whether there is a previous work-product we can
+ // re-use. Not only must the file exist, and the inputs not
+ // be dirty, but the hash of the symbols we will generate must
+ // be the same.
+ let previous_work_product =
+ scx.dep_graph().previous_work_product(&cgu_id).and_then(|work_product| {
+ if work_product.input_hash == symbol_name_hash {
+ debug!("trans_reuse_previous_work_products: reusing {:?}", work_product);
+ Some(work_product)
+ } else {
+ if scx.sess().opts.debugging_opts.incremental_info {
+ println!("incremental: CGU `{}` invalidated because of \
+ changed partitioning hash.",
+ cgu.name());
+ }
+ debug!("trans_reuse_previous_work_products: \
+ not reusing {:?} because hash changed to {:?}",
+ work_product, symbol_name_hash);
+ None
+ }
+ });
- let source = if let Some(buf) = ccx.previous_work_product() {
+ let source = if let Some(buf) = previous_work_product {
// Don't need to translate this module.
ModuleSource::Preexisting(buf.clone())
} else {
// Instantiate translation items without filling out definitions yet...
-
- let cgu = ccx.codegen_unit();
- let trans_items = cgu.items_in_deterministic_order(ccx.tcx(), &symbol_map);
+ let lcx = LocalCrateContext::new(scx, cgu, symbol_map.clone());
+ let ccx = CrateContext::new(scx, &lcx);
+ let trans_items = ccx.codegen_unit()
+ .items_in_deterministic_order(ccx.tcx(), &symbol_map);
for &(trans_item, linkage) in &trans_items {
trans_item.predefine(&ccx, linkage);
}
};
ModuleTranslation {
- name: String::from(ccx.codegen_unit().name()),
- symbol_name_hash: ccx.codegen_unit()
- .compute_symbol_name_hash(ccx.shared(),
- &symbol_map),
- source: source,
+ name: cgu_name,
+ symbol_name_hash,
+ source,
}
}
}
}
-/// For each CGU, identify if we can reuse an existing object file (or
-/// maybe other context).
-fn trans_reuse_previous_work_products(scx: &SharedCrateContext,
- codegen_units: &[CodegenUnit],
- symbol_map: &SymbolMap)
- -> Vec<Option<WorkProduct>> {
- debug!("trans_reuse_previous_work_products()");
- codegen_units
- .iter()
- .map(|cgu| {
- let id = cgu.work_product_id();
-
- let hash = cgu.compute_symbol_name_hash(scx, symbol_map);
-
- debug!("trans_reuse_previous_work_products: id={:?} hash={}", id, hash);
-
- if let Some(work_product) = scx.dep_graph().previous_work_product(&id) {
- if work_product.input_hash == hash {
- debug!("trans_reuse_previous_work_products: reusing {:?}", work_product);
- return Some(work_product);
- } else {
- if scx.sess().opts.debugging_opts.incremental_info {
- println!("incremental: CGU `{}` invalidated because of \
- changed partitioning hash.",
- cgu.name());
- }
- debug!("trans_reuse_previous_work_products: \
- not reusing {:?} because hash changed to {:?}",
- work_product, hash);
- }
- }
-
- None
- })
- .collect()
-}
-
fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>)
-> (Vec<CodegenUnit<'tcx>>, SymbolMap<'tcx>) {
let time_passes = scx.sess().time_passes();
use llvm;
use llvm::{ContextRef, ModuleRef, ValueRef};
-use rustc::dep_graph::{DepGraph, DepGraphSafe, DepNode, DepTrackingMap,
- DepTrackingMapConfig, WorkProduct};
+use rustc::dep_graph::{DepGraph, DepGraphSafe, DepNode, DepTrackingMap, DepTrackingMapConfig};
use middle::cstore::LinkMeta;
use rustc::hir;
use rustc::hir::def_id::DefId;
pub struct LocalCrateContext<'tcx> {
llmod: ModuleRef,
llcx: ContextRef,
- previous_work_product: Option<WorkProduct>,
codegen_unit: CodegenUnit<'tcx>,
needs_unwind_cleanup_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
/// Cache instances of monomorphic and polymorphic items
}
}
-/// This list owns a number of LocalCrateContexts and binds them to their common
-/// SharedCrateContext. This type just exists as a convenience, something to
-/// pass around all LocalCrateContexts with and get an iterator over them.
-pub struct CrateContextList<'a, 'tcx: 'a> {
- shared: &'a SharedCrateContext<'a, 'tcx>,
- local_ccxs: Vec<LocalCrateContext<'tcx>>,
-}
-
-impl<'a, 'tcx: 'a> CrateContextList<'a, 'tcx> {
- pub fn new(shared_ccx: &'a SharedCrateContext<'a, 'tcx>,
- codegen_units: Vec<CodegenUnit<'tcx>>,
- previous_work_products: Vec<Option<WorkProduct>>,
- symbol_map: Rc<SymbolMap<'tcx>>)
- -> CrateContextList<'a, 'tcx> {
- CrateContextList {
- shared: shared_ccx,
- local_ccxs: codegen_units.into_iter().zip(previous_work_products).map(|(cgu, wp)| {
- LocalCrateContext::new(shared_ccx, cgu, wp, symbol_map.clone())
- }).collect()
- }
- }
-
- /// Iterate over all crate contexts, whether or not they need
- /// translation. That is, whether or not a `.o` file is available
- /// for re-use from a previous incr. comp.).
- pub fn iter_all<'b>(&'b self) -> CrateContextIterator<'b, 'tcx> {
- CrateContextIterator {
- shared: self.shared,
- index: 0,
- local_ccxs: &self.local_ccxs[..],
- filter_to_previous_work_product_unavail: false,
- }
- }
-}
-
/// A CrateContext value binds together one LocalCrateContext with the
/// SharedCrateContext. It exists as a convenience wrapper, so we don't have to
/// pass around (SharedCrateContext, LocalCrateContext) tuples all over trans.
local_ccx: &'a LocalCrateContext<'tcx>,
}
-impl<'a, 'tcx> DepGraphSafe for CrateContext<'a, 'tcx> {
-}
-
-pub struct CrateContextIterator<'a, 'tcx: 'a> {
- shared: &'a SharedCrateContext<'a, 'tcx>,
- local_ccxs: &'a [LocalCrateContext<'tcx>],
- index: usize,
-
- /// if true, only return results where `previous_work_product` is none
- filter_to_previous_work_product_unavail: bool,
+impl<'a, 'tcx> CrateContext<'a, 'tcx> {
+ pub fn new(shared: &'a SharedCrateContext<'a, 'tcx>,
+ local_ccx: &'a LocalCrateContext<'tcx>)
+ -> Self {
+ CrateContext { shared, local_ccx }
+ }
}
-impl<'a, 'tcx> Iterator for CrateContextIterator<'a,'tcx> {
- type Item = CrateContext<'a, 'tcx>;
-
- fn next(&mut self) -> Option<CrateContext<'a, 'tcx>> {
- loop {
- if self.index >= self.local_ccxs.len() {
- return None;
- }
-
- let index = self.index;
- self.index += 1;
-
- let ccx = CrateContext {
- shared: self.shared,
- local_ccx: &self.local_ccxs[index],
- };
-
- if
- self.filter_to_previous_work_product_unavail &&
- ccx.previous_work_product().is_some()
- {
- continue;
- }
-
- return Some(ccx);
- }
- }
+impl<'a, 'tcx> DepGraphSafe for CrateContext<'a, 'tcx> {
}
pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode {
}
impl<'tcx> LocalCrateContext<'tcx> {
- fn new<'a>(shared: &SharedCrateContext<'a, 'tcx>,
- codegen_unit: CodegenUnit<'tcx>,
- previous_work_product: Option<WorkProduct>,
- symbol_map: Rc<SymbolMap<'tcx>>)
- -> LocalCrateContext<'tcx> {
+ pub fn new<'a>(shared: &SharedCrateContext<'a, 'tcx>,
+ codegen_unit: CodegenUnit<'tcx>,
+ symbol_map: Rc<SymbolMap<'tcx>>)
+ -> LocalCrateContext<'tcx> {
unsafe {
// Append ".rs" to LLVM module identifier.
//
let local_ccx = LocalCrateContext {
llmod: llmod,
llcx: llcx,
- previous_work_product: previous_work_product,
codegen_unit: codegen_unit,
needs_unwind_cleanup_cache: RefCell::new(FxHashMap()),
instances: RefCell::new(FxHashMap()),
self.local().llcx
}
- pub fn previous_work_product(&self) -> Option<&WorkProduct> {
- self.local().previous_work_product.as_ref()
- }
-
pub fn codegen_unit(&self) -> &CodegenUnit<'tcx> {
&self.local().codegen_unit
}