@@ -8,7 +8,7 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
8
8
use rustc_session:: config:: DebugInfo ;
9
9
use rustc_span:: symbol:: { kw, Symbol } ;
10
10
use rustc_span:: { BytePos , Span } ;
11
- use rustc_target:: abi:: { Abi , FieldIdx , Size , VariantIdx } ;
11
+ use rustc_target:: abi:: { Abi , FieldIdx , FieldsShape , Size , VariantIdx } ;
12
12
13
13
use super :: operand:: { OperandRef , OperandValue } ;
14
14
use super :: place:: PlaceRef ;
@@ -41,6 +41,9 @@ pub struct PerLocalVarDebugInfo<'tcx, D> {
41
41
42
42
/// `.place.projection` from `mir::VarDebugInfo`.
43
43
pub projection : & ' tcx ty:: List < mir:: PlaceElem < ' tcx > > ,
44
+
45
+ /// `references` from `mir::VarDebugInfo`.
46
+ pub references : u8 ,
44
47
}
45
48
46
49
#[ derive( Clone , Copy , Debug ) ]
@@ -80,6 +83,7 @@ trait DebugInfoOffsetLocation<'tcx, Bx> {
80
83
fn deref ( & self , bx : & mut Bx ) -> Self ;
81
84
fn layout ( & self ) -> TyAndLayout < ' tcx > ;
82
85
fn project_field ( & self , bx : & mut Bx , field : FieldIdx ) -> Self ;
86
+ fn project_constant_index ( & self , bx : & mut Bx , offset : u64 ) -> Self ;
83
87
fn downcast ( & self , bx : & mut Bx , variant : VariantIdx ) -> Self ;
84
88
}
85
89
@@ -98,6 +102,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
98
102
PlaceRef :: project_field ( * self , bx, field. index ( ) )
99
103
}
100
104
105
+ fn project_constant_index ( & self , bx : & mut Bx , offset : u64 ) -> Self {
106
+ let lloffset = bx. cx ( ) . const_usize ( offset) ;
107
+ self . project_index ( bx, lloffset)
108
+ }
109
+
101
110
fn downcast ( & self , bx : & mut Bx , variant : VariantIdx ) -> Self {
102
111
self . project_downcast ( bx, variant)
103
112
}
@@ -120,6 +129,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
120
129
self . field ( bx. cx ( ) , field. index ( ) )
121
130
}
122
131
132
+ fn project_constant_index ( & self , bx : & mut Bx , index : u64 ) -> Self {
133
+ self . field ( bx. cx ( ) , index as usize )
134
+ }
135
+
123
136
fn downcast ( & self , bx : & mut Bx , variant : VariantIdx ) -> Self {
124
137
self . for_variant ( bx. cx ( ) , variant)
125
138
}
@@ -165,6 +178,18 @@ fn calculate_debuginfo_offset<
165
178
mir:: ProjectionElem :: Downcast ( _, variant) => {
166
179
place = place. downcast ( bx, variant) ;
167
180
}
181
+ mir:: ProjectionElem :: ConstantIndex {
182
+ offset : index,
183
+ min_length : _,
184
+ from_end : false ,
185
+ } => {
186
+ let offset = indirect_offsets. last_mut ( ) . unwrap_or ( & mut direct_offset) ;
187
+ let FieldsShape :: Array { stride, count : _ } = place. layout ( ) . fields else {
188
+ span_bug ! ( var. source_info. span, "ConstantIndex on non-array type {:?}" , place. layout( ) )
189
+ } ;
190
+ * offset += stride * index;
191
+ place = place. project_constant_index ( bx, index) ;
192
+ }
168
193
_ => {
169
194
// Sanity check for `can_use_in_debuginfo`.
170
195
debug_assert ! ( !elem. can_use_in_debuginfo( ) ) ;
@@ -293,6 +318,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
293
318
dbg_var,
294
319
fragment : None ,
295
320
projection : ty:: List :: empty ( ) ,
321
+ references : 0 ,
296
322
} )
297
323
}
298
324
} else {
@@ -358,55 +384,74 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
358
384
let vars = vars. iter ( ) . cloned ( ) . chain ( fallback_var) ;
359
385
360
386
for var in vars {
361
- let Some ( dbg_var) = var. dbg_var else { continue } ;
362
- let Some ( dbg_loc) = self . dbg_loc ( var. source_info ) else { continue } ;
363
-
364
- let DebugInfoOffset { direct_offset, indirect_offsets, result : _ } =
365
- calculate_debuginfo_offset ( bx, local, & var, base. layout ) ;
366
-
367
- // When targeting MSVC, create extra allocas for arguments instead of pointing multiple
368
- // dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
369
- // not DWARF and LLVM doesn't support translating the resulting
370
- // [DW_OP_deref, DW_OP_plus_uconst, offset, DW_OP_deref] debug info to CodeView.
371
- // Creating extra allocas on the stack makes the resulting debug info simple enough
372
- // that LLVM can generate correct CodeView records and thus the values appear in the
373
- // debugger. (#83709)
374
- let should_create_individual_allocas = bx. cx ( ) . sess ( ) . target . is_like_msvc
375
- && self . mir . local_kind ( local) == mir:: LocalKind :: Arg
376
- // LLVM can handle simple things but anything more complex than just a direct
377
- // offset or one indirect offset of 0 is too complex for it to generate CV records
378
- // correctly.
379
- && ( direct_offset != Size :: ZERO
380
- || !matches ! ( & indirect_offsets[ ..] , [ Size :: ZERO ] | [ ] ) ) ;
381
-
382
- if should_create_individual_allocas {
383
- let DebugInfoOffset { direct_offset : _, indirect_offsets : _, result : place } =
384
- calculate_debuginfo_offset ( bx, local, & var, base) ;
385
-
386
- // Create a variable which will be a pointer to the actual value
387
- let ptr_ty = bx
388
- . tcx ( )
389
- . mk_ptr ( ty:: TypeAndMut { mutbl : mir:: Mutability :: Mut , ty : place. layout . ty } ) ;
390
- let ptr_layout = bx. layout_of ( ptr_ty) ;
391
- let alloca = PlaceRef :: alloca ( bx, ptr_layout) ;
392
- bx. set_var_name ( alloca. llval , & ( var. name . to_string ( ) + ".dbg.spill" ) ) ;
393
-
394
- // Write the pointer to the variable
395
- bx. store ( place. llval , alloca. llval , alloca. align ) ;
396
-
397
- // Point the debug info to `*alloca` for the current variable
398
- bx. dbg_var_addr ( dbg_var, dbg_loc, alloca. llval , Size :: ZERO , & [ Size :: ZERO ] , None ) ;
399
- } else {
400
- bx. dbg_var_addr (
401
- dbg_var,
402
- dbg_loc,
403
- base. llval ,
404
- direct_offset,
405
- & indirect_offsets,
406
- None ,
407
- ) ;
387
+ self . debug_introduce_local_as_var ( bx, local, base, var) ;
388
+ }
389
+ }
390
+
391
+ fn debug_introduce_local_as_var (
392
+ & self ,
393
+ bx : & mut Bx ,
394
+ local : mir:: Local ,
395
+ mut base : PlaceRef < ' tcx , Bx :: Value > ,
396
+ var : PerLocalVarDebugInfo < ' tcx , Bx :: DIVariable > ,
397
+ ) {
398
+ let Some ( dbg_var) = var. dbg_var else { return } ;
399
+ let Some ( dbg_loc) = self . dbg_loc ( var. source_info ) else { return } ;
400
+
401
+ let DebugInfoOffset { mut direct_offset, indirect_offsets, result : _ } =
402
+ calculate_debuginfo_offset ( bx, local, & var, base. layout ) ;
403
+ let mut indirect_offsets = & indirect_offsets[ ..] ;
404
+
405
+ // When targeting MSVC, create extra allocas for arguments instead of pointing multiple
406
+ // dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
407
+ // not DWARF and LLVM doesn't support translating the resulting
408
+ // [DW_OP_deref, DW_OP_plus_uconst, offset, DW_OP_deref] debug info to CodeView.
409
+ // Creating extra allocas on the stack makes the resulting debug info simple enough
410
+ // that LLVM can generate correct CodeView records and thus the values appear in the
411
+ // debugger. (#83709)
412
+ let should_create_individual_allocas = bx. cx ( ) . sess ( ) . target . is_like_msvc
413
+ && self . mir . local_kind ( local) == mir:: LocalKind :: Arg
414
+ // LLVM can handle simple things but anything more complex than just a direct
415
+ // offset or one indirect offset of 0 is too complex for it to generate CV records
416
+ // correctly.
417
+ && ( direct_offset != Size :: ZERO || !matches ! ( indirect_offsets, [ Size :: ZERO ] | [ ] ) ) ;
418
+
419
+ let create_alloca = |bx : & mut Bx , place : PlaceRef < ' tcx , Bx :: Value > , refcount| {
420
+ // Create a variable which will be a pointer to the actual value
421
+ let ptr_ty = bx
422
+ . tcx ( )
423
+ . mk_ptr ( ty:: TypeAndMut { mutbl : mir:: Mutability :: Mut , ty : place. layout . ty } ) ;
424
+ let ptr_layout = bx. layout_of ( ptr_ty) ;
425
+ let alloca = PlaceRef :: alloca ( bx, ptr_layout) ;
426
+ bx. set_var_name ( alloca. llval , & format ! ( "{}.ref{}.dbg.spill" , var. name, refcount) ) ;
427
+
428
+ // Write the pointer to the variable
429
+ bx. store ( place. llval , alloca. llval , alloca. align ) ;
430
+
431
+ // Point the debug info to `*alloca` for the current variable
432
+ alloca
433
+ } ;
434
+
435
+ if var. references > 0 {
436
+ base = calculate_debuginfo_offset ( bx, local, & var, base) . result ;
437
+
438
+ // Point the debug info to `&...&base == alloca` for the current variable
439
+ for refcount in 0 ..var. references {
440
+ base = create_alloca ( bx, base, refcount) ;
408
441
}
442
+
443
+ direct_offset = Size :: ZERO ;
444
+ indirect_offsets = & [ ] ;
445
+ } else if should_create_individual_allocas {
446
+ let place = calculate_debuginfo_offset ( bx, local, & var, base) . result ;
447
+
448
+ // Point the debug info to `*alloca` for the current variable
449
+ base = create_alloca ( bx, place, 0 ) ;
450
+ direct_offset = Size :: ZERO ;
451
+ indirect_offsets = & [ Size :: ZERO ] ;
409
452
}
453
+
454
+ bx. dbg_var_addr ( dbg_var, dbg_loc, base. llval , direct_offset, indirect_offsets, None ) ;
410
455
}
411
456
412
457
pub fn debug_introduce_locals ( & self , bx : & mut Bx ) {
@@ -439,7 +484,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
439
484
} ;
440
485
441
486
let dbg_var = dbg_scope_and_span. map ( |( dbg_scope, _, span) | {
442
- let ( var_ty, var_kind) = match var. value {
487
+ let ( mut var_ty, var_kind) = match var. value {
443
488
mir:: VarDebugInfoContents :: Place ( place) => {
444
489
let var_ty = self . monomorphized_place_ty ( place. as_ref ( ) ) ;
445
490
let var_kind = if let Some ( arg_index) = var. argument_index
@@ -476,6 +521,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
476
521
}
477
522
} ;
478
523
524
+ for _ in 0 ..var. references {
525
+ var_ty =
526
+ bx. tcx ( ) . mk_ptr ( ty:: TypeAndMut { mutbl : mir:: Mutability :: Mut , ty : var_ty } ) ;
527
+ }
528
+
479
529
self . cx . create_dbg_var ( var. name , var_ty, dbg_scope, var_kind, span)
480
530
} ) ;
481
531
@@ -487,6 +537,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
487
537
dbg_var,
488
538
fragment : None ,
489
539
projection : place. projection ,
540
+ references : var. references ,
490
541
} ) ;
491
542
}
492
543
mir:: VarDebugInfoContents :: Const ( c) => {
@@ -540,6 +591,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
540
591
Some ( fragment_start..fragment_start + fragment_layout. size )
541
592
} ,
542
593
projection : place. projection ,
594
+ references : var. references ,
543
595
} ) ;
544
596
}
545
597
}
0 commit comments