Skip to content

Commit 1fc6b19

Browse files
committed
Compute quoted args for debuginfo at most once per session
1 parent 99262f5 commit 1fc6b19

File tree

9 files changed

+90
-23
lines changed

9 files changed

+90
-23
lines changed

compiler/rustc_codegen_llvm/src/back/write.rs

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ use rustc_codegen_ssa::back::write::{
1616
TargetMachineFactoryFn,
1717
};
1818
use rustc_codegen_ssa::base::wants_wasm_eh;
19-
use rustc_codegen_ssa::debuginfo::command_line_args::quote_command_line_args;
2019
use rustc_codegen_ssa::traits::*;
2120
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, ModuleKind};
2221
use rustc_data_structures::profiling::SelfProfilerRef;
2322
use rustc_data_structures::small_c_str::SmallCStr;
2423
use rustc_errors::{DiagCtxtHandle, Level};
2524
use rustc_fs_util::{link_or_copy, path_to_c_string};
25+
use rustc_middle::middle::debuginfo::CommandLineArgsForDebuginfo;
2626
use rustc_middle::ty::TyCtxt;
2727
use rustc_session::Session;
2828
use rustc_session::config::{
@@ -108,7 +108,11 @@ pub(crate) fn create_informational_target_machine(
108108
sess: &Session,
109109
only_base_features: bool,
110110
) -> OwnedTargetMachine {
111-
let config = TargetMachineFactoryConfig { split_dwarf_file: None, output_obj_file: None };
111+
let config = TargetMachineFactoryConfig {
112+
split_dwarf_file: None,
113+
output_obj_file: None,
114+
args_for_debuginfo: None,
115+
};
112116
// Can't use query system here quite yet because this function is invoked before the query
113117
// system/tcx is set up.
114118
let features = llvm_util::global_llvm_features(sess, false, only_base_features);
@@ -133,7 +137,12 @@ pub(crate) fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> OwnedTar
133137
mod_name,
134138
tcx.sess.invocation_temp.as_deref(),
135139
));
136-
let config = TargetMachineFactoryConfig { split_dwarf_file, output_obj_file };
140+
141+
let config = TargetMachineFactoryConfig {
142+
split_dwarf_file,
143+
output_obj_file,
144+
args_for_debuginfo: Some(Arc::clone(tcx.args_for_debuginfo())),
145+
};
137146

138147
target_machine_factory(
139148
tcx.sess,
@@ -253,19 +262,6 @@ pub(crate) fn target_machine_factory(
253262

254263
let use_emulated_tls = matches!(sess.tls_model(), TlsModel::Emulated);
255264

256-
// Command-line information to be included in the target machine.
257-
// This seems to only be used for embedding in PDB debuginfo files.
258-
// FIXME(Zalathar): Maybe skip this for non-PDB targets?
259-
let argv0 = std::env::current_exe()
260-
.unwrap_or_default()
261-
.into_os_string()
262-
.into_string()
263-
.unwrap_or_default();
264-
let command_line_args = quote_command_line_args(&sess.expanded_args);
265-
// Self-profile counter for the number of bytes produced by command-line quoting.
266-
// Values are summed, so the summary result is cumulative across all TM factories.
267-
sess.prof.artifact_size("quoted_command_line_args", "-", command_line_args.len() as u64);
268-
269265
let debuginfo_compression = sess.opts.debuginfo_compression.to_string();
270266
match sess.opts.debuginfo_compression {
271267
rustc_session::config::DebugInfoCompression::Zlib => {
@@ -304,6 +300,14 @@ pub(crate) fn target_machine_factory(
304300
let split_dwarf_file = path_to_cstring_helper(config.split_dwarf_file);
305301
let output_obj_file = path_to_cstring_helper(config.output_obj_file);
306302

303+
let (argv0, quoted_args) = config
304+
.args_for_debuginfo
305+
.as_deref()
306+
.map(|CommandLineArgsForDebuginfo { argv0, quoted_args }| {
307+
(argv0.as_str(), quoted_args.as_str())
308+
})
309+
.unwrap_or_default();
310+
307311
OwnedTargetMachine::new(
308312
&triple,
309313
&cpu,
@@ -326,8 +330,8 @@ pub(crate) fn target_machine_factory(
326330
&output_obj_file,
327331
&debuginfo_compression,
328332
use_emulated_tls,
329-
&argv0,
330-
&command_line_args,
333+
argv0,
334+
quoted_args,
331335
use_wasm_eh,
332336
)
333337
})

compiler/rustc_codegen_ssa/src/back/write.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use rustc_incremental::{
2525
use rustc_metadata::fs::copy_to_stdout;
2626
use rustc_middle::bug;
2727
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
28+
use rustc_middle::middle::debuginfo::CommandLineArgsForDebuginfo;
2829
use rustc_middle::ty::TyCtxt;
2930
use rustc_session::Session;
3031
use rustc_session::config::{
@@ -283,6 +284,10 @@ pub struct TargetMachineFactoryConfig {
283284
/// The name of the output object file. Used for setting OutputFilenames in target options
284285
/// so that LLVM can emit the CodeView S_OBJNAME record in pdb files
285286
pub output_obj_file: Option<PathBuf>,
287+
288+
/// Contains a copy of [`TyCtxt::args_for_debuginfo`] for codegen,
289+
/// or `None` if the target machine is informational only.
290+
pub args_for_debuginfo: Option<Arc<CommandLineArgsForDebuginfo>>,
286291
}
287292

288293
impl TargetMachineFactoryConfig {
@@ -306,7 +311,12 @@ impl TargetMachineFactoryConfig {
306311
module_name,
307312
cgcx.invocation_temp.as_deref(),
308313
));
309-
TargetMachineFactoryConfig { split_dwarf_file, output_obj_file }
314+
315+
TargetMachineFactoryConfig {
316+
split_dwarf_file,
317+
output_obj_file,
318+
args_for_debuginfo: Some(Arc::clone(&cgcx.args_for_debuginfo)),
319+
}
310320
}
311321
}
312322

@@ -350,7 +360,7 @@ pub struct CodegenContext<B: WriteBackendMethods> {
350360
/// This will only be used within debug info, e.g. in the pdb file on windows
351361
/// This is mainly useful for other tools that reads that debuginfo to figure out
352362
/// how to call the compiler with the same arguments.
353-
pub expanded_args: Vec<String>,
363+
pub args_for_debuginfo: Arc<CommandLineArgsForDebuginfo>,
354364

355365
/// Emitter to use for diagnostics produced during codegen.
356366
pub diag_emitter: SharedEmitter,
@@ -1153,7 +1163,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
11531163
remark: sess.opts.cg.remark.clone(),
11541164
remark_dir,
11551165
incr_comp_session_dir: sess.incr_comp_session_dir_opt().map(|r| r.clone()),
1156-
expanded_args: tcx.sess.expanded_args.clone(),
1166+
args_for_debuginfo: Arc::clone(tcx.args_for_debuginfo()),
11571167
diag_emitter: shared_emitter.clone(),
11581168
output_filenames: Arc::clone(tcx.output_filenames(())),
11591169
module_config: regular_config,

compiler/rustc_codegen_ssa/src/debuginfo/command_line_args/mod.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,42 @@
1+
use std::sync::Arc;
2+
3+
use rustc_middle::middle::debuginfo::CommandLineArgsForDebuginfo;
4+
use rustc_middle::ty::TyCtxt;
5+
use rustc_middle::util::Providers;
6+
17
#[cfg(test)]
28
mod tests;
39

10+
pub(crate) fn provide(providers: &mut Providers) {
11+
providers.hooks.args_for_debuginfo = args_for_debuginfo;
12+
}
13+
14+
/// Hook implementation for [`TyCtxt::args_for_debuginfo`].
15+
fn args_for_debuginfo<'tcx>(tcx: TyCtxt<'tcx>) -> &'tcx Arc<CommandLineArgsForDebuginfo> {
16+
tcx.args_for_debuginfo_cache.get_or_init(|| {
17+
// Command-line information to be included in the target machine.
18+
// This seems to only be used for embedding in PDB debuginfo files.
19+
// FIXME(Zalathar): Maybe skip this for non-PDB targets?
20+
let argv0 = std::env::current_exe()
21+
.unwrap_or_default()
22+
.into_os_string()
23+
.into_string()
24+
.unwrap_or_default();
25+
let quoted_args = quote_command_line_args(&tcx.sess.expanded_args);
26+
27+
// Self-profile counter for the number of bytes produced by command-line quoting.
28+
tcx.prof.artifact_size("quoted_command_line_args", "-", quoted_args.len() as u64);
29+
30+
Arc::new(CommandLineArgsForDebuginfo { argv0, quoted_args })
31+
})
32+
}
33+
434
/// Joins command-line arguments into a single space-separated string, quoting
535
/// and escaping individual arguments as necessary.
636
///
737
/// The result is intended to be informational, for embedding in debug metadata,
838
/// and might not be properly quoted/escaped for actual command-line use.
9-
pub fn quote_command_line_args(args: &[String]) -> String {
39+
fn quote_command_line_args(args: &[String]) -> String {
1040
// Start with a decent-sized buffer, since rustc invocations tend to be long.
1141
let mut buf = String::with_capacity(128);
1242

compiler/rustc_codegen_ssa/src/debuginfo/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use rustc_middle::bug;
33
use rustc_middle::ty::layout::{IntegerExt, PrimitiveExt, TyAndLayout};
44
use rustc_middle::ty::{self, Ty, TyCtxt};
55

6-
pub mod command_line_args;
6+
pub(crate) mod command_line_args;
77
pub mod type_names;
88

99
/// Returns true if we want to generate a DW_TAG_enumeration_type description for

compiler/rustc_codegen_ssa/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ pub enum CodegenErrors {
271271
pub fn provide(providers: &mut Providers) {
272272
crate::back::symbol_export::provide(providers);
273273
crate::base::provide(providers);
274+
crate::debuginfo::command_line_args::provide(providers);
274275
crate::target_features::provide(providers);
275276
crate::codegen_attrs::provide(providers);
276277
providers.queries.global_backend_features = |_tcx: TyCtxt<'_>, ()| vec![];

compiler/rustc_middle/src/hooks/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
//! similar to queries, but queries come with a lot of machinery for caching and incremental
44
//! compilation, whereas hooks are just plain function pointers without any of the query magic.
55
6+
use std::sync::Arc;
7+
68
use rustc_hir::def_id::{DefId, DefPathHash};
79
use rustc_session::StableCrateId;
810
use rustc_span::def_id::{CrateNum, LocalDefId};
911
use rustc_span::{ExpnHash, ExpnId};
1012

13+
use crate::middle::debuginfo::CommandLineArgsForDebuginfo;
1114
use crate::mir;
1215
use crate::ty::{Ty, TyCtxt};
1316

@@ -102,6 +105,13 @@ declare_hooks! {
102105
/// Ensure the given scalar is valid for the given type.
103106
/// This checks non-recursive runtime validity.
104107
hook validate_scalar_in_layout(scalar: crate::ty::ScalarInt, ty: Ty<'tcx>) -> bool;
108+
109+
/// Builds a quoted form of _all_ command-line args, for inclusion in some
110+
/// forms of debuginfo (specifically PDB).
111+
///
112+
/// This needs to _not_ be a query, because it would ruin incremental
113+
/// compilation for CGUs that would otherwise be considered up-to-date.
114+
hook args_for_debuginfo() -> &'tcx Arc<CommandLineArgsForDebuginfo>;
105115
}
106116

107117
#[cold]
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#[derive(Debug)]
2+
pub struct CommandLineArgsForDebuginfo {
3+
pub argv0: String,
4+
pub quoted_args: String,
5+
}

compiler/rustc_middle/src/middle/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
pub mod codegen_fn_attrs;
22
pub mod debugger_visualizer;
3+
pub mod debuginfo;
34
pub mod dependency_format;
45
pub mod exported_symbols;
56
pub mod lang_items;

compiler/rustc_middle/src/ty/context.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ use crate::infer::canonical::{CanonicalParamEnvCache, CanonicalVarKind, Canonica
6666
use crate::lint::lint_level;
6767
use crate::metadata::ModChild;
6868
use crate::middle::codegen_fn_attrs::{CodegenFnAttrs, TargetFeature};
69+
use crate::middle::debuginfo::CommandLineArgsForDebuginfo;
6970
use crate::middle::resolve_bound_vars;
7071
use crate::mir::interpret::{self, Allocation, ConstAllocation};
7172
use crate::mir::{Body, Local, Place, PlaceElem, ProjectionKind, Promoted};
@@ -1593,6 +1594,10 @@ pub struct GlobalCtxt<'tcx> {
15931594

15941595
/// A jobserver reference used to release then acquire a token while waiting on a query.
15951596
pub jobserver_proxy: Arc<Proxy>,
1597+
1598+
/// Memoization slot for the [`TyCtxt::args_for_debuginfo`] hook, which needs
1599+
/// to not be a query, but should still be cached after being computed once.
1600+
pub args_for_debuginfo_cache: OnceLock<Arc<CommandLineArgsForDebuginfo>>,
15961601
}
15971602

15981603
impl<'tcx> GlobalCtxt<'tcx> {
@@ -1818,6 +1823,7 @@ impl<'tcx> TyCtxt<'tcx> {
18181823
alloc_map: interpret::AllocMap::new(),
18191824
current_gcx,
18201825
jobserver_proxy,
1826+
args_for_debuginfo_cache: OnceLock::new(),
18211827
});
18221828

18231829
// This is a separate function to work around a crash with parallel rustc (#135870)

0 commit comments

Comments
 (0)