Skip to content

Commit dde633e

Browse files
debuginfo: Added test cases for structs, tuples, enums, etc passed by value.
Also updated documentation comments in debuginfo and renamed DebugContext to CrateDebugContext.
1 parent 5e040e9 commit dde633e

9 files changed

+206
-63
lines changed

src/librustc/middle/trans/context.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ pub struct CrateContext {
111111
// decl_gc_metadata knows whether to link to the module metadata, which
112112
// is not emitted by LLVM's GC pass when no functions use GC.
113113
uses_gc: bool,
114-
dbg_cx: Option<debuginfo::DebugContext>,
114+
dbg_cx: Option<debuginfo::CrateDebugContext>,
115115
do_not_commit_warning_issued: bool
116116
}
117117

@@ -161,7 +161,7 @@ impl CrateContext {
161161

162162
let crate_map = decl_crate_map(sess, link_meta, llmod);
163163
let dbg_cx = if sess.opts.debuginfo {
164-
Some(debuginfo::DebugContext::new(llmod, name.to_owned()))
164+
Some(debuginfo::CrateDebugContext::new(llmod, name.to_owned()))
165165
} else {
166166
None
167167
};

src/librustc/middle/trans/debuginfo.rs

+28-21
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ where possible. This will hopefully ease the adaption of this module to future L
2727
2828
The public API of the module is a set of functions that will insert the correct metadata into the
2929
LLVM IR when called with the right parameters. The module is thus driven from an outside client with
30-
functions like `debuginfo::local_var_metadata(bcx: block, local: &ast::local)`.
30+
functions like `debuginfo::create_local_var_metadata(bcx: block, local: &ast::local)`.
3131
3232
Internally the module will try to reuse already created metadata by utilizing a cache. The way to
3333
get a shared metadata node when needed is thus to just call the corresponding function in this
@@ -37,9 +37,8 @@ module:
3737
3838
The function will take care of probing the cache for an existing node for that exact file path.
3939
40-
All private state used by the module is stored within a DebugContext struct, which in turn is
41-
contained in the CrateContext.
42-
40+
All private state used by the module is stored within either the CrateDebugContext struct (owned by
41+
the CrateContext) or the FunctionDebugContext (owned by the FunctionContext).
4342
4443
This file consists of three conceptual sections:
4544
1. The public interface of the module
@@ -92,7 +91,7 @@ static DW_ATE_unsigned_char: c_uint = 0x08;
9291
//=-------------------------------------------------------------------------------------------------
9392

9493
/// A context object for maintaining all state needed by the debuginfo module.
95-
pub struct DebugContext {
94+
pub struct CrateDebugContext {
9695
priv crate_file: ~str,
9796
priv llcontext: ContextRef,
9897
priv builder: DIBuilderRef,
@@ -101,13 +100,13 @@ pub struct DebugContext {
101100
priv created_types: HashMap<uint, DIType>,
102101
}
103102

104-
impl DebugContext {
105-
pub fn new(llmod: ModuleRef, crate: ~str) -> DebugContext {
106-
debug!("DebugContext::new");
103+
impl CrateDebugContext {
104+
pub fn new(llmod: ModuleRef, crate: ~str) -> CrateDebugContext {
105+
debug!("CrateDebugContext::new");
107106
let builder = unsafe { llvm::LLVMDIBuilderCreate(llmod) };
108107
// DIBuilder inherits context from the module, so we'd better use the same one
109108
let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
110-
return DebugContext {
109+
return CrateDebugContext {
111110
crate_file: crate,
112111
llcontext: llcontext,
113112
builder: builder,
@@ -165,9 +164,9 @@ struct FunctionDebugContextData {
165164
}
166165

167166
enum VariableAccess {
168-
// The value given is a pointer to data
167+
// The value given is a pointer to the data (T*)
169168
DirectVariable,
170-
// The value given has to be dereferenced once to get the pointer to data
169+
// The value given has to be dereferenced once to get the pointer to data (T**)
171170
IndirectVariable
172171
}
173172

@@ -224,9 +223,9 @@ pub fn create_local_var_metadata(bcx: @mut Block,
224223
}
225224
}
226225

227-
/// Creates debug information for a local variable introduced in the head of a match-statement arm.
226+
/// Creates debug information for a variable captured in a closure.
228227
///
229-
// /// Adds the created metadata nodes directly to the crate's IR.
228+
/// Adds the created metadata nodes directly to the crate's IR.
230229
pub fn create_captured_var_metadata(bcx: @mut Block,
231230
node_id: ast::NodeId,
232231
llptr: ValueRef,
@@ -321,7 +320,8 @@ pub fn create_self_argument_metadata(bcx: @mut Block,
321320
_) => {
322321
explicit_self.span
323322
}
324-
_ => bcx.ccx().sess.bug(fmt!("create_self_argument_metadata: unexpected sort of node: %?", fnitem))
323+
_ => bcx.ccx().sess.bug(
324+
fmt!("create_self_argument_metadata: unexpected sort of node: %?", fnitem))
325325
};
326326

327327
let scope_metadata = bcx.fcx.debug_context.get_ref(bcx.ccx(), span).fn_metadata;
@@ -361,14 +361,10 @@ pub fn create_argument_metadata(bcx: @mut Block,
361361
let fcx = bcx.fcx;
362362
let cx = fcx.ccx;
363363

364-
let pattern = arg.pat;
365-
let filename = span_start(cx, pattern.span).file.name;
366-
367364
let def_map = cx.tcx.def_map;
368-
let file_metadata = file_metadata(cx, filename);
369365
let scope_metadata = bcx.fcx.debug_context.get_ref(cx, arg.pat.span).fn_metadata;
370366

371-
do pat_util::pat_bindings(def_map, pattern) |_, node_id, span, path_ref| {
367+
do pat_util::pat_bindings(def_map, arg.pat) |_, node_id, span, path_ref| {
372368

373369
let llptr = match bcx.fcx.llargs.find_copy(&node_id) {
374370
Some(v) => v,
@@ -429,13 +425,24 @@ pub fn set_source_location(fcx: &FunctionContext,
429425
}
430426
}
431427

428+
/// Enables emitting source locations for the given functions.
429+
///
430+
/// Since we don't want source locations to be emitted for the function prelude, they are disabled
431+
/// when beginning to translate a new function. This functions switches source location emitting on
432+
/// and must therefore be called before the first real statement/expression of the function is
433+
/// translated.
432434
pub fn start_emitting_source_locations(fcx: &mut FunctionContext) {
433435
match fcx.debug_context {
434436
FunctionDebugContext(~ref mut data) => data.source_locations_enabled = true,
435-
_ => { /* safe to ignore */}
437+
_ => { /* safe to ignore */ }
436438
}
437439
}
438440

441+
/// Creates the function-specific debug context.
442+
///
443+
/// Returns the FunctionDebugContext for the function which holds state needed for debug info
444+
/// creation. The function may also return another variant of the FunctionDebugContext enum which
445+
/// indicates why no debuginfo should be created for the function.
439446
pub fn create_function_debug_context(cx: &mut CrateContext,
440447
fn_ast_id: ast::NodeId,
441448
param_substs: Option<@param_substs>,
@@ -1662,7 +1669,7 @@ fn bytes_to_bits(bytes: uint) -> c_ulonglong {
16621669
}
16631670

16641671
#[inline]
1665-
fn dbg_cx<'a>(cx: &'a mut CrateContext) -> &'a mut DebugContext {
1672+
fn dbg_cx<'a>(cx: &'a mut CrateContext) -> &'a mut CrateDebugContext {
16661673
cx.dbg_cx.get_mut_ref()
16671674
}
16681675

src/rustllvm/rustllvm.def.in

+3
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,9 @@ LLVMDIBuilderCreateEnumerator
608608
LLVMDIBuilderCreateEnumerationType
609609
LLVMDIBuilderCreateUnionType
610610
LLVMDIBuilderCreateTemplateTypeParameter
611+
LLVMDIBuilderCreateOpDeref
612+
LLVMDIBuilderCreateOpPlus
613+
LLVMDIBuilderCreateComplexVariable
611614
LLVMSetUnnamedAddr
612615
LLVMRustAddPass
613616
LLVMRustAddAnalysisPasses
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// Copyright 2013 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+
// compile-flags:-Z extra-debug-info
12+
// debugger:break zzz
13+
// debugger:run
14+
15+
// debugger:finish
16+
// debugger:print s
17+
// check:$1 = {a = 1, b = 2.5}
18+
// debugger:continue
19+
20+
// debugger:finish
21+
// debugger:print x
22+
// check:$2 = {a = 3, b = 4.5}
23+
// debugger:print y
24+
// check:$3 = 5
25+
// debugger:print z
26+
// check:$4 = 6.5
27+
// debugger:continue
28+
29+
// debugger:finish
30+
// debugger:print a
31+
// check:$5 = {7, 8, 9.5, 10.5}
32+
// debugger:continue
33+
34+
// debugger:finish
35+
// debugger:print a
36+
// check:$6 = {11.5, 12.5, 13, 14}
37+
// debugger:continue
38+
39+
// debugger:finish
40+
// debugger:print x
41+
// check:$7 = {{Case1, x = 0, y = 8970181431921507452}, {Case1, 0, 2088533116, 2088533116}}
42+
// debugger:continue
43+
44+
#[deriving(Clone)]
45+
struct Struct {
46+
a: int,
47+
b: float
48+
}
49+
50+
#[deriving(Clone)]
51+
struct StructStruct {
52+
a: Struct,
53+
b: Struct
54+
}
55+
56+
fn fun(s: Struct) {
57+
zzz();
58+
}
59+
60+
fn fun_fun(StructStruct { a: x, b: Struct { a: y, b: z } }: StructStruct) {
61+
zzz();
62+
}
63+
64+
fn tup(a: (int, uint, float, float)) {
65+
zzz();
66+
}
67+
68+
struct Newtype(float, float, int, uint);
69+
70+
fn new_type(a: Newtype) {
71+
zzz();
72+
}
73+
74+
// The first element is to ensure proper alignment, irrespective of the machines word size. Since
75+
// the size of the discriminant value is machine dependent, this has be taken into account when
76+
// datatype layout should be predictable as in this case.
77+
enum Enum {
78+
Case1 { x: i64, y: i64 },
79+
Case2 (i64, i32, i32),
80+
}
81+
82+
fn by_val_enum(x: Enum) {
83+
zzz();
84+
}
85+
86+
fn main() {
87+
fun(Struct { a: 1, b: 2.5 });
88+
fun_fun(StructStruct { a: Struct { a: 3, b: 4.5 }, b: Struct { a: 5, b: 6.5 } });
89+
tup((7, 8, 9.5, 10.5));
90+
new_type(Newtype(11.5, 12.5, 13, 14));
91+
92+
// 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
93+
// 0b01111100011111000111110001111100 = 2088533116
94+
// 0b0111110001111100 = 31868
95+
// 0b01111100 = 124
96+
by_val_enum(Case1 { x: 0, y: 8970181431921507452 });
97+
}
98+
99+
fn zzz() {()}

src/test/debug-info/by-value-struct-argument.rs

-34
This file was deleted.

src/test/debug-info/var-captured-in-managed-closure.rs

-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
12-
1311
// compile-flags:-Z extra-debug-info
1412
// debugger:break zzz
1513
// debugger:run
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright 2013 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+
// compile-flags:-Z extra-debug-info
12+
// debugger:break zzz
13+
// debugger:run
14+
// debugger:finish
15+
16+
// debugger:print variable
17+
// check:$1 = 1
18+
// debugger:print constant
19+
// check:$2 = 2
20+
// debugger:print a_struct
21+
// check:$3 = {a = -3, b = 4.5, c = 5}
22+
// debugger:print *struct_ref
23+
// check:$4 = {a = -3, b = 4.5, c = 5}
24+
// debugger:print *owned
25+
// check:$5 = 6
26+
// debugger:print managed->val
27+
// check:$6 = 7
28+
// debugger:print closure_local
29+
// check:$7 = 8
30+
// debugger:continue
31+
32+
#[allow(unused_variable)];
33+
34+
struct Struct {
35+
a: int,
36+
b: float,
37+
c: uint
38+
}
39+
40+
fn main() {
41+
let mut variable = 1;
42+
let constant = 2;
43+
44+
let a_struct = Struct {
45+
a: -3,
46+
b: 4.5,
47+
c: 5
48+
};
49+
50+
let struct_ref = &a_struct;
51+
let owned = ~6;
52+
let managed = @7;
53+
54+
let closure = || {
55+
let closure_local = 8;
56+
57+
let nested_closure = || {
58+
zzz();
59+
variable = constant + a_struct.a + struct_ref.a + *owned + *managed + closure_local;
60+
};
61+
62+
// breaking here will yield a wrong value for 'constant'. In particular, GDB will
63+
// read the value of the register that supposedly contains the pointer to 'constant'
64+
// and try derefence it. The register, however, already contains the actual value, and
65+
// not a pointer to it. -mw
66+
// zzz();
67+
68+
nested_closure();
69+
};
70+
71+
closure();
72+
}
73+
74+
fn zzz() {()}

src/test/debug-info/var-captured-in-sendable-closure.rs

-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
12-
1311
// compile-flags:-Z extra-debug-info
1412
// debugger:break zzz
1513
// debugger:run

src/test/debug-info/var-captured-in-stack-closure.rs

-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
12-
1311
// compile-flags:-Z extra-debug-info
1412
// debugger:break zzz
1513
// debugger:run

0 commit comments

Comments
 (0)