Skip to content

Commit

Permalink
rustc_codegen_ssa: move debuginfo-related things to a new mir::debugi…
Browse files Browse the repository at this point in the history
…nfo module.
  • Loading branch information
eddyb committed Oct 31, 2019
1 parent 92df638 commit 5059a3c
Show file tree
Hide file tree
Showing 7 changed files with 165 additions and 156 deletions.
12 changes: 6 additions & 6 deletions src/librustc_codegen_llvm/debuginfo/create_scope_map.rs
@@ -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};

Expand All @@ -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)
Expand Down Expand Up @@ -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;
}
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
11 changes: 6 additions & 5 deletions src/librustc_codegen_llvm/debuginfo/mod.rs
@@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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)
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_codegen_llvm/debuginfo/source_loc.rs
Expand Up @@ -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;
Expand Down
82 changes: 1 addition & 81 deletions src/librustc_codegen_ssa/debuginfo/mod.rs
@@ -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 changes: 145 additions & 0 deletions src/librustc_codegen_ssa/mir/debuginfo.rs
@@ -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
}
}
}

0 comments on commit 5059a3c

Please sign in to comment.