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. // See doc.rs for documentation.
mod doc; mod doc;
use rustc_codegen_ssa::mir::debuginfo::VariableAccess::*;
use rustc_codegen_ssa::mir::debuginfo::VariableKind::*; use rustc_codegen_ssa::mir::debuginfo::VariableKind::*;
use self::utils::{DIB, span_start, create_DIArray, is_node_local_to_unit}; 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_data_structures::small_c_str::SmallCStr;
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
use rustc_codegen_ssa::debuginfo::type_names; 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}; VariableKind};
use libc::c_uint; use libc::c_uint;
use std::cell::RefCell; use std::cell::RefCell;
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use smallvec::SmallVec;
use syntax_pos::{self, BytePos, Span, Pos}; use syntax_pos::{self, BytePos, Span, Pos};
use syntax::ast; use syntax::ast;
use syntax::symbol::Symbol; use syntax::symbol::Symbol;
use rustc::ty::layout::{self, LayoutOf, HasTyCtxt}; use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, Size};
use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::traits::*;
pub mod gdb; pub mod gdb;
@ -153,7 +153,9 @@ impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
variable_name: ast::Name, variable_name: ast::Name,
variable_type: Ty<'tcx>, variable_type: Ty<'tcx>,
scope_metadata: &'ll DIScope, scope_metadata: &'ll DIScope,
variable_access: VariableAccess<'_, &'ll Value>, variable_alloca: Self::Value,
direct_offset: Size,
indirect_offsets: &[Size],
variable_kind: VariableKind, variable_kind: VariableKind,
span: Span, span: Span,
) { ) {
@ -174,43 +176,55 @@ impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
}; };
let align = cx.align_of(variable_type); let align = cx.align_of(variable_type);
let name = SmallCStr::new(&variable_name.as_str()); // Convert the direct and indirect offsets to address ops.
match (variable_access, &[][..]) { let op_deref = || unsafe { llvm::LLVMRustDIBuilderCreateOpDeref() };
(DirectVariable { alloca }, address_operations) | let op_plus_uconst = || unsafe { llvm::LLVMRustDIBuilderCreateOpPlusUconst() };
(IndirectVariable {alloca, address_operations}, _) => { let mut addr_ops = SmallVec::<[_; 8]>::new();
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); if direct_offset.bytes() > 0 {
} addr_ops.push(op_plus_uconst());
source_loc::set_debug_location(self, UnknownLocation); 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( fn set_source_location(
@ -571,13 +585,4 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
fn debuginfo_finalize(&self) { fn debuginfo_finalize(&self) {
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 _; extern crate rustc_driver as _;
#[macro_use] extern crate log; #[macro_use] extern crate log;
extern crate smallvec;
extern crate syntax; extern crate syntax;
extern crate syntax_pos; extern crate syntax_pos;
extern crate rustc_errors as errors; extern crate rustc_errors as errors;

View file

@ -3,7 +3,7 @@ use rustc::hir::def_id::CrateNum;
use rustc::mir; use rustc::mir;
use rustc::session::config::DebugInfo; use rustc::session::config::DebugInfo;
use rustc::ty::{self, UpvarSubsts}; use rustc::ty::{self, UpvarSubsts};
use rustc::ty::layout::HasTyCtxt; use rustc::ty::layout::{HasTyCtxt, Size};
use rustc_target::abi::{Variants, VariantIdx}; use rustc_target::abi::{Variants, VariantIdx};
use crate::traits::*; use crate::traits::*;
@ -19,14 +19,6 @@ pub struct FunctionDebugContext<D> {
pub defining_crate: CrateNum, 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 { pub enum VariableKind {
ArgumentVariable(usize /*index*/), ArgumentVariable(usize /*index*/),
LocalVariable, LocalVariable,
@ -188,8 +180,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}); });
if let Some(scope) = scope { if let Some(scope) = scope {
bx.declare_local(debug_context, name, place.layout.ty, scope, bx.declare_local(debug_context, name, place.layout.ty, scope,
VariableAccess::DirectVariable { alloca: place.llval }, place.llval, Size::ZERO, &[], kind, span);
kind, span);
} }
} }
} }
@ -310,30 +301,35 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
} }
None => &closure_layout.fields, 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. // 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) { let ty = if let (true, &ty::Ref(_, ty, _)) = (by_ref, &ty.kind) {
ty ty
} else { } else {
ops = &ops[..ops.len() - 1]; indirect_offsets = &indirect_offsets[..indirect_offsets.len() - 1];
ty ty
}; };
let variable_access = VariableAccess::IndirectVariable {
alloca: place.llval,
address_operations: &ops
};
bx.declare_local( bx.declare_local(
debug_context, debug_context,
name, name,
ty, ty,
var_scope, var_scope,
variable_access, place.llval,
direct_offset,
indirect_offsets,
VariableKind::LocalVariable, VariableKind::LocalVariable,
var_span var_span
); );

View file

@ -1,8 +1,9 @@
use super::BackendTypes; use super::BackendTypes;
use crate::mir::debuginfo::{FunctionDebugContext, VariableAccess, VariableKind}; use crate::mir::debuginfo::{FunctionDebugContext, VariableKind};
use rustc::hir::def_id::CrateNum; use rustc::hir::def_id::CrateNum;
use rustc::mir; use rustc::mir;
use rustc::ty::{self, Ty, Instance}; use rustc::ty::{self, Ty, Instance};
use rustc::ty::layout::Size;
use syntax::ast::Name; use syntax::ast::Name;
use syntax_pos::{SourceFile, Span}; use syntax_pos::{SourceFile, Span};
@ -28,7 +29,6 @@ pub trait DebugInfoMethods<'tcx>: BackendTypes {
defining_crate: CrateNum, defining_crate: CrateNum,
) -> Self::DIScope; ) -> Self::DIScope;
fn debuginfo_finalize(&self); fn debuginfo_finalize(&self);
fn debuginfo_upvar_ops_sequence(&self, byte_offset_of_var_in_env: u64) -> [i64; 4];
} }
pub trait DebugInfoBuilderMethods<'tcx>: BackendTypes { pub trait DebugInfoBuilderMethods<'tcx>: BackendTypes {
@ -38,7 +38,10 @@ pub trait DebugInfoBuilderMethods<'tcx>: BackendTypes {
variable_name: Name, variable_name: Name,
variable_type: Ty<'tcx>, variable_type: Ty<'tcx>,
scope_metadata: Self::DIScope, 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, variable_kind: VariableKind,
span: Span, span: Span,
); );