Skip to content

Commit

Permalink
Auto merge of #120845 - petrochenkov:debmac, r=oli-obk
Browse files Browse the repository at this point in the history
debuginfo: Stabilize `-Z debug-macros`, `-Z collapse-macro-debuginfo` and `#[collapse_debuginfo]`

`-Z debug-macros` is "stabilized" by enabling it by default and removing.

`-Z collapse-macro-debuginfo` is stabilized as `-C collapse-macro-debuginfo`.
It now supports all typical boolean values (`parse_opt_bool`) in addition to just yes/no.

Default value of `collapse_debuginfo` was changed from `false` to `external` (i.e. collapsed if external, not collapsed if local) - #100758 (comment) describes some debugging scenarios that motivate this default as reasonable.
`#[collapse_debuginfo]` attribute without a value is no longer supported to avoid guessing the default.

Stabilization report: #120845 (comment)

Closes #100758
Closes #41743
Closes #39153
  • Loading branch information
bors committed Apr 25, 2024
2 parents 3a36386 + 98804c1 commit 78aad13
Show file tree
Hide file tree
Showing 31 changed files with 209 additions and 339 deletions.
9 changes: 3 additions & 6 deletions compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use cranelift_codegen::binemit::CodeOffset;
use cranelift_codegen::MachSrcLoc;
use gimli::write::{AttributeValue, FileId, FileInfo, LineProgram, LineString, LineStringTable};
use rustc_span::{
FileName, Pos, SourceFile, SourceFileAndLine, SourceFileHash, SourceFileHashAlgorithm,
hygiene, FileName, Pos, SourceFile, SourceFileAndLine, SourceFileHash, SourceFileHashAlgorithm,
};

use crate::debuginfo::emit::address_for_func;
Expand Down Expand Up @@ -63,11 +63,8 @@ impl DebugContext {
function_span: Span,
span: Span,
) -> (FileId, u64, u64) {
// Based on https://github.com/rust-lang/rust/blob/e369d87b015a84653343032833d65d0545fd3f26/src/librustc_codegen_ssa/mir/mod.rs#L116-L131
// In order to have a good line stepping behavior in debugger, we overwrite debug
// locations of macro expansions with that of the outermost expansion site (when the macro is
// annotated with `#[collapse_debuginfo]` or when `-Zdebug-macros` is provided).
let span = tcx.collapsed_debuginfo(span, function_span);
// Match behavior of `FunctionCx::adjusted_span_and_dbg_scope`.
let span = hygiene::walk_chain_collapsed(span, function_span);
match tcx.sess.source_map().lookup_line(span.lo()) {
Ok(SourceFileAndLine { sf: file, line }) => {
let file_id = self.add_source_file(&file);
Expand Down
22 changes: 3 additions & 19 deletions compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@ use rustc_index::IndexVec;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir;
use rustc_middle::ty;
use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_middle::ty::Instance;
use rustc_middle::ty::Ty;
use rustc_session::config::DebugInfo;
use rustc_span::symbol::{kw, Symbol};
use rustc_span::{BytePos, Span};
use rustc_span::{hygiene, BytePos, Span};
use rustc_target::abi::{Abi, FieldIdx, FieldsShape, Size, VariantIdx};

use super::operand::{OperandRef, OperandValue};
Expand Down Expand Up @@ -220,26 +219,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
&self,
source_info: mir::SourceInfo,
) -> Option<(Bx::DIScope, Option<Bx::DILocation>, Span)> {
let span = self.adjust_span_for_debugging(source_info.span);
let scope = &self.debug_context.as_ref()?.scopes[source_info.scope];
let span = hygiene::walk_chain_collapsed(source_info.span, self.mir.span);
Some((scope.adjust_dbg_scope_for_span(self.cx, span), scope.inlined_at, span))
}

/// In order to have a good line stepping behavior in debugger, we overwrite debug
/// locations of macro expansions with that of the outermost expansion site (when the macro is
/// annotated with `#[collapse_debuginfo]` or when `-Zdebug-macros` is provided).
fn adjust_span_for_debugging(&self, span: Span) -> Span {
// Bail out if debug info emission is not enabled.
if self.debug_context.is_none() {
return span;
}
// Walk up the macro expansion chain until we reach a non-expanded span.
// We also stop at the function body level because no line stepping can occur
// at the level above that.
// Use span of the outermost expansion site, while keeping the original lexical scope.
self.cx.tcx().collapsed_debuginfo(span, self.mir.span)
}

fn spill_operand_to_stack(
operand: OperandRef<'tcx, Bx::Value>,
name: Option<String>,
Expand Down
75 changes: 35 additions & 40 deletions compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -789,55 +789,50 @@ impl SyntaxExtension {
}
}

fn collapse_debuginfo_by_name(sess: &Session, attr: &Attribute) -> CollapseMacroDebuginfo {
use crate::errors::CollapseMacroDebuginfoIllegal;
// #[collapse_debuginfo] without enum value (#[collapse_debuginfo(no/external/yes)])
// considered as `yes`
attr.meta_item_list().map_or(CollapseMacroDebuginfo::Yes, |l| {
let [NestedMetaItem::MetaItem(item)] = &l[..] else {
sess.dcx().emit_err(CollapseMacroDebuginfoIllegal { span: attr.span });
return CollapseMacroDebuginfo::Unspecified;
};
if !item.is_word() {
sess.dcx().emit_err(CollapseMacroDebuginfoIllegal { span: item.span });
CollapseMacroDebuginfo::Unspecified
} else {
match item.name_or_empty() {
sym::no => CollapseMacroDebuginfo::No,
sym::external => CollapseMacroDebuginfo::External,
sym::yes => CollapseMacroDebuginfo::Yes,
_ => {
sess.dcx().emit_err(CollapseMacroDebuginfoIllegal { span: item.span });
CollapseMacroDebuginfo::Unspecified
}
}
}
})
fn collapse_debuginfo_by_name(attr: &Attribute) -> Result<CollapseMacroDebuginfo, Span> {
let list = attr.meta_item_list();
let Some([NestedMetaItem::MetaItem(item)]) = list.as_deref() else {
return Err(attr.span);
};
if !item.is_word() {
return Err(item.span);
}

match item.name_or_empty() {
sym::no => Ok(CollapseMacroDebuginfo::No),
sym::external => Ok(CollapseMacroDebuginfo::External),
sym::yes => Ok(CollapseMacroDebuginfo::Yes),
_ => Err(item.path.span),
}
}

/// if-ext - if macro from different crate (related to callsite code)
/// | cmd \ attr | no | (unspecified) | external | yes |
/// | no | no | no | no | no |
/// | (unspecified) | no | no | if-ext | yes |
/// | (unspecified) | no | if-ext | if-ext | yes |
/// | external | no | if-ext | if-ext | yes |
/// | yes | yes | yes | yes | yes |
fn get_collapse_debuginfo(sess: &Session, attrs: &[ast::Attribute], is_local: bool) -> bool {
let mut collapse_debuginfo_attr = attr::find_by_name(attrs, sym::collapse_debuginfo)
.map(|v| Self::collapse_debuginfo_by_name(sess, v))
.unwrap_or(CollapseMacroDebuginfo::Unspecified);
if collapse_debuginfo_attr == CollapseMacroDebuginfo::Unspecified
&& attr::contains_name(attrs, sym::rustc_builtin_macro)
{
collapse_debuginfo_attr = CollapseMacroDebuginfo::Yes;
}

let flag = sess.opts.unstable_opts.collapse_macro_debuginfo;
let attr = collapse_debuginfo_attr;
let ext = !is_local;
fn get_collapse_debuginfo(sess: &Session, attrs: &[ast::Attribute], ext: bool) -> bool {
let flag = sess.opts.cg.collapse_macro_debuginfo;
let attr = attr::find_by_name(attrs, sym::collapse_debuginfo)
.and_then(|attr| {
Self::collapse_debuginfo_by_name(attr)
.map_err(|span| {
sess.dcx().emit_err(errors::CollapseMacroDebuginfoIllegal { span })
})
.ok()
})
.unwrap_or_else(|| {
if attr::contains_name(attrs, sym::rustc_builtin_macro) {
CollapseMacroDebuginfo::Yes
} else {
CollapseMacroDebuginfo::Unspecified
}
});
#[rustfmt::skip]
let collapse_table = [
[false, false, false, false],
[false, false, ext, true],
[false, ext, ext, true],
[false, ext, ext, true],
[true, true, true, true],
];
Expand All @@ -864,7 +859,7 @@ impl SyntaxExtension {
let local_inner_macros = attr::find_by_name(attrs, sym::macro_export)
.and_then(|macro_export| macro_export.meta_item_list())
.is_some_and(|l| attr::list_contains_name(&l, sym::local_inner_macros));
let collapse_debuginfo = Self::get_collapse_debuginfo(sess, attrs, is_local);
let collapse_debuginfo = Self::get_collapse_debuginfo(sess, attrs, !is_local);
tracing::debug!(?name, ?local_inner_macros, ?collapse_debuginfo, ?allow_internal_unsafe);

let (builtin_name, helper_attrs) = attr::find_by_name(attrs, sym::rustc_builtin_macro)
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/accepted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ declare_features! (
(accepted, closure_to_fn_coercion, "1.19.0", Some(39817)),
/// Allows using the CMPXCHG16B target feature.
(accepted, cmpxchg16b_target_feature, "1.69.0", Some(44839)),
/// Allows use of the `#[collapse_debuginfo]` attribute.
(accepted, collapse_debuginfo, "CURRENT_RUSTC_VERSION", Some(100758)),
/// Allows usage of the `compile_error!` macro.
(accepted, compile_error, "1.20.0", Some(40872)),
/// Allows `impl Trait` in function return types.
Expand Down
9 changes: 3 additions & 6 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,9 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
template!(List: r#"natvis_file = "...", gdb_script_file = "...""#),
DuplicatesOk, EncodeCrossCrate::No
),
ungated!(collapse_debuginfo, Normal, template!(List: "no|external|yes"), ErrorFollowing,
EncodeCrossCrate::Yes
),

// ==========================================================================
// Unstable attributes:
Expand Down Expand Up @@ -516,12 +519,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
EncodeCrossCrate::Yes, experimental!(deprecated_safe),
),

// `#[collapse_debuginfo]`
gated!(
collapse_debuginfo, Normal, template!(Word, List: "no|external|yes"), ErrorFollowing,
EncodeCrossCrate::No, experimental!(collapse_debuginfo)
),

// RFC 2397
gated!(
do_not_recommend, Normal, template!(Word), WarnFollowing,
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,8 +395,6 @@ declare_features! (
(unstable, closure_track_caller, "1.57.0", Some(87417)),
/// Allows to use the `#[cmse_nonsecure_entry]` attribute.
(unstable, cmse_nonsecure_entry, "1.48.0", Some(75835)),
/// Allows use of the `#[collapse_debuginfo]` attribute.
(unstable, collapse_debuginfo, "1.65.0", Some(100758)),
/// Allows `async {}` expressions in const contexts.
(unstable, const_async_blocks, "1.53.0", Some(85368)),
/// Allows `const || {}` closures in const contexts.
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,7 @@ fn test_codegen_options_tracking_hash() {
// Make sure that changing a [TRACKED] option changes the hash.
// tidy-alphabetical-start
tracked!(code_model, Some(CodeModel::Large));
tracked!(collapse_macro_debuginfo, CollapseMacroDebuginfo::Yes);
tracked!(control_flow_guard, CFGuard::Checks);
tracked!(debug_assertions, Some(true));
tracked!(debuginfo, DebugInfo::Limited);
Expand Down Expand Up @@ -760,12 +761,10 @@ fn test_unstable_options_tracking_hash() {
})
);
tracked!(codegen_backend, Some("abc".to_string()));
tracked!(collapse_macro_debuginfo, CollapseMacroDebuginfo::Yes);
tracked!(coverage_options, CoverageOptions { branch: true, mcdc: true });
tracked!(crate_attr, vec!["abc".to_string()]);
tracked!(cross_crate_inline_threshold, InliningThreshold::Always);
tracked!(debug_info_for_profiling, true);
tracked!(debug_macros, true);
tracked!(default_hidden_visibility, Some(true));
tracked!(dep_info_omit_d_target, true);
tracked!(direct_access_external_data, Some(true));
Expand Down
18 changes: 1 addition & 17 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ use rustc_session::lint::LintBuffer;
pub use rustc_session::lint::RegisteredTools;
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{hygiene, ExpnId, ExpnKind, Span};
use rustc_span::{ExpnId, ExpnKind, Span};
use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
pub use rustc_target::abi::{ReprFlags, ReprOptions};
pub use rustc_type_ir::{DebugWithInfcx, InferCtxtLike, WithInfcx};
Expand Down Expand Up @@ -2013,22 +2013,6 @@ impl<'tcx> TyCtxt<'tcx> {
(ident, scope)
}

/// Returns corrected span if the debuginfo for `span` should be collapsed to the outermost
/// expansion site (with collapse_debuginfo attribute if the corresponding feature enabled).
/// Only applies when `Span` is the result of macro expansion.
///
/// - If the `collapse_debuginfo` feature is enabled then debuginfo is not collapsed by default
/// and only when a (some enclosing) macro definition is annotated with `#[collapse_debuginfo]`.
/// - If `collapse_debuginfo` is not enabled, then debuginfo is collapsed by default.
///
/// When `-Zdebug-macros` is provided then debuginfo will never be collapsed.
pub fn collapsed_debuginfo(self, span: Span, upto: Span) -> Span {
if self.sess.opts.unstable_opts.debug_macros || !span.from_expansion() {
return span;
}
hygiene::walk_chain_collapsed(span, upto, self.features().collapse_debuginfo)
}

#[inline]
pub fn is_const_fn_raw(self, def_id: DefId) -> bool {
matches!(
Expand Down
22 changes: 15 additions & 7 deletions compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1358,10 +1358,20 @@ mod parse {
slot: &mut CollapseMacroDebuginfo,
v: Option<&str>,
) -> bool {
if v.is_some() {
let mut bool_arg = None;
if parse_opt_bool(&mut bool_arg, v) {
*slot = if bool_arg.unwrap() {
CollapseMacroDebuginfo::Yes
} else {
CollapseMacroDebuginfo::No
};
return true;
}
}

*slot = match v {
Some("no") => CollapseMacroDebuginfo::No,
Some("external") => CollapseMacroDebuginfo::External,
Some("yes") => CollapseMacroDebuginfo::Yes,
_ => return false,
};
true
Expand Down Expand Up @@ -1460,6 +1470,9 @@ options! {
"choose the code model to use (`rustc --print code-models` for details)"),
codegen_units: Option<usize> = (None, parse_opt_number, [UNTRACKED],
"divide crate into N units to optimize in parallel"),
collapse_macro_debuginfo: CollapseMacroDebuginfo = (CollapseMacroDebuginfo::Unspecified,
parse_collapse_macro_debuginfo, [TRACKED],
"set option to collapse debuginfo for macros"),
control_flow_guard: CFGuard = (CFGuard::Disabled, parse_cfguard, [TRACKED],
"use Windows Control Flow Guard (default: no)"),
debug_assertions: Option<bool> = (None, parse_opt_bool, [TRACKED],
Expand Down Expand Up @@ -1607,9 +1620,6 @@ options! {
"show all expected values in check-cfg diagnostics (default: no)"),
codegen_backend: Option<String> = (None, parse_opt_string, [TRACKED],
"the backend to use"),
collapse_macro_debuginfo: CollapseMacroDebuginfo = (CollapseMacroDebuginfo::Unspecified,
parse_collapse_macro_debuginfo, [TRACKED],
"set option to collapse debuginfo for macros"),
combine_cgu: bool = (false, parse_bool, [TRACKED],
"combine CGUs into a single one"),
coverage_options: CoverageOptions = (CoverageOptions::default(), parse_coverage_options, [TRACKED],
Expand All @@ -1620,8 +1630,6 @@ options! {
"threshold to allow cross crate inlining of functions"),
debug_info_for_profiling: bool = (false, parse_bool, [TRACKED],
"emit discriminators and other data necessary for AutoFDO"),
debug_macros: bool = (false, parse_bool, [TRACKED],
"emit line numbers debug info inside macros (default: no)"),
debuginfo_compression: DebugInfoCompression = (DebugInfoCompression::None, parse_debuginfo_compression, [TRACKED],
"compress debug info sections (none, zlib, zstd, default: none)"),
deduplicate_diagnostics: bool = (true, parse_bool, [UNTRACKED],
Expand Down
38 changes: 15 additions & 23 deletions compiler/rustc_span/src/hygiene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,28 +459,21 @@ impl HygieneData {
span
}

// We need to walk up and update return span if we meet macro instantiation to be collapsed
fn walk_chain_collapsed(
&self,
mut span: Span,
to: Span,
collapse_debuginfo_feature_enabled: bool,
) -> Span {
fn walk_chain_collapsed(&self, mut span: Span, to: Span) -> Span {
let orig_span = span;
let mut ret_span = span;

debug!(
"walk_chain_collapsed({:?}, {:?}), feature_enable={}",
span, to, collapse_debuginfo_feature_enabled,
);
debug!("walk_chain_collapsed({:?}, {:?})", span, to);
debug!("walk_chain_collapsed: span ctxt = {:?}", span.ctxt());
while !span.eq_ctxt(to) && span.from_expansion() {
let outer_expn = self.outer_expn(span.ctxt());
while let ctxt = span.ctxt()
&& !ctxt.is_root()
&& ctxt != to.ctxt()
{
let outer_expn = self.outer_expn(ctxt);
debug!("walk_chain_collapsed({:?}): outer_expn={:?}", span, outer_expn);
let expn_data = self.expn_data(outer_expn);
debug!("walk_chain_collapsed({:?}): expn_data={:?}", span, expn_data);
span = expn_data.call_site;
if !collapse_debuginfo_feature_enabled || expn_data.collapse_debuginfo {
if expn_data.collapse_debuginfo {
ret_span = span;
}
}
Expand Down Expand Up @@ -604,14 +597,13 @@ pub fn walk_chain(span: Span, to: SyntaxContext) -> Span {
HygieneData::with(|data| data.walk_chain(span, to))
}

pub fn walk_chain_collapsed(
span: Span,
to: Span,
collapse_debuginfo_feature_enabled: bool,
) -> Span {
HygieneData::with(|hdata| {
hdata.walk_chain_collapsed(span, to, collapse_debuginfo_feature_enabled)
})
/// In order to have good line stepping behavior in debugger, for the given span we return its
/// outermost macro call site that still has a `#[collapse_debuginfo(yes)]` property on it.
/// We also stop walking call sites at the function body level because no line stepping can occur
/// at the level above that.
/// The returned span can then be used in emitted debuginfo.
pub fn walk_chain_collapsed(span: Span, to: Span) -> Span {
HygieneData::with(|data| data.walk_chain_collapsed(span, to))
}

pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symbol) {
Expand Down
12 changes: 12 additions & 0 deletions src/doc/rustc/src/codegen-options/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,18 @@ generated code, but may be slower to compile.
The default value, if not specified, is 16 for non-incremental builds. For
incremental builds the default is 256 which allows caching to be more granular.

## collapse-macro-debuginfo

This flag controls whether code locations from a macro definition are collapsed into a single
location associated with that macro's call site, when generating debuginfo for this crate.

This option, if passed, overrides both default collapsing behavior and `#[collapse_debuginfo]`
attributes in code.

* `y`, `yes`, `on`, `true`: collapse code locations in debuginfo.
* `n`, `no`, `off` or `false`: do not collapse code locations in debuginfo.
* `external`: collapse code locations in debuginfo only if the macro comes from a different crate.

## control-flow-guard

This flag controls whether LLVM enables the Windows [Control Flow
Expand Down
Loading

0 comments on commit 78aad13

Please sign in to comment.