about summary refs log tree commit diff
path: root/src/librustc_codegen_llvm/debuginfo
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-11-01 11:34:51 +0000
committerbors <bors@rust-lang.org>2019-11-01 11:34:51 +0000
commit01e5d91482e3e8fb9f55efabab760db2d50ddaff (patch)
tree99beaa3196bfef915068b2b985b5581134758843 /src/librustc_codegen_llvm/debuginfo
parent253fc0ed742c235fa34c5d78814fa7b8a5e5e055 (diff)
parent60a22665c8c6aff406ffa453965b011eca50ef0c (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.rs58
-rw-r--r--src/librustc_codegen_llvm/debuginfo/mod.rs159
-rw-r--r--src/librustc_codegen_llvm/debuginfo/source_loc.rs17
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
     };