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.
This commit is contained in:
parent
eb3e9c1f45
commit
0504a33383
@ -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(
|
||||
|
@ -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), &[]);
|
||||
}
|
||||
|
||||
|
@ -946,6 +946,7 @@ pub mod debuginfo {
|
||||
NoDebug,
|
||||
FullDebug,
|
||||
LineTablesOnly,
|
||||
DebugDirectivesOnly,
|
||||
}
|
||||
|
||||
impl DebugEmissionKind {
|
||||
@ -953,8 +954,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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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",
|
||||
});
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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.");
|
||||
}
|
||||
|
@ -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") {
|
||||
|
@ -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<LinkerFlavorCli>, 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<bool> = (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],
|
||||
|
@ -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`.
|
||||
|
||||
|
28
tests/codegen/debug-limited.rs
Normal file
28
tests/codegen/debug-limited.rs
Normal file
@ -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
|
28
tests/codegen/debug-line-directives-only.rs
Normal file
28
tests/codegen/debug-line-directives-only.rs
Normal file
@ -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
|
28
tests/codegen/debug-line-tables-only.rs
Normal file
28
tests/codegen/debug-line-tables-only.rs
Normal file
@ -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
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user