From 029f48552364aef98f3963e7a2f1671e59193834 Mon Sep 17 00:00:00 2001 From: Julia Tatz Date: Tue, 6 Apr 2021 16:00:35 -0400 Subject: [PATCH 1/2] Preserve, clarify, and extend debug information `-Cdebuginfo=1` was never line tables only and can't be due to backwards compatibility issues. This was clarified and an option for line tables only was added. Additionally an option for line info directives only was added, which is well needed for some targets. The debug info options should now behave the same as clang's debug info options. --- .../src/debuginfo/metadata.rs | 19 +----------- .../rustc_codegen_llvm/src/debuginfo/mod.rs | 2 +- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 6 ++-- compiler/rustc_codegen_ssa/src/back/linker.rs | 3 ++ compiler/rustc_interface/src/tests.rs | 4 +-- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 3 ++ compiler/rustc_session/src/config.rs | 30 ++++--------------- compiler/rustc_session/src/options.rs | 30 ++++++++++--------- src/doc/rustc/src/codegen-options/index.md | 8 +++-- src/test/codegen/debug-limited.rs | 28 +++++++++++++++++ .../codegen/debug-line-directives-only.rs | 28 +++++++++++++++++ src/test/codegen/debug-line-tables-only.rs | 28 +++++++++++++++++ 12 files changed, 124 insertions(+), 65 deletions(-) create mode 100644 src/test/codegen/debug-limited.rs create mode 100644 src/test/codegen/debug-line-directives-only.rs create mode 100644 src/test/codegen/debug-line-tables-only.rs diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 346c51c5426d8..33435fd185f80 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -1019,24 +1019,7 @@ pub fn compile_unit_metadata( } .unwrap_or_default(); let split_name = split_name.to_str().unwrap(); - - // FIXME(#60020): - // - // This should actually be - // - // let kind = DebugEmissionKind::from_generic(tcx.sess.opts.debuginfo); - // - // That is, we should set LLVM's emission kind to `LineTablesOnly` if - // we are compiling with "limited" debuginfo. However, some of the - // existing tools relied on slightly more debuginfo being generated than - // would be the case with `LineTablesOnly`, and we did not want to break - // these tools in a "drive-by fix", without a good idea or plan about - // what limited debuginfo should exactly look like. So for now we keep - // the emission kind as `FullDebug`. - // - // See https://github.com/rust-lang/rust/issues/60020 for details. - let kind = DebugEmissionKind::FullDebug; - assert!(tcx.sess.opts.debuginfo != DebugInfo::None); + let kind = DebugEmissionKind::from_generic(tcx.sess.opts.debuginfo); unsafe { let compile_unit_file = llvm::LLVMRustDIBuilderCreateFile( diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 914376d58ddee..f88627ed34594 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -372,7 +372,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { cx: &CodegenCx<'ll, 'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, ) -> &'ll DIArray { - if cx.sess().opts.debuginfo == DebugInfo::Limited { + if cx.sess().opts.debuginfo != DebugInfo::Full { return create_DIArray(DIB(cx), &[]); } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 3f2ed02d90df3..e2018e2d815b7 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -872,6 +872,7 @@ pub mod debuginfo { NoDebug, FullDebug, LineTablesOnly, + DebugDirectivesOnly, } impl DebugEmissionKind { @@ -879,8 +880,9 @@ pub mod debuginfo { use rustc_session::config::DebugInfo; match kind { DebugInfo::None => DebugEmissionKind::NoDebug, - DebugInfo::Limited => DebugEmissionKind::LineTablesOnly, - DebugInfo::Full => DebugEmissionKind::FullDebug, + DebugInfo::LineDirectivesOnly => DebugEmissionKind::DebugDirectivesOnly, + DebugInfo::LineTablesOnly => DebugEmissionKind::LineTablesOnly, + DebugInfo::Limited | DebugInfo::Full => DebugEmissionKind::FullDebug, } } } diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 9e1c6a169f152..170c837cd2ad4 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1114,8 +1114,11 @@ impl<'a> Linker for EmLinker<'a> { fn debuginfo(&mut self, _strip: Strip) { // Preserve names or generate source maps depending on debug info + // For more information see https://emscripten.org/docs/tools_reference/emcc.html#emcc-g self.cmd.arg(match self.sess.opts.debuginfo { DebugInfo::None => "-g0", + DebugInfo::LineDirectivesOnly => "-g3", + DebugInfo::LineTablesOnly => "-g3", DebugInfo::Limited => "-g3", DebugInfo::Full => "-g4", }); diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index afab919bc3c2c..a65292fd700ed 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -8,7 +8,7 @@ use rustc_session::config::{build_configuration, build_session_options, to_crate use rustc_session::config::{rustc_optgroups, ErrorOutputType, ExternLocation, Options, Passes}; use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath}; use rustc_session::config::{ - Externs, OutputType, OutputTypes, SymbolManglingVersion, WasiExecModel, + DebugInfo, Externs, OutputType, OutputTypes, SymbolManglingVersion, WasiExecModel, }; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; @@ -564,7 +564,7 @@ fn test_codegen_options_tracking_hash() { tracked!(code_model, Some(CodeModel::Large)); tracked!(control_flow_guard, CFGuard::Checks); tracked!(debug_assertions, Some(true)); - tracked!(debuginfo, 0xdeadbeef); + tracked!(debuginfo, DebugInfo::Limited); tracked!(embed_bitcode, false); tracked!(force_frame_pointers, Some(false)); tracked!(force_unwind_tables, Some(true)); diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 4f07a0c67c13f..d5466ac38c563 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -641,6 +641,7 @@ enum class LLVMRustDebugEmissionKind { NoDebug, FullDebug, LineTablesOnly, + DebugDirectivesOnly, }; static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) { @@ -651,6 +652,8 @@ static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) return DICompileUnit::DebugEmissionKind::FullDebug; case LLVMRustDebugEmissionKind::LineTablesOnly: return DICompileUnit::DebugEmissionKind::LineTablesOnly; + case LLVMRustDebugEmissionKind::DebugDirectivesOnly: + return DICompileUnit::DebugEmissionKind::DebugDirectivesOnly; default: report_fatal_error("bad DebugEmissionKind."); } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index fdedb7e6a4afe..6f55b073cc1f5 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -201,6 +201,8 @@ impl_stable_hash_via_hash!(SymbolManglingVersion); #[derive(Clone, Copy, Debug, PartialEq, Hash)] pub enum DebugInfo { None, + LineDirectivesOnly, + LineTablesOnly, Limited, Full, } @@ -1561,11 +1563,7 @@ fn parse_opt_level( } } -fn select_debuginfo( - matches: &getopts::Matches, - cg: &CodegenOptions, - error_format: ErrorOutputType, -) -> DebugInfo { +fn select_debuginfo(matches: &getopts::Matches, cg: &CodegenOptions) -> DebugInfo { let max_g = matches.opt_positions("g").into_iter().max(); let max_c = matches .opt_strs_pos("C") @@ -1575,25 +1573,7 @@ fn select_debuginfo( if let Some("debuginfo") = s.splitn(2, '=').next() { Some(i) } else { None } }) .max(); - if max_g > max_c { - DebugInfo::Full - } else { - match cg.debuginfo { - 0 => DebugInfo::None, - 1 => DebugInfo::Limited, - 2 => DebugInfo::Full, - arg => { - early_error( - error_format, - &format!( - "debug info level needs to be between \ - 0-2 (instead was `{}`)", - arg - ), - ); - } - } - } + if max_g > max_c { DebugInfo::Full } else { cg.debuginfo } } fn parse_native_lib_kind( @@ -2055,7 +2035,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { // to use them interchangeably. See the note above (regarding `-O` and `-C opt-level`) // for more details. let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == OptLevel::No); - let debuginfo = select_debuginfo(matches, &cg, error_format); + let debuginfo = select_debuginfo(matches, &cg); let mut search_paths = vec![]; for s in &matches.opt_strs("L") { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 9a1be40558ccb..b1bf607cb9eae 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -355,6 +355,7 @@ mod desc { pub const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2"; pub const parse_cfguard: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`"; + pub const parse_debuginfo: &str = "either an integer (0, 1, 2), `none`, `line-directives-only`, `line-tables-only`, `limited`, or `full`"; pub const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`"; pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavor::one_of(); pub const parse_optimization_fuel: &str = "crate=integer"; @@ -509,17 +510,6 @@ mod parse { } } - /// Use this for any numeric option that has a static default. - crate fn parse_number(slot: &mut T, v: Option<&str>) -> bool { - match v.and_then(|s| s.parse().ok()) { - Some(i) => { - *slot = i; - true - } - None => false, - } - } - /// Use this for any numeric option that lacks a static default. crate fn parse_opt_number(slot: &mut Option, v: Option<&str>) -> bool { match v { @@ -633,6 +623,18 @@ mod parse { true } + crate fn parse_debuginfo(slot: &mut DebugInfo, v: Option<&str>) -> bool { + match v { + Some("0") | Some("none") => *slot = DebugInfo::None, + Some("line-directives-only") => *slot = DebugInfo::LineDirectivesOnly, + Some("line-tables-only") => *slot = DebugInfo::LineTablesOnly, + Some("1") | Some("limited") => *slot = DebugInfo::Limited, + Some("2") | Some("full") => *slot = DebugInfo::Full, + _ => return false, + } + true + } + crate fn parse_linker_flavor(slot: &mut Option, v: Option<&str>) -> bool { match v.and_then(LinkerFlavor::from_str) { Some(lf) => *slot = Some(lf), @@ -905,9 +907,9 @@ options! { "use Windows Control Flow Guard (default: no)"), debug_assertions: Option = (None, parse_opt_bool, [TRACKED], "explicitly enable the `cfg(debug_assertions)` directive"), - debuginfo: usize = (0, parse_number, [TRACKED], - "debug info emission level (0 = no debug info, 1 = line tables only, \ - 2 = full debug info with variable and type information; default: 0)"), + debuginfo: DebugInfo = (DebugInfo::None, parse_debuginfo, [TRACKED], + "debug info emission level (0-2, none, line-directives-only, \ + line-tables-only, limited, or full; default: 0)"), default_linker_libraries: bool = (false, parse_bool, [UNTRACKED], "allow the linker to link its default libraries (default: no)"), embed_bitcode: bool = (true, parse_bool, [TRACKED], diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 05384117ac175..1c16e29afd9dd 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -71,9 +71,11 @@ If not specified, debug assertions are automatically enabled only if the This flag controls the generation of debug information. It takes one of the following values: -* `0`: no debug info at all (the default). -* `1`: line tables only. -* `2`: full debug info. +* `0` or `none`: no debug info at all (the default). +* `line-directives-only`: line info directives only. +* `line-tables-only`: line tables only. +* `1` or `limited`: debug info without type information. +* `2` or `full`: full debug info. Note: The [`-g` flag][option-g-debug] is an alias for `-C debuginfo=2`. diff --git a/src/test/codegen/debug-limited.rs b/src/test/codegen/debug-limited.rs new file mode 100644 index 0000000000000..fafee0ef583a4 --- /dev/null +++ b/src/test/codegen/debug-limited.rs @@ -0,0 +1,28 @@ +// Verify that the limited debuginfo option emits llvm's FullDebugInfo, but no type info. +// +// ignore-windows +// compile-flags: -C debuginfo=limited + +#[repr(C)] +struct StructType { + a: i64, + b: i32 +} + +extern "C" { + fn creator() -> *mut StructType; + fn save(p: *const StructType); +} + +fn main() { + unsafe { + let value: &mut StructType = &mut* creator(); + value.a = 7; + save(value as *const StructType) + } +} + +// CHECK: !DICompileUnit +// CHECK: emissionKind: FullDebug +// CHECK: !DILocation +// CHECK-NOT: !DIBasicType diff --git a/src/test/codegen/debug-line-directives-only.rs b/src/test/codegen/debug-line-directives-only.rs new file mode 100644 index 0000000000000..0dd22931b30a5 --- /dev/null +++ b/src/test/codegen/debug-line-directives-only.rs @@ -0,0 +1,28 @@ +// Verify that the only debuginfo generated are the line directives. +// +// ignore-windows +// compile-flags: -C debuginfo=line-directives-only + +#[repr(C)] +struct StructType { + a: i64, + b: i32 +} + +extern "C" { + fn creator() -> *mut StructType; + fn save(p: *const StructType); +} + +fn main() { + unsafe { + let value: &mut StructType = &mut* creator(); + value.a = 7; + save(value as *const StructType) + } +} + +// CHECK: !DICompileUnit +// CHECK: emissionKind: DebugDirectivesOnly +// CHECK: !DILocation +// CHECK-NOT: !DIBasicType diff --git a/src/test/codegen/debug-line-tables-only.rs b/src/test/codegen/debug-line-tables-only.rs new file mode 100644 index 0000000000000..3d109d4ae519f --- /dev/null +++ b/src/test/codegen/debug-line-tables-only.rs @@ -0,0 +1,28 @@ +// Verify that the only debuginfo generated are the line tables. +// +// ignore-windows +// compile-flags: -C debuginfo=line-tables-only + +#[repr(C)] +struct StructType { + a: i64, + b: i32 +} + +extern "C" { + fn creator() -> *mut StructType; + fn save(p: *const StructType); +} + +fn main() { + unsafe { + let value: &mut StructType = &mut* creator(); + value.a = 7; + save(value as *const StructType) + } +} + +// CHECK: !DICompileUnit +// CHECK: emissionKind: LineTablesOnly +// CHECK: !DILocation +// CHECK-NOT: !DIBasicType From 8bfc6418f23a78a43e3e1610c57df80502fa3cf1 Mon Sep 17 00:00:00 2001 From: Julia Tatz Date: Fri, 3 Sep 2021 13:00:39 -0400 Subject: [PATCH 2/2] More in-depth documentation for the new debuginfo options --- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 10 ++++++++++ src/doc/rustc/src/codegen-options/index.md | 4 ++-- src/test/codegen/debug-limited.rs | 5 ++--- src/test/codegen/debug-line-directives-only.rs | 5 ++--- src/test/codegen/debug-line-tables-only.rs | 5 ++--- 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index e2018e2d815b7..de160020a0cce 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -877,6 +877,16 @@ pub mod debuginfo { impl DebugEmissionKind { pub fn from_generic(kind: rustc_session::config::DebugInfo) -> Self { + // We should be setting LLVM's emission kind to `LineTablesOnly` if + // we are compiling with "limited" debuginfo. However, some of the + // existing tools relied on slightly more debuginfo being generated than + // would be the case with `LineTablesOnly`, and we did not want to break + // these tools in a "drive-by fix", without a good idea or plan about + // what limited debuginfo should exactly look like. So for now we are + // instead adding a new debuginfo option "line-tables-only" so as to + // not break anything and to allow users to have 'limited' debug info. + // + // See https://github.com/rust-lang/rust/issues/60020 for details. use rustc_session::config::DebugInfo; match kind { DebugInfo::None => DebugEmissionKind::NoDebug, diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 1c16e29afd9dd..c323e032ff7d7 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -72,8 +72,8 @@ This flag controls the generation of debug information. It takes one of the following values: * `0` or `none`: no debug info at all (the default). -* `line-directives-only`: line info directives only. -* `line-tables-only`: line tables only. +* `line-directives-only`: line info directives only, (For the nvptx* targets this enables [profiling](https://reviews.llvm.org/D46061), but on other targets the behavior is unspecified). +* `line-tables-only`: line tables only, (Generates the minimal amount of debug info for backtraces with filename/line number info, but not anything else, i.e. variable or function parameter info). * `1` or `limited`: debug info without type information. * `2` or `full`: full debug info. diff --git a/src/test/codegen/debug-limited.rs b/src/test/codegen/debug-limited.rs index fafee0ef583a4..48d676887fdd5 100644 --- a/src/test/codegen/debug-limited.rs +++ b/src/test/codegen/debug-limited.rs @@ -1,12 +1,11 @@ // Verify that the limited debuginfo option emits llvm's FullDebugInfo, but no type info. // -// ignore-windows // compile-flags: -C debuginfo=limited #[repr(C)] struct StructType { a: i64, - b: i32 + b: i32, } extern "C" { @@ -16,7 +15,7 @@ extern "C" { fn main() { unsafe { - let value: &mut StructType = &mut* creator(); + let value: &mut StructType = &mut *creator(); value.a = 7; save(value as *const StructType) } diff --git a/src/test/codegen/debug-line-directives-only.rs b/src/test/codegen/debug-line-directives-only.rs index 0dd22931b30a5..750bdd49de075 100644 --- a/src/test/codegen/debug-line-directives-only.rs +++ b/src/test/codegen/debug-line-directives-only.rs @@ -1,12 +1,11 @@ // Verify that the only debuginfo generated are the line directives. // -// ignore-windows // compile-flags: -C debuginfo=line-directives-only #[repr(C)] struct StructType { a: i64, - b: i32 + b: i32, } extern "C" { @@ -16,7 +15,7 @@ extern "C" { fn main() { unsafe { - let value: &mut StructType = &mut* creator(); + let value: &mut StructType = &mut *creator(); value.a = 7; save(value as *const StructType) } diff --git a/src/test/codegen/debug-line-tables-only.rs b/src/test/codegen/debug-line-tables-only.rs index 3d109d4ae519f..3ed165a6f6967 100644 --- a/src/test/codegen/debug-line-tables-only.rs +++ b/src/test/codegen/debug-line-tables-only.rs @@ -1,12 +1,11 @@ // Verify that the only debuginfo generated are the line tables. // -// ignore-windows // compile-flags: -C debuginfo=line-tables-only #[repr(C)] struct StructType { a: i64, - b: i32 + b: i32, } extern "C" { @@ -16,7 +15,7 @@ extern "C" { fn main() { unsafe { - let value: &mut StructType = &mut* creator(); + let value: &mut StructType = &mut *creator(); value.a = 7; save(value as *const StructType) }