@@ -60,6 +60,7 @@ use middle::trans::type_::Type;
60
60
use middle:: trans:: adt;
61
61
use middle:: trans;
62
62
use middle:: ty;
63
+ use middle:: pat_util;
63
64
use util:: ppaux:: ty_to_str;
64
65
65
66
use std:: hashmap:: HashMap ;
@@ -71,15 +72,15 @@ use syntax::{ast, codemap, ast_util, ast_map};
71
72
72
73
static DW_LANG_RUST : int = 0x9000 ;
73
74
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 ;
76
77
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 ;
83
84
84
85
85
86
@@ -90,14 +91,16 @@ static DW_ATE_unsigned_char: int = 0x08;
90
91
91
92
/// A context object for maintaining all state needed by the debuginfo module.
92
93
pub struct DebugContext {
93
- crate_file : ~str ,
94
- llcontext : ContextRef ,
95
- builder : DIBuilderRef ,
96
- curr_loc : ( uint , uint ) ,
97
- created_files : HashMap < ~str , DIFile > ,
98
- created_functions : HashMap < ast:: node_id , DISubprogram > ,
99
- created_blocks : HashMap < ast:: node_id , DILexicalBlock > ,
100
- created_types : HashMap < uint , DIType >
94
+ priv crate_file : ~str ,
95
+ priv llcontext : ContextRef ,
96
+ priv builder : DIBuilderRef ,
97
+ priv curr_loc : ( uint , uint ) ,
98
+ priv created_files : HashMap < ~str , DIFile > ,
99
+ priv created_functions : HashMap < ast:: node_id , DISubprogram > ,
100
+ priv created_blocks : HashMap < ast:: node_id , DILexicalBlock > ,
101
+ priv created_types : HashMap < uint , DIType > ,
102
+ priv last_function_context_id : ast:: node_id ,
103
+ priv argument_counter : uint ,
101
104
}
102
105
103
106
impl DebugContext {
@@ -115,6 +118,8 @@ impl DebugContext {
115
118
created_functions : HashMap :: new ( ) ,
116
119
created_blocks : HashMap :: new ( ) ,
117
120
created_types : HashMap :: new ( ) ,
121
+ last_function_context_id : -1 , // magic value :(
122
+ argument_counter : 1 ,
118
123
} ;
119
124
}
120
125
}
@@ -132,126 +137,147 @@ pub fn finalize(cx: @mut CrateContext) {
132
137
/// Creates debug information for the given local variable.
133
138
///
134
139
/// 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 {
140
+ pub fn create_local_var_metadata ( bcx : @mut Block , local : & ast:: Local ) {
137
141
let cx = bcx. ccx ( ) ;
142
+ let def_map = cx. tcx . def_map ;
143
+ let pattern = local. pat ;
138
144
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
- }
145
+ let scope = match bcx. parent {
146
+ None => create_function_metadata ( bcx. fcx ) ,
147
+ Some ( _) => lexical_block_metadata ( bcx)
146
148
} ;
147
149
148
- let name : & str = cx . sess . str_of ( ident ) ;
149
- debug ! ( "create_local_var_metadata: %s" , name ) ;
150
+ let filename = span_start ( cx , local . span ) . file . name ;
151
+ let file_metadata = file_metadata ( cx , filename ) ;
150
152
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 ) ;
153
+ do pat_util:: pat_bindings ( def_map, pattern) |_, node_id, span, path_ref| {
155
154
156
- let context = match bcx. parent {
157
- None => create_function_metadata ( bcx. fcx ) ,
158
- Some ( _) => lexical_block_metadata ( bcx)
159
- } ;
155
+ let ident = ast_util:: path_to_ident ( path_ref) ;
156
+ let name: & str = cx. sess . str_of ( ident) ;
157
+ debug ! ( "create_local_var_metadata: %s" , name) ;
158
+ let loc = span_start ( cx, span) ;
159
+ let ty = node_id_type ( bcx, node_id) ;
160
+ let type_metadata = type_metadata ( cx, ty, span) ;
161
+
162
+ let var_metadata = do name. as_c_str |name| {
163
+ unsafe {
164
+ llvm:: LLVMDIBuilderCreateLocalVariable (
165
+ DIB ( cx) ,
166
+ DW_TAG_auto_variable ,
167
+ scope,
168
+ name,
169
+ file_metadata,
170
+ loc. line as c_uint ,
171
+ type_metadata,
172
+ false ,
173
+ 0 ,
174
+ 0 )
175
+ }
176
+ } ;
177
+
178
+ let llptr = match bcx. fcx . lllocals . find_copy ( & node_id) {
179
+ Some ( v) => v,
180
+ None => {
181
+ bcx. tcx ( ) . sess . span_bug ( span, fmt ! ( "No entry in lllocals table for %?" , node_id) ) ;
182
+ }
183
+ } ;
160
184
161
- let var_metadata = do name . as_c_str |name| {
185
+ set_debug_location ( cx , lexical_block_metadata ( bcx ) , loc . line , loc . col . to_uint ( ) ) ;
162
186
unsafe {
163
- llvm:: LLVMDIBuilderCreateLocalVariable (
187
+ let instr = llvm:: LLVMDIBuilderInsertDeclareAtEnd (
164
188
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
- } ;
189
+ llptr,
190
+ var_metadata,
191
+ bcx. llbb ) ;
176
192
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) ) ;
193
+ llvm:: LLVMSetInstDebugLocation ( trans:: build:: B ( bcx) . llbuilder , instr) ;
184
194
}
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) ;
191
195
}
192
-
193
- return var_metadata;
194
196
}
195
197
196
198
/// Creates debug information for the given function argument.
197
199
///
198
200
/// Adds the created metadata nodes directly to the crate's IR.
199
- /// The return value should be ignored if called from outside of the debuginfo module.
200
- pub fn create_argument_metadata ( bcx : @mut Block , arg : & ast:: arg , span : span ) -> Option < DIVariable > {
201
- debug ! ( "create_argument_metadata" ) ;
202
- if true {
203
- // XXX create_argument_metadata disabled for now because "node_id_type(bcx, arg.id)" below
204
- // blows up:
205
- // "error: internal compiler error: node_id_to_type: no type for node `arg (id=10)`"
206
- return None ;
207
- }
208
-
201
+ pub fn create_argument_metadata ( bcx : @mut Block ,
202
+ arg : & ast:: arg ) {
209
203
let fcx = bcx. fcx ;
210
204
let cx = fcx. ccx ;
211
205
212
- let loc = span_start ( cx, span) ;
213
- if "<intrinsic>" == loc. file . name {
214
- return None ;
206
+ let pattern = arg. pat ;
207
+ let filename = span_start ( cx, pattern. span ) . file . name ;
208
+
209
+ if fcx. id == -1 ||
210
+ fcx. span . is_none ( ) ||
211
+ "<intrinsic>" == filename {
212
+ return ;
215
213
}
216
214
217
- let ty = node_id_type ( bcx, arg. id ) ;
218
- let type_metadata = type_metadata ( cx, ty, arg. ty . span ) ;
219
- let file_metadata = file_metadata ( cx, loc. file . name ) ;
220
- let context = create_function_metadata ( fcx) ;
221
-
222
- match arg. pat . node {
223
- ast:: pat_ident( _, ref path, _) => {
224
- // XXX: This is wrong; it should work for multiple bindings.
225
- let ident = path. idents . last ( ) ;
226
- let name: & str = cx. sess . str_of ( * ident) ;
227
- let var_metadata = do name. as_c_str |name| {
228
- unsafe {
229
- llvm:: LLVMDIBuilderCreateLocalVariable (
230
- DIB ( cx) ,
231
- DW_TAG_arg_variable as u32 ,
232
- context,
233
- name,
234
- file_metadata,
235
- loc. line as c_uint ,
236
- type_metadata,
237
- false ,
238
- 0 ,
239
- 0 )
240
- // XXX need to pass in a real argument number
241
- }
242
- } ;
215
+ // Limited the scope within which `debug_context` is live,
216
+ // otherwise => borrowing errors
217
+ {
218
+ let debug_context = dbg_cx ( cx) ;
219
+
220
+ // If this is a new function, reset the counter. llvm::DIBuilder
221
+ // wants arguments to be indexed starting from 1.
222
+ if fcx. id != debug_context. last_function_context_id {
223
+ debug_context. argument_counter = 1 ;
224
+ }
225
+ // Keep track of the function we are in
226
+ debug_context. last_function_context_id = fcx. id ;
227
+ }
228
+
229
+ let def_map = cx. tcx . def_map ;
230
+ let file_metadata = file_metadata ( cx, filename) ;
231
+ let scope = create_function_metadata ( fcx) ;
232
+
233
+ do pat_util:: pat_bindings ( def_map, pattern) |_, node_id, span, path_ref| {
234
+
235
+ let ty = node_id_type ( bcx, node_id) ;
236
+ let type_metadata = type_metadata ( cx, ty, codemap:: dummy_sp ( ) ) ;
237
+ let loc = span_start ( cx, span) ;
238
+ let ident = ast_util:: path_to_ident ( path_ref) ;
239
+ let name: & str = cx. sess . str_of ( ident) ;
240
+ debug ! ( "create_argument_metadata: %s" , name) ;
241
+
242
+ let argument_index = {
243
+ let debug_context = dbg_cx ( cx) ;
244
+ let argument_index = debug_context. argument_counter ;
245
+ debug_context. argument_counter += 1 ;
246
+ argument_index as c_uint
247
+ } ;
243
248
244
- let llptr = fcx. llargs . get_copy ( & arg. id ) ;
245
- set_debug_location ( cx, lexical_block_metadata ( bcx) , loc. line , loc. col . to_uint ( ) ) ;
249
+ let arg_metadata = do name. as_c_str |name| {
246
250
unsafe {
247
- let instr = llvm:: LLVMDIBuilderInsertDeclareAtEnd (
248
- DIB ( cx) , llptr, var_metadata, bcx. llbb ) ;
249
- llvm:: LLVMSetInstDebugLocation ( trans:: build:: B ( bcx) . llbuilder , instr) ;
251
+ llvm:: LLVMDIBuilderCreateLocalVariable (
252
+ DIB ( cx) ,
253
+ DW_TAG_arg_variable ,
254
+ scope,
255
+ name,
256
+ file_metadata,
257
+ loc. line as c_uint ,
258
+ type_metadata,
259
+ false ,
260
+ 0 ,
261
+ argument_index)
250
262
}
251
- return Some ( var_metadata) ;
252
- }
253
- _ => {
254
- return None ;
263
+ } ;
264
+
265
+ let llptr = match bcx. fcx . llargs . find_copy ( & node_id) {
266
+ Some ( v) => v,
267
+ None => {
268
+ bcx. tcx ( ) . sess . span_bug ( span, fmt ! ( "No entry in llargs table for %?" , node_id) ) ;
269
+ }
270
+ } ;
271
+
272
+ set_debug_location ( cx, lexical_block_metadata ( bcx) , loc. line , loc. col . to_uint ( ) ) ;
273
+ unsafe {
274
+ let instr = llvm:: LLVMDIBuilderInsertDeclareAtEnd (
275
+ DIB ( cx) ,
276
+ llptr,
277
+ arg_metadata,
278
+ bcx. llbb ) ;
279
+
280
+ llvm:: LLVMSetInstDebugLocation ( trans:: build:: B ( bcx) . llbuilder , instr) ;
255
281
}
256
282
}
257
283
}
@@ -274,7 +300,6 @@ pub fn update_source_pos(bcx: @mut Block, span: span) {
274
300
/// The return value should be ignored if called from outside of the debuginfo module.
275
301
pub fn create_function_metadata ( fcx : & FunctionContext ) -> DISubprogram {
276
302
let cx = fcx. ccx ;
277
- let span = fcx. span . get ( ) ;
278
303
279
304
let fnitem = cx. tcx . items . get_copy ( & fcx. id ) ;
280
305
let ( ident, ret_ty, id) = match fnitem {
@@ -320,14 +345,19 @@ pub fn create_function_metadata(fcx: &FunctionContext) -> DISubprogram {
320
345
_) => {
321
346
( ident, ty, id)
322
347
}
323
- _ => fcx. ccx . sess . bug ( "create_function_metadata: unexpected sort of node" )
348
+ _ => fcx. ccx . sess . bug ( fmt ! ( "create_function_metadata: unexpected sort of node: %?" , fnitem ) )
324
349
} ;
325
350
326
351
match dbg_cx ( cx) . created_functions . find ( & id) {
327
352
Some ( fn_metadata) => return * fn_metadata,
328
353
None => ( )
329
354
}
330
355
356
+ let span = match fcx. span {
357
+ Some ( value) => value,
358
+ None => codemap:: dummy_sp ( )
359
+ } ;
360
+
331
361
debug ! ( "create_function_metadata: %s, %s" ,
332
362
cx. sess. str_of( ident) ,
333
363
cx. sess. codemap. span_to_str( span) ) ;
@@ -527,7 +557,7 @@ fn basic_type_metadata(cx: &mut CrateContext, t: ty::t) -> DIType {
527
557
name,
528
558
bytes_to_bits ( size) ,
529
559
bytes_to_bits ( align) ,
530
- encoding as c_uint )
560
+ encoding)
531
561
}
532
562
} ;
533
563
@@ -608,8 +638,6 @@ fn tuple_metadata(cx: &mut CrateContext,
608
638
fn enum_metadata ( cx : & mut CrateContext ,
609
639
enum_type : ty:: t ,
610
640
enum_def_id : ast:: def_id ,
611
- // _substs is only needed in the other version. Will go away with new snapshot.
612
- _substs : & ty:: substs ,
613
641
span : span )
614
642
-> DIType {
615
643
@@ -1113,8 +1141,8 @@ fn type_metadata(cx: &mut CrateContext,
1113
1141
}
1114
1142
}
1115
1143
} ,
1116
- ty:: ty_enum( def_id, ref substs ) => {
1117
- enum_metadata ( cx, t, def_id, substs , span)
1144
+ ty:: ty_enum( def_id, _ ) => {
1145
+ enum_metadata ( cx, t, def_id, span)
1118
1146
} ,
1119
1147
ty:: ty_box( ref mt) => {
1120
1148
create_pointer_to_box_metadata ( cx, t, mt. ty )
0 commit comments