rustc_codegen_llvm: add support for inlined function debuginfo.
This commit is contained in:
parent
737499593d
commit
0ce4452fce
5 changed files with 137 additions and 64 deletions
|
@ -12,8 +12,8 @@ use super::operand::OperandValue;
|
|||
use super::place::PlaceRef;
|
||||
use super::{FunctionCx, LocalRef};
|
||||
|
||||
pub struct FunctionDebugContext<D> {
|
||||
pub scopes: IndexVec<mir::SourceScope, DebugScope<D>>,
|
||||
pub struct FunctionDebugContext<S, L> {
|
||||
pub scopes: IndexVec<mir::SourceScope, DebugScope<S, L>>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
|
@ -36,15 +36,42 @@ pub struct PerLocalVarDebugInfo<'tcx, D> {
|
|||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct DebugScope<D> {
|
||||
pub struct DebugScope<S, L> {
|
||||
// FIXME(eddyb) this should never be `None`, after initialization.
|
||||
pub dbg_scope: Option<D>,
|
||||
pub dbg_scope: Option<S>,
|
||||
|
||||
/// Call site location, if this scope was inlined from another function.
|
||||
pub inlined_at: Option<L>,
|
||||
|
||||
// Start and end offsets of the file to which this DIScope belongs.
|
||||
// These are used to quickly determine whether some span refers to the same file.
|
||||
pub file_start_pos: BytePos,
|
||||
pub file_end_pos: BytePos,
|
||||
}
|
||||
|
||||
impl<'tcx, S: Copy, L: Copy> DebugScope<S, L> {
|
||||
/// DILocations inherit source file name from the parent DIScope. Due to macro expansions
|
||||
/// it may so happen that the current span belongs to a different file than the DIScope
|
||||
/// corresponding to span's containing source scope. If so, we need to create a DIScope
|
||||
/// "extension" into that file.
|
||||
pub fn adjust_dbg_scope_for_span<Cx: CodegenMethods<'tcx, DIScope = S, DILocation = L>>(
|
||||
&self,
|
||||
cx: &Cx,
|
||||
span: Span,
|
||||
) -> S {
|
||||
// FIXME(eddyb) this should never be `None`.
|
||||
let dbg_scope = self.dbg_scope.unwrap();
|
||||
|
||||
let pos = span.lo();
|
||||
if pos < self.file_start_pos || pos >= self.file_end_pos {
|
||||
let sm = cx.sess().source_map();
|
||||
cx.extend_scope_to_file(dbg_scope, &sm.lookup_char_pos(pos).file)
|
||||
} else {
|
||||
dbg_scope
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
pub fn set_debug_loc(&self, bx: &mut Bx, source_info: mir::SourceInfo) {
|
||||
bx.set_span(source_info.span);
|
||||
|
@ -54,19 +81,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
|
||||
fn dbg_loc(&self, source_info: mir::SourceInfo) -> Option<Bx::DILocation> {
|
||||
let (scope, span) = self.dbg_scope_and_span(source_info)?;
|
||||
Some(self.cx.dbg_loc(scope, span))
|
||||
let span = self.adjust_span_for_debugging(source_info.span);
|
||||
let scope = &self.debug_context.as_ref()?.scopes[source_info.scope];
|
||||
let dbg_scope = scope.adjust_dbg_scope_for_span(self.cx, span);
|
||||
Some(self.cx.dbg_loc(dbg_scope, scope.inlined_at, span))
|
||||
}
|
||||
|
||||
fn dbg_scope_and_span(&self, source_info: mir::SourceInfo) -> Option<(Bx::DIScope, 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
|
||||
/// (unless the crate is being compiled with `-Z debug-macros`).
|
||||
fn adjust_span_for_debugging(&self, mut span: Span) -> Span {
|
||||
// Bail out if debug info emission is not enabled.
|
||||
let debug_context = self.debug_context.as_ref()?;
|
||||
let scope = &debug_context.scopes[source_info.scope];
|
||||
if self.debug_context.is_none() {
|
||||
return 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
|
||||
// (unless the crate is being compiled with `-Z debug-macros`).
|
||||
let mut span = source_info.span;
|
||||
if span.from_expansion() && !self.cx.sess().opts.debugging_opts.debug_macros {
|
||||
// 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
|
||||
|
@ -75,20 +104,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
span = rustc_span::hygiene::walk_chain(span, self.mir.span.ctxt());
|
||||
}
|
||||
|
||||
// FIXME(eddyb) this should never be `None`.
|
||||
let mut dbg_scope = scope.dbg_scope?;
|
||||
|
||||
// DILocations inherit source file name from the parent DIScope. Due to macro expansions
|
||||
// it may so happen that the current span belongs to a different file than the DIScope
|
||||
// corresponding to span's containing source scope. If so, we need to create a DIScope
|
||||
// "extension" into that file.
|
||||
let pos = span.lo();
|
||||
if pos < scope.file_start_pos || pos >= scope.file_end_pos {
|
||||
let sm = self.cx.sess().source_map();
|
||||
dbg_scope = self.cx.extend_scope_to_file(dbg_scope, &sm.lookup_char_pos(pos).file);
|
||||
}
|
||||
|
||||
Some((dbg_scope, span))
|
||||
span
|
||||
}
|
||||
|
||||
/// Apply debuginfo and/or name, after creating the `alloca` for a local,
|
||||
|
@ -130,11 +146,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
let name = kw::Invalid;
|
||||
let decl = &self.mir.local_decls[local];
|
||||
let dbg_var = if full_debug_info {
|
||||
self.dbg_scope_and_span(decl.source_info).map(|(scope, span)| {
|
||||
self.debug_context.as_ref().map(|debug_context| {
|
||||
// FIXME(eddyb) is this `+ 1` needed at all?
|
||||
let kind = VariableKind::ArgumentVariable(arg_index + 1);
|
||||
|
||||
self.cx.create_dbg_var(name, self.monomorphize(&decl.ty), scope, kind, span)
|
||||
let arg_ty = self.monomorphize(&decl.ty);
|
||||
|
||||
let span = self.adjust_span_for_debugging(decl.source_info.span);
|
||||
let scope = &debug_context.scopes[decl.source_info.scope];
|
||||
let dbg_scope = scope.adjust_dbg_scope_for_span(self.cx, span);
|
||||
|
||||
self.cx.create_dbg_var(name, arg_ty, dbg_scope, kind, span)
|
||||
})
|
||||
} else {
|
||||
None
|
||||
|
@ -288,9 +310,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
|
||||
let mut per_local = IndexVec::from_elem(vec![], &self.mir.local_decls);
|
||||
for var in &self.mir.var_debug_info {
|
||||
let scope_and_span =
|
||||
if full_debug_info { self.dbg_scope_and_span(var.source_info) } else { None };
|
||||
let dbg_var = scope_and_span.map(|(scope, span)| {
|
||||
let dbg_scope_and_span = if full_debug_info {
|
||||
self.debug_context.as_ref().map(|debug_context| {
|
||||
let span = self.adjust_span_for_debugging(var.source_info.span);
|
||||
let scope = &debug_context.scopes[var.source_info.scope];
|
||||
(scope.adjust_dbg_scope_for_span(self.cx, span), span)
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let dbg_var = dbg_scope_and_span.map(|(dbg_scope, span)| {
|
||||
let place = var.place;
|
||||
let var_ty = self.monomorphized_place_ty(place.as_ref());
|
||||
let var_kind = if self.mir.local_kind(place.local) == mir::LocalKind::Arg
|
||||
|
@ -306,7 +335,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
} else {
|
||||
VariableKind::LocalVariable
|
||||
};
|
||||
self.cx.create_dbg_var(var.name, var_ty, scope, var_kind, span)
|
||||
self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span)
|
||||
});
|
||||
|
||||
per_local[var.place.local].push(PerLocalVarDebugInfo {
|
||||
|
|
|
@ -26,7 +26,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
|
|||
|
||||
mir: &'tcx mir::Body<'tcx>,
|
||||
|
||||
debug_context: Option<FunctionDebugContext<Bx::DIScope>>,
|
||||
debug_context: Option<FunctionDebugContext<Bx::DIScope, Bx::DILocation>>,
|
||||
|
||||
llfn: Bx::Function,
|
||||
|
||||
|
|
|
@ -18,8 +18,8 @@ pub trait DebugInfoMethods<'tcx>: BackendTypes {
|
|||
instance: Instance<'tcx>,
|
||||
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
|
||||
llfn: Self::Function,
|
||||
mir: &mir::Body<'_>,
|
||||
) -> Option<FunctionDebugContext<Self::DIScope>>;
|
||||
mir: &mir::Body<'tcx>,
|
||||
) -> Option<FunctionDebugContext<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.).
|
||||
|
@ -30,7 +30,12 @@ pub trait DebugInfoMethods<'tcx>: BackendTypes {
|
|||
maybe_definition_llfn: Option<Self::Function>,
|
||||
) -> Self::DIScope;
|
||||
|
||||
fn dbg_loc(&self, scope: Self::DIScope, span: Span) -> Self::DILocation;
|
||||
fn dbg_loc(
|
||||
&self,
|
||||
scope: Self::DIScope,
|
||||
inlined_at: Option<Self::DILocation>,
|
||||
span: Span,
|
||||
) -> Self::DILocation;
|
||||
|
||||
fn extend_scope_to_file(
|
||||
&self,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue