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:
bors 2023-10-13 00:09:30 +00:00
commit 130ff8cb6c
19 changed files with 274 additions and 322 deletions

View File

@ -3650,6 +3650,7 @@ dependencies = [
"serde_json",
"smallvec",
"tempfile",
"thin-vec",
"thorin-dwp",
"tracing",
"windows",

View File

@ -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 }
}

View File

@ -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;
}
}

View File

@ -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" }

View File

@ -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

View File

@ -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 });
}
}
}
}
}

View File

@ -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 =

View File

@ -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;
}

View File

@ -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 {

View File

@ -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;

View File

@ -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

View File

@ -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> {

View File

@ -16,7 +16,6 @@ extern crate rustc_middle;
extern crate tracing;
mod assert_dep_graph;
pub mod assert_module_sources;
mod errors;
mod persist;

View File

@ -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);
}

View File

@ -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

View File

@ -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 });
}
}
}
}
}

View File

@ -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,

View File

@ -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;

View File

@ -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)),