rust/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs

96 lines
3.3 KiB
Rust
Raw Normal View History

use super::metadata::{file_metadata, UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER};
use super::utils::DIB;
2019-12-22 17:42:04 -05:00
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext};
use rustc_codegen_ssa::traits::*;
2015-04-29 18:14:37 +12:00
2019-12-22 17:42:04 -05:00
use crate::common::CodegenCx;
2019-02-18 03:58:58 +09:00
use crate::llvm;
use crate::llvm::debuginfo::DIScope;
2020-03-29 16:41:09 +02:00
use rustc_middle::mir::{Body, SourceScope};
use rustc_session::config::DebugInfo;
2015-04-29 18:14:37 +12:00
use rustc_index::bit_set::BitSet;
use rustc_index::vec::Idx;
2019-02-08 14:53:55 +01:00
/// Produces DIScope DIEs for each MIR Scope which has variables defined in it.
pub fn compute_mir_scopes(
2018-07-17 18:26:58 +03:00
cx: &CodegenCx<'ll, '_>,
mir: &Body<'_>,
fn_dbg_scope: &'ll DIScope,
debug_context: &mut FunctionDebugContext<&'ll DIScope>,
) {
// Find all the scopes with variables defined in them.
Merge indexed_set.rs into bitvec.rs, and rename it bit_set.rs. Currently we have two files implementing bitsets (and 2D bit matrices). This commit combines them into one, taking the best features from each. This involves renaming a lot of things. The high level changes are as follows. - bitvec.rs --> bit_set.rs - indexed_set.rs --> (removed) - BitArray + IdxSet --> BitSet (merged, see below) - BitVector --> GrowableBitSet - {,Sparse,Hybrid}IdxSet --> {,Sparse,Hybrid}BitSet - BitMatrix --> BitMatrix - SparseBitMatrix --> SparseBitMatrix The changes within the bitset types themselves are as follows. ``` OLD OLD NEW BitArray<C> IdxSet<T> BitSet<T> -------- ------ ------ grow - grow new - (remove) new_empty new_empty new_empty new_filled new_filled new_filled - to_hybrid to_hybrid clear clear clear set_up_to set_up_to set_up_to clear_above - clear_above count - count contains(T) contains(&T) contains(T) contains_all - superset is_empty - is_empty insert(T) add(&T) insert(T) insert_all - insert_all() remove(T) remove(&T) remove(T) words words words words_mut words_mut words_mut - overwrite overwrite merge union union - subtract subtract - intersect intersect iter iter iter ``` In general, when choosing names I went with: - names that are more obvious (e.g. `BitSet` over `IdxSet`). - names that are more like the Rust libraries (e.g. `T` over `C`, `insert` over `add`); - names that are more set-like (e.g. `union` over `merge`, `superset` over `contains_all`, `domain_size` over `num_bits`). Also, using `T` for index arguments seems more sensible than `&T` -- even though the latter is standard in Rust collection types -- because indices are always copyable. It also results in fewer `&` and `*` sigils in practice.
2018-09-14 15:07:25 +10:00
let mut has_variables = BitSet::new_empty(mir.source_scopes.len());
// Only consider variables when they're going to be emitted.
// FIXME(eddyb) don't even allocate `has_variables` otherwise.
if cx.sess().opts.debuginfo == DebugInfo::Full {
// FIXME(eddyb) take into account that arguments always have debuginfo,
// irrespective of their name (assuming full debuginfo is enabled).
// NOTE(eddyb) actually, on second thought, those are always in the
// function scope, which always exists.
for var_debug_info in &mir.var_debug_info {
has_variables.insert(var_debug_info.source_info.scope);
}
}
// Instantiate all scopes.
for idx in 0..mir.source_scopes.len() {
let scope = SourceScope::new(idx);
make_mir_scope(cx, &mir, fn_dbg_scope, &has_variables, debug_context, scope);
}
}
2019-12-22 17:42:04 -05:00
fn make_mir_scope(
cx: &CodegenCx<'ll, '_>,
mir: &Body<'_>,
fn_dbg_scope: &'ll DIScope,
2019-12-22 17:42:04 -05:00
has_variables: &BitSet<SourceScope>,
debug_context: &mut FunctionDebugContext<&'ll DIScope>,
2019-12-22 17:42:04 -05:00
scope: SourceScope,
) {
if debug_context.scopes[scope].dbg_scope.is_some() {
return;
}
let scope_data = &mir.source_scopes[scope];
let parent_scope = if let Some(parent) = scope_data.parent_scope {
make_mir_scope(cx, mir, fn_dbg_scope, has_variables, debug_context, parent);
debug_context.scopes[parent]
} else {
// The root is the function itself.
let loc = cx.lookup_debug_loc(mir.span.lo());
debug_context.scopes[scope] = DebugScope {
dbg_scope: Some(fn_dbg_scope),
file_start_pos: loc.file.start_pos,
file_end_pos: loc.file.end_pos,
};
return;
};
if !has_variables.contains(scope) {
// Do not create a DIScope if there are no variables
// defined in this MIR Scope, to avoid debuginfo bloat.
debug_context.scopes[scope] = parent_scope;
return;
}
let loc = cx.lookup_debug_loc(scope_data.span.lo());
let file_metadata = file_metadata(cx, &loc.file);
let dbg_scope = unsafe {
Some(llvm::LLVMRustDIBuilderCreateLexicalBlock(
2018-01-05 07:04:08 +02:00
DIB(cx),
parent_scope.dbg_scope.unwrap(),
file_metadata,
loc.line.unwrap_or(UNKNOWN_LINE_NUMBER),
loc.col.unwrap_or(UNKNOWN_COLUMN_NUMBER),
2019-12-22 17:42:04 -05:00
))
};
debug_context.scopes[scope] = DebugScope {
dbg_scope,
file_start_pos: loc.file.start_pos,
file_end_pos: loc.file.end_pos,
};
}