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

rustc_mir: track inlined callees in SourceScopeData. #68965

Merged
merged 18 commits into from
Oct 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
1 change: 1 addition & 0 deletions compiler/rustc_codegen_llvm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ impl BackendTypes for Builder<'_, 'll, 'tcx> {
type Funclet = <CodegenCx<'ll, 'tcx> as BackendTypes>::Funclet;

type DIScope = <CodegenCx<'ll, 'tcx> as BackendTypes>::DIScope;
type DILocation = <CodegenCx<'ll, 'tcx> as BackendTypes>::DILocation;
type DIVariable = <CodegenCx<'ll, 'tcx> as BackendTypes>::DIVariable;
}

Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_codegen_llvm/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,15 @@ impl Funclet<'ll> {

impl BackendTypes for CodegenCx<'ll, 'tcx> {
type Value = &'ll Value;
// FIXME(eddyb) replace this with a `Function` "subclass" of `Value`.
type Function = &'ll Value;

type BasicBlock = &'ll BasicBlock;
type Type = &'ll Type;
type Funclet = Funclet<'ll>;

type DIScope = &'ll llvm::debuginfo::DIScope;
type DILocation = &'ll llvm::debuginfo::DILocation;
type DIVariable = &'ll llvm::debuginfo::DIVariable;
}

Expand Down
81 changes: 55 additions & 26 deletions compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,26 @@ use super::utils::DIB;
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext};
use rustc_codegen_ssa::traits::*;

use crate::abi::FnAbi;
use crate::common::CodegenCx;
use crate::llvm;
use crate::llvm::debuginfo::{DIScope, DISubprogram};
use crate::llvm::debuginfo::{DILocation, DIScope};
use rustc_middle::mir::{Body, SourceScope};
use rustc_middle::ty::layout::FnAbiExt;
use rustc_middle::ty::{self, Instance};
use rustc_session::config::DebugInfo;

use rustc_index::bit_set::BitSet;
use rustc_index::vec::Idx;

/// Produces DIScope DIEs for each MIR Scope which has variables defined in it.
// FIXME(eddyb) almost all of this should be in `rustc_codegen_ssa::mir::debuginfo`.
pub fn compute_mir_scopes(
cx: &CodegenCx<'ll, '_>,
mir: &Body<'_>,
fn_metadata: &'ll DISubprogram,
debug_context: &mut FunctionDebugContext<&'ll DIScope>,
cx: &CodegenCx<'ll, 'tcx>,
instance: Instance<'tcx>,
mir: &Body<'tcx>,
fn_dbg_scope: &'ll DIScope,
debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>,
) {
// Find all the scopes with variables defined in them.
let mut has_variables = BitSet::new_empty(mir.source_scopes.len());
Expand All @@ -37,58 +42,82 @@ pub fn compute_mir_scopes(
// Instantiate all scopes.
for idx in 0..mir.source_scopes.len() {
let scope = SourceScope::new(idx);
make_mir_scope(cx, &mir, fn_metadata, &has_variables, debug_context, scope);
make_mir_scope(cx, instance, &mir, fn_dbg_scope, &has_variables, debug_context, scope);
}
}

fn make_mir_scope(
cx: &CodegenCx<'ll, '_>,
mir: &Body<'_>,
fn_metadata: &'ll DISubprogram,
cx: &CodegenCx<'ll, 'tcx>,
instance: Instance<'tcx>,
mir: &Body<'tcx>,
fn_dbg_scope: &'ll DIScope,
has_variables: &BitSet<SourceScope>,
debug_context: &mut FunctionDebugContext<&'ll DISubprogram>,
debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>,
scope: SourceScope,
) {
if debug_context.scopes[scope].is_valid() {
if debug_context.scopes[scope].dbg_scope.is_some() {
return;
}

let scope_data = &mir.source_scopes[scope];
let parent_scope = if let Some(parent) = scope_data.parent_scope {
make_mir_scope(cx, mir, fn_metadata, has_variables, debug_context, parent);
make_mir_scope(cx, instance, mir, fn_dbg_scope, has_variables, debug_context, parent);
debug_context.scopes[parent]
} else {
// The root is the function itself.
let loc = cx.lookup_debug_loc(mir.span.lo());
debug_context.scopes[scope] = DebugScope {
scope_metadata: Some(fn_metadata),
dbg_scope: Some(fn_dbg_scope),
inlined_at: None,
file_start_pos: loc.file.start_pos,
file_end_pos: loc.file.end_pos,
};
return;
};

if !has_variables.contains(scope) {
// Do not create a DIScope if there are no variables
// defined in this MIR Scope, to avoid debuginfo bloat.
if !has_variables.contains(scope) && scope_data.inlined.is_none() {
// Do not create a DIScope if there are no variables defined in this
// MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat.
debug_context.scopes[scope] = parent_scope;
return;
}

let loc = cx.lookup_debug_loc(scope_data.span.lo());
let file_metadata = file_metadata(cx, &loc.file, debug_context.defining_crate);
let file_metadata = file_metadata(cx, &loc.file);

let scope_metadata = unsafe {
Some(llvm::LLVMRustDIBuilderCreateLexicalBlock(
DIB(cx),
parent_scope.scope_metadata.unwrap(),
file_metadata,
loc.line.unwrap_or(UNKNOWN_LINE_NUMBER),
loc.col.unwrap_or(UNKNOWN_COLUMN_NUMBER),
))
let dbg_scope = match scope_data.inlined {
Some((callee, _)) => {
// FIXME(eddyb) this would be `self.monomorphize(&callee)`
// if this is moved to `rustc_codegen_ssa::mir::debuginfo`.
let callee = cx.tcx.subst_and_normalize_erasing_regions(
instance.substs,
ty::ParamEnv::reveal_all(),
&callee,
);
let callee_fn_abi = FnAbi::of_instance(cx, callee, &[]);
cx.dbg_scope_fn(callee, &callee_fn_abi, None)
}
None => unsafe {
llvm::LLVMRustDIBuilderCreateLexicalBlock(
DIB(cx),
parent_scope.dbg_scope.unwrap(),
file_metadata,
loc.line.unwrap_or(UNKNOWN_LINE_NUMBER),
loc.col.unwrap_or(UNKNOWN_COLUMN_NUMBER),
)
},
};

let inlined_at = scope_data.inlined.map(|(_, callsite_span)| {
// FIXME(eddyb) this doesn't account for the macro-related
// `Span` fixups that `rustc_codegen_ssa::mir::debuginfo` does.
let callsite_scope = parent_scope.adjust_dbg_scope_for_span(cx, callsite_span);
cx.dbg_loc(callsite_scope, parent_scope.inlined_at, callsite_span)
});

debug_context.scopes[scope] = DebugScope {
scope_metadata,
dbg_scope: Some(dbg_scope),
inlined_at: inlined_at.or(parent_scope.inlined_at),
file_start_pos: loc.file.start_pos,
file_end_pos: loc.file.end_pos,
};
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/debuginfo/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
//! utilizing a cache. The way to get a shared metadata node when needed is
//! thus to just call the corresponding function in this module:
//!
//! let file_metadata = file_metadata(crate_context, path);
//! let file_metadata = file_metadata(cx, file);
//!
//! The function will take care of probing the cache for an existing node for
//! that exact file path.
Expand Down
21 changes: 8 additions & 13 deletions compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_fs_util::path_to_c_string;
use rustc_hir::def::CtorKind;
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::ich::NodeIdHashingMode;
use rustc_middle::mir::interpret::truncate;
Expand Down Expand Up @@ -760,16 +760,12 @@ fn hex_encode(data: &[u8]) -> String {
hex_string
}

pub fn file_metadata(
cx: &CodegenCx<'ll, '_>,
source_file: &SourceFile,
defining_crate: CrateNum,
) -> &'ll DIFile {
debug!("file_metadata: file_name: {}, defining_crate: {}", source_file.name, defining_crate);
pub fn file_metadata(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) -> &'ll DIFile {
debug!("file_metadata: file_name: {}", source_file.name);

let hash = Some(&source_file.src_hash);
let file_name = Some(source_file.name.to_string());
let directory = if defining_crate == LOCAL_CRATE {
let directory = if source_file.is_real_file() && !source_file.is_imported() {
Some(cx.sess().working_dir.0.to_string_lossy().to_string())
} else {
// If the path comes from an upstream crate we assume it has been made
Expand Down Expand Up @@ -1835,7 +1831,7 @@ impl<'tcx> VariantInfo<'_, 'tcx> {
if !span.is_dummy() {
let loc = cx.lookup_debug_loc(span.lo());
return Some(SourceInfo {
file: file_metadata(cx, &loc.file, def_id.krate),
file: file_metadata(cx, &loc.file),
line: loc.line.unwrap_or(UNKNOWN_LINE_NUMBER),
});
}
Expand Down Expand Up @@ -2474,7 +2470,7 @@ pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global

let (file_metadata, line_number) = if !span.is_dummy() {
let loc = cx.lookup_debug_loc(span.lo());
(file_metadata(cx, &loc.file, LOCAL_CRATE), loc.line)
(file_metadata(cx, &loc.file), loc.line)
} else {
(unknown_file_metadata(cx), None)
};
Expand Down Expand Up @@ -2576,9 +2572,8 @@ pub fn create_vtable_metadata(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, vtable: &
pub fn extend_scope_to_file(
cx: &CodegenCx<'ll, '_>,
scope_metadata: &'ll DIScope,
file: &rustc_span::SourceFile,
defining_crate: CrateNum,
file: &SourceFile,
) -> &'ll DILexicalBlock {
let file_metadata = file_metadata(cx, &file, defining_crate);
let file_metadata = file_metadata(cx, file);
unsafe { llvm::LLVMRustDIBuilderCreateLexicalBlockFile(DIB(cx), scope_metadata, file_metadata) }
}
Loading