Skip to content

Commit f4518cd

Browse files
committed
Initial support for emitting DWARF for static vars.
Only supports crate level statics. No debug info is generated for function level statics. Closes #9227.
1 parent 13dafa0 commit f4518cd

15 files changed

+711
-77
lines changed

src/librustc/lib/llvm.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ pub mod debuginfo {
277277
pub type DIDerivedType = DIType;
278278
pub type DICompositeType = DIDerivedType;
279279
pub type DIVariable = DIDescriptor;
280+
pub type DIGlobalVariable = DIDescriptor;
280281
pub type DIArray = DIDescriptor;
281282
pub type DISubrange = DIDescriptor;
282283

@@ -1589,6 +1590,18 @@ pub mod llvm {
15891590
Col: c_uint)
15901591
-> DILexicalBlock;
15911592

1593+
pub fn LLVMDIBuilderCreateStaticVariable(Builder: DIBuilderRef,
1594+
Context: DIDescriptor,
1595+
Name: *c_char,
1596+
LinkageName: *c_char,
1597+
File: DIFile,
1598+
LineNo: c_uint,
1599+
Ty: DIType,
1600+
isLocalToUnit: bool,
1601+
Val: ValueRef,
1602+
Decl: ValueRef)
1603+
-> DIGlobalVariable;
1604+
15921605
pub fn LLVMDIBuilderCreateLocalVariable(Builder: DIBuilderRef,
15931606
Tag: c_uint,
15941607
Scope: DIDescriptor,

src/librustc/middle/trans/consts.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use middle::trans::inline;
2828
use middle::trans::machine;
2929
use middle::trans::type_::Type;
3030
use middle::trans::type_of;
31+
use middle::trans::debuginfo;
3132
use middle::ty;
3233
use util::ppaux::{Repr, ty_to_str};
3334

@@ -688,5 +689,6 @@ pub fn trans_const(ccx: &CrateContext, m: ast::Mutability, id: ast::NodeId) {
688689
if m != ast::MutMutable {
689690
llvm::LLVMSetGlobalConstant(g, True);
690691
}
692+
debuginfo::create_global_var_metadata(ccx, id, g);
691693
}
692694
}

src/librustc/middle/trans/debuginfo.rs

Lines changed: 72 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,66 @@ pub fn finalize(cx: &CrateContext) {
280280
};
281281
}
282282

283+
/// Creates debug information for the given global variable.
284+
///
285+
/// Adds the created metadata nodes directly to the crate's IR.
286+
pub fn create_global_var_metadata(cx: &CrateContext,
287+
node_id: ast::NodeId,
288+
global: ValueRef) {
289+
if cx.dbg_cx.is_none() {
290+
return;
291+
}
292+
293+
let var_item = cx.tcx.map.get(node_id);
294+
295+
let (ident, span) = match var_item {
296+
ast_map::NodeItem(item) => {
297+
match item.node {
298+
ast::ItemStatic(..) => (item.ident, item.span),
299+
_ => cx.sess().span_bug(item.span,
300+
format!("debuginfo::create_global_var_metadata() -
301+
Captured var-id refers to unexpected ast_item
302+
variant: {:?}",
303+
var_item))
304+
}
305+
},
306+
_ => cx.sess().bug(format!("debuginfo::create_global_var_metadata() - Captured var-id \
307+
refers to unexpected ast_map variant: {:?}",
308+
var_item))
309+
};
310+
311+
let filename = span_start(cx, span).file.name.clone();
312+
let file_metadata = file_metadata(cx, filename);
313+
314+
let is_local_to_unit = is_node_local_to_unit(cx, node_id);
315+
let loc = span_start(cx, span);
316+
317+
let variable_type = ty::node_id_to_type(cx.tcx(), node_id);
318+
let type_metadata = type_metadata(cx, variable_type, span);
319+
320+
let namespace_node = namespace_for_item(cx, ast_util::local_def(node_id));
321+
let var_name = token::get_ident(ident).get().to_str();
322+
let linkage_name = namespace_node.mangled_name_of_contained_item(var_name);
323+
let var_scope = namespace_node.scope;
324+
325+
var_name.with_c_str(|var_name| {
326+
linkage_name.with_c_str(|linkage_name| {
327+
unsafe {
328+
llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx),
329+
var_scope,
330+
var_name,
331+
linkage_name,
332+
file_metadata,
333+
loc.line as c_uint,
334+
type_metadata,
335+
is_local_to_unit,
336+
global,
337+
ptr::null());
338+
}
339+
})
340+
});
341+
}
342+
283343
/// Creates debug information for the given local variable.
284344
///
285345
/// Adds the created metadata nodes directly to the crate's IR.
@@ -640,13 +700,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
640700
// Clang sets this parameter to the opening brace of the function's block, so let's do this too.
641701
let scope_line = span_start(cx, top_level_block.span).line;
642702

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

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

911+
fn is_node_local_to_unit(cx: &CrateContext, node_id: ast::NodeId) -> bool
912+
{
913+
// The is_local_to_unit flag indicates whether a function is local to the current compilation
914+
// unit (i.e. if it is *static* in the C-sense). The *reachable* set should provide a good
915+
// approximation of this, as it contains everything that might leak out of the current crate
916+
// (by being externally visible or by being inlined into something externally visible). It might
917+
// better to use the `exported_items` set from `driver::CrateAnalysis` in the future, but (atm)
918+
// this set is not available in the translation pass.
919+
!cx.reachable.contains(&node_id)
920+
}
921+
857922
fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
858923
return unsafe {
859924
llvm::LLVMDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32)

src/rustllvm/RustWrapper.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,28 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateLexicalBlock(
323323
unwrapDI<DIFile>(File), Line, Col));
324324
}
325325

326+
extern "C" LLVMValueRef LLVMDIBuilderCreateStaticVariable(
327+
DIBuilderRef Builder,
328+
LLVMValueRef Context,
329+
const char* Name,
330+
const char* LinkageName,
331+
LLVMValueRef File,
332+
unsigned LineNo,
333+
LLVMValueRef Ty,
334+
bool isLocalToUnit,
335+
LLVMValueRef Val,
336+
LLVMValueRef Decl = NULL) {
337+
return wrap(Builder->createStaticVariable(unwrapDI<DIDescriptor>(Context),
338+
Name,
339+
LinkageName,
340+
unwrapDI<DIFile>(File),
341+
LineNo,
342+
unwrapDI<DIType>(Ty),
343+
isLocalToUnit,
344+
unwrap(Val),
345+
unwrapDI<MDNode*>(Decl)));
346+
}
347+
326348
extern "C" LLVMValueRef LLVMDIBuilderCreateLocalVariable(
327349
DIBuilderRef Builder,
328350
unsigned Tag,

src/rustllvm/rustllvm.def.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,7 @@ LLVMDIBuilderCreate
586586
LLVMDIBuilderDispose
587587
LLVMDIBuilderFinalize
588588
LLVMDIBuilderCreateCompileUnit
589+
LLVMDIBuilderCreateStaticVariable
589590
LLVMDIBuilderCreateLocalVariable
590591
LLVMDIBuilderCreateFunction
591592
LLVMDIBuilderCreateFile
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// ignore-android: FIXME(#10381)
12+
13+
// compile-flags:-g
14+
// debugger:rbreak zzz
15+
// debugger:run
16+
// debugger:finish
17+
// debugger:whatis 'basic-types-globals-metadata::B'
18+
// check:type = bool
19+
// debugger:whatis 'basic-types-globals-metadata::I'
20+
// check:type = int
21+
// debugger:whatis 'basic-types-globals-metadata::C'
22+
// check:type = char
23+
// debugger:whatis 'basic-types-globals-metadata::I8'
24+
// check:type = i8
25+
// debugger:whatis 'basic-types-globals-metadata::I16'
26+
// check:type = i16
27+
// debugger:whatis 'basic-types-globals-metadata::I32'
28+
// check:type = i32
29+
// debugger:whatis 'basic-types-globals-metadata::I64'
30+
// check:type = i64
31+
// debugger:whatis 'basic-types-globals-metadata::U'
32+
// check:type = uint
33+
// debugger:whatis 'basic-types-globals-metadata::U8'
34+
// check:type = u8
35+
// debugger:whatis 'basic-types-globals-metadata::U16'
36+
// check:type = u16
37+
// debugger:whatis 'basic-types-globals-metadata::U32'
38+
// check:type = u32
39+
// debugger:whatis 'basic-types-globals-metadata::U64'
40+
// check:type = u64
41+
// debugger:whatis 'basic-types-globals-metadata::F32'
42+
// check:type = f32
43+
// debugger:whatis 'basic-types-globals-metadata::F64'
44+
// check:type = f64
45+
// debugger:continue
46+
47+
#[allow(unused_variable)];
48+
49+
static B: bool = false;
50+
static I: int = -1;
51+
static C: char = 'a';
52+
static I8: i8 = 68;
53+
static I16: i16 = -16;
54+
static I32: i32 = -32;
55+
static I64: i64 = -64;
56+
static U: uint = 1;
57+
static U8: u8 = 100;
58+
static U16: u16 = 16;
59+
static U32: u32 = 32;
60+
static U64: u64 = 64;
61+
static F32: f32 = 2.5;
62+
static F64: f64 = 3.5;
63+
64+
fn main() {
65+
_zzz();
66+
}
67+
68+
fn _zzz() {()}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Caveats - gdb prints any 8-bit value (meaning rust I8 and u8 values)
12+
// as its numerical value along with its associated ASCII char, there
13+
// doesn't seem to be any way around this. Also, gdb doesn't know
14+
// about UTF-32 character encoding and will print a rust char as only
15+
// its numerical value.
16+
17+
// ignore-android: FIXME(#10381)
18+
19+
// compile-flags:-g
20+
// debugger:rbreak zzz
21+
// debugger:run
22+
// debugger:finish
23+
// debugger:print 'basic-types-globals::B'
24+
// check:$1 = false
25+
// debugger:print 'basic-types-globals::I'
26+
// check:$2 = -1
27+
// debugger:print 'basic-types-globals::C'
28+
// check:$3 = 97
29+
// debugger:print/d 'basic-types-globals::I8'
30+
// check:$4 = 68
31+
// debugger:print 'basic-types-globals::I16'
32+
// check:$5 = -16
33+
// debugger:print 'basic-types-globals::I32'
34+
// check:$6 = -32
35+
// debugger:print 'basic-types-globals::I64'
36+
// check:$7 = -64
37+
// debugger:print 'basic-types-globals::U'
38+
// check:$8 = 1
39+
// debugger:print/d 'basic-types-globals::U8'
40+
// check:$9 = 100
41+
// debugger:print 'basic-types-globals::U16'
42+
// check:$10 = 16
43+
// debugger:print 'basic-types-globals::U32'
44+
// check:$11 = 32
45+
// debugger:print 'basic-types-globals::U64'
46+
// check:$12 = 64
47+
// debugger:print 'basic-types-globals::F32'
48+
// check:$13 = 2.5
49+
// debugger:print 'basic-types-globals::F64'
50+
// check:$14 = 3.5
51+
// debugger:continue
52+
53+
#[allow(unused_variable)];
54+
55+
static B: bool = false;
56+
static I: int = -1;
57+
static C: char = 'a';
58+
static I8: i8 = 68;
59+
static I16: i16 = -16;
60+
static I32: i32 = -32;
61+
static I64: i64 = -64;
62+
static U: uint = 1;
63+
static U8: u8 = 100;
64+
static U16: u16 = 16;
65+
static U32: u32 = 32;
66+
static U64: u64 = 64;
67+
static F32: f32 = 2.5;
68+
static F64: f64 = 3.5;
69+
70+
fn main() {
71+
_zzz();
72+
}
73+
74+
fn _zzz() {()}

src/test/debug-info/basic-types-metadata.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,7 @@
4646
// check:type = f64
4747
// debugger:info functions _yyy
4848
// check:[...]![...]_yyy([...])([...]);
49-
// debugger:detach
50-
// debugger:quit
49+
// debugger:continue
5150

5251
#[allow(unused_variable)];
5352

0 commit comments

Comments
 (0)