Skip to content
Closed
115 changes: 82 additions & 33 deletions src/librustc/dep_graph/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,13 +204,31 @@ impl DepGraph {
where C: DepGraphSafe + StableHashingContextProvider<'gcx>,
R: HashStable<StableHashingContext<'gcx>>,
{
self.with_task_impl(key, cx, arg, false, task,
self.with_task_impl(key, cx, arg, false, true, task,
|key| OpenTask::Regular(Lock::new(RegularOpenTask {
node: key,
reads: SmallVec::new(),
read_set: FxHashSet(),
})),
|data, key, task| data.borrow_mut().complete_task(key, task))
|data, key, task| data.borrow_mut().complete_task(key, task, false))
}

pub fn with_forced_task<'gcx, C, A, R>(&self,
key: DepNode,
cx: C,
arg: A,
task: fn(C, A) -> R)
-> (R, DepNodeIndex)
where C: DepGraphSafe + StableHashingContextProvider<'gcx>,
R: HashStable<StableHashingContext<'gcx>>,
{
self.with_task_impl(key, cx, arg, false, false, task,
|key| OpenTask::Regular(Lock::new(RegularOpenTask {
node: key,
reads: SmallVec::new(),
read_set: FxHashSet(),
})),
|data, key, task| data.borrow_mut().complete_task(key, task, true))
}

/// Creates a new dep-graph input with value `input`
Expand All @@ -226,7 +244,7 @@ impl DepGraph {
arg
}

self.with_task_impl(key, cx, input, true, identity_fn,
self.with_task_impl(key, cx, input, true, true, identity_fn,
|_| OpenTask::Ignore,
|data, key, _| data.borrow_mut().alloc_node(key, SmallVec::new()))
}
Expand All @@ -237,6 +255,7 @@ impl DepGraph {
cx: C,
arg: A,
no_tcx: bool,
do_fingerprinting: bool,
task: fn(C, A) -> R,
create_task: fn(DepNode) -> OpenTask,
finish_task_and_alloc_depnode: fn(&Lock<CurrentDepGraph>,
Expand Down Expand Up @@ -282,41 +301,58 @@ impl DepGraph {

let dep_node_index = finish_task_and_alloc_depnode(&data.current, key, open_task);

let mut stable_hasher = StableHasher::new();
result.hash_stable(&mut hcx, &mut stable_hasher);
if do_fingerprinting {
let mut stable_hasher = StableHasher::new();
result.hash_stable(&mut hcx, &mut stable_hasher);

let current_fingerprint = stable_hasher.finish();
let current_fingerprint = stable_hasher.finish();

// Store the current fingerprint
{
let mut fingerprints = self.fingerprints.borrow_mut();
// Store the current fingerprint
{
let mut fingerprints = self.fingerprints.borrow_mut();

if dep_node_index.index() >= fingerprints.len() {
fingerprints.resize(dep_node_index.index() + 1, Fingerprint::ZERO);
}

if dep_node_index.index() >= fingerprints.len() {
fingerprints.resize(dep_node_index.index() + 1, Fingerprint::ZERO);
debug_assert!(fingerprints[dep_node_index] == Fingerprint::ZERO,
"DepGraph::with_task() - Duplicate fingerprint \
insertion for {:?}", key);
fingerprints[dep_node_index] = current_fingerprint;
}

debug_assert!(fingerprints[dep_node_index] == Fingerprint::ZERO,
"DepGraph::with_task() - Duplicate fingerprint \
insertion for {:?}", key);
fingerprints[dep_node_index] = current_fingerprint;
}
// Determine the color of the new DepNode.
if let Some(prev_index) = data.previous.node_to_index_opt(&key) {
let prev_fingerprint = data.previous.fingerprint_by_index(prev_index);

// Determine the color of the new DepNode.
if let Some(prev_index) = data.previous.node_to_index_opt(&key) {
let prev_fingerprint = data.previous.fingerprint_by_index(prev_index);
let color = if current_fingerprint == prev_fingerprint {
DepNodeColor::Green(dep_node_index)
} else {
DepNodeColor::Red
};

let color = if current_fingerprint == prev_fingerprint {
DepNodeColor::Green(dep_node_index)
} else {
DepNodeColor::Red
};
let mut colors = data.colors.borrow_mut();
debug_assert!(colors.get(prev_index).is_none(),
"DepGraph::with_task() - Duplicate DepNodeColor \
insertion for {:?}", key);

colors.insert(prev_index, color);
}
} else {
// Always store a ZERO fingerprint
{
let mut fingerprints = self.fingerprints.borrow_mut();

let mut colors = data.colors.borrow_mut();
debug_assert!(colors.get(prev_index).is_none(),
"DepGraph::with_task() - Duplicate DepNodeColor \
insertion for {:?}", key);
if dep_node_index.index() >= fingerprints.len() {
fingerprints.resize(dep_node_index.index() + 1, Fingerprint::ZERO);
}

fingerprints[dep_node_index] = Fingerprint::ZERO;
}

colors.insert(prev_index, color);
if let Some(prev_index) = data.previous.node_to_index_opt(&key) {
data.colors.borrow_mut().insert(prev_index, DepNodeColor::Red);
}
}

(result, dep_node_index)
Expand Down Expand Up @@ -378,7 +414,7 @@ impl DepGraph {
}

/// Execute something within an "eval-always" task which is a task
// that runs whenever anything changes.
/// that runs whenever anything changes.
pub fn with_eval_always_task<'gcx, C, A, R>(&self,
key: DepNode,
cx: C,
Expand All @@ -388,7 +424,7 @@ impl DepGraph {
where C: DepGraphSafe + StableHashingContextProvider<'gcx>,
R: HashStable<StableHashingContext<'gcx>>,
{
self.with_task_impl(key, cx, arg, false, task,
self.with_task_impl(key, cx, arg, false, true, task,
|key| OpenTask::EvalAlways { node: key },
|data, key, task| data.borrow_mut().complete_eval_always_task(key, task))
}
Expand Down Expand Up @@ -939,7 +975,11 @@ impl CurrentDepGraph {
}
}

fn complete_task(&mut self, key: DepNode, task: OpenTask) -> DepNodeIndex {
fn complete_task(&mut self,
key: DepNode,
task: OpenTask,
allow_existing_dep_node: bool)
-> DepNodeIndex {
if let OpenTask::Regular(task) = task {
let RegularOpenTask {
node,
Expand Down Expand Up @@ -970,7 +1010,16 @@ impl CurrentDepGraph {
}
}

self.alloc_node(node, reads)
if allow_existing_dep_node {
if let Some(&dep_node_index) = self.node_to_node_index.get(&node) {
self.edges[dep_node_index] = reads;
dep_node_index
} else {
self.alloc_node(node, reads)
}
} else {
self.alloc_node(node, reads)
}
} else {
bug!("complete_task() - Expected regular task to be popped")
}
Expand Down
79 changes: 77 additions & 2 deletions src/librustc/mir/mono.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -173,6 +174,80 @@ impl<'tcx> CodegenUnit<'tcx> {
self.size_estimate = Some(size_estimate + delta);
}
}

/// 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:
///
/// ```
/// <crate-name>.<crate-disambiguator>(-<component>)*[.<special-suffix>]
/// ```
///
/// The '.' before `<special-suffix>` 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<I, C, S>(tcx: TyCtxt,
cnum: CrateNum,
components: I,
special_suffix: Option<S>)
-> InternedString
where I: IntoIterator<Item=C>,
C: fmt::Display,
S: fmt::Display,
{
let cgu_name = CodegenUnit::build_cgu_name_no_mangle(tcx,
cnum,
components,
special_suffix);

if 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<I, C, S>(tcx: TyCtxt,
cnum: CrateNum,
components: I,
special_suffix: Option<S>)
-> InternedString
where I: IntoIterator<Item=C>,
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
write!(cgu_name,
"{}.{}",
tcx.crate_name(cnum),
tcx.crate_disambiguator(cnum)).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()
}
}

impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for CodegenUnit<'tcx> {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1973,7 +1973,7 @@ pub fn build_session_options_and_crate_config(
(&None, &None) => None,
}.map(|m| PathBuf::from(m));

if cg.lto != Lto::No && incremental.is_some() {
if cg.lto == Lto::Fat && incremental.is_some() {
early_error(
error_format,
"can't perform LTO when compiling incrementally",
Expand Down
14 changes: 9 additions & 5 deletions src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,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;
Expand Down Expand Up @@ -582,11 +583,6 @@ impl Session {
return config::Lto::No;
}

// Right now ThinLTO isn't compatible with incremental compilation.
if self.opts.incremental.is_some() {
return config::Lto::No;
}

// Now we're in "defaults" territory. By default we enable ThinLTO for
// optimized compiles (anything greater than O0).
match self.opts.optimize {
Expand Down Expand Up @@ -1185,6 +1181,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<Fingerprint> for CrateDisambiguator {
fn from(fingerprint: Fingerprint) -> CrateDisambiguator {
CrateDisambiguator(fingerprint)
Expand Down
6 changes: 0 additions & 6 deletions src/librustc/ty/query/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -702,12 +702,6 @@ impl<'tcx> QueryDescription<'tcx> for queries::codegen_unit<'tcx> {
}
}

impl<'tcx> QueryDescription<'tcx> for queries::compile_codegen_unit<'tcx> {
fn describe(_tcx: TyCtxt, _: InternedString) -> String {
format!("compile_codegen_unit")
}
}

impl<'tcx> QueryDescription<'tcx> for queries::output_filenames<'tcx> {
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
format!("output_filenames")
Expand Down
3 changes: 1 addition & 2 deletions src/librustc/ty/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use middle::stability::{self, DeprecationEntry};
use middle::lang_items::{LanguageItems, LangItem};
use middle::exported_symbols::{SymbolExportLevel, ExportedSymbol};
use mir::interpret::ConstEvalResult;
use mir::mono::{CodegenUnit, Stats};
use mir::mono::CodegenUnit;
use mir;
use mir::interpret::{GlobalId, Allocation};
use session::{CompileResult, CrateDisambiguator};
Expand Down Expand Up @@ -436,7 +436,6 @@ define_queries! { <'tcx>
-> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>),
[] fn is_codegened_item: IsCodegenedItem(DefId) -> bool,
[] fn codegen_unit: CodegenUnit(InternedString) -> Arc<CodegenUnit<'tcx>>,
[] fn compile_codegen_unit: CompileCodegenUnit(InternedString) -> Stats,
[] fn output_filenames: output_filenames_node(CrateNum)
-> Arc<OutputFilenames>,

Expand Down
7 changes: 0 additions & 7 deletions src/librustc_codegen_llvm/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,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};
Expand Down
Loading