summaryrefslogtreecommitdiff
path: root/src/librustc_codegen_ssa
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustc_codegen_ssa')
-rw-r--r--src/librustc_codegen_ssa/mir/block.rs74
-rw-r--r--src/librustc_codegen_ssa/mir/debuginfo.rs172
-rw-r--r--src/librustc_codegen_ssa/mir/mod.rs2
-rw-r--r--src/librustc_codegen_ssa/traits/backend.rs1
-rw-r--r--src/librustc_codegen_ssa/traits/debuginfo.rs28
-rw-r--r--src/librustc_codegen_ssa/traits/mod.rs1
6 files changed, 155 insertions, 123 deletions
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index 8433f793020..32299a5b490 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -15,7 +15,7 @@ use rustc::mir::AssertKind;
use rustc::ty::layout::{self, FnAbiExt, HasTyCtxt, LayoutOf};
use rustc::ty::{self, Instance, Ty, TypeFoldable};
use rustc_index::vec::Idx;
-use rustc_span::{source_map::Span, symbol::Symbol};
+use rustc_span::{Span, Symbol};
use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode};
use rustc_target::spec::abi::Abi;
@@ -403,7 +403,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
self.set_debug_loc(&mut bx, terminator.source_info);
// Get the location information.
- let location = self.get_caller_location(&mut bx, span).immediate();
+ let location = self.get_caller_location(&mut bx, terminator.source_info).immediate();
// Put together the arguments to the panic entry point.
let (lang_item, args) = match msg {
@@ -440,7 +440,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
bx: &mut Bx,
intrinsic: Option<&str>,
instance: Option<Instance<'tcx>>,
- span: Span,
+ source_info: mir::SourceInfo,
destination: &Option<(mir::Place<'tcx>, mir::BasicBlock)>,
cleanup: Option<mir::BasicBlock>,
) -> bool {
@@ -481,12 +481,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
format!("attempted to leave type `{}` uninitialized, which is invalid", ty)
};
let msg = bx.const_str(Symbol::intern(&msg_str));
- let location = self.get_caller_location(bx, span).immediate();
+ let location = self.get_caller_location(bx, source_info).immediate();
// Obtain the panic entry point.
// FIXME: dedup this with `codegen_assert_terminator` above.
- let def_id =
- common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem);
+ let def_id = common::langcall(
+ bx.tcx(),
+ Some(source_info.span),
+ "",
+ lang_items::PanicFnLangItem,
+ );
let instance = ty::Instance::mono(bx.tcx(), def_id);
let fn_abi = FnAbi::of_instance(bx, instance, &[]);
let llfn = bx.get_fn_addr(instance);
@@ -526,7 +530,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
destination: &Option<(mir::Place<'tcx>, mir::BasicBlock)>,
cleanup: Option<mir::BasicBlock>,
) {
- let span = terminator.source_info.span;
+ let source_info = terminator.source_info;
+ let span = source_info.span;
+
// Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
let callee = self.codegen_operand(&mut bx, func);
@@ -607,7 +613,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
&mut bx,
intrinsic,
instance,
- span,
+ source_info,
destination,
cleanup,
) {
@@ -628,7 +634,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
if intrinsic == Some("caller_location") {
if let Some((_, target)) = destination.as_ref() {
- let location = self.get_caller_location(&mut bx, span);
+ let location = self.get_caller_location(&mut bx, source_info);
if let ReturnDest::IndirectOperand(tmp, _) = ret_dest {
location.val.store(&mut bx, tmp);
@@ -680,13 +686,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
})
.collect();
- bx.codegen_intrinsic_call(
- *instance.as_ref().unwrap(),
- &fn_abi,
- &args,
- dest,
- terminator.source_info.span,
- );
+ bx.codegen_intrinsic_call(*instance.as_ref().unwrap(), &fn_abi, &args, dest, span);
if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
self.store_return(&mut bx, ret_dest, &fn_abi.ret, dst.llval);
@@ -792,7 +792,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
args.len() + 1,
"#[track_caller] fn's must have 1 more argument in their ABI than in their MIR",
);
- let location = self.get_caller_location(&mut bx, span);
+ let location = self.get_caller_location(&mut bx, source_info);
let last_arg = fn_abi.args.last().unwrap();
self.codegen_argument(&mut bx, location, &mut llargs, last_arg);
}
@@ -1035,17 +1035,47 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
}
- fn get_caller_location(&mut self, bx: &mut Bx, span: Span) -> OperandRef<'tcx, Bx::Value> {
- self.caller_location.unwrap_or_else(|| {
+ fn get_caller_location(
+ &mut self,
+ bx: &mut Bx,
+ source_info: mir::SourceInfo,
+ ) -> OperandRef<'tcx, Bx::Value> {
+ let tcx = bx.tcx();
+
+ let mut span_to_caller_location = |span: Span| {
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
- let caller = bx.tcx().sess.source_map().lookup_char_pos(topmost.lo());
- let const_loc = bx.tcx().const_caller_location((
+ let caller = tcx.sess.source_map().lookup_char_pos(topmost.lo());
+ let const_loc = tcx.const_caller_location((
Symbol::intern(&caller.file.name.to_string()),
caller.line as u32,
caller.col_display as u32 + 1,
));
OperandRef::from_const(bx, const_loc, bx.tcx().caller_location_ty())
- })
+ };
+
+ // Walk up the `SourceScope`s, in case some of them are from MIR inlining.
+ let mut caller_span = source_info.span;
+ let mut scope = source_info.scope;
+ loop {
+ let scope_data = &self.mir.source_scopes[scope];
+
+ if let Some((callee, callsite_span)) = scope_data.inlined {
+ // Stop before ("inside") the callsite of a non-`#[track_caller]` function.
+ if !callee.def.requires_caller_location(tcx) {
+ return span_to_caller_location(caller_span);
+ }
+ caller_span = callsite_span;
+ }
+
+ // Skip past all of the parents with `inlined: None`.
+ match scope_data.inlined_parent_scope {
+ Some(parent) => scope = parent,
+ None => break,
+ }
+ }
+
+ // No inlined `SourceScope`s, or all of them were `#[track_caller]`.
+ self.caller_location.unwrap_or_else(|| span_to_caller_location(caller_span))
}
fn get_personality_slot(&mut self, bx: &mut Bx) -> PlaceRef<'tcx, Bx::Value> {
diff --git a/src/librustc_codegen_ssa/mir/debuginfo.rs b/src/librustc_codegen_ssa/mir/debuginfo.rs
index cbe5f511152..45bbfa4f099 100644
--- a/src/librustc_codegen_ssa/mir/debuginfo.rs
+++ b/src/librustc_codegen_ssa/mir/debuginfo.rs
@@ -2,7 +2,6 @@ use crate::traits::*;
use rustc::mir;
use rustc::ty;
use rustc::ty::layout::{LayoutOf, Size};
-use rustc_hir::def_id::CrateNum;
use rustc_index::vec::IndexVec;
use rustc_session::config::DebugInfo;
@@ -13,9 +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 defining_crate: CrateNum,
+pub struct FunctionDebugContext<S, L> {
+ pub scopes: IndexVec<mir::SourceScope, DebugScope<S, L>>,
}
#[derive(Copy, Clone)]
@@ -38,76 +36,74 @@ pub struct PerLocalVarDebugInfo<'tcx, D> {
}
#[derive(Clone, Copy, Debug)]
-pub struct DebugScope<D> {
- pub scope_metadata: Option<D>,
+pub struct DebugScope<S, L> {
+ // FIXME(eddyb) this should never be `None`, after initialization.
+ 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<D> DebugScope<D> {
- pub fn is_valid(&self) -> bool {
- self.scope_metadata.is_some()
+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) {
- let (scope, span) = self.debug_loc(source_info);
- if let Some(scope) = scope {
- bx.set_source_location(scope, span);
+ if let Some(dbg_loc) = self.dbg_loc(source_info) {
+ bx.set_dbg_loc(dbg_loc);
}
}
- pub fn debug_loc(&self, source_info: mir::SourceInfo) -> (Option<Bx::DIScope>, Span) {
+ fn dbg_loc(&self, source_info: mir::SourceInfo) -> Option<Bx::DILocation> {
+ 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))
+ }
+
+ /// 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.
- match self.debug_context {
- None => return (None, source_info.span),
- Some(_) => {}
+ 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`).
- if !source_info.span.from_expansion() || self.cx.sess().opts.debugging_opts.debug_macros {
- let scope = self.scope_metadata_for_loc(source_info.scope, source_info.span.lo());
- (scope, source_info.span)
- } else {
+ 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
// at the level above that.
- let span = rustc_span::hygiene::walk_chain(source_info.span, self.mir.span.ctxt());
- let scope = self.scope_metadata_for_loc(source_info.scope, span.lo());
// Use span of the outermost expansion site, while keeping the original lexical scope.
- (scope, span)
+ span = rustc_span::hygiene::walk_chain(span, self.mir.span.ctxt());
}
- }
- // 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.
- fn scope_metadata_for_loc(
- &self,
- scope_id: mir::SourceScope,
- pos: BytePos,
- ) -> Option<Bx::DIScope> {
- let debug_context = self.debug_context.as_ref()?;
- let scope_metadata = debug_context.scopes[scope_id].scope_metadata;
- if pos < debug_context.scopes[scope_id].file_start_pos
- || pos >= debug_context.scopes[scope_id].file_end_pos
- {
- let sm = self.cx.sess().source_map();
- let defining_crate = debug_context.defining_crate;
- Some(self.cx.extend_scope_to_file(
- scope_metadata.unwrap(),
- &sm.lookup_char_pos(pos).file,
- defining_crate,
- ))
- } else {
- scope_metadata
- }
+ span
}
/// Apply debuginfo and/or name, after creating the `alloca` for a local,
@@ -147,24 +143,22 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
} else {
let name = kw::Invalid;
let decl = &self.mir.local_decls[local];
- let (scope, span) = if full_debug_info {
- self.debug_loc(decl.source_info)
+ let dbg_var = if full_debug_info {
+ self.debug_context.as_ref().map(|debug_context| {
+ // FIXME(eddyb) is this `+ 1` needed at all?
+ let kind = VariableKind::ArgumentVariable(arg_index + 1);
+
+ 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, decl.source_info.span)
+ None
};
- let dbg_var = scope.map(|scope| {
- // FIXME(eddyb) is this `+ 1` needed at all?
- let kind = VariableKind::ArgumentVariable(arg_index + 1);
-
- self.cx.create_dbg_var(
- self.debug_context.as_ref().unwrap(),
- name,
- self.monomorphize(&decl.ty),
- scope,
- kind,
- span,
- )
- });
Some(PerLocalVarDebugInfo {
name,
@@ -238,6 +232,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let vars = vars.iter().copied().chain(fallback_var);
for var in vars {
+ let dbg_var = match var.dbg_var {
+ Some(dbg_var) => dbg_var,
+ None => continue,
+ };
+ let dbg_loc = match self.dbg_loc(var.source_info) {
+ Some(dbg_loc) => dbg_loc,
+ None => continue,
+ };
+
let mut layout = base.layout;
let mut direct_offset = Size::ZERO;
// FIXME(eddyb) use smallvec here.
@@ -274,19 +277,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
}
- let (scope, span) = self.debug_loc(var.source_info);
- if let Some(scope) = scope {
- if let Some(dbg_var) = var.dbg_var {
- bx.dbg_var_addr(
- dbg_var,
- scope,
- base.llval,
- direct_offset,
- &indirect_offsets,
- span,
- );
- }
- }
+ bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, direct_offset, &indirect_offsets);
}
}
@@ -310,12 +301,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, span) = if full_debug_info {
- self.debug_loc(var.source_info)
+ 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, var.source_info.span)
+ None
};
- let dbg_var = scope.map(|scope| {
+ 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
@@ -331,14 +326,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
} else {
VariableKind::LocalVariable
};
- self.cx.create_dbg_var(
- self.debug_context.as_ref().unwrap(),
- 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 {
diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs
index 64ead19b358..72ceb3c597a 100644
--- a/src/librustc_codegen_ssa/mir/mod.rs
+++ b/src/librustc_codegen_ssa/mir/mod.rs
@@ -23,7 +23,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
mir: mir::ReadOnlyBodyAndCache<'tcx, 'tcx>,
- debug_context: Option<FunctionDebugContext<Bx::DIScope>>,
+ debug_context: Option<FunctionDebugContext<Bx::DIScope, Bx::DILocation>>,
llfn: Bx::Function,
diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs
index 7acae300a2f..bb479a27c86 100644
--- a/src/librustc_codegen_ssa/traits/backend.rs
+++ b/src/librustc_codegen_ssa/traits/backend.rs
@@ -24,6 +24,7 @@ pub trait BackendTypes {
// FIXME(eddyb) find a common convention for all of the debuginfo-related
// names (choose between `Dbg`, `Debug`, `DebugInfo`, `DI` etc.).
type DIScope: Copy;
+ type DILocation: Copy;
type DIVariable: Copy;
}
diff --git a/src/librustc_codegen_ssa/traits/debuginfo.rs b/src/librustc_codegen_ssa/traits/debuginfo.rs
index 14c5a1b8ee9..7408d78bbe7 100644
--- a/src/librustc_codegen_ssa/traits/debuginfo.rs
+++ b/src/librustc_codegen_ssa/traits/debuginfo.rs
@@ -4,7 +4,6 @@ use rustc::mir;
use rustc::ty::layout::Size;
use rustc::ty::{Instance, Ty};
use rustc_ast::ast::Name;
-use rustc_hir::def_id::CrateNum;
use rustc_span::{SourceFile, Span};
use rustc_target::abi::call::FnAbi;
@@ -20,14 +19,29 @@ 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.).
+ fn dbg_scope_fn(
+ &self,
+ instance: Instance<'tcx>,
+ fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
+ maybe_definition_llfn: Option<Self::Function>,
+ ) -> Self::DIScope;
+
+ fn dbg_loc(
+ &self,
+ scope: Self::DIScope,
+ inlined_at: Option<Self::DILocation>,
+ span: Span,
+ ) -> Self::DILocation;
fn extend_scope_to_file(
&self,
scope_metadata: Self::DIScope,
file: &SourceFile,
- defining_crate: CrateNum,
) -> Self::DIScope;
fn debuginfo_finalize(&self);
@@ -35,7 +49,6 @@ pub trait DebugInfoMethods<'tcx>: BackendTypes {
// names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
fn create_dbg_var(
&self,
- dbg_context: &FunctionDebugContext<Self::DIScope>,
variable_name: Name,
variable_type: Ty<'tcx>,
scope_metadata: Self::DIScope,
@@ -50,14 +63,13 @@ pub trait DebugInfoBuilderMethods: BackendTypes {
fn dbg_var_addr(
&mut self,
dbg_var: Self::DIVariable,
- scope_metadata: Self::DIScope,
+ dbg_loc: Self::DILocation,
variable_alloca: Self::Value,
direct_offset: Size,
// NB: each offset implies a deref (i.e. they're steps in a pointer chain).
indirect_offsets: &[Size],
- span: Span,
);
- fn set_source_location(&mut self, scope: Self::DIScope, span: Span);
+ fn set_dbg_loc(&mut self, dbg_loc: Self::DILocation);
fn insert_reference_to_gdb_debug_scripts_section_global(&mut self);
fn set_var_name(&mut self, value: Self::Value, name: &str);
}
diff --git a/src/librustc_codegen_ssa/traits/mod.rs b/src/librustc_codegen_ssa/traits/mod.rs
index d03ff8d4d37..d5b423d22a5 100644
--- a/src/librustc_codegen_ssa/traits/mod.rs
+++ b/src/librustc_codegen_ssa/traits/mod.rs
@@ -93,6 +93,7 @@ pub trait HasCodegen<'tcx>:
Type = Self::Type,
Funclet = Self::Funclet,
DIScope = Self::DIScope,
+ DILocation = Self::DILocation,
DIVariable = Self::DIVariable,
>;
}