@@ -163,11 +163,12 @@ struct FunctionDebugContextData {
163
163
source_locations_enabled : bool ,
164
164
}
165
165
166
- enum VariableAccess {
167
- // The value given is a pointer to the data (T*)
168
- DirectVariable ,
169
- // The value given has to be dereferenced once to get the pointer to data (T**)
170
- IndirectVariable
166
+ enum VariableAccess < ' self > {
167
+ // The llptr given is an alloca containing the variable's value
168
+ DirectVariable { alloca : ValueRef } ,
169
+ // The llptr given is an alloca containing the start of some pointer chain leading to the
170
+ // variable's content.
171
+ IndirectVariable { alloca : ValueRef , address_operations : & ' self [ ValueRef ] }
171
172
}
172
173
173
174
enum VariableKind {
@@ -213,11 +214,10 @@ pub fn create_local_var_metadata(bcx: @mut Block,
213
214
let scope_metadata = scope_metadata ( bcx. fcx , node_id, span) ;
214
215
215
216
declare_local ( bcx,
216
- llptr,
217
217
var_ident,
218
218
var_type,
219
219
scope_metadata,
220
- DirectVariable ,
220
+ DirectVariable { alloca : llptr } ,
221
221
LocalVariable ,
222
222
span) ;
223
223
}
@@ -228,7 +228,10 @@ pub fn create_local_var_metadata(bcx: @mut Block,
228
228
/// Adds the created metadata nodes directly to the crate's IR.
229
229
pub fn create_captured_var_metadata ( bcx : @mut Block ,
230
230
node_id : ast:: NodeId ,
231
- llptr : ValueRef ,
231
+ env_data_type : ty:: t ,
232
+ env_pointer : ValueRef ,
233
+ env_index : uint ,
234
+ closure_sigil : ast:: Sigil ,
232
235
span : Span ) {
233
236
if fn_should_be_ignored ( bcx. fcx ) {
234
237
return ;
@@ -250,15 +253,39 @@ pub fn create_captured_var_metadata(bcx: @mut Block,
250
253
Captured var-id refers to unexpected ast_map variant: %?", ast_item) ) ;
251
254
}
252
255
} ;
256
+
253
257
let variable_type = node_id_type ( bcx, node_id) ;
254
258
let scope_metadata = bcx. fcx . debug_context . get_ref ( cx, span) . fn_metadata ;
255
259
260
+ let llvm_env_data_type = type_of:: type_of ( cx, env_data_type) ;
261
+ let byte_offset_of_var_in_env = machine:: llelement_offset ( cx, llvm_env_data_type, env_index) ;
262
+
263
+ let address_operations = unsafe {
264
+ [ llvm:: LLVMDIBuilderCreateOpDeref ( Type :: i64 ( ) . to_ref ( ) ) ,
265
+ llvm:: LLVMDIBuilderCreateOpPlus ( Type :: i64 ( ) . to_ref ( ) ) ,
266
+ C_i64 ( byte_offset_of_var_in_env as i64 ) ,
267
+ llvm:: LLVMDIBuilderCreateOpDeref ( Type :: i64 ( ) . to_ref ( ) ) ]
268
+ } ;
269
+
270
+ let address_op_count = match closure_sigil {
271
+ ast:: BorrowedSigil => {
272
+ address_operations. len ( )
273
+ }
274
+ ast:: ManagedSigil | ast:: OwnedSigil => {
275
+ address_operations. len ( ) - 1
276
+ }
277
+ } ;
278
+
279
+ let variable_access = IndirectVariable {
280
+ alloca : env_pointer,
281
+ address_operations : address_operations. slice_to ( address_op_count)
282
+ } ;
283
+
256
284
declare_local ( bcx,
257
- llptr,
258
285
variable_ident,
259
286
variable_type,
260
287
scope_metadata,
261
- IndirectVariable ,
288
+ variable_access ,
262
289
CapturedVariable ,
263
290
span) ;
264
291
}
@@ -285,11 +312,10 @@ pub fn create_match_binding_metadata(bcx: @mut Block,
285
312
let scope_metadata = scope_metadata ( bcx. fcx , node_id, span) ;
286
313
287
314
declare_local ( bcx,
288
- llptr,
289
315
variable_ident,
290
316
variable_type,
291
317
scope_metadata,
292
- DirectVariable ,
318
+ DirectVariable { alloca : llptr } ,
293
319
LocalVariable ,
294
320
span) ;
295
321
}
@@ -333,14 +359,17 @@ pub fn create_self_argument_metadata(bcx: @mut Block,
333
359
argument_index
334
360
} ;
335
361
362
+ let address_operations = & [ unsafe { llvm:: LLVMDIBuilderCreateOpDeref ( Type :: i64 ( ) . to_ref ( ) ) } ] ;
363
+
336
364
let variable_access = if unsafe { llvm:: LLVMIsAAllocaInst ( llptr) } != ptr:: null ( ) {
337
- DirectVariable
365
+ DirectVariable { alloca : llptr }
338
366
} else {
339
- IndirectVariable
367
+ // This is not stable and may break with future LLVM versions. llptr should really always
368
+ // be an alloca. Anything else is not supported and just works by chance.
369
+ IndirectVariable { alloca : llptr, address_operations : address_operations }
340
370
} ;
341
371
342
372
declare_local ( bcx,
343
- llptr,
344
373
special_idents:: self_,
345
374
type_of_self,
346
375
scope_metadata,
@@ -373,11 +402,10 @@ pub fn create_argument_metadata(bcx: @mut Block,
373
402
}
374
403
} ;
375
404
376
- let variable_access = if unsafe { llvm:: LLVMIsAAllocaInst ( llptr) } != ptr:: null ( ) {
377
- DirectVariable
378
- } else {
379
- IndirectVariable
380
- } ;
405
+ if unsafe { llvm:: LLVMIsAAllocaInst ( llptr) } == ptr:: null ( ) {
406
+ cx. sess . span_bug ( span, "debuginfo::create_argument_metadata() - \
407
+ Referenced variable location is not an alloca!") ;
408
+ }
381
409
382
410
let argument_type = node_id_type ( bcx, node_id) ;
383
411
let argument_ident = ast_util:: path_to_ident ( path_ref) ;
@@ -390,11 +418,10 @@ pub fn create_argument_metadata(bcx: @mut Block,
390
418
} ;
391
419
392
420
declare_local ( bcx,
393
- llptr,
394
421
argument_ident,
395
422
argument_type,
396
423
scope_metadata,
397
- variable_access ,
424
+ DirectVariable { alloca : llptr } ,
398
425
ArgumentVariable ( argument_index) ,
399
426
span) ;
400
427
}
@@ -783,7 +810,6 @@ fn compile_unit_metadata(cx: @mut CrateContext) {
783
810
}
784
811
785
812
fn declare_local ( bcx : @mut Block ,
786
- llptr : ValueRef ,
787
813
variable_ident : ast:: Ident ,
788
814
variable_type : ty:: t ,
789
815
scope_metadata : DIScope ,
@@ -805,45 +831,48 @@ fn declare_local(bcx: @mut Block,
805
831
CapturedVariable => 0
806
832
} as c_uint ;
807
833
808
- let var_metadata = do name. with_c_str |name| {
834
+ let ( var_alloca , var_metadata) = do name. with_c_str |name| {
809
835
match variable_access {
810
- DirectVariable => unsafe {
811
- llvm:: LLVMDIBuilderCreateLocalVariable (
812
- DIB ( cx) ,
813
- DW_TAG_auto_variable ,
814
- scope_metadata,
815
- name,
816
- file_metadata,
817
- loc. line as c_uint ,
818
- type_metadata,
819
- cx. sess . opts . optimize != session:: No ,
820
- 0 ,
821
- argument_index)
822
- } ,
823
- IndirectVariable => unsafe {
824
- let address_op = llvm:: LLVMDIBuilderCreateOpDeref ( Type :: i64 ( ) . to_ref ( ) ) ;
825
- let address_op_count = 1 ;
826
-
827
- llvm:: LLVMDIBuilderCreateComplexVariable (
828
- DIB ( cx) ,
829
- DW_TAG_auto_variable ,
830
- scope_metadata,
831
- name,
832
- file_metadata,
833
- loc. line as c_uint ,
834
- type_metadata,
835
- ptr:: to_unsafe_ptr ( & address_op) ,
836
- address_op_count,
837
- argument_index)
838
- }
836
+ DirectVariable { alloca } => (
837
+ alloca,
838
+ unsafe {
839
+ llvm:: LLVMDIBuilderCreateLocalVariable (
840
+ DIB ( cx) ,
841
+ DW_TAG_auto_variable ,
842
+ scope_metadata,
843
+ name,
844
+ file_metadata,
845
+ loc. line as c_uint ,
846
+ type_metadata,
847
+ cx. sess . opts . optimize != session:: No ,
848
+ 0 ,
849
+ argument_index)
850
+ }
851
+ ) ,
852
+ IndirectVariable { alloca, address_operations } => (
853
+ alloca,
854
+ unsafe {
855
+ llvm:: LLVMDIBuilderCreateComplexVariable (
856
+ DIB ( cx) ,
857
+ DW_TAG_auto_variable ,
858
+ scope_metadata,
859
+ name,
860
+ file_metadata,
861
+ loc. line as c_uint ,
862
+ type_metadata,
863
+ vec:: raw:: to_ptr ( address_operations) ,
864
+ address_operations. len ( ) as c_uint ,
865
+ argument_index)
866
+ }
867
+ )
839
868
}
840
869
} ;
841
870
842
871
set_debug_location ( cx, DebugLocation :: new ( scope_metadata, loc. line , * loc. col ) ) ;
843
872
unsafe {
844
873
let instr = llvm:: LLVMDIBuilderInsertDeclareAtEnd (
845
874
DIB ( cx) ,
846
- llptr ,
875
+ var_alloca ,
847
876
var_metadata,
848
877
bcx. llbb ) ;
849
878
0 commit comments