@@ -8,7 +8,7 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
88use rustc_session:: config:: DebugInfo ;
99use rustc_span:: symbol:: { kw, Symbol } ;
1010use rustc_span:: { BytePos , Span } ;
11- use rustc_target:: abi:: { Abi , FieldIdx , Size , VariantIdx } ;
11+ use rustc_target:: abi:: { Abi , FieldIdx , FieldsShape , Size , VariantIdx } ;
1212
1313use super :: operand:: { OperandRef , OperandValue } ;
1414use super :: place:: PlaceRef ;
@@ -41,6 +41,9 @@ pub struct PerLocalVarDebugInfo<'tcx, D> {
4141
4242 /// `.place.projection` from `mir::VarDebugInfo`.
4343 pub projection : & ' tcx ty:: List < mir:: PlaceElem < ' tcx > > ,
44+
45+ /// `references` from `mir::VarDebugInfo`.
46+ pub references : u8 ,
4447}
4548
4649#[ derive( Clone , Copy , Debug ) ]
@@ -80,6 +83,7 @@ trait DebugInfoOffsetLocation<'tcx, Bx> {
8083 fn deref ( & self , bx : & mut Bx ) -> Self ;
8184 fn layout ( & self ) -> TyAndLayout < ' tcx > ;
8285 fn project_field ( & self , bx : & mut Bx , field : FieldIdx ) -> Self ;
86+ fn project_constant_index ( & self , bx : & mut Bx , offset : u64 ) -> Self ;
8387 fn downcast ( & self , bx : & mut Bx , variant : VariantIdx ) -> Self ;
8488}
8589
@@ -98,6 +102,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
98102 PlaceRef :: project_field ( * self , bx, field. index ( ) )
99103 }
100104
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+
101110 fn downcast ( & self , bx : & mut Bx , variant : VariantIdx ) -> Self {
102111 self . project_downcast ( bx, variant)
103112 }
@@ -120,6 +129,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
120129 self . field ( bx. cx ( ) , field. index ( ) )
121130 }
122131
132+ fn project_constant_index ( & self , bx : & mut Bx , index : u64 ) -> Self {
133+ self . field ( bx. cx ( ) , index as usize )
134+ }
135+
123136 fn downcast ( & self , bx : & mut Bx , variant : VariantIdx ) -> Self {
124137 self . for_variant ( bx. cx ( ) , variant)
125138 }
@@ -165,6 +178,18 @@ fn calculate_debuginfo_offset<
165178 mir:: ProjectionElem :: Downcast ( _, variant) => {
166179 place = place. downcast ( bx, variant) ;
167180 }
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+ }
168193 _ => {
169194 // Sanity check for `can_use_in_debuginfo`.
170195 debug_assert ! ( !elem. can_use_in_debuginfo( ) ) ;
@@ -293,6 +318,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
293318 dbg_var,
294319 fragment : None ,
295320 projection : ty:: List :: empty ( ) ,
321+ references : 0 ,
296322 } )
297323 }
298324 } else {
@@ -358,55 +384,74 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
358384 let vars = vars. iter ( ) . cloned ( ) . chain ( fallback_var) ;
359385
360386 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) ;
408441 }
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 ] ;
409452 }
453+
454+ bx. dbg_var_addr ( dbg_var, dbg_loc, base. llval , direct_offset, indirect_offsets, None ) ;
410455 }
411456
412457 pub fn debug_introduce_locals ( & self , bx : & mut Bx ) {
@@ -439,7 +484,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
439484 } ;
440485
441486 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 {
443488 mir:: VarDebugInfoContents :: Place ( place) => {
444489 let var_ty = self . monomorphized_place_ty ( place. as_ref ( ) ) ;
445490 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> {
476521 }
477522 } ;
478523
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+
479529 self . cx . create_dbg_var ( var. name , var_ty, dbg_scope, var_kind, span)
480530 } ) ;
481531
@@ -487,6 +537,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
487537 dbg_var,
488538 fragment : None ,
489539 projection : place. projection ,
540+ references : var. references ,
490541 } ) ;
491542 }
492543 mir:: VarDebugInfoContents :: Const ( c) => {
@@ -540,6 +591,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
540591 Some ( fragment_start..fragment_start + fragment_layout. size )
541592 } ,
542593 projection : place. projection ,
594+ references : var. references ,
543595 } ) ;
544596 }
545597 }
0 commit comments