mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Auto merge of #115964 - bjorn3:cgu_reuse_tracker_global_state, r=cjgillot
Remove cgu_reuse_tracker from Session This removes a bit of global mutable state. It will now miss post-lto cgu reuse when ThinLTO determines that a cgu doesn't get changed, but there weren't any tests for this anyway and a test for it would be fragile to the exact implementation of ThinLTO in LLVM.
This commit is contained in:
commit
130ff8cb6c
@ -3650,6 +3650,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"smallvec",
|
||||
"tempfile",
|
||||
"thin-vec",
|
||||
"thorin-dwp",
|
||||
"tracing",
|
||||
"windows",
|
||||
|
@ -7,14 +7,15 @@ use std::sync::Arc;
|
||||
use std::thread::JoinHandle;
|
||||
|
||||
use cranelift_object::{ObjectBuilder, ObjectModule};
|
||||
use rustc_codegen_ssa::assert_module_sources::CguReuse;
|
||||
use rustc_codegen_ssa::back::metadata::create_compressed_metadata_file;
|
||||
use rustc_codegen_ssa::base::determine_cgu_reuse;
|
||||
use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind};
|
||||
use rustc_data_structures::profiling::SelfProfilerRef;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_metadata::EncodedMetadata;
|
||||
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
||||
use rustc_middle::mir::mono::{CodegenUnit, MonoItem};
|
||||
use rustc_session::cgu_reuse_tracker::CguReuse;
|
||||
use rustc_session::config::{DebugInfo, OutputFilenames, OutputType};
|
||||
use rustc_session::Session;
|
||||
|
||||
@ -374,43 +375,47 @@ pub(crate) fn run_aot(
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the CGU reuse
|
||||
let cgu_reuse = tcx.sess.time("find_cgu_reuse", || {
|
||||
cgus.iter().map(|cgu| determine_cgu_reuse(tcx, &cgu)).collect::<Vec<_>>()
|
||||
});
|
||||
|
||||
rustc_codegen_ssa::assert_module_sources::assert_module_sources(tcx, &|cgu_reuse_tracker| {
|
||||
for (i, cgu) in cgus.iter().enumerate() {
|
||||
let cgu_reuse = cgu_reuse[i];
|
||||
cgu_reuse_tracker.set_actual_reuse(cgu.name().as_str(), cgu_reuse);
|
||||
}
|
||||
});
|
||||
|
||||
let global_asm_config = Arc::new(crate::global_asm::GlobalAsmConfig::new(tcx));
|
||||
|
||||
let mut concurrency_limiter = ConcurrencyLimiter::new(tcx.sess, cgus.len());
|
||||
|
||||
let modules = tcx.sess.time("codegen mono items", || {
|
||||
cgus.iter()
|
||||
.map(|cgu| {
|
||||
let cgu_reuse = if backend_config.disable_incr_cache {
|
||||
CguReuse::No
|
||||
} else {
|
||||
determine_cgu_reuse(tcx, cgu)
|
||||
};
|
||||
tcx.sess.cgu_reuse_tracker.set_actual_reuse(cgu.name().as_str(), cgu_reuse);
|
||||
|
||||
match cgu_reuse {
|
||||
CguReuse::No => {
|
||||
let dep_node = cgu.codegen_dep_node(tcx);
|
||||
tcx.dep_graph
|
||||
.with_task(
|
||||
dep_node,
|
||||
tcx,
|
||||
(
|
||||
backend_config.clone(),
|
||||
global_asm_config.clone(),
|
||||
cgu.name(),
|
||||
concurrency_limiter.acquire(tcx.sess.diagnostic()),
|
||||
),
|
||||
module_codegen,
|
||||
Some(rustc_middle::dep_graph::hash_result),
|
||||
)
|
||||
.0
|
||||
}
|
||||
CguReuse::PreLto => unreachable!(),
|
||||
CguReuse::PostLto => {
|
||||
concurrency_limiter.job_already_done();
|
||||
OngoingModuleCodegen::Sync(reuse_workproduct_for_cgu(tcx, cgu))
|
||||
}
|
||||
.enumerate()
|
||||
.map(|(i, cgu)| match cgu_reuse[i] {
|
||||
CguReuse::No => {
|
||||
let dep_node = cgu.codegen_dep_node(tcx);
|
||||
tcx.dep_graph
|
||||
.with_task(
|
||||
dep_node,
|
||||
tcx,
|
||||
(
|
||||
backend_config.clone(),
|
||||
global_asm_config.clone(),
|
||||
cgu.name(),
|
||||
concurrency_limiter.acquire(tcx.sess.diagnostic()),
|
||||
),
|
||||
module_codegen,
|
||||
Some(rustc_middle::dep_graph::hash_result),
|
||||
)
|
||||
.0
|
||||
}
|
||||
CguReuse::PreLto => unreachable!("LTO not yet supported"),
|
||||
CguReuse::PostLto => {
|
||||
concurrency_limiter.job_already_done();
|
||||
OngoingModuleCodegen::Sync(reuse_workproduct_for_cgu(tcx, cgu))
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
@ -489,32 +494,3 @@ pub(crate) fn run_aot(
|
||||
concurrency_limiter,
|
||||
})
|
||||
}
|
||||
|
||||
// Adapted from https://github.com/rust-lang/rust/blob/303d8aff6092709edd4dbd35b1c88e9aa40bf6d8/src/librustc_codegen_ssa/base.rs#L922-L953
|
||||
fn determine_cgu_reuse<'tcx>(tcx: TyCtxt<'tcx>, cgu: &CodegenUnit<'tcx>) -> CguReuse {
|
||||
if !tcx.dep_graph.is_fully_enabled() {
|
||||
return CguReuse::No;
|
||||
}
|
||||
|
||||
let work_product_id = &cgu.work_product_id();
|
||||
if tcx.dep_graph.previous_work_product(work_product_id).is_none() {
|
||||
// We don't have anything cached for this CGU. This can happen
|
||||
// if the CGU did not exist in the previous session.
|
||||
return CguReuse::No;
|
||||
}
|
||||
|
||||
// Try to mark the CGU as green. If it we can do so, it means that nothing
|
||||
// affecting the LLVM module has changed and we can re-use a cached version.
|
||||
// If we compile with any kind of LTO, this means we can re-use the bitcode
|
||||
// of the Pre-LTO stage (possibly also the Post-LTO version but we'll only
|
||||
// know that later). If we are not doing LTO, there is only one optimized
|
||||
// version of each module, so we re-use that.
|
||||
let dep_node = cgu.codegen_dep_node(tcx);
|
||||
assert!(
|
||||
!tcx.dep_graph.dep_node_exists(&dep_node),
|
||||
"CompileCodegenUnit dep-node for CGU `{}` already exists before marking.",
|
||||
cgu.name()
|
||||
);
|
||||
|
||||
if tcx.try_mark_green(&dep_node) { CguReuse::PostLto } else { CguReuse::No }
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ use rustc_hir::def_id::LOCAL_CRATE;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::dep_graph::WorkProduct;
|
||||
use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel};
|
||||
use rustc_session::cgu_reuse_tracker::CguReuse;
|
||||
use rustc_session::config::{self, CrateType, Lto};
|
||||
|
||||
use std::ffi::{CStr, CString};
|
||||
@ -584,7 +583,6 @@ fn thin_lto(
|
||||
copy_jobs.push(work_product);
|
||||
info!(" - {}: re-used", module_name);
|
||||
assert!(cgcx.incr_comp_session_dir.is_some());
|
||||
cgcx.cgu_reuse_tracker.set_actual_reuse(module_name, CguReuse::PostLto);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ pathdiff = "0.2.0"
|
||||
serde_json = "1.0.59"
|
||||
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
|
||||
regex = "1.4"
|
||||
thin-vec = "0.2.12"
|
||||
|
||||
rustc_serialize = { path = "../rustc_serialize" }
|
||||
rustc_arena = { path = "../rustc_arena" }
|
||||
|
@ -11,6 +11,9 @@ codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing
|
||||
|
||||
codegen_ssa_binary_output_to_tty = option `-o` or `--emit` is used to write binary output type `{$shorthand}` to stdout, but stdout is a tty
|
||||
|
||||
codegen_ssa_cgu_not_recorded =
|
||||
CGU-reuse for `{$cgu_user_name}` is (mangled: `{$cgu_name}`) was not recorded
|
||||
|
||||
codegen_ssa_check_installed_visual_studio = please ensure that Visual Studio 2017 or later, or Build Tools for Visual Studio were installed with the Visual C++ option.
|
||||
|
||||
codegen_ssa_copy_path = could not copy {$from} to {$to}: {$error}
|
||||
@ -39,6 +42,8 @@ codegen_ssa_failed_to_get_layout = failed to get layout for {$ty}: {$err}
|
||||
|
||||
codegen_ssa_failed_to_write = failed to write {$path}: {$error}
|
||||
|
||||
codegen_ssa_field_associated_value_expected = associated value expected for `{$name}`
|
||||
|
||||
codegen_ssa_ignoring_emit_path = ignoring emit path because multiple .{$extension} files were produced
|
||||
|
||||
codegen_ssa_ignoring_output = ignoring -o because multiple .{$extension} files were produced
|
||||
@ -46,6 +51,12 @@ codegen_ssa_ignoring_output = ignoring -o because multiple .{$extension} files w
|
||||
codegen_ssa_illegal_link_ordinal_format = illegal ordinal format in `link_ordinal`
|
||||
.note = an unsuffixed integer value, e.g., `1`, is expected
|
||||
|
||||
codegen_ssa_incorrect_cgu_reuse_type =
|
||||
CGU-reuse for `{$cgu_user_name}` is `{$actual_reuse}` but should be {$at_least ->
|
||||
[one] {"at least "}
|
||||
*[other] {""}
|
||||
}`{$expected_reuse}`
|
||||
|
||||
codegen_ssa_insufficient_vs_code_product = VS Code is a different product, and is not sufficient.
|
||||
|
||||
codegen_ssa_invalid_link_ordinal_nargs = incorrect number of arguments to `#[link_ordinal]`
|
||||
@ -153,12 +164,18 @@ codegen_ssa_linker_unsupported_modifier = `as-needed` modifier not supported for
|
||||
|
||||
codegen_ssa_linking_failed = linking with `{$linker_path}` failed: {$exit_status}
|
||||
|
||||
codegen_ssa_malformed_cgu_name =
|
||||
found malformed codegen unit name `{$user_path}`. codegen units names must always start with the name of the crate (`{$crate_name}` in this case).
|
||||
|
||||
codegen_ssa_metadata_object_file_write = error writing metadata object file: {$error}
|
||||
|
||||
codegen_ssa_missing_cpp_build_tool_component = or a necessary component may be missing from the "C++ build tools" workload
|
||||
|
||||
codegen_ssa_missing_memory_ordering = Atomic intrinsic missing memory ordering
|
||||
|
||||
codegen_ssa_missing_query_depgraph =
|
||||
found CGU-reuse attribute but `-Zquery-dep-graph` was not specified
|
||||
|
||||
codegen_ssa_msvc_missing_linker = the msvc targets depend on the msvc linker but `link.exe` was not found
|
||||
|
||||
codegen_ssa_multiple_external_func_decl = multiple declarations of external function `{$function}` from library `{$library_name}` have different calling conventions
|
||||
@ -166,6 +183,11 @@ codegen_ssa_multiple_external_func_decl = multiple declarations of external func
|
||||
codegen_ssa_multiple_main_functions = entry symbol `main` declared multiple times
|
||||
.help = did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead
|
||||
|
||||
codegen_ssa_no_field = no field `{$name}`
|
||||
|
||||
codegen_ssa_no_module_named =
|
||||
no module named `{$user_path}` (mangled: {$cgu_name}). available modules: {$cgu_names}
|
||||
|
||||
codegen_ssa_no_natvis_directory = error enumerating natvis directory: {$error}
|
||||
|
||||
codegen_ssa_processing_dymutil_failed = processing debug info with `dsymutil` failed: {$status}
|
||||
@ -297,6 +319,8 @@ codegen_ssa_unknown_atomic_operation = unknown atomic operation
|
||||
|
||||
codegen_ssa_unknown_atomic_ordering = unknown ordering in atomic intrinsic
|
||||
|
||||
codegen_ssa_unknown_reuse_kind = unknown cgu-reuse-kind `{$kind}` specified
|
||||
|
||||
codegen_ssa_unsupported_arch = unsupported arch `{$arch}` for os `{$os}`
|
||||
|
||||
codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target
|
||||
|
@ -25,16 +25,21 @@
|
||||
|
||||
use crate::errors;
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::unord::UnordSet;
|
||||
use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
|
||||
use rustc_hir::def_id::LOCAL_CRATE;
|
||||
use rustc_middle::mir::mono::CodegenUnitNameBuilder;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::cgu_reuse_tracker::*;
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
#[allow(missing_docs)]
|
||||
pub fn assert_module_sources(tcx: TyCtxt<'_>) {
|
||||
pub fn assert_module_sources(tcx: TyCtxt<'_>, set_reuse: &dyn Fn(&mut CguReuseTracker)) {
|
||||
tcx.dep_graph.with_ignore(|| {
|
||||
if tcx.sess.opts.incremental.is_none() {
|
||||
return;
|
||||
@ -43,21 +48,34 @@ pub fn assert_module_sources(tcx: TyCtxt<'_>) {
|
||||
let available_cgus =
|
||||
tcx.collect_and_partition_mono_items(()).1.iter().map(|cgu| cgu.name()).collect();
|
||||
|
||||
let ams = AssertModuleSource { tcx, available_cgus };
|
||||
let mut ams = AssertModuleSource {
|
||||
tcx,
|
||||
available_cgus,
|
||||
cgu_reuse_tracker: if tcx.sess.opts.unstable_opts.query_dep_graph {
|
||||
CguReuseTracker::new()
|
||||
} else {
|
||||
CguReuseTracker::new_disabled()
|
||||
},
|
||||
};
|
||||
|
||||
for attr in tcx.hir().attrs(rustc_hir::CRATE_HIR_ID) {
|
||||
ams.check_attr(attr);
|
||||
}
|
||||
})
|
||||
|
||||
set_reuse(&mut ams.cgu_reuse_tracker);
|
||||
|
||||
ams.cgu_reuse_tracker.check_expected_reuse(tcx.sess);
|
||||
});
|
||||
}
|
||||
|
||||
struct AssertModuleSource<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
available_cgus: UnordSet<Symbol>,
|
||||
cgu_reuse_tracker: CguReuseTracker,
|
||||
}
|
||||
|
||||
impl<'tcx> AssertModuleSource<'tcx> {
|
||||
fn check_attr(&self, attr: &ast::Attribute) {
|
||||
fn check_attr(&mut self, attr: &ast::Attribute) {
|
||||
let (expected_reuse, comp_kind) = if attr.has_name(sym::rustc_partition_reused) {
|
||||
(CguReuse::PreLto, ComparisonKind::AtLeast)
|
||||
} else if attr.has_name(sym::rustc_partition_codegened) {
|
||||
@ -129,7 +147,7 @@ impl<'tcx> AssertModuleSource<'tcx> {
|
||||
});
|
||||
}
|
||||
|
||||
self.tcx.sess.cgu_reuse_tracker.set_expectation(
|
||||
self.cgu_reuse_tracker.set_expectation(
|
||||
cgu_name,
|
||||
&user_path,
|
||||
attr.span,
|
||||
@ -169,3 +187,109 @@ impl<'tcx> AssertModuleSource<'tcx> {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
|
||||
pub enum CguReuse {
|
||||
No,
|
||||
PreLto,
|
||||
PostLto,
|
||||
}
|
||||
|
||||
impl fmt::Display for CguReuse {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
CguReuse::No => write!(f, "No"),
|
||||
CguReuse::PreLto => write!(f, "PreLto "),
|
||||
CguReuse::PostLto => write!(f, "PostLto "),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for CguReuse {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Owned(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum ComparisonKind {
|
||||
Exact,
|
||||
AtLeast,
|
||||
}
|
||||
|
||||
struct TrackerData {
|
||||
actual_reuse: FxHashMap<String, CguReuse>,
|
||||
expected_reuse: FxHashMap<String, (String, Span, CguReuse, ComparisonKind)>,
|
||||
}
|
||||
|
||||
pub struct CguReuseTracker {
|
||||
data: Option<TrackerData>,
|
||||
}
|
||||
|
||||
impl CguReuseTracker {
|
||||
fn new() -> CguReuseTracker {
|
||||
let data =
|
||||
TrackerData { actual_reuse: Default::default(), expected_reuse: Default::default() };
|
||||
|
||||
CguReuseTracker { data: Some(data) }
|
||||
}
|
||||
|
||||
fn new_disabled() -> CguReuseTracker {
|
||||
CguReuseTracker { data: None }
|
||||
}
|
||||
|
||||
pub fn set_actual_reuse(&mut self, cgu_name: &str, kind: CguReuse) {
|
||||
if let Some(data) = &mut self.data {
|
||||
debug!("set_actual_reuse({cgu_name:?}, {kind:?})");
|
||||
|
||||
let prev_reuse = data.actual_reuse.insert(cgu_name.to_string(), kind);
|
||||
assert!(prev_reuse.is_none());
|
||||
}
|
||||
}
|
||||
|
||||
fn set_expectation(
|
||||
&mut self,
|
||||
cgu_name: Symbol,
|
||||
cgu_user_name: &str,
|
||||
error_span: Span,
|
||||
expected_reuse: CguReuse,
|
||||
comparison_kind: ComparisonKind,
|
||||
) {
|
||||
if let Some(data) = &mut self.data {
|
||||
debug!("set_expectation({cgu_name:?}, {expected_reuse:?}, {comparison_kind:?})");
|
||||
|
||||
data.expected_reuse.insert(
|
||||
cgu_name.to_string(),
|
||||
(cgu_user_name.to_string(), error_span, expected_reuse, comparison_kind),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_expected_reuse(&self, sess: &Session) {
|
||||
if let Some(ref data) = self.data {
|
||||
for (cgu_name, &(ref cgu_user_name, ref error_span, expected_reuse, comparison_kind)) in
|
||||
&data.expected_reuse
|
||||
{
|
||||
if let Some(&actual_reuse) = data.actual_reuse.get(cgu_name) {
|
||||
let (error, at_least) = match comparison_kind {
|
||||
ComparisonKind::Exact => (expected_reuse != actual_reuse, false),
|
||||
ComparisonKind::AtLeast => (actual_reuse < expected_reuse, true),
|
||||
};
|
||||
|
||||
if error {
|
||||
let at_least = if at_least { 1 } else { 0 };
|
||||
errors::IncorrectCguReuseType {
|
||||
span: *error_span,
|
||||
cgu_user_name,
|
||||
actual_reuse,
|
||||
expected_reuse,
|
||||
at_least,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
sess.emit_fatal(errors::CguNotRecorded { cgu_user_name, cgu_name });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -26,7 +26,6 @@ use rustc_metadata::EncodedMetadata;
|
||||
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
||||
use rustc_middle::middle::exported_symbols::SymbolExportInfo;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::cgu_reuse_tracker::CguReuseTracker;
|
||||
use rustc_session::config::{self, CrateType, Lto, OutFileName, OutputFilenames, OutputType};
|
||||
use rustc_session::config::{Passes, SwitchWithOptPath};
|
||||
use rustc_session::Session;
|
||||
@ -366,8 +365,6 @@ pub struct CodegenContext<B: WriteBackendMethods> {
|
||||
/// The incremental compilation session directory, or None if we are not
|
||||
/// compiling incrementally
|
||||
pub incr_comp_session_dir: Option<PathBuf>,
|
||||
/// Used to update CGU re-use information during the thinlto phase.
|
||||
pub cgu_reuse_tracker: CguReuseTracker,
|
||||
/// Channel back to the main control thread to send messages to
|
||||
pub coordinator_send: Sender<Box<dyn Any + Send>>,
|
||||
}
|
||||
@ -1119,7 +1116,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
||||
remark: sess.opts.cg.remark.clone(),
|
||||
remark_dir,
|
||||
incr_comp_session_dir: sess.incr_comp_session_dir_opt().map(|r| r.clone()),
|
||||
cgu_reuse_tracker: sess.cgu_reuse_tracker.clone(),
|
||||
coordinator_send,
|
||||
expanded_args: tcx.sess.expanded_args.clone(),
|
||||
diag_emitter: shared_emitter.clone(),
|
||||
@ -1969,8 +1965,6 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {
|
||||
}
|
||||
});
|
||||
|
||||
sess.cgu_reuse_tracker.check_expected_reuse(sess);
|
||||
|
||||
sess.abort_if_errors();
|
||||
|
||||
let work_products =
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::assert_module_sources::CguReuse;
|
||||
use crate::back::link::are_upstream_rust_objects_already_included;
|
||||
use crate::back::metadata::create_compressed_metadata_file;
|
||||
use crate::back::write::{
|
||||
@ -31,7 +32,6 @@ use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
|
||||
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
|
||||
use rustc_session::cgu_reuse_tracker::CguReuse;
|
||||
use rustc_session::config::{self, CrateType, EntryFnType, OutputType};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::symbol::sym;
|
||||
@ -683,6 +683,13 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
||||
codegen_units.iter().map(|cgu| determine_cgu_reuse(tcx, &cgu)).collect::<Vec<_>>()
|
||||
});
|
||||
|
||||
crate::assert_module_sources::assert_module_sources(tcx, &|cgu_reuse_tracker| {
|
||||
for (i, cgu) in codegen_units.iter().enumerate() {
|
||||
let cgu_reuse = cgu_reuse[i];
|
||||
cgu_reuse_tracker.set_actual_reuse(cgu.name().as_str(), cgu_reuse);
|
||||
}
|
||||
});
|
||||
|
||||
let mut total_codegen_time = Duration::new(0, 0);
|
||||
let start_rss = tcx.sess.opts.unstable_opts.time_passes.then(|| get_resident_set_size());
|
||||
|
||||
@ -727,7 +734,6 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
||||
ongoing_codegen.check_for_errors(tcx.sess);
|
||||
|
||||
let cgu_reuse = cgu_reuse[i];
|
||||
tcx.sess.cgu_reuse_tracker.set_actual_reuse(cgu.name().as_str(), cgu_reuse);
|
||||
|
||||
match cgu_reuse {
|
||||
CguReuse::No => {
|
||||
@ -994,7 +1000,7 @@ pub fn provide(providers: &mut Providers) {
|
||||
};
|
||||
}
|
||||
|
||||
fn determine_cgu_reuse<'tcx>(tcx: TyCtxt<'tcx>, cgu: &CodegenUnit<'tcx>) -> CguReuse {
|
||||
pub fn determine_cgu_reuse<'tcx>(tcx: TyCtxt<'tcx>, cgu: &CodegenUnit<'tcx>) -> CguReuse {
|
||||
if !tcx.dep_graph.is_fully_enabled() {
|
||||
return CguReuse::No;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
//! Errors emitted by codegen_ssa
|
||||
|
||||
use crate::assert_module_sources::CguReuse;
|
||||
use crate::back::command::Command;
|
||||
use crate::fluent_generated as fluent;
|
||||
use rustc_errors::{
|
||||
@ -16,6 +17,74 @@ use std::io::Error;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::ExitStatus;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_incorrect_cgu_reuse_type)]
|
||||
pub struct IncorrectCguReuseType<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub cgu_user_name: &'a str,
|
||||
pub actual_reuse: CguReuse,
|
||||
pub expected_reuse: CguReuse,
|
||||
pub at_least: u8,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_cgu_not_recorded)]
|
||||
pub struct CguNotRecorded<'a> {
|
||||
pub cgu_user_name: &'a str,
|
||||
pub cgu_name: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_unknown_reuse_kind)]
|
||||
pub struct UnknownReuseKind {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub kind: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_missing_query_depgraph)]
|
||||
pub struct MissingQueryDepGraph {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_malformed_cgu_name)]
|
||||
pub struct MalformedCguName {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub user_path: String,
|
||||
pub crate_name: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_no_module_named)]
|
||||
pub struct NoModuleNamed<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub user_path: &'a str,
|
||||
pub cgu_name: Symbol,
|
||||
pub cgu_names: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_field_associated_value_expected)]
|
||||
pub struct FieldAssociatedValueExpected {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_no_field)]
|
||||
pub struct NoField {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_lib_def_write_failure)]
|
||||
pub struct LibDefWriteFailure {
|
||||
|
@ -46,6 +46,7 @@ use std::collections::BTreeSet;
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub mod assert_module_sources;
|
||||
pub mod back;
|
||||
pub mod base;
|
||||
pub mod codegen_attrs;
|
||||
|
@ -46,8 +46,6 @@ incremental_delete_partial = failed to delete partly initialized session dir `{$
|
||||
|
||||
incremental_delete_workproduct = file-system error deleting outdated file `{$path}`: {$err}
|
||||
|
||||
incremental_field_associated_value_expected = associated value expected for `{$name}`
|
||||
|
||||
incremental_finalize = error finalizing incremental compilation session directory `{$path}`: {$err}
|
||||
|
||||
incremental_finalized_gc_failed =
|
||||
@ -63,25 +61,15 @@ incremental_load_dep_graph = could not load dep-graph from `{$path}`: {$err}
|
||||
|
||||
incremental_lock_unsupported =
|
||||
the filesystem for the incremental path at {$session_dir} does not appear to support locking, consider changing the incremental path to a filesystem that supports locking or disable incremental compilation
|
||||
incremental_malformed_cgu_name =
|
||||
found malformed codegen unit name `{$user_path}`. codegen units names must always start with the name of the crate (`{$crate_name}` in this case).
|
||||
|
||||
incremental_missing_depnode = missing `DepNode` variant
|
||||
|
||||
incremental_missing_if_this_changed = no `#[rustc_if_this_changed]` annotation detected
|
||||
|
||||
incremental_missing_query_depgraph =
|
||||
found CGU-reuse attribute but `-Zquery-dep-graph` was not specified
|
||||
|
||||
incremental_move_dep_graph = failed to move dependency graph from `{$from}` to `{$to}`: {$err}
|
||||
|
||||
incremental_no_cfg = no cfg attribute
|
||||
|
||||
incremental_no_field = no field `{$name}`
|
||||
|
||||
incremental_no_module_named =
|
||||
no module named `{$user_path}` (mangled: {$cgu_name}). available modules: {$cgu_names}
|
||||
|
||||
incremental_no_path = no path from `{$source}` to `{$target}`
|
||||
|
||||
incremental_not_clean = `{$dep_node_str}` should be clean but is not
|
||||
@ -107,8 +95,6 @@ incremental_undefined_clean_dirty_assertions_item =
|
||||
|
||||
incremental_unknown_item = unknown item `{$name}`
|
||||
|
||||
incremental_unknown_reuse_kind = unknown cgu-reuse-kind `{$kind}` specified
|
||||
|
||||
incremental_unrecognized_depnode = unrecognized `DepNode` variant: {$name}
|
||||
|
||||
incremental_unrecognized_depnode_label = dep-node label `{$label}` not recognized
|
||||
|
@ -40,56 +40,6 @@ pub struct NoPath {
|
||||
pub source: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_unknown_reuse_kind)]
|
||||
pub struct UnknownReuseKind {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub kind: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_missing_query_depgraph)]
|
||||
pub struct MissingQueryDepGraph {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_malformed_cgu_name)]
|
||||
pub struct MalformedCguName {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub user_path: String,
|
||||
pub crate_name: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_no_module_named)]
|
||||
pub struct NoModuleNamed<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub user_path: &'a str,
|
||||
pub cgu_name: Symbol,
|
||||
pub cgu_names: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_field_associated_value_expected)]
|
||||
pub struct FieldAssociatedValueExpected {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_no_field)]
|
||||
pub struct NoField {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(incremental_assertion_auto)]
|
||||
pub struct AssertionAuto<'a> {
|
||||
|
@ -16,7 +16,6 @@ extern crate rustc_middle;
|
||||
extern crate tracing;
|
||||
|
||||
mod assert_dep_graph;
|
||||
pub mod assert_module_sources;
|
||||
mod errors;
|
||||
mod persist;
|
||||
|
||||
|
@ -957,10 +957,9 @@ pub fn start_codegen<'tcx>(
|
||||
codegen_backend.codegen_crate(tcx, metadata, need_metadata_module)
|
||||
});
|
||||
|
||||
// Don't run these test assertions when not doing codegen. Compiletest tries to build
|
||||
// Don't run this test assertions when not doing codegen. Compiletest tries to build
|
||||
// build-fail tests in check mode first and expects it to not give an error in that case.
|
||||
if tcx.sess.opts.output_types.should_codegen() {
|
||||
rustc_incremental::assert_module_sources::assert_module_sources(tcx);
|
||||
rustc_symbol_mangling::test::report_symbol_names(tcx);
|
||||
}
|
||||
|
||||
|
@ -5,9 +5,6 @@ session_cannot_enable_crt_static_linux = sanitizer is incompatible with statical
|
||||
|
||||
session_cannot_mix_and_match_sanitizers = `-Zsanitizer={$first}` is incompatible with `-Zsanitizer={$second}`
|
||||
|
||||
session_cgu_not_recorded =
|
||||
CGU-reuse for `{$cgu_user_name}` is (mangled: `{$cgu_name}`) was not recorded
|
||||
|
||||
session_cli_feature_diagnostic_help =
|
||||
add `-Zcrate-attr="feature({$feature})"` to the command-line options to enable
|
||||
|
||||
@ -34,12 +31,6 @@ session_hexadecimal_float_literal_not_supported = hexadecimal float literal is n
|
||||
session_incompatible_linker_flavor = linker flavor `{$flavor}` is incompatible with the current target
|
||||
.note = compatible flavors are: {$compatible_list}
|
||||
|
||||
session_incorrect_cgu_reuse_type =
|
||||
CGU-reuse for `{$cgu_user_name}` is `{$actual_reuse}` but should be {$at_least ->
|
||||
[one] {"at least "}
|
||||
*[other] {""}
|
||||
}`{$expected_reuse}`
|
||||
|
||||
session_instrumentation_not_supported = {$us} instrumentation is not supported for this target
|
||||
|
||||
session_int_literal_too_large = integer literal is too large
|
||||
|
@ -1,136 +0,0 @@
|
||||
//! Some facilities for tracking how codegen-units are reused during incremental
|
||||
//! compilation. This is used for incremental compilation tests and debug
|
||||
//! output.
|
||||
|
||||
use crate::errors::{CguNotRecorded, IncorrectCguReuseType};
|
||||
use crate::Session;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
|
||||
use rustc_span::{Span, Symbol};
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::{self};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
|
||||
pub enum CguReuse {
|
||||
No,
|
||||
PreLto,
|
||||
PostLto,
|
||||
}
|
||||
|
||||
impl fmt::Display for CguReuse {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
CguReuse::No => write!(f, "No"),
|
||||
CguReuse::PreLto => write!(f, "PreLto "),
|
||||
CguReuse::PostLto => write!(f, "PostLto "),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagnosticArg for CguReuse {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Owned(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum ComparisonKind {
|
||||
Exact,
|
||||
AtLeast,
|
||||
}
|
||||
|
||||
struct TrackerData {
|
||||
actual_reuse: FxHashMap<String, CguReuse>,
|
||||
expected_reuse: FxHashMap<String, (String, SendSpan, CguReuse, ComparisonKind)>,
|
||||
}
|
||||
|
||||
// Span does not implement `Send`, so we can't just store it in the shared
|
||||
// `TrackerData` object. Instead of splitting up `TrackerData` into shared and
|
||||
// non-shared parts (which would be complicated), we just mark the `Span` here
|
||||
// explicitly as `Send`. That's safe because the span data here is only ever
|
||||
// accessed from the main thread.
|
||||
struct SendSpan(Span);
|
||||
unsafe impl Send for SendSpan {}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CguReuseTracker {
|
||||
data: Option<Arc<Mutex<TrackerData>>>,
|
||||
}
|
||||
|
||||
impl CguReuseTracker {
|
||||
pub fn new() -> CguReuseTracker {
|
||||
let data =
|
||||
TrackerData { actual_reuse: Default::default(), expected_reuse: Default::default() };
|
||||
|
||||
CguReuseTracker { data: Some(Arc::new(Mutex::new(data))) }
|
||||
}
|
||||
|
||||
pub fn new_disabled() -> CguReuseTracker {
|
||||
CguReuseTracker { data: None }
|
||||
}
|
||||
|
||||
pub fn set_actual_reuse(&self, cgu_name: &str, kind: CguReuse) {
|
||||
if let Some(ref data) = self.data {
|
||||
debug!("set_actual_reuse({cgu_name:?}, {kind:?})");
|
||||
|
||||
let prev_reuse = data.lock().unwrap().actual_reuse.insert(cgu_name.to_string(), kind);
|
||||
|
||||
if let Some(prev_reuse) = prev_reuse {
|
||||
// The only time it is legal to overwrite reuse state is when
|
||||
// we discover during ThinLTO that we can actually reuse the
|
||||
// post-LTO version of a CGU.
|
||||
assert_eq!(prev_reuse, CguReuse::PreLto);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_expectation(
|
||||
&self,
|
||||
cgu_name: Symbol,
|
||||
cgu_user_name: &str,
|
||||
error_span: Span,
|
||||
expected_reuse: CguReuse,
|
||||
comparison_kind: ComparisonKind,
|
||||
) {
|
||||
if let Some(ref data) = self.data {
|
||||
debug!("set_expectation({cgu_name:?}, {expected_reuse:?}, {comparison_kind:?})");
|
||||
let mut data = data.lock().unwrap();
|
||||
|
||||
data.expected_reuse.insert(
|
||||
cgu_name.to_string(),
|
||||
(cgu_user_name.to_string(), SendSpan(error_span), expected_reuse, comparison_kind),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_expected_reuse(&self, sess: &Session) {
|
||||
if let Some(ref data) = self.data {
|
||||
let data = data.lock().unwrap();
|
||||
|
||||
for (cgu_name, &(ref cgu_user_name, ref error_span, expected_reuse, comparison_kind)) in
|
||||
&data.expected_reuse
|
||||
{
|
||||
if let Some(&actual_reuse) = data.actual_reuse.get(cgu_name) {
|
||||
let (error, at_least) = match comparison_kind {
|
||||
ComparisonKind::Exact => (expected_reuse != actual_reuse, false),
|
||||
ComparisonKind::AtLeast => (actual_reuse < expected_reuse, true),
|
||||
};
|
||||
|
||||
if error {
|
||||
let at_least = if at_least { 1 } else { 0 };
|
||||
IncorrectCguReuseType {
|
||||
span: error_span.0,
|
||||
cgu_user_name,
|
||||
actual_reuse,
|
||||
expected_reuse,
|
||||
at_least,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
sess.emit_fatal(CguNotRecorded { cgu_user_name, cgu_name });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use crate::cgu_reuse_tracker::CguReuse;
|
||||
use crate::parse::ParseSess;
|
||||
use rustc_ast::token;
|
||||
use rustc_ast::util::literal::LitError;
|
||||
@ -9,24 +8,6 @@ use rustc_macros::Diagnostic;
|
||||
use rustc_span::{BytePos, Span, Symbol};
|
||||
use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple};
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(session_incorrect_cgu_reuse_type)]
|
||||
pub struct IncorrectCguReuseType<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub cgu_user_name: &'a str,
|
||||
pub actual_reuse: CguReuse,
|
||||
pub expected_reuse: CguReuse,
|
||||
pub at_least: u8,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(session_cgu_not_recorded)]
|
||||
pub struct CguNotRecorded<'a> {
|
||||
pub cgu_user_name: &'a str,
|
||||
pub cgu_name: &'a str,
|
||||
}
|
||||
|
||||
pub struct FeatureGateError {
|
||||
pub span: MultiSpan,
|
||||
pub explain: DiagnosticMessage,
|
||||
|
@ -23,7 +23,6 @@ extern crate tracing;
|
||||
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
|
||||
use rustc_fluent_macro::fluent_messages;
|
||||
|
||||
pub mod cgu_reuse_tracker;
|
||||
pub mod utils;
|
||||
pub use lint::{declare_lint, declare_lint_pass, declare_tool_lint, impl_lint_pass};
|
||||
pub use rustc_lint_defs as lint;
|
||||
|
@ -1,4 +1,3 @@
|
||||
use crate::cgu_reuse_tracker::CguReuseTracker;
|
||||
use crate::code_stats::CodeStats;
|
||||
pub use crate::code_stats::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
|
||||
use crate::config::{
|
||||
@ -153,9 +152,6 @@ pub struct Session {
|
||||
pub io: CompilerIO,
|
||||
|
||||
incr_comp_session: OneThread<RefCell<IncrCompSession>>,
|
||||
/// Used for incremental compilation tests. Will only be populated if
|
||||
/// `-Zquery-dep-graph` is specified.
|
||||
pub cgu_reuse_tracker: CguReuseTracker,
|
||||
|
||||
/// Used by `-Z self-profile`.
|
||||
pub prof: SelfProfilerRef,
|
||||
@ -1431,12 +1427,6 @@ pub fn build_session(
|
||||
});
|
||||
let print_fuel = AtomicU64::new(0);
|
||||
|
||||
let cgu_reuse_tracker = if sopts.unstable_opts.query_dep_graph {
|
||||
CguReuseTracker::new()
|
||||
} else {
|
||||
CguReuseTracker::new_disabled()
|
||||
};
|
||||
|
||||
let prof = SelfProfilerRef::new(
|
||||
self_profiler,
|
||||
sopts.unstable_opts.time_passes.then(|| sopts.unstable_opts.time_passes_format),
|
||||
@ -1461,7 +1451,6 @@ pub fn build_session(
|
||||
sysroot,
|
||||
io,
|
||||
incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
|
||||
cgu_reuse_tracker,
|
||||
prof,
|
||||
perf_stats: PerfStats {
|
||||
symbol_hash_time: Lock::new(Duration::from_secs(0)),
|
||||
|
Loading…
Reference in New Issue
Block a user