diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index e2a592d851a8c..4bf6762d1f604 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -830,24 +830,7 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>( } .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 5392534cfcb79..41a75c9d775f2 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -402,7 +402,7 @@ impl<'ll, 'tcx> 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 0d63e634ad888..556c6602ff430 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -946,15 +946,27 @@ pub mod debuginfo { NoDebug, FullDebug, LineTablesOnly, + DebugDirectivesOnly, } 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, - 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 69bb00f804d3c..65dfc325a118f 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1121,9 +1121,12 @@ impl<'a> Linker for EmLinker<'a> { fn debuginfo(&mut self, _strip: Strip, _: &[PathBuf]) { // 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::Limited => "--profiling-funcs", + DebugInfo::Limited | DebugInfo::LineTablesOnly | DebugInfo::LineDirectivesOnly => { + "--profiling-funcs" + } DebugInfo::Full => "-g", }); } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index eb5990507fb6d..10dfd32d418a2 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -5,6 +5,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::profiling::TimePassesFormat; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; use rustc_session::config::rustc_optgroups; +use rustc_session::config::DebugInfo; use rustc_session::config::Input; use rustc_session::config::InstrumentXRay; use rustc_session::config::TraitSolver; @@ -574,7 +575,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 e3493caaaf74e..6a2fd5aa6e6a3 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -682,6 +682,7 @@ enum class LLVMRustDebugEmissionKind { NoDebug, FullDebug, LineTablesOnly, + DebugDirectivesOnly, }; static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) { @@ -692,6 +693,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 485c3f554625a..1d8fedb8bd792 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -260,6 +260,8 @@ pub enum SymbolManglingVersion { #[derive(Clone, Copy, Debug, PartialEq, Hash)] pub enum DebugInfo { None, + LineDirectivesOnly, + LineTablesOnly, Limited, Full, } @@ -1979,11 +1981,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") @@ -1993,24 +1991,7 @@ fn select_debuginfo( if let Some("debuginfo") = s.split('=').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 } } pub(crate) fn parse_assert_incr_state( @@ -2498,7 +2479,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 c75af48e80af4..953d6561669fe 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -377,6 +377,7 @@ mod desc { pub const parse_cfguard: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`"; pub const parse_cfprotection: &str = "`none`|`no`|`n` (default), `branch`, `return`, or `full`|`yes`|`y` (equivalent to `branch` and `return`)"; + 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::LinkerFlavorCli::one_of(); pub const parse_optimization_fuel: &str = "crate=integer"; @@ -767,6 +768,18 @@ mod parse { true } + pub(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 + } + pub(crate) fn parse_linker_flavor(slot: &mut Option, v: Option<&str>) -> bool { match v.and_then(LinkerFlavorCli::from_str) { Some(lf) => *slot = Some(lf), @@ -1217,9 +1230,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 c7f120dafeafd..62347f169a5eb 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. For the nvptx* targets this enables [profiling](https://reviews.llvm.org/D46061). For other use cases, `line-tables-only` is the better, more compatible choice. +* `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. no variable or function parameter info. +* `1` or `limited`: debug info without type or variable-level information. +* `2` or `full`: full debug info. Note: The [`-g` flag][option-g-debug] is an alias for `-C debuginfo=2`. diff --git a/tests/codegen/debug-limited.rs b/tests/codegen/debug-limited.rs new file mode 100644 index 0000000000000..48d676887fdd5 --- /dev/null +++ b/tests/codegen/debug-limited.rs @@ -0,0 +1,27 @@ +// Verify that the limited debuginfo option emits llvm's FullDebugInfo, but no type info. +// +// 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/tests/codegen/debug-line-directives-only.rs b/tests/codegen/debug-line-directives-only.rs new file mode 100644 index 0000000000000..750bdd49de075 --- /dev/null +++ b/tests/codegen/debug-line-directives-only.rs @@ -0,0 +1,27 @@ +// Verify that the only debuginfo generated are the line directives. +// +// 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/tests/codegen/debug-line-tables-only.rs b/tests/codegen/debug-line-tables-only.rs new file mode 100644 index 0000000000000..3ed165a6f6967 --- /dev/null +++ b/tests/codegen/debug-line-tables-only.rs @@ -0,0 +1,27 @@ +// Verify that the only debuginfo generated are the line tables. +// +// 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 diff --git a/tests/rustdoc-ui/c-help.stdout b/tests/rustdoc-ui/c-help.stdout index 75b2e2a2a43f4..0bd2d73efee53 100644 --- a/tests/rustdoc-ui/c-help.stdout +++ b/tests/rustdoc-ui/c-help.stdout @@ -3,7 +3,7 @@ -C codegen-units=val -- divide crate into N units to optimize in parallel -C control-flow-guard=val -- use Windows Control Flow Guard (default: no) -C debug-assertions=val -- explicitly enable the `cfg(debug_assertions)` directive - -C debuginfo=val -- debug info emission level (0 = no debug info, 1 = line tables only, 2 = full debug info with variable and type information; default: 0) + -C debuginfo=val -- debug info emission level (0-2, none, line-directives-only, line-tables-only, limited, or full; default: 0) -C default-linker-libraries=val -- allow the linker to link its default libraries (default: no) -C embed-bitcode=val -- emit bitcode in rlibs (default: yes) -C extra-filename=val -- extra data to put in each output filename