rustc_codegen_ssa: hide address ops from the declare_local interface.

This commit is contained in:
Eduard-Mihai Burtescu 2019-09-12 12:29:46 +03:00
parent c2e7743da8
commit 1e42072673
4 changed files with 76 additions and 71 deletions

View file

@ -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()]
}
}
}

View file

@ -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;

View file

@ -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
);

View file

@ -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,
);