Skip to content

Commit 84288ed

Browse files
committed
Auto merge of #97500 - GuillaumeGomez:rollup-ms1bvps, r=GuillaumeGomez
Rollup of 5 pull requests Successful merges: - #96950 (Add regression test for #96395) - #97028 (Add support for embedding pretty printers via `#[debugger_visualizer]` attribute) - #97478 (Remove FIXME on `ExtCtxt::fn_decl()`) - #97479 (Make some tests check-pass) - #97482 (ptr::invalid is not equivalent to a int2ptr cast) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 14f477e + 774d7ce commit 84288ed

38 files changed

+482
-218
lines changed

compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs

+54-2
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@ use crate::llvm;
55
use crate::builder::Builder;
66
use crate::common::CodegenCx;
77
use crate::value::Value;
8+
use rustc_codegen_ssa::base::collect_debugger_visualizers_transitive;
89
use rustc_codegen_ssa::traits::*;
10+
use rustc_hir::def_id::LOCAL_CRATE;
911
use rustc_middle::bug;
10-
use rustc_session::config::DebugInfo;
12+
use rustc_session::config::{CrateType, DebugInfo};
1113

1214
use rustc_span::symbol::sym;
15+
use rustc_span::DebuggerVisualizerType;
1316

1417
/// Inserts a side-effect free instruction sequence that makes sure that the
1518
/// .debug_gdb_scripts global is referenced, so it isn't removed by the linker.
@@ -37,9 +40,33 @@ pub fn get_or_insert_gdb_debug_scripts_section_global<'ll>(cx: &CodegenCx<'ll, '
3740

3841
section_var.unwrap_or_else(|| {
3942
let section_name = b".debug_gdb_scripts\0";
40-
let section_contents = b"\x01gdb_load_rust_pretty_printers.py\0";
43+
let mut section_contents = Vec::new();
44+
45+
// Add the pretty printers for the standard library first.
46+
section_contents.extend_from_slice(b"\x01gdb_load_rust_pretty_printers.py\0");
47+
48+
// Next, add the pretty printers that were specified via the `#[debugger_visualizer]` attribute.
49+
let visualizers = collect_debugger_visualizers_transitive(
50+
cx.tcx,
51+
DebuggerVisualizerType::GdbPrettyPrinter,
52+
);
53+
let crate_name = cx.tcx.crate_name(LOCAL_CRATE);
54+
for (index, visualizer) in visualizers.iter().enumerate() {
55+
// The initial byte `4` instructs GDB that the following pretty printer
56+
// is defined inline as opposed to in a standalone file.
57+
section_contents.extend_from_slice(b"\x04");
58+
let vis_name = format!("pretty-printer-{}-{}\n", crate_name.as_str(), index);
59+
section_contents.extend_from_slice(vis_name.as_bytes());
60+
section_contents.extend_from_slice(&visualizer.src);
61+
62+
// The final byte `0` tells GDB that the pretty printer has been
63+
// fully defined and can continue searching for additional
64+
// pretty printers.
65+
section_contents.extend_from_slice(b"\0");
66+
}
4167

4268
unsafe {
69+
let section_contents = section_contents.as_slice();
4370
let llvm_type = cx.type_array(cx.type_i8(), section_contents.len() as u64);
4471

4572
let section_var = cx
@@ -62,7 +89,32 @@ pub fn needs_gdb_debug_scripts_section(cx: &CodegenCx<'_, '_>) -> bool {
6289
let omit_gdb_pretty_printer_section =
6390
cx.tcx.sess.contains_name(cx.tcx.hir().krate_attrs(), sym::omit_gdb_pretty_printer_section);
6491

92+
// To ensure the section `__rustc_debug_gdb_scripts_section__` will not create
93+
// ODR violations at link time, this section will not be emitted for rlibs since
94+
// each rlib could produce a different set of visualizers that would be embedded
95+
// in the `.debug_gdb_scripts` section. For that reason, we make sure that the
96+
// section is only emitted for leaf crates.
97+
let embed_visualizers = cx.sess().crate_types().iter().any(|&crate_type| match crate_type {
98+
CrateType::Executable | CrateType::Dylib | CrateType::Cdylib | CrateType::Staticlib => {
99+
// These are crate types for which we will embed pretty printers since they
100+
// are treated as leaf crates.
101+
true
102+
}
103+
CrateType::ProcMacro => {
104+
// We could embed pretty printers for proc macro crates too but it does not
105+
// seem like a good default, since this is a rare use case and we don't
106+
// want to slow down the common case.
107+
false
108+
}
109+
CrateType::Rlib => {
110+
// As per the above description, embedding pretty printers for rlibs could
111+
// lead to ODR violations so we skip this crate type as well.
112+
false
113+
}
114+
});
115+
65116
!omit_gdb_pretty_printer_section
66117
&& cx.sess().opts.debuginfo != DebugInfo::None
67118
&& cx.sess().target.emit_debug_gdb_scripts
119+
&& embed_visualizers
68120
}

compiler/rustc_codegen_ssa/src/back/link.rs

+34-40
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_data_structures::memmap::Mmap;
55
use rustc_data_structures::temp_dir::MaybeTempDir;
66
use rustc_errors::{ErrorGuaranteed, Handler};
77
use rustc_fs_util::fix_windows_verbatim_for_gcc;
8-
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
8+
use rustc_hir::def_id::CrateNum;
99
use rustc_middle::middle::dependency_format::Linkage;
1010
use rustc_middle::middle::exported_symbols::SymbolExportKind;
1111
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip};
@@ -18,6 +18,7 @@ use rustc_session::utils::NativeLibKind;
1818
/// need out of the shared crate context before we get rid of it.
1919
use rustc_session::{filesearch, Session};
2020
use rustc_span::symbol::Symbol;
21+
use rustc_span::DebuggerVisualizerFile;
2122
use rustc_target::spec::crt_objects::{CrtObjects, CrtObjectsFallback};
2223
use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor, SplitDebuginfo};
2324
use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Target};
@@ -37,6 +38,7 @@ use regex::Regex;
3738
use tempfile::Builder as TempFileBuilder;
3839

3940
use std::borrow::Borrow;
41+
use std::collections::BTreeSet;
4042
use std::ffi::OsString;
4143
use std::fs::{File, OpenOptions};
4244
use std::io::{BufWriter, Write};
@@ -2099,14 +2101,16 @@ fn add_order_independent_options(
20992101
// Pass optimization flags down to the linker.
21002102
cmd.optimize();
21012103

2102-
let debugger_visualizer_paths = if sess.target.is_like_msvc {
2103-
collect_debugger_visualizers(tmpdir, sess, &codegen_results.crate_info)
2104-
} else {
2105-
Vec::new()
2106-
};
2104+
// Gather the set of NatVis files, if any, and write them out to a temp directory.
2105+
let natvis_visualizers = collect_natvis_visualizers(
2106+
tmpdir,
2107+
sess,
2108+
&codegen_results.crate_info.local_crate_name,
2109+
&codegen_results.crate_info.natvis_debugger_visualizers,
2110+
);
21072111

2108-
// Pass debuginfo and strip flags down to the linker.
2109-
cmd.debuginfo(strip_value(sess), &debugger_visualizer_paths);
2112+
// Pass debuginfo, NatVis debugger visualizers and strip flags down to the linker.
2113+
cmd.debuginfo(strip_value(sess), &natvis_visualizers);
21102114

21112115
// We want to prevent the compiler from accidentally leaking in any system libraries,
21122116
// so by default we tell linkers not to link to any default libraries.
@@ -2125,43 +2129,33 @@ fn add_order_independent_options(
21252129
add_rpath_args(cmd, sess, codegen_results, out_filename);
21262130
}
21272131

2128-
// Write the debugger visualizer files for each crate to the temp directory and gather the file paths.
2129-
fn collect_debugger_visualizers(
2132+
// Write the NatVis debugger visualizer files for each crate to the temp directory and gather the file paths.
2133+
fn collect_natvis_visualizers(
21302134
tmpdir: &Path,
21312135
sess: &Session,
2132-
crate_info: &CrateInfo,
2136+
crate_name: &Symbol,
2137+
natvis_debugger_visualizers: &BTreeSet<DebuggerVisualizerFile>,
21332138
) -> Vec<PathBuf> {
2134-
let mut visualizer_paths = Vec::new();
2135-
let debugger_visualizers = &crate_info.debugger_visualizers;
2136-
let mut index = 0;
2139+
let mut visualizer_paths = Vec::with_capacity(natvis_debugger_visualizers.len());
21372140

2138-
for (&cnum, visualizers) in debugger_visualizers {
2139-
let crate_name = if cnum == LOCAL_CRATE {
2140-
crate_info.local_crate_name.as_str()
2141-
} else {
2142-
crate_info.crate_name[&cnum].as_str()
2143-
};
2141+
for (index, visualizer) in natvis_debugger_visualizers.iter().enumerate() {
2142+
let visualizer_out_file = tmpdir.join(format!("{}-{}.natvis", crate_name.as_str(), index));
21442143

2145-
for visualizer in visualizers {
2146-
let visualizer_out_file = tmpdir.join(format!("{}-{}.natvis", crate_name, index));
2147-
2148-
match fs::write(&visualizer_out_file, &visualizer.src) {
2149-
Ok(()) => {
2150-
visualizer_paths.push(visualizer_out_file.clone());
2151-
index += 1;
2152-
}
2153-
Err(error) => {
2154-
sess.warn(
2155-
format!(
2156-
"Unable to write debugger visualizer file `{}`: {} ",
2157-
visualizer_out_file.display(),
2158-
error
2159-
)
2160-
.as_str(),
2161-
);
2162-
}
2163-
};
2164-
}
2144+
match fs::write(&visualizer_out_file, &visualizer.src) {
2145+
Ok(()) => {
2146+
visualizer_paths.push(visualizer_out_file);
2147+
}
2148+
Err(error) => {
2149+
sess.warn(
2150+
format!(
2151+
"Unable to write debugger visualizer file `{}`: {} ",
2152+
visualizer_out_file.display(),
2153+
error
2154+
)
2155+
.as_str(),
2156+
);
2157+
}
2158+
};
21652159
}
21662160
visualizer_paths
21672161
}

compiler/rustc_codegen_ssa/src/back/linker.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ pub trait Linker {
183183
fn optimize(&mut self);
184184
fn pgo_gen(&mut self);
185185
fn control_flow_guard(&mut self);
186-
fn debuginfo(&mut self, strip: Strip, debugger_visualizers: &[PathBuf]);
186+
fn debuginfo(&mut self, strip: Strip, natvis_debugger_visualizers: &[PathBuf]);
187187
fn no_crt_objects(&mut self);
188188
fn no_default_libraries(&mut self);
189189
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]);
@@ -915,7 +915,7 @@ impl<'a> Linker for MsvcLinker<'a> {
915915
self.cmd.arg("/guard:cf");
916916
}
917917

918-
fn debuginfo(&mut self, strip: Strip, debugger_visualizers: &[PathBuf]) {
918+
fn debuginfo(&mut self, strip: Strip, natvis_debugger_visualizers: &[PathBuf]) {
919919
match strip {
920920
Strip::None => {
921921
// This will cause the Microsoft linker to generate a PDB file
@@ -944,7 +944,7 @@ impl<'a> Linker for MsvcLinker<'a> {
944944
}
945945

946946
// This will cause the Microsoft linker to embed .natvis info for all crates into the PDB file
947-
for path in debugger_visualizers {
947+
for path in natvis_debugger_visualizers {
948948
let mut arg = OsString::from("/NATVIS:");
949949
arg.push(path);
950950
self.cmd.arg(arg);

compiler/rustc_codegen_ssa/src/base.rs

+48-13
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
3131
use rustc_middle::ty::query::Providers;
3232
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
3333
use rustc_session::cgu_reuse_tracker::CguReuse;
34-
use rustc_session::config::{self, EntryFnType, OutputType};
34+
use rustc_session::config::{self, CrateType, EntryFnType, OutputType};
3535
use rustc_session::Session;
3636
use rustc_span::symbol::sym;
37+
use rustc_span::{DebuggerVisualizerFile, DebuggerVisualizerType};
3738
use rustc_target::abi::{Align, VariantIdx};
3839

40+
use std::collections::BTreeSet;
3941
use std::convert::TryFrom;
4042
use std::ops::{Deref, DerefMut};
4143
use std::time::{Duration, Instant};
@@ -487,6 +489,29 @@ fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
487489
}
488490
}
489491

492+
/// This function returns all of the debugger visualizers specified for the
493+
/// current crate as well as all upstream crates transitively that match the
494+
/// `visualizer_type` specified.
495+
pub fn collect_debugger_visualizers_transitive(
496+
tcx: TyCtxt<'_>,
497+
visualizer_type: DebuggerVisualizerType,
498+
) -> BTreeSet<DebuggerVisualizerFile> {
499+
tcx.debugger_visualizers(LOCAL_CRATE)
500+
.iter()
501+
.chain(
502+
tcx.crates(())
503+
.iter()
504+
.filter(|&cnum| {
505+
let used_crate_source = tcx.used_crate_source(*cnum);
506+
used_crate_source.rlib.is_some() || used_crate_source.rmeta.is_some()
507+
})
508+
.flat_map(|&cnum| tcx.debugger_visualizers(cnum)),
509+
)
510+
.filter(|visualizer| visualizer.visualizer_type == visualizer_type)
511+
.cloned()
512+
.collect::<BTreeSet<_>>()
513+
}
514+
490515
pub fn codegen_crate<B: ExtraBackendMethods>(
491516
backend: B,
492517
tcx: TyCtxt<'_>,
@@ -838,13 +863,8 @@ impl CrateInfo {
838863
missing_lang_items: Default::default(),
839864
dependency_formats: tcx.dependency_formats(()).clone(),
840865
windows_subsystem,
841-
debugger_visualizers: Default::default(),
866+
natvis_debugger_visualizers: Default::default(),
842867
};
843-
let debugger_visualizers = tcx.debugger_visualizers(LOCAL_CRATE).clone();
844-
if !debugger_visualizers.is_empty() {
845-
info.debugger_visualizers.insert(LOCAL_CRATE, debugger_visualizers);
846-
}
847-
848868
let lang_items = tcx.lang_items();
849869

850870
let crates = tcx.crates(());
@@ -882,14 +902,29 @@ impl CrateInfo {
882902
let missing =
883903
missing.iter().cloned().filter(|&l| lang_items::required(tcx, l)).collect();
884904
info.missing_lang_items.insert(cnum, missing);
905+
}
885906

886-
// Only include debugger visualizer files from crates that will be statically linked.
887-
if used_crate_source.rlib.is_some() || used_crate_source.rmeta.is_some() {
888-
let debugger_visualizers = tcx.debugger_visualizers(cnum).clone();
889-
if !debugger_visualizers.is_empty() {
890-
info.debugger_visualizers.insert(cnum, debugger_visualizers);
891-
}
907+
let embed_visualizers = tcx.sess.crate_types().iter().any(|&crate_type| match crate_type {
908+
CrateType::Executable | CrateType::Dylib | CrateType::Cdylib => {
909+
// These are crate types for which we invoke the linker and can embed
910+
// NatVis visualizers.
911+
true
912+
}
913+
CrateType::ProcMacro => {
914+
// We could embed NatVis for proc macro crates too (to improve the debugging
915+
// experience for them) but it does not seem like a good default, since
916+
// this is a rare use case and we don't want to slow down the common case.
917+
false
892918
}
919+
CrateType::Staticlib | CrateType::Rlib => {
920+
// We don't invoke the linker for these, so we don't need to collect the NatVis for them.
921+
false
922+
}
923+
});
924+
925+
if tcx.sess.target.is_like_msvc && embed_visualizers {
926+
info.natvis_debugger_visualizers =
927+
collect_debugger_visualizers_transitive(tcx, DebuggerVisualizerType::Natvis);
893928
}
894929

895930
info

compiler/rustc_codegen_ssa/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use rustc_session::cstore::{self, CrateSource};
3636
use rustc_session::utils::NativeLibKind;
3737
use rustc_span::symbol::Symbol;
3838
use rustc_span::DebuggerVisualizerFile;
39+
use std::collections::BTreeSet;
3940
use std::path::{Path, PathBuf};
4041

4142
pub mod back;
@@ -157,7 +158,7 @@ pub struct CrateInfo {
157158
pub missing_lang_items: FxHashMap<CrateNum, Vec<LangItem>>,
158159
pub dependency_formats: Lrc<Dependencies>,
159160
pub windows_subsystem: Option<String>,
160-
pub debugger_visualizers: FxHashMap<CrateNum, Vec<DebuggerVisualizerFile>>,
161+
pub natvis_debugger_visualizers: BTreeSet<DebuggerVisualizerFile>,
161162
}
162163

163164
#[derive(Encodable, Decodable)]

compiler/rustc_expand/src/build.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ impl<'a> ExtCtxt<'a> {
514514
}
515515
}
516516

517-
// FIXME: unused `self`
517+
// `self` is unused but keep it as method for the convenience use.
518518
pub fn fn_decl(&self, inputs: Vec<ast::Param>, output: ast::FnRetTy) -> P<ast::FnDecl> {
519519
P(ast::FnDecl { inputs, output })
520520
}

compiler/rustc_feature/src/builtin_attrs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
399399

400400
// RFC #3191: #[debugger_visualizer] support
401401
gated!(
402-
debugger_visualizer, Normal, template!(List: r#"natvis_file = "...""#),
402+
debugger_visualizer, Normal, template!(List: r#"natvis_file = "...", gdb_script_file = "...""#),
403403
DuplicatesOk, experimental!(debugger_visualizer)
404404
),
405405

0 commit comments

Comments
 (0)