Skip to content

Commit

Permalink
Initial support for emitting DWARF for static vars.
Browse files Browse the repository at this point in the history
Only supports crate level statics. No debug info is generated for
function level statics. Closes rust-lang#9227.
  • Loading branch information
cmacknz committed Mar 28, 2014
1 parent 13dafa0 commit f4518cd
Show file tree
Hide file tree
Showing 15 changed files with 711 additions and 77 deletions.
13 changes: 13 additions & 0 deletions src/librustc/lib/llvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ pub mod debuginfo {
pub type DIDerivedType = DIType;
pub type DICompositeType = DIDerivedType;
pub type DIVariable = DIDescriptor;
pub type DIGlobalVariable = DIDescriptor;
pub type DIArray = DIDescriptor;
pub type DISubrange = DIDescriptor;

Expand Down Expand Up @@ -1589,6 +1590,18 @@ pub mod llvm {
Col: c_uint)
-> DILexicalBlock;

pub fn LLVMDIBuilderCreateStaticVariable(Builder: DIBuilderRef,
Context: DIDescriptor,
Name: *c_char,
LinkageName: *c_char,
File: DIFile,
LineNo: c_uint,
Ty: DIType,
isLocalToUnit: bool,
Val: ValueRef,
Decl: ValueRef)
-> DIGlobalVariable;

pub fn LLVMDIBuilderCreateLocalVariable(Builder: DIBuilderRef,
Tag: c_uint,
Scope: DIDescriptor,
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/middle/trans/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use middle::trans::inline;
use middle::trans::machine;
use middle::trans::type_::Type;
use middle::trans::type_of;
use middle::trans::debuginfo;
use middle::ty;
use util::ppaux::{Repr, ty_to_str};

Expand Down Expand Up @@ -688,5 +689,6 @@ pub fn trans_const(ccx: &CrateContext, m: ast::Mutability, id: ast::NodeId) {
if m != ast::MutMutable {
llvm::LLVMSetGlobalConstant(g, True);
}
debuginfo::create_global_var_metadata(ccx, id, g);
}
}
79 changes: 72 additions & 7 deletions src/librustc/middle/trans/debuginfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,66 @@ pub fn finalize(cx: &CrateContext) {
};
}

/// Creates debug information for the given global variable.
///
/// Adds the created metadata nodes directly to the crate's IR.
pub fn create_global_var_metadata(cx: &CrateContext,
node_id: ast::NodeId,
global: ValueRef) {
if cx.dbg_cx.is_none() {
return;
}

let var_item = cx.tcx.map.get(node_id);

let (ident, span) = match var_item {
ast_map::NodeItem(item) => {
match item.node {
ast::ItemStatic(..) => (item.ident, item.span),
_ => cx.sess().span_bug(item.span,
format!("debuginfo::create_global_var_metadata() -
Captured var-id refers to unexpected ast_item
variant: {:?}",
var_item))
}
},
_ => cx.sess().bug(format!("debuginfo::create_global_var_metadata() - Captured var-id \
refers to unexpected ast_map variant: {:?}",
var_item))
};

let filename = span_start(cx, span).file.name.clone();
let file_metadata = file_metadata(cx, filename);

let is_local_to_unit = is_node_local_to_unit(cx, node_id);
let loc = span_start(cx, span);

let variable_type = ty::node_id_to_type(cx.tcx(), node_id);
let type_metadata = type_metadata(cx, variable_type, span);

let namespace_node = namespace_for_item(cx, ast_util::local_def(node_id));
let var_name = token::get_ident(ident).get().to_str();
let linkage_name = namespace_node.mangled_name_of_contained_item(var_name);
let var_scope = namespace_node.scope;

var_name.with_c_str(|var_name| {
linkage_name.with_c_str(|linkage_name| {
unsafe {
llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx),
var_scope,
var_name,
linkage_name,
file_metadata,
loc.line as c_uint,
type_metadata,
is_local_to_unit,
global,
ptr::null());
}
})
});
}

/// Creates debug information for the given local variable.
///
/// Adds the created metadata nodes directly to the crate's IR.
Expand Down Expand Up @@ -640,13 +700,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
// Clang sets this parameter to the opening brace of the function's block, so let's do this too.
let scope_line = span_start(cx, top_level_block.span).line;

// The is_local_to_unit flag indicates whether a function is local to the current compilation
// unit (i.e. if it is *static* in the C-sense). The *reachable* set should provide a good
// approximation of this, as it contains everything that might leak out of the current crate
// (by being externally visible or by being inlined into something externally visible). It might
// better to use the `exported_items` set from `driver::CrateAnalysis` in the future, but (atm)
// this set is not available in the translation pass.
let is_local_to_unit = !cx.reachable.contains(&fn_ast_id);
let is_local_to_unit = is_node_local_to_unit(cx, fn_ast_id);

let fn_metadata = function_name.with_c_str(|function_name| {
linkage_name.with_c_str(|linkage_name| {
Expand Down Expand Up @@ -854,6 +908,17 @@ pub fn create_function_debug_context(cx: &CrateContext,
// Module-Internal debug info creation functions
//=-------------------------------------------------------------------------------------------------

fn is_node_local_to_unit(cx: &CrateContext, node_id: ast::NodeId) -> bool
{
// The is_local_to_unit flag indicates whether a function is local to the current compilation
// unit (i.e. if it is *static* in the C-sense). The *reachable* set should provide a good
// approximation of this, as it contains everything that might leak out of the current crate
// (by being externally visible or by being inlined into something externally visible). It might
// better to use the `exported_items` set from `driver::CrateAnalysis` in the future, but (atm)
// this set is not available in the translation pass.
!cx.reachable.contains(&node_id)
}

fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
return unsafe {
llvm::LLVMDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32)
Expand Down
22 changes: 22 additions & 0 deletions src/rustllvm/RustWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,28 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateLexicalBlock(
unwrapDI<DIFile>(File), Line, Col));
}

extern "C" LLVMValueRef LLVMDIBuilderCreateStaticVariable(
DIBuilderRef Builder,
LLVMValueRef Context,
const char* Name,
const char* LinkageName,
LLVMValueRef File,
unsigned LineNo,
LLVMValueRef Ty,
bool isLocalToUnit,
LLVMValueRef Val,
LLVMValueRef Decl = NULL) {
return wrap(Builder->createStaticVariable(unwrapDI<DIDescriptor>(Context),
Name,
LinkageName,
unwrapDI<DIFile>(File),
LineNo,
unwrapDI<DIType>(Ty),
isLocalToUnit,
unwrap(Val),
unwrapDI<MDNode*>(Decl)));
}

extern "C" LLVMValueRef LLVMDIBuilderCreateLocalVariable(
DIBuilderRef Builder,
unsigned Tag,
Expand Down
1 change: 1 addition & 0 deletions src/rustllvm/rustllvm.def.in
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,7 @@ LLVMDIBuilderCreate
LLVMDIBuilderDispose
LLVMDIBuilderFinalize
LLVMDIBuilderCreateCompileUnit
LLVMDIBuilderCreateStaticVariable
LLVMDIBuilderCreateLocalVariable
LLVMDIBuilderCreateFunction
LLVMDIBuilderCreateFile
Expand Down
68 changes: 68 additions & 0 deletions src/test/debug-info/basic-types-globals-metadata.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-android: FIXME(#10381)

// compile-flags:-g
// debugger:rbreak zzz
// debugger:run
// debugger:finish
// debugger:whatis 'basic-types-globals-metadata::B'
// check:type = bool
// debugger:whatis 'basic-types-globals-metadata::I'
// check:type = int
// debugger:whatis 'basic-types-globals-metadata::C'
// check:type = char
// debugger:whatis 'basic-types-globals-metadata::I8'
// check:type = i8
// debugger:whatis 'basic-types-globals-metadata::I16'
// check:type = i16
// debugger:whatis 'basic-types-globals-metadata::I32'
// check:type = i32
// debugger:whatis 'basic-types-globals-metadata::I64'
// check:type = i64
// debugger:whatis 'basic-types-globals-metadata::U'
// check:type = uint
// debugger:whatis 'basic-types-globals-metadata::U8'
// check:type = u8
// debugger:whatis 'basic-types-globals-metadata::U16'
// check:type = u16
// debugger:whatis 'basic-types-globals-metadata::U32'
// check:type = u32
// debugger:whatis 'basic-types-globals-metadata::U64'
// check:type = u64
// debugger:whatis 'basic-types-globals-metadata::F32'
// check:type = f32
// debugger:whatis 'basic-types-globals-metadata::F64'
// check:type = f64
// debugger:continue

#[allow(unused_variable)];

static B: bool = false;
static I: int = -1;
static C: char = 'a';
static I8: i8 = 68;
static I16: i16 = -16;
static I32: i32 = -32;
static I64: i64 = -64;
static U: uint = 1;
static U8: u8 = 100;
static U16: u16 = 16;
static U32: u32 = 32;
static U64: u64 = 64;
static F32: f32 = 2.5;
static F64: f64 = 3.5;

fn main() {
_zzz();
}

fn _zzz() {()}
74 changes: 74 additions & 0 deletions src/test/debug-info/basic-types-globals.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Caveats - gdb prints any 8-bit value (meaning rust I8 and u8 values)
// as its numerical value along with its associated ASCII char, there
// doesn't seem to be any way around this. Also, gdb doesn't know
// about UTF-32 character encoding and will print a rust char as only
// its numerical value.

// ignore-android: FIXME(#10381)

// compile-flags:-g
// debugger:rbreak zzz
// debugger:run
// debugger:finish
// debugger:print 'basic-types-globals::B'
// check:$1 = false
// debugger:print 'basic-types-globals::I'
// check:$2 = -1
// debugger:print 'basic-types-globals::C'
// check:$3 = 97
// debugger:print/d 'basic-types-globals::I8'
// check:$4 = 68
// debugger:print 'basic-types-globals::I16'
// check:$5 = -16
// debugger:print 'basic-types-globals::I32'
// check:$6 = -32
// debugger:print 'basic-types-globals::I64'
// check:$7 = -64
// debugger:print 'basic-types-globals::U'
// check:$8 = 1
// debugger:print/d 'basic-types-globals::U8'
// check:$9 = 100
// debugger:print 'basic-types-globals::U16'
// check:$10 = 16
// debugger:print 'basic-types-globals::U32'
// check:$11 = 32
// debugger:print 'basic-types-globals::U64'
// check:$12 = 64
// debugger:print 'basic-types-globals::F32'
// check:$13 = 2.5
// debugger:print 'basic-types-globals::F64'
// check:$14 = 3.5
// debugger:continue

#[allow(unused_variable)];

static B: bool = false;
static I: int = -1;
static C: char = 'a';
static I8: i8 = 68;
static I16: i16 = -16;
static I32: i32 = -32;
static I64: i64 = -64;
static U: uint = 1;
static U8: u8 = 100;
static U16: u16 = 16;
static U32: u32 = 32;
static U64: u64 = 64;
static F32: f32 = 2.5;
static F64: f64 = 3.5;

fn main() {
_zzz();
}

fn _zzz() {()}
3 changes: 1 addition & 2 deletions src/test/debug-info/basic-types-metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@
// check:type = f64
// debugger:info functions _yyy
// check:[...]![...]_yyy([...])([...]);
// debugger:detach
// debugger:quit
// debugger:continue

#[allow(unused_variable)];

Expand Down
Loading

0 comments on commit f4518cd

Please sign in to comment.