@@ -163,11 +163,12 @@ struct FunctionDebugContextData {
163163 source_locations_enabled : bool ,
164164}
165165
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 ] }
171172}
172173
173174enum VariableKind {
@@ -213,11 +214,10 @@ pub fn create_local_var_metadata(bcx: @mut Block,
213214 let scope_metadata = scope_metadata ( bcx. fcx , node_id, span) ;
214215
215216 declare_local ( bcx,
216- llptr,
217217 var_ident,
218218 var_type,
219219 scope_metadata,
220- DirectVariable ,
220+ DirectVariable { alloca : llptr } ,
221221 LocalVariable ,
222222 span) ;
223223 }
@@ -228,7 +228,10 @@ pub fn create_local_var_metadata(bcx: @mut Block,
228228/// Adds the created metadata nodes directly to the crate's IR.
229229pub fn create_captured_var_metadata ( bcx : @mut Block ,
230230 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 ,
232235 span : Span ) {
233236 if fn_should_be_ignored ( bcx. fcx ) {
234237 return ;
@@ -250,15 +253,39 @@ pub fn create_captured_var_metadata(bcx: @mut Block,
250253 Captured var-id refers to unexpected ast_map variant: %?", ast_item) ) ;
251254 }
252255 } ;
256+
253257 let variable_type = node_id_type ( bcx, node_id) ;
254258 let scope_metadata = bcx. fcx . debug_context . get_ref ( cx, span) . fn_metadata ;
255259
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+
256284 declare_local ( bcx,
257- llptr,
258285 variable_ident,
259286 variable_type,
260287 scope_metadata,
261- IndirectVariable ,
288+ variable_access ,
262289 CapturedVariable ,
263290 span) ;
264291}
@@ -285,11 +312,10 @@ pub fn create_match_binding_metadata(bcx: @mut Block,
285312 let scope_metadata = scope_metadata ( bcx. fcx , node_id, span) ;
286313
287314 declare_local ( bcx,
288- llptr,
289315 variable_ident,
290316 variable_type,
291317 scope_metadata,
292- DirectVariable ,
318+ DirectVariable { alloca : llptr } ,
293319 LocalVariable ,
294320 span) ;
295321}
@@ -333,14 +359,17 @@ pub fn create_self_argument_metadata(bcx: @mut Block,
333359 argument_index
334360 } ;
335361
362+ let address_operations = & [ unsafe { llvm:: LLVMDIBuilderCreateOpDeref ( Type :: i64 ( ) . to_ref ( ) ) } ] ;
363+
336364 let variable_access = if unsafe { llvm:: LLVMIsAAllocaInst ( llptr) } != ptr:: null ( ) {
337- DirectVariable
365+ DirectVariable { alloca : llptr }
338366 } 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 }
340370 } ;
341371
342372 declare_local ( bcx,
343- llptr,
344373 special_idents:: self_,
345374 type_of_self,
346375 scope_metadata,
@@ -373,11 +402,10 @@ pub fn create_argument_metadata(bcx: @mut Block,
373402 }
374403 } ;
375404
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+ }
381409
382410 let argument_type = node_id_type ( bcx, node_id) ;
383411 let argument_ident = ast_util:: path_to_ident ( path_ref) ;
@@ -390,11 +418,10 @@ pub fn create_argument_metadata(bcx: @mut Block,
390418 } ;
391419
392420 declare_local ( bcx,
393- llptr,
394421 argument_ident,
395422 argument_type,
396423 scope_metadata,
397- variable_access ,
424+ DirectVariable { alloca : llptr } ,
398425 ArgumentVariable ( argument_index) ,
399426 span) ;
400427 }
@@ -783,7 +810,6 @@ fn compile_unit_metadata(cx: @mut CrateContext) {
783810}
784811
785812fn declare_local ( bcx : @mut Block ,
786- llptr : ValueRef ,
787813 variable_ident : ast:: Ident ,
788814 variable_type : ty:: t ,
789815 scope_metadata : DIScope ,
@@ -805,45 +831,48 @@ fn declare_local(bcx: @mut Block,
805831 CapturedVariable => 0
806832 } as c_uint ;
807833
808- let var_metadata = do name. with_c_str |name| {
834+ let ( var_alloca , var_metadata) = do name. with_c_str |name| {
809835 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+ )
839868 }
840869 } ;
841870
842871 set_debug_location ( cx, DebugLocation :: new ( scope_metadata, loc. line , * loc. col ) ) ;
843872 unsafe {
844873 let instr = llvm:: LLVMDIBuilderInsertDeclareAtEnd (
845874 DIB ( cx) ,
846- llptr ,
875+ var_alloca ,
847876 var_metadata,
848877 bcx. llbb ) ;
849878
0 commit comments