rustc_codegen_llvm: add support for inlined function debuginfo.
This commit is contained in:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user