about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_codegen_llvm/debuginfo/mod.rs101
-rw-r--r--src/librustc_codegen_llvm/lib.rs1
-rw-r--r--src/librustc_codegen_ssa/mir/debuginfo.rs38
-rw-r--r--src/librustc_codegen_ssa/traits/debuginfo.rs9
4 files changed, 77 insertions, 72 deletions
diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs
index 01563a3eed3..7713fe47004 100644
--- a/src/librustc_codegen_llvm/debuginfo/mod.rs
+++ b/src/librustc_codegen_llvm/debuginfo/mod.rs
@@ -1,7 +1,6 @@
 // See doc.rs for documentation.
 mod doc;
 
-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};
@@ -28,17 +27,18 @@ 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::type_names;
-use rustc_codegen_ssa::mir::debuginfo::{FunctionDebugContext, DebugScope, VariableAccess,
+use rustc_codegen_ssa::mir::debuginfo::{FunctionDebugContext, DebugScope,
     VariableKind};
 
 use libc::c_uint;
 use std::cell::RefCell;
 use std::ffi::{CStr, CString};
 
+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;
@@ -153,7 +153,9 @@ impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
         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,
     ) {
@@ -174,43 +176,55 @@ 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(
@@ -571,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/lib.rs b/src/librustc_codegen_llvm/lib.rs
index 2ad6c28cd08..e7562c399b2 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -38,6 +38,7 @@ extern crate rustc_fs_util;
 extern crate rustc_driver as _;
 
 #[macro_use] extern crate log;
+extern crate smallvec;
 extern crate syntax;
 extern crate syntax_pos;
 extern crate rustc_errors as errors;
diff --git a/src/librustc_codegen_ssa/mir/debuginfo.rs b/src/librustc_codegen_ssa/mir/debuginfo.rs
index f6c7a378811..4e9d859c5c5 100644
--- a/src/librustc_codegen_ssa/mir/debuginfo.rs
+++ b/src/librustc_codegen_ssa/mir/debuginfo.rs
@@ -3,7 +3,7 @@ use rustc::hir::def_id::CrateNum;
 use rustc::mir;
 use rustc::session::config::DebugInfo;
 use rustc::ty::{self, UpvarSubsts};
-use rustc::ty::layout::HasTyCtxt;
+use rustc::ty::layout::{HasTyCtxt, Size};
 use rustc_target::abi::{Variants, VariantIdx};
 use crate::traits::*;
 
@@ -19,14 +19,6 @@ pub struct FunctionDebugContext<D> {
     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,
@@ -188,8 +180,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             });
             if let Some(scope) = scope {
                 bx.declare_local(debug_context, name, place.layout.ty, scope,
-                    VariableAccess::DirectVariable { alloca: place.llval },
-                    kind, span);
+                    place.llval, Size::ZERO, &[], kind, span);
             }
         }
     }
@@ -310,30 +301,35 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     }
                     None => &closure_layout.fields,
                 };
-                let byte_offset_of_var_in_env = fields.offset(field).bytes();
-
-                let ops = bx.debuginfo_upvar_ops_sequence(byte_offset_of_var_in_env);
 
                 // The environment and the capture can each be indirect.
-                let mut ops = if env_ref { &ops[..] } else { &ops[1..] };
+                let mut direct_offset = Size::ZERO;
+                let indirect_offsets = [
+                    fields.offset(field),
+                    Size::ZERO,
+                ];
+                let mut indirect_offsets = &indirect_offsets[..];
+
+                if !env_ref {
+                    direct_offset = indirect_offsets[0];
+                    indirect_offsets = &indirect_offsets[1..];
+                }
 
                 let ty = if let (true, &ty::Ref(_, ty, _)) = (by_ref, &ty.kind) {
                     ty
                 } else {
-                    ops = &ops[..ops.len() - 1];
+                    indirect_offsets = &indirect_offsets[..indirect_offsets.len() - 1];
                     ty
                 };
 
-                let variable_access = VariableAccess::IndirectVariable {
-                    alloca: place.llval,
-                    address_operations: &ops
-                };
                 bx.declare_local(
                     debug_context,
                     name,
                     ty,
                     var_scope,
-                    variable_access,
+                    place.llval,
+                    direct_offset,
+                    indirect_offsets,
                     VariableKind::LocalVariable,
                     var_span
                 );
diff --git a/src/librustc_codegen_ssa/traits/debuginfo.rs b/src/librustc_codegen_ssa/traits/debuginfo.rs
index ac4e1b94d7f..802eaaa357a 100644
--- a/src/librustc_codegen_ssa/traits/debuginfo.rs
+++ b/src/librustc_codegen_ssa/traits/debuginfo.rs
@@ -1,8 +1,9 @@
 use super::BackendTypes;
-use crate::mir::debuginfo::{FunctionDebugContext, VariableAccess, VariableKind};
+use crate::mir::debuginfo::{FunctionDebugContext, VariableKind};
 use rustc::hir::def_id::CrateNum;
 use rustc::mir;
 use rustc::ty::{self, Ty, Instance};
+use rustc::ty::layout::Size;
 use syntax::ast::Name;
 use syntax_pos::{SourceFile, Span};
 
@@ -28,7 +29,6 @@ pub trait DebugInfoMethods<'tcx>: BackendTypes {
         defining_crate: CrateNum,
     ) -> Self::DIScope;
     fn debuginfo_finalize(&self);
-    fn debuginfo_upvar_ops_sequence(&self, byte_offset_of_var_in_env: u64) -> [i64; 4];
 }
 
 pub trait DebugInfoBuilderMethods<'tcx>: BackendTypes {
@@ -38,7 +38,10 @@ pub trait DebugInfoBuilderMethods<'tcx>: BackendTypes {
         variable_name: Name,
         variable_type: Ty<'tcx>,
         scope_metadata: Self::DIScope,
-        variable_access: VariableAccess<'_, Self::Value>,
+        variable_alloca: Self::Value,
+        direct_offset: Size,
+        // NB: each offset implies a deref (i.e. they're steps in a pointer chain).
+        indirect_offsets: &[Size],
         variable_kind: VariableKind,
         span: Span,
     );