Skip to content

Initial support for emitting DWARF for static variables #13143

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 29, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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