diff options
| author | bors <bors@rust-lang.org> | 2019-11-01 11:34:51 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2019-11-01 11:34:51 +0000 |
| commit | 01e5d91482e3e8fb9f55efabab760db2d50ddaff (patch) | |
| tree | 99beaa3196bfef915068b2b985b5581134758843 /src/librustc_codegen_llvm/debuginfo | |
| parent | 253fc0ed742c235fa34c5d78814fa7b8a5e5e055 (diff) | |
| parent | 60a22665c8c6aff406ffa453965b011eca50ef0c (diff) | |
Auto merge of #65718 - eddyb:codegen-var-debuginfo, r=nikomatsakis
rustc_codegen_ssa: introduce MIR VarDebugInfo, but only for codegen. These are all the codegen changes necessary for #56231. The refactors were performed locally to codegen, and in several steps, to ease reviewing and avoid introducing changes in behavior (as I'm not sure our debuginfo tests cover enough). r? @michaelwoerister cc @nagisa @rkruppe @oli-obk
Diffstat (limited to 'src/librustc_codegen_llvm/debuginfo')
| -rw-r--r-- | src/librustc_codegen_llvm/debuginfo/create_scope_map.rs | 58 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/debuginfo/mod.rs | 159 | ||||
| -rw-r--r-- | src/librustc_codegen_llvm/debuginfo/source_loc.rs | 17 |
3 files changed, 108 insertions, 126 deletions
diff --git a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs b/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs index bdb7467a101..6ee76b71fce 100644 --- a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs +++ b/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, DebugScope}; use super::metadata::file_metadata; use super::utils::{DIB, span_start}; @@ -12,34 +12,20 @@ use libc::c_uint; use syntax_pos::Pos; use rustc_index::bit_set::BitSet; -use rustc_index::vec::{Idx, IndexVec}; - -use syntax_pos::BytePos; +use rustc_index::vec::Idx; /// Produces DIScope DIEs for each MIR Scope which has variables defined in it. -/// If debuginfo is disabled, the returned vector is empty. -pub fn create_mir_scopes( +pub fn compute_mir_scopes( cx: &CodegenCx<'ll, '_>, mir: &Body<'_>, - debug_context: &FunctionDebugContext<&'ll DISubprogram>, -) -> IndexVec<SourceScope, MirDebugScope<&'ll DIScope>> { - let null_scope = MirDebugScope { - scope_metadata: None, - file_start_pos: BytePos(0), - file_end_pos: BytePos(0) - }; - let mut scopes = IndexVec::from_elem(null_scope, &mir.source_scopes); - - let debug_context = match *debug_context { - FunctionDebugContext::RegularContext(ref data) => data, - FunctionDebugContext::DebugInfoDisabled | - FunctionDebugContext::FunctionWithoutDebugInfo => { - return scopes; - } - }; - + fn_metadata: &'ll DISubprogram, + debug_context: &mut FunctionDebugContext<&'ll DIScope>, +) { // Find all the scopes with variables defined in them. let mut has_variables = BitSet::new_empty(mir.source_scopes.len()); + // FIXME(eddyb) base this on `decl.name`, or even better, on debuginfo. + // FIXME(eddyb) take into account that arguments always have debuginfo, + // irrespective of their name (assuming full debuginfo is enabled). for var in mir.vars_iter() { let decl = &mir.local_decls[var]; has_variables.insert(decl.visibility_scope); @@ -48,31 +34,29 @@ pub fn create_mir_scopes( // Instantiate all scopes. for idx in 0..mir.source_scopes.len() { let scope = SourceScope::new(idx); - make_mir_scope(cx, &mir, &has_variables, debug_context, scope, &mut scopes); + make_mir_scope(cx, &mir, fn_metadata, &has_variables, debug_context, scope); } - - scopes } fn make_mir_scope(cx: &CodegenCx<'ll, '_>, mir: &Body<'_>, + fn_metadata: &'ll DISubprogram, has_variables: &BitSet<SourceScope>, - debug_context: &FunctionDebugContextData<&'ll DISubprogram>, - scope: SourceScope, - scopes: &mut IndexVec<SourceScope, MirDebugScope<&'ll DIScope>>) { - if scopes[scope].is_valid() { + debug_context: &mut FunctionDebugContext<&'ll DISubprogram>, + scope: SourceScope) { + if debug_context.scopes[scope].is_valid() { return; } let scope_data = &mir.source_scopes[scope]; let parent_scope = if let Some(parent) = scope_data.parent_scope { - make_mir_scope(cx, mir, has_variables, debug_context, parent, scopes); - scopes[parent] + make_mir_scope(cx, mir, fn_metadata, has_variables, debug_context, parent); + debug_context.scopes[parent] } else { // The root is the function itself. let loc = span_start(cx, mir.span); - scopes[scope] = MirDebugScope { - scope_metadata: Some(debug_context.fn_metadata), + debug_context.scopes[scope] = DebugScope { + scope_metadata: Some(fn_metadata), file_start_pos: loc.file.start_pos, file_end_pos: loc.file.end_pos, }; @@ -86,8 +70,8 @@ fn make_mir_scope(cx: &CodegenCx<'ll, '_>, // However, we don't skip creating a nested scope if // our parent is the root, because we might want to // put arguments in the root and not have shadowing. - if parent_scope.scope_metadata.unwrap() != debug_context.fn_metadata { - scopes[scope] = parent_scope; + if parent_scope.scope_metadata.unwrap() != fn_metadata { + debug_context.scopes[scope] = parent_scope; return; } } @@ -105,7 +89,7 @@ fn make_mir_scope(cx: &CodegenCx<'ll, '_>, loc.line as c_uint, loc.col.to_usize() as c_uint)) }; - scopes[scope] = MirDebugScope { + debug_context.scopes[scope] = DebugScope { scope_metadata, file_start_pos: loc.file.start_pos, file_end_pos: loc.file.end_pos, diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index 5b59f4c28de..7713fe47004 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -1,8 +1,7 @@ // 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::VariableKind::*; use self::utils::{DIB, span_start, create_DIArray, is_node_local_to_unit}; use self::namespace::mangled_name_of_instance; @@ -11,7 +10,7 @@ use self::metadata::{type_metadata, file_metadata, TypeMap}; use self::source_loc::InternalDebugLocation::{self, UnknownLocation}; use crate::llvm; -use crate::llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilder, DISubprogram, DIArray, DIFlags, +use crate::llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilder, DIArray, DIFlags, DISPFlags, DILexicalBlock}; use rustc::hir::CodegenFnAttrFlags; use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE}; @@ -27,17 +26,19 @@ 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, + VariableKind}; use libc::c_uint; use std::cell::RefCell; use std::ffi::{CStr, CString}; -use syntax_pos::{self, Span, Pos}; +use smallvec::SmallVec; +use syntax_pos::{self, BytePos, Span, Pos}; use syntax::ast; use syntax::symbol::Symbol; -use rustc::ty::layout::{self, LayoutOf, HasTyCtxt}; +use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, Size}; use rustc_codegen_ssa::traits::*; pub mod gdb; @@ -47,7 +48,7 @@ pub mod metadata; mod create_scope_map; mod source_loc; -pub use self::create_scope_map::{create_mir_scopes}; +pub use self::create_scope_map::compute_mir_scopes; pub use self::metadata::create_global_var_metadata; pub use self::metadata::extend_scope_to_file; pub use self::source_loc::set_source_location; @@ -148,21 +149,23 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) { impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { fn declare_local( &mut self, - dbg_context: &FunctionDebugContext<&'ll DISubprogram>, + dbg_context: &FunctionDebugContext<&'ll DIScope>, variable_name: ast::Name, variable_type: Ty<'tcx>, scope_metadata: &'ll DIScope, - variable_access: VariableAccess<'_, &'ll Value>, + variable_alloca: Self::Value, + direct_offset: Size, + indirect_offsets: &[Size], variable_kind: VariableKind, span: Span, ) { - assert!(!dbg_context.get_ref(span).source_locations_enabled); + assert!(!dbg_context.source_locations_enabled); let cx = self.cx(); let file = span_start(cx, span).file; let file_metadata = file_metadata(cx, &file.name, - dbg_context.get_ref(span).defining_crate); + dbg_context.defining_crate); let loc = span_start(cx, span); let type_metadata = type_metadata(cx, variable_type, span); @@ -173,49 +176,61 @@ impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { }; let align = cx.align_of(variable_type); - let name = SmallCStr::new(&variable_name.as_str()); - match (variable_access, &[][..]) { - (DirectVariable { alloca }, address_operations) | - (IndirectVariable {alloca, address_operations}, _) => { - let metadata = unsafe { - llvm::LLVMRustDIBuilderCreateVariable( - DIB(cx), - dwarf_tag, - scope_metadata, - name.as_ptr(), - file_metadata, - loc.line as c_uint, - type_metadata, - cx.sess().opts.optimize != config::OptLevel::No, - DIFlags::FlagZero, - argument_index, - align.bytes() as u32, - ) - }; - source_loc::set_debug_location(self, - InternalDebugLocation::new(scope_metadata, loc.line, loc.col.to_usize())); - unsafe { - let debug_loc = llvm::LLVMGetCurrentDebugLocation(self.llbuilder); - let instr = llvm::LLVMRustDIBuilderInsertDeclareAtEnd( - DIB(cx), - alloca, - metadata, - address_operations.as_ptr(), - address_operations.len() as c_uint, - debug_loc, - self.llbb()); - - llvm::LLVMSetInstDebugLocation(self.llbuilder, instr); - } - source_loc::set_debug_location(self, UnknownLocation); + // Convert the direct and indirect offsets to address ops. + let op_deref = || unsafe { llvm::LLVMRustDIBuilderCreateOpDeref() }; + let op_plus_uconst = || unsafe { llvm::LLVMRustDIBuilderCreateOpPlusUconst() }; + let mut addr_ops = SmallVec::<[_; 8]>::new(); + + if direct_offset.bytes() > 0 { + addr_ops.push(op_plus_uconst()); + addr_ops.push(direct_offset.bytes() as i64); + } + for &offset in indirect_offsets { + addr_ops.push(op_deref()); + if offset.bytes() > 0 { + addr_ops.push(op_plus_uconst()); + addr_ops.push(offset.bytes() as i64); } } + + let name = SmallCStr::new(&variable_name.as_str()); + let metadata = unsafe { + llvm::LLVMRustDIBuilderCreateVariable( + DIB(cx), + dwarf_tag, + scope_metadata, + name.as_ptr(), + file_metadata, + loc.line as c_uint, + type_metadata, + cx.sess().opts.optimize != config::OptLevel::No, + DIFlags::FlagZero, + argument_index, + align.bytes() as u32, + ) + }; + source_loc::set_debug_location(self, + InternalDebugLocation::new(scope_metadata, loc.line, loc.col.to_usize())); + unsafe { + let debug_loc = llvm::LLVMGetCurrentDebugLocation(self.llbuilder); + let instr = llvm::LLVMRustDIBuilderInsertDeclareAtEnd( + DIB(cx), + variable_alloca, + metadata, + addr_ops.as_ptr(), + addr_ops.len() as c_uint, + debug_loc, + self.llbb()); + + llvm::LLVMSetInstDebugLocation(self.llbuilder, instr); + } + source_loc::set_debug_location(self, UnknownLocation); } fn set_source_location( &mut self, - debug_context: &mut FunctionDebugContext<&'ll DISubprogram>, - scope: Option<&'ll DIScope>, + debug_context: &mut FunctionDebugContext<&'ll DIScope>, + scope: &'ll DIScope, span: Span, ) { set_source_location(debug_context, &self, scope, span) @@ -224,7 +239,7 @@ impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { gdb::insert_reference_to_gdb_debug_scripts_section_global(self) } - fn set_var_name(&mut self, value: &'ll Value, name: impl ToString) { + fn set_var_name(&mut self, value: &'ll Value, name: &str) { // Avoid wasting time if LLVM value names aren't even enabled. if self.sess().fewer_names() { return; @@ -254,7 +269,7 @@ impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { Err(_) => return, } - let cname = CString::new(name.to_string()).unwrap(); + let cname = SmallCStr::new(name); unsafe { llvm::LLVMSetValueName(value, cname.as_ptr()); } @@ -268,14 +283,14 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { sig: ty::FnSig<'tcx>, llfn: &'ll Value, mir: &mir::Body<'_>, - ) -> FunctionDebugContext<&'ll DISubprogram> { + ) -> Option<FunctionDebugContext<&'ll DIScope>> { if self.sess().opts.debuginfo == DebugInfo::None { - return FunctionDebugContext::DebugInfoDisabled; + return None; } if let InstanceDef::Item(def_id) = instance.def { if self.tcx().codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NO_DEBUG) { - return FunctionDebugContext::FunctionWithoutDebugInfo; + return None; } } @@ -284,7 +299,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { // This can be the case for functions inlined from another crate if span.is_dummy() { // FIXME(simulacrum): Probably can't happen; remove. - return FunctionDebugContext::FunctionWithoutDebugInfo; + return None; } let def_id = instance.def_id(); @@ -357,14 +372,23 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { None) }; - // Initialize fn debug context (including scope map and namespace map) - let fn_debug_context = FunctionDebugContextData { - fn_metadata, + // Initialize fn debug context (including scopes). + // FIXME(eddyb) figure out a way to not need `Option` for `scope_metadata`. + let null_scope = DebugScope { + scope_metadata: None, + file_start_pos: BytePos(0), + file_end_pos: BytePos(0) + }; + let mut fn_debug_context = FunctionDebugContext { + scopes: IndexVec::from_elem(null_scope, &mir.source_scopes), source_locations_enabled: false, defining_crate: def_id.krate, }; - return FunctionDebugContext::RegularContext(fn_debug_context); + // Fill in all the scopes, with the information from the MIR body. + compute_mir_scopes(self, mir, fn_metadata, &mut fn_debug_context); + + return Some(fn_debug_context); fn get_function_signature<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, @@ -549,14 +573,6 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { metadata::create_vtable_metadata(self, ty, vtable) } - fn create_mir_scopes( - &self, - mir: &mir::Body<'_>, - debug_context: &mut FunctionDebugContext<&'ll DISubprogram>, - ) -> IndexVec<mir::SourceScope, MirDebugScope<&'ll DIScope>> { - create_scope_map::create_mir_scopes(self, mir, debug_context) - } - fn extend_scope_to_file( &self, scope_metadata: &'ll DIScope, @@ -569,13 +585,4 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn debuginfo_finalize(&self) { finalize(self) } - - fn debuginfo_upvar_ops_sequence(&self, byte_offset_of_var_in_env: u64) -> [i64; 4] { - unsafe { - [llvm::LLVMRustDIBuilderCreateOpDeref(), - llvm::LLVMRustDIBuilderCreateOpPlusUconst(), - byte_offset_of_var_in_env as i64, - llvm::LLVMRustDIBuilderCreateOpDeref()] - } - } } diff --git a/src/librustc_codegen_llvm/debuginfo/source_loc.rs b/src/librustc_codegen_llvm/debuginfo/source_loc.rs index dec93a65dba..ccb3bde1cbe 100644 --- a/src/librustc_codegen_llvm/debuginfo/source_loc.rs +++ b/src/librustc_codegen_llvm/debuginfo/source_loc.rs @@ -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; @@ -18,22 +18,13 @@ use syntax_pos::{Span, Pos}; pub fn set_source_location<D>( debug_context: &FunctionDebugContext<D>, bx: &Builder<'_, 'll, '_>, - scope: Option<&'ll DIScope>, + scope: &'ll DIScope, span: Span, ) { - let function_debug_context = match *debug_context { - FunctionDebugContext::DebugInfoDisabled => return, - FunctionDebugContext::FunctionWithoutDebugInfo => { - set_debug_location(bx, UnknownLocation); - return; - } - FunctionDebugContext::RegularContext(ref data) => data - }; - - let dbg_loc = if function_debug_context.source_locations_enabled { + let dbg_loc = if debug_context.source_locations_enabled { debug!("set_source_location: {}", bx.sess().source_map().span_to_string(span)); let loc = span_start(bx.cx(), span); - InternalDebugLocation::new(scope.unwrap(), loc.line, loc.col.to_usize()) + InternalDebugLocation::new(scope, loc.line, loc.col.to_usize()) } else { UnknownLocation }; |
