Use the same DISubprogram for each instance of the same inlined function within the caller
This commit is contained in:
parent
faee636ebf
commit
687bffa493
@ -55,7 +55,7 @@ fn create_function_debug_context(
|
||||
_fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
|
||||
_llfn: RValue<'gcc>,
|
||||
_mir: &mir::Body<'tcx>,
|
||||
) -> Option<FunctionDebugContext<Self::DIScope, Self::DILocation>> {
|
||||
) -> Option<FunctionDebugContext<'tcx, Self::DIScope, Self::DILocation>> {
|
||||
// TODO(antoyo)
|
||||
None
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ pub fn compute_mir_scopes<'ll, 'tcx>(
|
||||
cx: &CodegenCx<'ll, 'tcx>,
|
||||
instance: Instance<'tcx>,
|
||||
mir: &Body<'tcx>,
|
||||
debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>,
|
||||
debug_context: &mut FunctionDebugContext<'tcx, &'ll DIScope, &'ll DILocation>,
|
||||
) {
|
||||
// Find all scopes with variables defined in them.
|
||||
let variables = if cx.sess().opts.debuginfo == DebugInfo::Full {
|
||||
@ -51,7 +51,7 @@ fn make_mir_scope<'ll, 'tcx>(
|
||||
instance: Instance<'tcx>,
|
||||
mir: &Body<'tcx>,
|
||||
variables: &Option<BitSet<SourceScope>>,
|
||||
debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>,
|
||||
debug_context: &mut FunctionDebugContext<'tcx, &'ll DIScope, &'ll DILocation>,
|
||||
instantiated: &mut BitSet<SourceScope>,
|
||||
scope: SourceScope,
|
||||
) {
|
||||
@ -84,7 +84,6 @@ fn make_mir_scope<'ll, 'tcx>(
|
||||
}
|
||||
|
||||
let loc = cx.lookup_debug_loc(scope_data.span.lo());
|
||||
let file_metadata = file_metadata(cx, &loc.file);
|
||||
|
||||
let dbg_scope = match scope_data.inlined {
|
||||
Some((callee, _)) => {
|
||||
@ -95,10 +94,17 @@ fn make_mir_scope<'ll, 'tcx>(
|
||||
ty::ParamEnv::reveal_all(),
|
||||
ty::EarlyBinder::bind(callee),
|
||||
);
|
||||
debug_context.inlined_function_scopes.entry(callee).or_insert_with(|| {
|
||||
let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty());
|
||||
cx.dbg_scope_fn(callee, callee_fn_abi, None)
|
||||
})
|
||||
}
|
||||
None => unsafe {
|
||||
None => {
|
||||
let file_metadata = file_metadata(cx, &loc.file);
|
||||
debug_context
|
||||
.lexical_blocks
|
||||
.entry((parent_scope.dbg_scope, loc.line, loc.col, file_metadata))
|
||||
.or_insert_with(|| unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateLexicalBlock(
|
||||
DIB(cx),
|
||||
parent_scope.dbg_scope,
|
||||
@ -106,7 +112,8 @@ fn make_mir_scope<'ll, 'tcx>(
|
||||
loc.line,
|
||||
loc.col,
|
||||
)
|
||||
},
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
let inlined_at = scope_data.inlined.map(|(_, callsite_span)| {
|
||||
|
@ -5,7 +5,7 @@
|
||||
use self::metadata::{file_metadata, type_di_node};
|
||||
use self::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER};
|
||||
use self::namespace::mangled_name_of_instance;
|
||||
use self::utils::{create_DIArray, is_node_local_to_unit, DIB};
|
||||
use self::utils::{create_DIArray, debug_context, is_node_local_to_unit, DIB};
|
||||
|
||||
use crate::abi::FnAbi;
|
||||
use crate::builder::Builder;
|
||||
@ -67,6 +67,8 @@ pub struct CodegenUnitDebugContext<'ll, 'tcx> {
|
||||
type_map: metadata::TypeMap<'ll, 'tcx>,
|
||||
namespace_map: RefCell<DefIdMap<&'ll DIScope>>,
|
||||
recursion_marker_type: OnceCell<&'ll DIType>,
|
||||
/// Maps a varaible (name, scope, kind (argument or local), span) to its debug information.
|
||||
variables: RefCell<FxHashMap<(Symbol, &'ll DIScope, VariableKind, Span), &'ll DIVariable>>,
|
||||
}
|
||||
|
||||
impl Drop for CodegenUnitDebugContext<'_, '_> {
|
||||
@ -91,6 +93,7 @@ pub fn new(llmod: &'ll llvm::Module) -> Self {
|
||||
type_map: Default::default(),
|
||||
namespace_map: RefCell::new(Default::default()),
|
||||
recursion_marker_type: OnceCell::new(),
|
||||
variables: RefCell::new(Default::default()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -292,7 +295,7 @@ fn create_function_debug_context(
|
||||
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
|
||||
llfn: &'ll Value,
|
||||
mir: &mir::Body<'tcx>,
|
||||
) -> Option<FunctionDebugContext<&'ll DIScope, &'ll DILocation>> {
|
||||
) -> Option<FunctionDebugContext<'tcx, &'ll DIScope, &'ll DILocation>> {
|
||||
if self.sess().opts.debuginfo == DebugInfo::None {
|
||||
return None;
|
||||
}
|
||||
@ -304,8 +307,11 @@ fn create_function_debug_context(
|
||||
file_start_pos: BytePos(0),
|
||||
file_end_pos: BytePos(0),
|
||||
};
|
||||
let mut fn_debug_context =
|
||||
FunctionDebugContext { scopes: IndexVec::from_elem(empty_scope, &mir.source_scopes) };
|
||||
let mut fn_debug_context = FunctionDebugContext {
|
||||
scopes: IndexVec::from_elem(empty_scope, &mir.source_scopes),
|
||||
inlined_function_scopes: Default::default(),
|
||||
lexical_blocks: Default::default(),
|
||||
};
|
||||
|
||||
// Fill in all the scopes, with the information from the MIR body.
|
||||
compute_mir_scopes(self, instance, mir, &mut fn_debug_context);
|
||||
@ -606,6 +612,11 @@ fn create_dbg_var(
|
||||
variable_kind: VariableKind,
|
||||
span: Span,
|
||||
) -> &'ll DIVariable {
|
||||
debug_context(self)
|
||||
.variables
|
||||
.borrow_mut()
|
||||
.entry((variable_name, scope_metadata, variable_kind, span))
|
||||
.or_insert_with(|| {
|
||||
let loc = self.lookup_debug_loc(span.lo());
|
||||
let file_metadata = file_metadata(self, &loc.file);
|
||||
|
||||
@ -634,5 +645,6 @@ fn create_dbg_var(
|
||||
align.bytes() as u32,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,12 @@
|
||||
use crate::traits::*;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
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::Instance;
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_session::config::DebugInfo;
|
||||
use rustc_span::symbol::{kw, Symbol};
|
||||
@ -17,11 +19,19 @@
|
||||
|
||||
use std::ops::Range;
|
||||
|
||||
pub struct FunctionDebugContext<S, L> {
|
||||
pub struct FunctionDebugContext<'tcx, S, L> {
|
||||
/// Maps from source code to the corresponding debug info scope.
|
||||
pub scopes: IndexVec<mir::SourceScope, DebugScope<S, L>>,
|
||||
|
||||
/// Maps from a given inlined function to its debug info declaration.
|
||||
pub inlined_function_scopes: FxHashMap<Instance<'tcx>, S>,
|
||||
|
||||
/// Maps from a lexical block (parent scope, line, column, file) to its debug info declaration.
|
||||
/// This is particularily useful if the parent scope is an inlined function.
|
||||
pub lexical_blocks: FxHashMap<(S, u32, u32, S), S>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum VariableKind {
|
||||
ArgumentVariable(usize /*index*/),
|
||||
LocalVariable,
|
||||
|
@ -45,7 +45,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
|
||||
|
||||
mir: &'tcx mir::Body<'tcx>,
|
||||
|
||||
debug_context: Option<FunctionDebugContext<Bx::DIScope, Bx::DILocation>>,
|
||||
debug_context: Option<FunctionDebugContext<'tcx, Bx::DIScope, Bx::DILocation>>,
|
||||
|
||||
llfn: Bx::Function,
|
||||
|
||||
|
@ -26,7 +26,7 @@ fn create_function_debug_context(
|
||||
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
|
||||
llfn: Self::Function,
|
||||
mir: &mir::Body<'tcx>,
|
||||
) -> Option<FunctionDebugContext<Self::DIScope, Self::DILocation>>;
|
||||
) -> Option<FunctionDebugContext<'tcx, Self::DIScope, Self::DILocation>>;
|
||||
|
||||
// FIXME(eddyb) find a common convention for all of the debuginfo-related
|
||||
// names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
|
||||
|
26
tests/codegen/debuginfo-inline-callsite-location.rs
Normal file
26
tests/codegen/debuginfo-inline-callsite-location.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// compile-flags: -g -O
|
||||
|
||||
// Check that each inline call site for the same function uses the same "sub-program" so that LLVM
|
||||
// can correctly merge the debug info if it merges the inlined code (e.g., for merging of tail
|
||||
// calls to panic.
|
||||
|
||||
// CHECK: tail call void @_ZN4core9panicking5panic17h{{([0-9a-z]{16})}}E
|
||||
// CHECK-SAME: !dbg ![[#first_dbg:]]
|
||||
// CHECK: tail call void @_ZN4core9panicking5panic17h{{([0-9a-z]{16})}}E
|
||||
// CHECK-SAME: !dbg ![[#second_dbg:]]
|
||||
|
||||
// CHECK: ![[#func_dbg:]] = distinct !DISubprogram(name: "unwrap<i32>"
|
||||
// CHECK: ![[#first_dbg]] = !DILocation(line: [[#]]
|
||||
// CHECK-SAME: scope: ![[#func_dbg]], inlinedAt: ![[#]])
|
||||
// CHECK: ![[#second_dbg]] = !DILocation(line: [[#]]
|
||||
// CHECK-SAME: scope: ![[#func_dbg]], inlinedAt: ![[#]])
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn add_numbers(x: &Option<i32>, y: &Option<i32>) -> i32 {
|
||||
let x1 = x.unwrap();
|
||||
let y1 = y.unwrap();
|
||||
|
||||
x1 + y1
|
||||
}
|
Loading…
Reference in New Issue
Block a user