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
19 changed files with 274 additions and 322 deletions
|
@ -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…
Add table
Add a link
Reference in a new issue