From 1e42072673929227239215bb2f3333f5351f88ca Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 12 Sep 2019 12:29:46 +0300 Subject: [PATCH] rustc_codegen_ssa: hide address ops from the declare_local interface. --- src/librustc_codegen_llvm/debuginfo/mod.rs | 99 ++++++++++---------- src/librustc_codegen_llvm/lib.rs | 1 + src/librustc_codegen_ssa/mir/debuginfo.rs | 38 ++++---- src/librustc_codegen_ssa/traits/debuginfo.rs | 9 +- 4 files changed, 76 insertions(+), 71 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()); + // 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(); - llvm::LLVMSetInstDebugLocation(self.llbuilder, instr); - } - source_loc::set_debug_location(self, UnknownLocation); + 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 { 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, );