Skip to content

Commit 203f96f

Browse files
debuginfo: Implemented support for destructured locals.
Conflicts: src/librustc/middle/trans/debuginfo.rs src/test/debug-info/destructured-local.rs
1 parent 4cf3072 commit 203f96f

File tree

2 files changed

+236
-61
lines changed

2 files changed

+236
-61
lines changed

src/librustc/middle/trans/debuginfo.rs

Lines changed: 54 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ use middle::trans::type_::Type;
6060
use middle::trans::adt;
6161
use middle::trans;
6262
use middle::ty;
63+
use middle::pat_util;
6364
use util::ppaux::ty_to_str;
6465

6566
use std::hashmap::HashMap;
@@ -71,15 +72,15 @@ use syntax::{ast, codemap, ast_util, ast_map};
7172

7273
static DW_LANG_RUST: int = 0x9000;
7374

74-
static DW_TAG_auto_variable: int = 0x100;
75-
static DW_TAG_arg_variable: int = 0x101;
75+
static DW_TAG_auto_variable: c_uint = 0x100;
76+
static DW_TAG_arg_variable: c_uint = 0x101;
7677

77-
static DW_ATE_boolean: int = 0x02;
78-
static DW_ATE_float: int = 0x04;
79-
static DW_ATE_signed: int = 0x05;
80-
static DW_ATE_signed_char: int = 0x06;
81-
static DW_ATE_unsigned: int = 0x07;
82-
static DW_ATE_unsigned_char: int = 0x08;
78+
static DW_ATE_boolean: c_uint = 0x02;
79+
static DW_ATE_float: c_uint = 0x04;
80+
static DW_ATE_signed: c_uint = 0x05;
81+
static DW_ATE_signed_char: c_uint = 0x06;
82+
static DW_ATE_unsigned: c_uint = 0x07;
83+
static DW_ATE_unsigned_char: c_uint = 0x08;
8384

8485

8586

@@ -132,65 +133,62 @@ pub fn finalize(cx: @mut CrateContext) {
132133
/// Creates debug information for the given local variable.
133134
///
134135
/// Adds the created metadata nodes directly to the crate's IR.
135-
/// The return value should be ignored if called from outside of the debuginfo module.
136-
pub fn create_local_var_metadata(bcx: @mut Block, local: @ast::Local) -> DIVariable {
136+
pub fn create_local_var_metadata(bcx: @mut Block, local: &ast::Local) {
137137
let cx = bcx.ccx();
138-
139-
let ident = match local.pat.node {
140-
ast::pat_ident(_, ref pth, _) => ast_util::path_to_ident(pth),
141-
// FIXME this should be handled (#2533)
142-
_ => {
143-
bcx.sess().span_note(local.span, "debuginfo for pattern bindings NYI");
144-
return ptr::null();
145-
}
146-
};
147-
148-
let name: &str = cx.sess.str_of(ident);
149-
debug!("create_local_var_metadata: %s", name);
150-
151-
let loc = span_start(cx, local.span);
152-
let ty = node_id_type(bcx, local.id);
153-
let type_metadata = type_metadata(cx, ty, local.ty.span);
154-
let file_metadata = file_metadata(cx, loc.file.name);
138+
let def_map = cx.tcx.def_map;
139+
let pattern = local.node.pat;
155140

156141
let context = match bcx.parent {
157142
None => create_function_metadata(bcx.fcx),
158143
Some(_) => lexical_block_metadata(bcx)
159144
};
160145

161-
let var_metadata = do name.as_c_str |name| {
146+
do pat_util::pat_bindings(def_map, pattern) |_, node_id, span, path_ref| {
147+
148+
let ident = ast_util::path_to_ident(path_ref);
149+
let name: &str = cx.sess.str_of(ident);
150+
debug!("create_local_var_metadata: %s", name);
151+
let loc = span_start(cx, span);
152+
let ty = node_id_type(bcx, node_id);
153+
let type_metadata = type_metadata(cx, ty, span);
154+
let file_metadata = file_metadata(cx, loc.file.name);
155+
156+
let var_metadata = do as_c_str(name) |name| {
157+
unsafe {
158+
llvm::LLVMDIBuilderCreateLocalVariable(
159+
DIB(cx),
160+
DW_TAG_auto_variable,
161+
context,
162+
name,
163+
file_metadata,
164+
loc.line as c_uint,
165+
type_metadata,
166+
false,
167+
0,
168+
0)
169+
}
170+
};
171+
172+
let llptr = match bcx.fcx.lllocals.find_copy(&node_id) {
173+
Some(v) => v,
174+
None => {
175+
bcx.tcx().sess.span_bug(
176+
local.span,
177+
fmt!("No entry in lllocals table for %?", local.node.id));
178+
}
179+
};
180+
181+
set_debug_location(cx, lexical_block_metadata(bcx), loc.line, loc.col.to_uint());
162182
unsafe {
163-
llvm::LLVMDIBuilderCreateLocalVariable(
183+
let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
164184
DIB(cx),
165-
DW_TAG_auto_variable as u32,
166-
context,
167-
name,
168-
file_metadata,
169-
loc.line as c_uint,
170-
type_metadata,
171-
false,
172-
0,
173-
0)
174-
}
175-
};
185+
llptr,
186+
var_metadata,
187+
bcx.llbb);
176188

177-
// FIXME(#6814) Should use `pat_util::pat_bindings` for pats like (a, b) etc
178-
let llptr = match bcx.fcx.lllocals.find_copy(&local.pat.id) {
179-
Some(v) => v,
180-
None => {
181-
bcx.tcx().sess.span_bug(
182-
local.span,
183-
fmt!("No entry in lllocals table for %?", local.id));
189+
llvm::LLVMSetInstDebugLocation(trans::build::B(bcx), instr);
184190
}
185-
};
186-
187-
set_debug_location(cx, lexical_block_metadata(bcx), loc.line, loc.col.to_uint());
188-
unsafe {
189-
let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(DIB(cx), llptr, var_metadata, bcx.llbb);
190-
llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr);
191191
}
192-
193-
return var_metadata;
194192
}
195193

196194
/// Creates debug information for the given function argument.
@@ -527,7 +525,7 @@ fn basic_type_metadata(cx: &mut CrateContext, t: ty::t) -> DIType {
527525
name,
528526
bytes_to_bits(size),
529527
bytes_to_bits(align),
530-
encoding as c_uint)
528+
encoding)
531529
}
532530
};
533531

src/test/debug-info/destructured-local.rs

Lines changed: 182 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,198 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// xfail-test
12-
1311
// compile-flags:-Z extra-debug-info
1412
// debugger:break zzz
1513
// debugger:run
1614
// debugger:finish
1715

1816
// debugger:print a
19-
// check:$1 = 9898
20-
17+
// check:$1 = 1
2118
// debugger:print b
2219
// check:$2 = false
2320

21+
// debugger:print c
22+
// check:$3 = 2
23+
// debugger:print d
24+
// check:$4 = 3
25+
// debugger:print e
26+
// check:$5 = 4
27+
28+
// debugger:print f
29+
// check:$6 = 5
30+
// debugger:print g
31+
// check:$7 = {6, 7}
32+
33+
// debugger:print h
34+
// check:$8 = 8
35+
// debugger:print i
36+
// check:$9 = {a = 9, b = 10}
37+
// debugger:print j
38+
// check:$10 = 11
39+
40+
// debugger:print k
41+
// check:$11 = 12
42+
// debugger:print l
43+
// check:$12 = 13
44+
45+
// debugger:print m
46+
// check:$13 = 14
47+
// debugger:print n
48+
// check:$14 = 16
49+
50+
// debugger:print o
51+
// check:$15 = 18
52+
53+
// debugger:print p
54+
// check:$16 = 19
55+
// debugger:print q
56+
// check:$17 = 20
57+
// debugger:print r
58+
// check:$18 = {a = 21, b = 22}
59+
60+
// debugger:print s
61+
// check:$19 = 24
62+
// debugger:print t
63+
// check:$20 = 23
64+
65+
// debugger:print u
66+
// check:$21 = 25
67+
// debugger:print v
68+
// check:$22 = 26
69+
// debugger:print w
70+
// check:$23 = 27
71+
// debugger:print x
72+
// check:$24 = 28
73+
// debugger:print y
74+
// check:$25 = 29
75+
// debugger:print z
76+
// check:$26 = 30
77+
// debugger:print ae
78+
// check:$27 = 31
79+
// debugger:print oe
80+
// check:$28 = 32
81+
// debugger:print ue
82+
// check:$29 = 33
83+
84+
// debugger:print aa
85+
// check:$30 = {34, 35}
86+
87+
// debugger:print bb
88+
// check:$31 = {36, 37}
89+
90+
// debugger:print cc
91+
// check:$32 = 38
92+
93+
// debugger:print dd
94+
// check:$33 = {40, 41, 42}
95+
96+
// debugger:print *ee
97+
// check:$34 = {43, 44, 45}
98+
99+
// debugger:print *ff
100+
// check:$35 = 46
101+
102+
// debugger:print gg
103+
// check:$36 = {47, 48}
104+
105+
// debugger:print *hh
106+
// check:$37 = 50
107+
108+
// debugger:print ii
109+
// check:$38 = 51
110+
111+
// debugger:print *jj
112+
// check:$39 = 52
113+
114+
// debugger:print kk
115+
// check:$40 = 53
116+
117+
// debugger:print ll
118+
// check:$41 = 54
119+
120+
// debugger:print mm
121+
// check:$42 = 55
122+
123+
// debugger:print *nn
124+
// check:$43 = 56
125+
126+
127+
struct Struct {
128+
a: i64,
129+
b: i32
130+
}
131+
132+
enum Univariant {
133+
Unit(i32)
134+
}
135+
136+
struct TupleStruct (float, int);
137+
138+
24139
fn main() {
25-
let (a, b): (int, bool) = (9898, false);
140+
// simple tuple
141+
let (a, b) : (int, bool) = (1, false);
142+
143+
// nested tuple
144+
let (c, (d, e)) : (int, (u16, u16)) = (2, (3, 4));
145+
146+
// bind tuple-typed value to one name (destructure only first level)
147+
let (f, g) : (int, (u32, u32)) = (5, (6, 7));
148+
149+
// struct as tuple element
150+
let (h, i, j) : (i16, Struct, i16) = (8, Struct { a: 9, b: 10 }, 11);
151+
152+
// struct pattern
153+
let Struct { a: k, b: l } = Struct { a: 12, b: 13 };
154+
155+
// ignored tuple element
156+
let (m, _, n) = (14, 15, 16);
157+
158+
// ignored struct field
159+
let Struct { b: o, _ } = Struct { a: 17, b: 18 };
160+
161+
// one struct destructured, one not
162+
let (Struct { a: p, b: q }, r) = (Struct { a: 19, b: 20 }, Struct { a: 21, b: 22 });
163+
164+
// different order of struct fields
165+
let Struct { b: s, a: t } = Struct { a: 23, b: 24 };
166+
167+
// complex nesting
168+
let ((u, v), ((w, (x, Struct { a: y, b: z})), Struct { a: ae, b: oe }), ue) =
169+
((25, 26), ((27, (28, Struct { a: 29, b: 30})), Struct { a: 31, b: 32 }), 33);
170+
171+
// managed box
172+
let @aa = @(34, 35);
173+
174+
// borrowed pointer
175+
let &bb = &(36, 37);
176+
177+
// contained borrowed pointer
178+
let (&cc, _) = (&38, 39);
179+
180+
// unique pointer
181+
let ~dd = ~(40, 41, 42);
182+
183+
// ref binding
184+
let ref ee = (43, 44, 45);
185+
186+
// ref binding in tuple
187+
let (ref ff, gg) = (46, (47, 48));
188+
189+
// ref binding in struct
190+
let Struct { b: ref hh, _ } = Struct { a: 49, b: 50 };
191+
192+
// univariant enum
193+
let Unit(ii) = Unit(51);
194+
195+
// univariant enum with ref binding
196+
let Unit(ref jj) = Unit(52);
197+
198+
// tuple struct
199+
let TupleStruct(kk, ll) = TupleStruct(53.0, 54);
200+
201+
// tuple struct with ref binding
202+
let TupleStruct(mm, ref nn) = TupleStruct(55.0, 56);
26203

27204
zzz();
28205
}

0 commit comments

Comments
 (0)