rustc_codegen_ssa: move debuginfo-related things to a new mir::debuginfo module.
This commit is contained in:
parent
92df638162
commit
5059a3c7d4
@ -1,4 +1,4 @@
|
||||
use rustc_codegen_ssa::debuginfo::{FunctionDebugContext, FunctionDebugContextData, MirDebugScope};
|
||||
use rustc_codegen_ssa::mir::debuginfo::{FunctionDebugContext, FunctionDebugContextData, DebugScope};
|
||||
use super::metadata::file_metadata;
|
||||
use super::utils::{DIB, span_start};
|
||||
|
||||
@ -22,8 +22,8 @@ pub fn create_mir_scopes(
|
||||
cx: &CodegenCx<'ll, '_>,
|
||||
mir: &Body<'_>,
|
||||
debug_context: &FunctionDebugContext<&'ll DISubprogram>,
|
||||
) -> IndexVec<SourceScope, MirDebugScope<&'ll DIScope>> {
|
||||
let null_scope = MirDebugScope {
|
||||
) -> IndexVec<SourceScope, DebugScope<&'ll DIScope>> {
|
||||
let null_scope = DebugScope {
|
||||
scope_metadata: None,
|
||||
file_start_pos: BytePos(0),
|
||||
file_end_pos: BytePos(0)
|
||||
@ -59,7 +59,7 @@ fn make_mir_scope(cx: &CodegenCx<'ll, '_>,
|
||||
has_variables: &BitSet<SourceScope>,
|
||||
debug_context: &FunctionDebugContextData<&'ll DISubprogram>,
|
||||
scope: SourceScope,
|
||||
scopes: &mut IndexVec<SourceScope, MirDebugScope<&'ll DIScope>>) {
|
||||
scopes: &mut IndexVec<SourceScope, DebugScope<&'ll DIScope>>) {
|
||||
if scopes[scope].is_valid() {
|
||||
return;
|
||||
}
|
||||
@ -71,7 +71,7 @@ fn make_mir_scope(cx: &CodegenCx<'ll, '_>,
|
||||
} else {
|
||||
// The root is the function itself.
|
||||
let loc = span_start(cx, mir.span);
|
||||
scopes[scope] = MirDebugScope {
|
||||
scopes[scope] = DebugScope {
|
||||
scope_metadata: Some(debug_context.fn_metadata),
|
||||
file_start_pos: loc.file.start_pos,
|
||||
file_end_pos: loc.file.end_pos,
|
||||
@ -105,7 +105,7 @@ fn make_mir_scope(cx: &CodegenCx<'ll, '_>,
|
||||
loc.line as c_uint,
|
||||
loc.col.to_usize() as c_uint))
|
||||
};
|
||||
scopes[scope] = MirDebugScope {
|
||||
scopes[scope] = DebugScope {
|
||||
scope_metadata,
|
||||
file_start_pos: loc.file.start_pos,
|
||||
file_end_pos: loc.file.end_pos,
|
||||
|
@ -1,8 +1,8 @@
|
||||
// See doc.rs for documentation.
|
||||
mod doc;
|
||||
|
||||
use rustc_codegen_ssa::debuginfo::VariableAccess::*;
|
||||
use rustc_codegen_ssa::debuginfo::VariableKind::*;
|
||||
use rustc_codegen_ssa::mir::debuginfo::VariableAccess::*;
|
||||
use rustc_codegen_ssa::mir::debuginfo::VariableKind::*;
|
||||
|
||||
use self::utils::{DIB, span_start, create_DIArray, is_node_local_to_unit};
|
||||
use self::namespace::mangled_name_of_instance;
|
||||
@ -27,8 +27,9 @@ use rustc::session::config::{self, DebugInfo};
|
||||
use rustc::util::nodemap::{DefIdMap, FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::small_c_str::SmallCStr;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_codegen_ssa::debuginfo::{FunctionDebugContext, MirDebugScope, VariableAccess,
|
||||
VariableKind, FunctionDebugContextData, type_names};
|
||||
use rustc_codegen_ssa::debuginfo::type_names;
|
||||
use rustc_codegen_ssa::mir::debuginfo::{FunctionDebugContext, DebugScope, VariableAccess,
|
||||
VariableKind, FunctionDebugContextData};
|
||||
|
||||
use libc::c_uint;
|
||||
use std::cell::RefCell;
|
||||
@ -553,7 +554,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
&self,
|
||||
mir: &mir::Body<'_>,
|
||||
debug_context: &mut FunctionDebugContext<&'ll DISubprogram>,
|
||||
) -> IndexVec<mir::SourceScope, MirDebugScope<&'ll DIScope>> {
|
||||
) -> IndexVec<mir::SourceScope, DebugScope<&'ll DIScope>> {
|
||||
create_scope_map::create_mir_scopes(self, mir, debug_context)
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ use self::InternalDebugLocation::*;
|
||||
|
||||
use super::utils::{debug_context, span_start};
|
||||
use super::metadata::UNKNOWN_COLUMN_NUMBER;
|
||||
use rustc_codegen_ssa::debuginfo::FunctionDebugContext;
|
||||
use rustc_codegen_ssa::mir::debuginfo::FunctionDebugContext;
|
||||
|
||||
use crate::llvm;
|
||||
use crate::llvm::debuginfo::DIScope;
|
||||
|
@ -1,82 +1,2 @@
|
||||
use syntax_pos::{BytePos, Span};
|
||||
use rustc::hir::def_id::CrateNum;
|
||||
|
||||
// FIXME(eddyb) find a place for this (or a way to replace it).
|
||||
pub mod type_names;
|
||||
|
||||
pub enum FunctionDebugContext<D> {
|
||||
RegularContext(FunctionDebugContextData<D>),
|
||||
DebugInfoDisabled,
|
||||
FunctionWithoutDebugInfo,
|
||||
}
|
||||
|
||||
impl<D> FunctionDebugContext<D> {
|
||||
pub fn get_ref(&self, span: Span) -> &FunctionDebugContextData<D> {
|
||||
match *self {
|
||||
FunctionDebugContext::RegularContext(ref data) => data,
|
||||
FunctionDebugContext::DebugInfoDisabled => {
|
||||
span_bug!(
|
||||
span,
|
||||
"debuginfo: Error trying to access FunctionDebugContext \
|
||||
although debug info is disabled!",
|
||||
);
|
||||
}
|
||||
FunctionDebugContext::FunctionWithoutDebugInfo => {
|
||||
span_bug!(
|
||||
span,
|
||||
"debuginfo: Error trying to access FunctionDebugContext \
|
||||
for function that should be ignored by debug info!",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Enables emitting source locations for the given functions.
|
||||
///
|
||||
/// Since we don't want source locations to be emitted for the function prelude,
|
||||
/// they are disabled when beginning to codegen a new function. This functions
|
||||
/// switches source location emitting on and must therefore be called before the
|
||||
/// first real statement/expression of the function is codegened.
|
||||
pub fn start_emitting_source_locations<D>(dbg_context: &mut FunctionDebugContext<D>) {
|
||||
match *dbg_context {
|
||||
FunctionDebugContext::RegularContext(ref mut data) => {
|
||||
data.source_locations_enabled = true;
|
||||
},
|
||||
_ => { /* safe to ignore */ }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FunctionDebugContextData<D> {
|
||||
pub fn_metadata: D,
|
||||
pub source_locations_enabled: bool,
|
||||
pub defining_crate: CrateNum,
|
||||
}
|
||||
|
||||
pub enum VariableAccess<'a, V> {
|
||||
// The llptr given is an alloca containing the variable's value
|
||||
DirectVariable { alloca: V },
|
||||
// The llptr given is an alloca containing the start of some pointer chain
|
||||
// leading to the variable's content.
|
||||
IndirectVariable { alloca: V, address_operations: &'a [i64] }
|
||||
}
|
||||
|
||||
pub enum VariableKind {
|
||||
ArgumentVariable(usize /*index*/),
|
||||
LocalVariable,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct MirDebugScope<D> {
|
||||
pub scope_metadata: Option<D>,
|
||||
// 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> MirDebugScope<D> {
|
||||
pub fn is_valid(&self) -> bool {
|
||||
!self.scope_metadata.is_none()
|
||||
}
|
||||
}
|
||||
|
145
src/librustc_codegen_ssa/mir/debuginfo.rs
Normal file
145
src/librustc_codegen_ssa/mir/debuginfo.rs
Normal file
@ -0,0 +1,145 @@
|
||||
use rustc::hir::def_id::CrateNum;
|
||||
use rustc::mir;
|
||||
use crate::traits::*;
|
||||
|
||||
use syntax_pos::{DUMMY_SP, BytePos, Span};
|
||||
|
||||
use super::FunctionCx;
|
||||
|
||||
pub enum FunctionDebugContext<D> {
|
||||
RegularContext(FunctionDebugContextData<D>),
|
||||
DebugInfoDisabled,
|
||||
FunctionWithoutDebugInfo,
|
||||
}
|
||||
|
||||
impl<D> FunctionDebugContext<D> {
|
||||
pub fn get_ref(&self, span: Span) -> &FunctionDebugContextData<D> {
|
||||
match *self {
|
||||
FunctionDebugContext::RegularContext(ref data) => data,
|
||||
FunctionDebugContext::DebugInfoDisabled => {
|
||||
span_bug!(
|
||||
span,
|
||||
"debuginfo: Error trying to access FunctionDebugContext \
|
||||
although debug info is disabled!",
|
||||
);
|
||||
}
|
||||
FunctionDebugContext::FunctionWithoutDebugInfo => {
|
||||
span_bug!(
|
||||
span,
|
||||
"debuginfo: Error trying to access FunctionDebugContext \
|
||||
for function that should be ignored by debug info!",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Enables emitting source locations for the given functions.
|
||||
///
|
||||
/// Since we don't want source locations to be emitted for the function prelude,
|
||||
/// they are disabled when beginning to codegen a new function. This functions
|
||||
/// switches source location emitting on and must therefore be called before the
|
||||
/// first real statement/expression of the function is codegened.
|
||||
pub fn start_emitting_source_locations<D>(dbg_context: &mut FunctionDebugContext<D>) {
|
||||
match *dbg_context {
|
||||
FunctionDebugContext::RegularContext(ref mut data) => {
|
||||
data.source_locations_enabled = true;
|
||||
},
|
||||
_ => { /* safe to ignore */ }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FunctionDebugContextData<D> {
|
||||
pub fn_metadata: D,
|
||||
pub source_locations_enabled: bool,
|
||||
pub defining_crate: CrateNum,
|
||||
}
|
||||
|
||||
pub enum VariableAccess<'a, V> {
|
||||
// The llptr given is an alloca containing the variable's value
|
||||
DirectVariable { alloca: V },
|
||||
// The llptr given is an alloca containing the start of some pointer chain
|
||||
// leading to the variable's content.
|
||||
IndirectVariable { alloca: V, address_operations: &'a [i64] }
|
||||
}
|
||||
|
||||
pub enum VariableKind {
|
||||
ArgumentVariable(usize /*index*/),
|
||||
LocalVariable,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct DebugScope<D> {
|
||||
pub scope_metadata: Option<D>,
|
||||
// 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_none()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
pub fn set_debug_loc(
|
||||
&mut self,
|
||||
bx: &mut Bx,
|
||||
source_info: mir::SourceInfo
|
||||
) {
|
||||
let (scope, span) = self.debug_loc(source_info);
|
||||
bx.set_source_location(&mut self.debug_context, scope, span);
|
||||
}
|
||||
|
||||
pub fn debug_loc(&self, source_info: mir::SourceInfo) -> (Option<Bx::DIScope>, Span) {
|
||||
// Bail out if debug info emission is not enabled.
|
||||
match self.debug_context {
|
||||
FunctionDebugContext::DebugInfoDisabled |
|
||||
FunctionDebugContext::FunctionWithoutDebugInfo => {
|
||||
return (self.scopes[source_info.scope].scope_metadata, source_info.span);
|
||||
}
|
||||
FunctionDebugContext::RegularContext(_) =>{}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
// 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 = syntax_pos::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)
|
||||
}
|
||||
}
|
||||
|
||||
// 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 scope_metadata = self.scopes[scope_id].scope_metadata;
|
||||
if pos < self.scopes[scope_id].file_start_pos ||
|
||||
pos >= self.scopes[scope_id].file_end_pos {
|
||||
let sm = self.cx.sess().source_map();
|
||||
let defining_crate = self.debug_context.get_ref(DUMMY_SP).defining_crate;
|
||||
Some(self.cx.extend_scope_to_file(
|
||||
scope_metadata.unwrap(),
|
||||
&sm.lookup_char_pos(pos).file,
|
||||
defining_crate
|
||||
))
|
||||
} else {
|
||||
scope_metadata
|
||||
}
|
||||
}
|
||||
}
|
@ -5,10 +5,9 @@ use rustc::session::config::DebugInfo;
|
||||
use rustc_target::abi::call::{FnType, PassMode};
|
||||
use rustc_target::abi::{Variants, VariantIdx};
|
||||
use crate::base;
|
||||
use crate::debuginfo::{self, VariableAccess, VariableKind, FunctionDebugContext};
|
||||
use crate::traits::*;
|
||||
|
||||
use syntax_pos::{DUMMY_SP, BytePos, Span};
|
||||
use syntax_pos::DUMMY_SP;
|
||||
use syntax::symbol::kw;
|
||||
|
||||
use std::iter;
|
||||
@ -17,6 +16,7 @@ use rustc_index::bit_set::BitSet;
|
||||
use rustc_index::vec::IndexVec;
|
||||
|
||||
use self::analyze::CleanupKind;
|
||||
use self::debuginfo::{VariableAccess, VariableKind, FunctionDebugContext};
|
||||
use self::place::PlaceRef;
|
||||
use rustc::mir::traversal;
|
||||
|
||||
@ -80,7 +80,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
|
||||
locals: IndexVec<mir::Local, LocalRef<'tcx, Bx::Value>>,
|
||||
|
||||
/// Debug information for MIR scopes.
|
||||
scopes: IndexVec<mir::SourceScope, debuginfo::MirDebugScope<Bx::DIScope>>,
|
||||
scopes: IndexVec<mir::SourceScope, debuginfo::DebugScope<Bx::DIScope>>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
@ -93,64 +93,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
value,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn set_debug_loc(
|
||||
&mut self,
|
||||
bx: &mut Bx,
|
||||
source_info: mir::SourceInfo
|
||||
) {
|
||||
let (scope, span) = self.debug_loc(source_info);
|
||||
bx.set_source_location(&mut self.debug_context, scope, span);
|
||||
}
|
||||
|
||||
pub fn debug_loc(&self, source_info: mir::SourceInfo) -> (Option<Bx::DIScope>, Span) {
|
||||
// Bail out if debug info emission is not enabled.
|
||||
match self.debug_context {
|
||||
FunctionDebugContext::DebugInfoDisabled |
|
||||
FunctionDebugContext::FunctionWithoutDebugInfo => {
|
||||
return (self.scopes[source_info.scope].scope_metadata, source_info.span);
|
||||
}
|
||||
FunctionDebugContext::RegularContext(_) =>{}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
// 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 = syntax_pos::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)
|
||||
}
|
||||
}
|
||||
|
||||
// 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 scope_metadata = self.scopes[scope_id].scope_metadata;
|
||||
if pos < self.scopes[scope_id].file_start_pos ||
|
||||
pos >= self.scopes[scope_id].file_end_pos {
|
||||
let sm = self.cx.sess().source_map();
|
||||
let defining_crate = self.debug_context.get_ref(DUMMY_SP).defining_crate;
|
||||
Some(self.cx.extend_scope_to_file(
|
||||
scope_metadata.unwrap(),
|
||||
&sm.lookup_char_pos(pos).file,
|
||||
defining_crate
|
||||
))
|
||||
} else {
|
||||
scope_metadata
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum LocalRef<'tcx, V> {
|
||||
@ -721,6 +663,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
mod analyze;
|
||||
mod block;
|
||||
pub mod constant;
|
||||
pub mod debuginfo;
|
||||
pub mod place;
|
||||
pub mod operand;
|
||||
mod rvalue;
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::BackendTypes;
|
||||
use crate::debuginfo::{FunctionDebugContext, MirDebugScope, VariableAccess, VariableKind};
|
||||
use crate::mir::debuginfo::{FunctionDebugContext, DebugScope, VariableAccess, VariableKind};
|
||||
use rustc::hir::def_id::CrateNum;
|
||||
use rustc::mir;
|
||||
use rustc::ty::{self, Ty, Instance};
|
||||
@ -28,7 +28,7 @@ pub trait DebugInfoMethods<'tcx>: BackendTypes {
|
||||
&self,
|
||||
mir: &mir::Body<'_>,
|
||||
debug_context: &mut FunctionDebugContext<Self::DIScope>,
|
||||
) -> IndexVec<mir::SourceScope, MirDebugScope<Self::DIScope>>;
|
||||
) -> IndexVec<mir::SourceScope, DebugScope<Self::DIScope>>;
|
||||
fn extend_scope_to_file(
|
||||
&self,
|
||||
scope_metadata: Self::DIScope,
|
||||
|
Loading…
x
Reference in New Issue
Block a user