Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend -Cdebuginfo with new options and named aliases #83947

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 1 addition & 18 deletions compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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), &[]);
}

Expand Down
16 changes: 14 additions & 2 deletions compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -872,15 +872,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,
jdtatz marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
});
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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));
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,7 @@ enum class LLVMRustDebugEmissionKind {
NoDebug,
FullDebug,
LineTablesOnly,
DebugDirectivesOnly,
};

static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) {
Expand All @@ -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.");
}
Expand Down
30 changes: 5 additions & 25 deletions compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ impl_stable_hash_via_hash!(SymbolManglingVersion);
#[derive(Clone, Copy, Debug, PartialEq, Hash)]
pub enum DebugInfo {
None,
LineDirectivesOnly,
LineTablesOnly,
Limited,
Full,
}
Expand Down Expand Up @@ -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")
Expand All @@ -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(
Expand Down Expand Up @@ -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") {
Expand Down
30 changes: 16 additions & 14 deletions compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -509,17 +510,6 @@ mod parse {
}
}

/// Use this for any numeric option that has a static default.
crate fn parse_number<T: Copy + FromStr>(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<T: Copy + FromStr>(slot: &mut Option<T>, v: Option<&str>) -> bool {
match v {
Expand Down Expand Up @@ -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<LinkerFlavor>, v: Option<&str>) -> bool {
match v.and_then(LinkerFlavor::from_str) {
Some(lf) => *slot = Some(lf),
Expand Down Expand Up @@ -905,9 +907,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],
Expand Down
8 changes: 5 additions & 3 deletions src/doc/rustc/src/codegen-options/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -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), but on other targets the behavior is unspecified).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, claiming unspecified behaviour in our flags unnecessarily feels… bad? Could we just say "enables profiling for some targets" (also what kind of profiling? sampling? instrumented?) for now?

* `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.
Copy link
Contributor

@petrochenkov petrochenkov Aug 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to document what all these options actually mean, in practice.
I.e. in which ways can you debug an executable built with the given option.

Also, it would be good to define what "line info directives" and "line tables" mean, at least by giving links to relevant documents.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the new documentation I added clear enough for unfamiliar users?


Note: The [`-g` flag][option-g-debug] is an alias for `-C debuginfo=2`.

Expand Down
27 changes: 27 additions & 0 deletions src/test/codegen/debug-limited.rs
Original file line number Diff line number Diff line change
@@ -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
27 changes: 27 additions & 0 deletions src/test/codegen/debug-line-directives-only.rs
Original file line number Diff line number Diff line change
@@ -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
27 changes: 27 additions & 0 deletions src/test/codegen/debug-line-tables-only.rs
Original file line number Diff line number Diff line change
@@ -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