Skip to content

Commit

Permalink
Remove cgu_reuse_tracker from Session
Browse files Browse the repository at this point in the history
This removes a bit of global mutable state
  • Loading branch information
bjorn3 committed Sep 30, 2023
1 parent d8d47ae commit 68f99cc
Show file tree
Hide file tree
Showing 18 changed files with 284 additions and 279 deletions.
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3548,6 +3548,7 @@ dependencies = [
"serde_json",
"smallvec",
"tempfile",
"thin-vec",
"thorin-dwp",
"tracing",
"windows",
Expand Down
68 changes: 36 additions & 32 deletions compiler/rustc_codegen_cranelift/src/driver/aot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::path::PathBuf;
use std::sync::Arc;
use std::thread::JoinHandle;

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};
Expand All @@ -14,7 +15,6 @@ 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;

Expand Down Expand Up @@ -376,43 +376,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!(),
CguReuse::PostLto => {
concurrency_limiter.job_already_done();
OngoingModuleCodegen::Sync(reuse_workproduct_for_cgu(tcx, cgu))
}
})
.collect::<Vec<_>>()
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_ssa/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
24 changes: 24 additions & 0 deletions compiler/rustc_codegen_ssa/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down Expand Up @@ -39,13 +42,21 @@ 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
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]`
Expand Down Expand Up @@ -153,19 +164,30 @@ 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
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_option_gcc_only = option `-Z gcc-ld` is used even though linker flavor is not gcc
Expand Down Expand Up @@ -299,6 +321,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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,22 @@
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::{self};
use std::sync::{Arc, Mutex};
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(&CguReuseTracker)) {
tcx.dep_graph.with_ignore(|| {
if tcx.sess.opts.incremental.is_none() {
return;
Expand All @@ -43,17 +49,30 @@ 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 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(&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> {
Expand Down Expand Up @@ -129,7 +148,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,
Expand Down Expand Up @@ -169,3 +188,121 @@ 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, 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);
assert!(prev_reuse.is_none());
}
}

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 };
errors::IncorrectCguReuseType {
span: error_span.0,
cgu_user_name,
actual_reuse,
expected_reuse,
at_least,
};
}
} else {
sess.emit_fatal(errors::CguNotRecorded { cgu_user_name, cgu_name });
}
}
}
}
}
2 changes: 0 additions & 2 deletions compiler/rustc_codegen_ssa/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1965,8 +1965,6 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {
}
});

sess.cgu_reuse_tracker.check_expected_reuse(sess);

sess.abort_if_errors();

let work_products =
Expand Down
Loading

0 comments on commit 68f99cc

Please sign in to comment.