Skip to content

Commit

Permalink
rustc_codegen_ssa: hide address ops from the declare_local interface.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Oct 31, 2019
1 parent c2e7743 commit 1e42072
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 72 deletions.
101 changes: 53 additions & 48 deletions 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};
Expand All @@ -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;
Expand Down Expand Up @@ -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,
) {
Expand All @@ -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(
Expand Down Expand Up @@ -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()]
}
}
}
1 change: 1 addition & 0 deletions src/librustc_codegen_llvm/lib.rs
Expand Up @@ -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;
Expand Down
38 changes: 17 additions & 21 deletions src/librustc_codegen_ssa/mir/debuginfo.rs
Expand Up @@ -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::*;

Expand All @@ -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,
Expand Down Expand Up @@ -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);
}
}
}
Expand Down Expand Up @@ -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
);
Expand Down
9 changes: 6 additions & 3 deletions 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};

Expand All @@ -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 {
Expand All @@ -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,
);
Expand Down

0 comments on commit 1e42072

Please sign in to comment.