Skip to content

Commit 450e99f

Browse files
committed
Auto merge of #98051 - davidtwco:split-dwarf-stabilization, r=wesleywiser
session: stabilize split debuginfo on linux Stabilize the `-Csplit-debuginfo` flag... - ...on Linux for all values of the flag. Split DWARF has been implemented for a few months, hasn't had any bug reports and has had some promising benchmarking for incremental debug build performance. - ..on other platforms for the default value. It doesn't make any sense that `-Csplit-debuginfo=packed` is unstable on Windows MSVC when that's the default behaviour, but keep the other values unstable.
2 parents 42fa8ac + cf2c492 commit 450e99f

File tree

14 files changed

+184
-60
lines changed

14 files changed

+184
-60
lines changed

compiler/rustc_session/src/config.rs

-7
Original file line numberDiff line numberDiff line change
@@ -2423,13 +2423,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
24232423

24242424
let pretty = parse_pretty(&unstable_opts, error_format);
24252425

2426-
if !unstable_opts.unstable_options
2427-
&& !target_triple.triple().contains("apple")
2428-
&& cg.split_debuginfo.is_some()
2429-
{
2430-
early_error(error_format, "`-Csplit-debuginfo` is unstable on this platform");
2431-
}
2432-
24332426
// Try to find a directory containing the Rust `src`, for more details see
24342427
// the doc comment on the `real_rust_source_base_dir` field.
24352428
let tmp_buf;

compiler/rustc_session/src/session.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use rustc_span::{sym, SourceFileHashAlgorithm, Symbol};
3131
use rustc_target::asm::InlineAsmArch;
3232
use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel};
3333
use rustc_target::spec::{
34-
SanitizerSet, SplitDebuginfo, StackProtector, Target, TargetTriple, TlsModel,
34+
DebuginfoKind, SanitizerSet, SplitDebuginfo, StackProtector, Target, TargetTriple, TlsModel,
3535
};
3636

3737
use std::cell::{self, RefCell};
@@ -670,8 +670,9 @@ impl Session {
670670
)
671671
}
672672

673+
/// Returns `true` if the target can use the current split debuginfo configuration.
673674
pub fn target_can_use_split_dwarf(&self) -> bool {
674-
!self.target.is_like_windows && !self.target.is_like_osx
675+
self.target.debuginfo_kind == DebuginfoKind::Dwarf
675676
}
676677

677678
pub fn generate_proc_macro_decls_symbol(&self, stable_crate_id: StableCrateId) -> String {
@@ -1552,6 +1553,15 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
15521553
sess.err(&format!("requested DWARF version {} is greater than 5", dwarf_version));
15531554
}
15541555
}
1556+
1557+
if !sess.target.options.supported_split_debuginfo.contains(&sess.split_debuginfo())
1558+
&& !sess.opts.unstable_opts.unstable_options
1559+
{
1560+
sess.err(&format!(
1561+
"`-Csplit-debuginfo={}` is unstable on this platform",
1562+
sess.split_debuginfo()
1563+
));
1564+
}
15551565
}
15561566

15571567
/// Holds data on the current incremental compilation session, if there is one.

compiler/rustc_target/src/spec/apple_base.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{borrow::Cow, env};
22

3-
use crate::spec::{cvs, FramePointer, SplitDebuginfo, TargetOptions};
3+
use crate::spec::{cvs, DebuginfoKind, FramePointer, SplitDebuginfo, TargetOptions};
44
use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor};
55

66
fn pre_link_args(os: &'static str, arch: &'static str, abi: &'static str) -> LinkArgs {
@@ -76,9 +76,15 @@ pub fn opts(os: &'static str, arch: &'static str, abi: &'static str) -> TargetOp
7676
eh_frame_header: false,
7777
lld_flavor: LldFlavor::Ld64,
7878

79+
debuginfo_kind: DebuginfoKind::DwarfDsym,
7980
// The historical default for macOS targets is to run `dsymutil` which
8081
// generates a packed version of debuginfo split from the main file.
8182
split_debuginfo: SplitDebuginfo::Packed,
83+
supported_split_debuginfo: Cow::Borrowed(&[
84+
SplitDebuginfo::Packed,
85+
SplitDebuginfo::Unpacked,
86+
SplitDebuginfo::Off,
87+
]),
8288

8389
// This environment variable is pretty magical but is intended for
8490
// producing deterministic builds. This was first discovered to be used

compiler/rustc_target/src/spec/linux_base.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use crate::spec::{cvs, RelroLevel, TargetOptions};
1+
use crate::spec::{cvs, RelroLevel, SplitDebuginfo, TargetOptions};
2+
use std::borrow::Cow;
23

34
pub fn opts() -> TargetOptions {
45
TargetOptions {
@@ -10,6 +11,11 @@ pub fn opts() -> TargetOptions {
1011
relro_level: RelroLevel::Full,
1112
has_thread_local: true,
1213
crt_static_respected: true,
14+
supported_split_debuginfo: Cow::Borrowed(&[
15+
SplitDebuginfo::Packed,
16+
SplitDebuginfo::Unpacked,
17+
SplitDebuginfo::Off,
18+
]),
1319
..Default::default()
1420
}
1521
}

compiler/rustc_target/src/spec/mod.rs

+99-5
Original file line numberDiff line numberDiff line change
@@ -468,23 +468,74 @@ impl fmt::Display for LinkOutputKind {
468468

469469
pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<StaticCow<str>>>;
470470

471-
#[derive(Clone, Copy, Hash, Debug, PartialEq, Eq)]
471+
/// Which kind of debuginfo does the target use?
472+
///
473+
/// Useful in determining whether a target supports Split DWARF (a target with
474+
/// `DebuginfoKind::Dwarf` and supporting `SplitDebuginfo::Unpacked` for example).
475+
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
476+
pub enum DebuginfoKind {
477+
/// DWARF debuginfo (such as that used on `x86_64_unknown_linux_gnu`).
478+
#[default]
479+
Dwarf,
480+
/// DWARF debuginfo in dSYM files (such as on Apple platforms).
481+
DwarfDsym,
482+
/// Program database files (such as on Windows).
483+
Pdb,
484+
}
485+
486+
impl DebuginfoKind {
487+
fn as_str(&self) -> &'static str {
488+
match self {
489+
DebuginfoKind::Dwarf => "dwarf",
490+
DebuginfoKind::DwarfDsym => "dwarf-dsym",
491+
DebuginfoKind::Pdb => "pdb",
492+
}
493+
}
494+
}
495+
496+
impl FromStr for DebuginfoKind {
497+
type Err = ();
498+
499+
fn from_str(s: &str) -> Result<Self, ()> {
500+
Ok(match s {
501+
"dwarf" => DebuginfoKind::Dwarf,
502+
"dwarf-dsym" => DebuginfoKind::DwarfDsym,
503+
"pdb" => DebuginfoKind::Pdb,
504+
_ => return Err(()),
505+
})
506+
}
507+
}
508+
509+
impl ToJson for DebuginfoKind {
510+
fn to_json(&self) -> Json {
511+
self.as_str().to_json()
512+
}
513+
}
514+
515+
impl fmt::Display for DebuginfoKind {
516+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
517+
f.write_str(self.as_str())
518+
}
519+
}
520+
521+
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
472522
pub enum SplitDebuginfo {
473523
/// Split debug-information is disabled, meaning that on supported platforms
474524
/// you can find all debug information in the executable itself. This is
475525
/// only supported for ELF effectively.
476526
///
477527
/// * Windows - not supported
478528
/// * macOS - don't run `dsymutil`
479-
/// * ELF - `.dwarf_*` sections
529+
/// * ELF - `.debug_*` sections
530+
#[default]
480531
Off,
481532

482533
/// Split debug-information can be found in a "packed" location separate
483534
/// from the final artifact. This is supported on all platforms.
484535
///
485536
/// * Windows - `*.pdb`
486537
/// * macOS - `*.dSYM` (run `dsymutil`)
487-
/// * ELF - `*.dwp` (run `rust-llvm-dwp`)
538+
/// * ELF - `*.dwp` (run `thorin`)
488539
Packed,
489540

490541
/// Split debug-information can be found in individual object files on the
@@ -509,7 +560,7 @@ impl SplitDebuginfo {
509560
impl FromStr for SplitDebuginfo {
510561
type Err = ();
511562

512-
fn from_str(s: &str) -> Result<SplitDebuginfo, ()> {
563+
fn from_str(s: &str) -> Result<Self, ()> {
513564
Ok(match s {
514565
"off" => SplitDebuginfo::Off,
515566
"unpacked" => SplitDebuginfo::Unpacked,
@@ -1436,9 +1487,13 @@ pub struct TargetOptions {
14361487
/// thumb and arm interworking.
14371488
pub has_thumb_interworking: bool,
14381489

1490+
/// Which kind of debuginfo is used by this target?
1491+
pub debuginfo_kind: DebuginfoKind,
14391492
/// How to handle split debug information, if at all. Specifying `None` has
14401493
/// target-specific meaning.
14411494
pub split_debuginfo: SplitDebuginfo,
1495+
/// Which kinds of split debuginfo are supported by the target?
1496+
pub supported_split_debuginfo: StaticCow<[SplitDebuginfo]>,
14421497

14431498
/// The sanitizers supported by this target
14441499
///
@@ -1596,7 +1651,10 @@ impl Default for TargetOptions {
15961651
use_ctors_section: false,
15971652
eh_frame_header: true,
15981653
has_thumb_interworking: false,
1599-
split_debuginfo: SplitDebuginfo::Off,
1654+
debuginfo_kind: Default::default(),
1655+
split_debuginfo: Default::default(),
1656+
// `Off` is supported by default, but targets can remove this manually, e.g. Windows.
1657+
supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
16001658
supported_sanitizers: SanitizerSet::empty(),
16011659
default_adjusted_cabi: None,
16021660
c_enum_min_bits: 32,
@@ -1869,6 +1927,19 @@ impl Target {
18691927
Some(Ok(()))
18701928
})).unwrap_or(Ok(()))
18711929
} );
1930+
($key_name:ident, DebuginfoKind) => ( {
1931+
let name = (stringify!($key_name)).replace("_", "-");
1932+
obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
1933+
match s.parse::<DebuginfoKind>() {
1934+
Ok(level) => base.$key_name = level,
1935+
_ => return Some(Err(
1936+
format!("'{s}' is not a valid value for debuginfo-kind. Use 'dwarf', \
1937+
'dwarf-dsym' or 'pdb'.")
1938+
)),
1939+
}
1940+
Some(Ok(()))
1941+
})).unwrap_or(Ok(()))
1942+
} );
18721943
($key_name:ident, SplitDebuginfo) => ( {
18731944
let name = (stringify!($key_name)).replace("_", "-");
18741945
obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
@@ -1905,6 +1976,25 @@ impl Target {
19051976
}
19061977
}
19071978
} );
1979+
($key_name:ident, falliable_list) => ( {
1980+
let name = (stringify!($key_name)).replace("_", "-");
1981+
obj.remove(&name).and_then(|j| {
1982+
if let Some(v) = j.as_array() {
1983+
match v.iter().map(|a| FromStr::from_str(a.as_str().unwrap())).collect() {
1984+
Ok(l) => { base.$key_name = l },
1985+
// FIXME: `falliable_list` can't re-use the `key!` macro for list
1986+
// elements and the error messages from that macro, so it has a bad
1987+
// generic message instead
1988+
Err(_) => return Some(Err(
1989+
format!("`{:?}` is not a valid value for `{}`", j, name)
1990+
)),
1991+
}
1992+
} else {
1993+
incorrect_type.push(name)
1994+
}
1995+
Some(Ok(()))
1996+
}).unwrap_or(Ok(()))
1997+
} );
19081998
($key_name:ident, optional) => ( {
19091999
let name = (stringify!($key_name)).replace("_", "-");
19102000
if let Some(o) = obj.remove(&name) {
@@ -2191,7 +2281,9 @@ impl Target {
21912281
key!(use_ctors_section, bool);
21922282
key!(eh_frame_header, bool);
21932283
key!(has_thumb_interworking, bool);
2284+
key!(debuginfo_kind, DebuginfoKind)?;
21942285
key!(split_debuginfo, SplitDebuginfo)?;
2286+
key!(supported_split_debuginfo, falliable_list)?;
21952287
key!(supported_sanitizers, SanitizerSet)?;
21962288
key!(default_adjusted_cabi, Option<Abi>)?;
21972289
key!(c_enum_min_bits, u64);
@@ -2435,7 +2527,9 @@ impl ToJson for Target {
24352527
target_option_val!(use_ctors_section);
24362528
target_option_val!(eh_frame_header);
24372529
target_option_val!(has_thumb_interworking);
2530+
target_option_val!(debuginfo_kind);
24382531
target_option_val!(split_debuginfo);
2532+
target_option_val!(supported_split_debuginfo);
24392533
target_option_val!(supported_sanitizers);
24402534
target_option_val!(c_enum_min_bits);
24412535
target_option_val!(generate_arange_section);

compiler/rustc_target/src/spec/msvc_base.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::spec::{LinkerFlavor, LldFlavor, SplitDebuginfo, TargetOptions};
2+
use std::borrow::Cow;
23

34
pub fn opts() -> TargetOptions {
45
// Suppress the verbose logo and authorship debugging output, which would needlessly
@@ -18,6 +19,7 @@ pub fn opts() -> TargetOptions {
1819
// Currently this is the only supported method of debuginfo on MSVC
1920
// where `*.pdb` files show up next to the final artifact.
2021
split_debuginfo: SplitDebuginfo::Packed,
22+
supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Packed]),
2123

2224
..Default::default()
2325
}

compiler/rustc_target/src/spec/windows_gnu_base.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::spec::crt_objects::{self, LinkSelfContainedDefault};
2-
use crate::spec::{cvs, LinkerFlavor, TargetOptions};
2+
use crate::spec::{cvs, DebuginfoKind, LinkerFlavor, SplitDebuginfo, TargetOptions};
3+
use std::borrow::Cow;
34

45
pub fn opts() -> TargetOptions {
56
let mut pre_link_args = TargetOptions::link_args(
@@ -86,6 +87,10 @@ pub fn opts() -> TargetOptions {
8687
emit_debug_gdb_scripts: false,
8788
requires_uwtable: true,
8889
eh_frame_header: false,
90+
// FIXME(davidtwco): Support Split DWARF on Windows GNU - may require LLVM changes to
91+
// output DWO, despite using DWARF, doesn't use ELF..
92+
debuginfo_kind: DebuginfoKind::Pdb,
93+
supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
8994
..Default::default()
9095
}
9196
}

compiler/rustc_target/src/spec/windows_msvc_base.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::spec::{cvs, TargetOptions};
1+
use crate::spec::{cvs, DebuginfoKind, TargetOptions};
22

33
pub fn opts() -> TargetOptions {
44
let base = super::msvc_base::opts();
@@ -28,6 +28,7 @@ pub fn opts() -> TargetOptions {
2828
// not ever be possible for us to pass this flag.
2929
no_default_libraries: false,
3030
has_thread_local: true,
31+
debuginfo_kind: DebuginfoKind::Pdb,
3132

3233
..base
3334
}

src/bootstrap/builder.rs

+14-16
Original file line numberDiff line numberDiff line change
@@ -1759,23 +1759,21 @@ impl<'a> Builder<'a> {
17591759
},
17601760
);
17611761

1762-
if !target.contains("windows") {
1763-
let needs_unstable_opts = target.contains("linux")
1764-
|| target.contains("solaris")
1765-
|| target.contains("windows")
1766-
|| target.contains("bsd")
1767-
|| target.contains("dragonfly")
1768-
|| target.contains("illumos");
1769-
1770-
if needs_unstable_opts {
1771-
rustflags.arg("-Zunstable-options");
1772-
}
1773-
match self.config.rust_split_debuginfo {
1774-
SplitDebuginfo::Packed => rustflags.arg("-Csplit-debuginfo=packed"),
1775-
SplitDebuginfo::Unpacked => rustflags.arg("-Csplit-debuginfo=unpacked"),
1776-
SplitDebuginfo::Off => rustflags.arg("-Csplit-debuginfo=off"),
1777-
};
1762+
let split_debuginfo_is_stable = target.contains("linux")
1763+
|| target.contains("apple")
1764+
|| (target.contains("msvc")
1765+
&& self.config.rust_split_debuginfo == SplitDebuginfo::Packed)
1766+
|| (target.contains("windows")
1767+
&& self.config.rust_split_debuginfo == SplitDebuginfo::Off);
1768+
1769+
if !split_debuginfo_is_stable {
1770+
rustflags.arg("-Zunstable-options");
17781771
}
1772+
match self.config.rust_split_debuginfo {
1773+
SplitDebuginfo::Packed => rustflags.arg("-Csplit-debuginfo=packed"),
1774+
SplitDebuginfo::Unpacked => rustflags.arg("-Csplit-debuginfo=unpacked"),
1775+
SplitDebuginfo::Off => rustflags.arg("-Csplit-debuginfo=off"),
1776+
};
17791777

17801778
if self.config.cmd.bless() {
17811779
// Bless `expect!` tests.

src/test/incremental/split_debuginfo_cached.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
// only-x86_64-unknown-linux-gnu
77
// revisions:rpass1 rpass2
88

9-
// [rpass1]compile-flags: -g -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split
10-
// [rpass2]compile-flags: -g -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split
9+
// [rpass1]compile-flags: -g -Zquery-dep-graph -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split
10+
// [rpass2]compile-flags: -g -Zquery-dep-graph -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split
1111

1212
#![feature(rustc_attrs)]
1313
// For `rpass2`, nothing has changed so everything should re-used.

src/test/incremental/split_debuginfo_mode.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
// only-x86_64-unknown-linux-gnu
77
// revisions:rpass1 rpass2 rpass3 rpass4
88

9-
// [rpass1]compile-flags: -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=unpacked -Zsplit-dwarf-kind=single -Zsplit-dwarf-inlining=on
10-
// [rpass2]compile-flags: -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=packed -Zsplit-dwarf-kind=single -Zsplit-dwarf-inlining=on
11-
// [rpass3]compile-flags: -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split -Zsplit-dwarf-inlining=on
12-
// [rpass4]compile-flags: -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split -Zsplit-dwarf-inlining=off
9+
// [rpass1]compile-flags: -Zquery-dep-graph -Csplit-debuginfo=unpacked -Zsplit-dwarf-kind=single -Zsplit-dwarf-inlining=on
10+
// [rpass2]compile-flags: -Zquery-dep-graph -Csplit-debuginfo=packed -Zsplit-dwarf-kind=single -Zsplit-dwarf-inlining=on
11+
// [rpass3]compile-flags: -Zquery-dep-graph -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split -Zsplit-dwarf-inlining=on
12+
// [rpass4]compile-flags: -Zquery-dep-graph -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split -Zsplit-dwarf-inlining=off
1313

1414
#![feature(rustc_attrs)]
1515
// For rpass2 we change -Csplit-debuginfo and thus expect every CGU to be recompiled

0 commit comments

Comments
 (0)