@@ -17,8 +17,6 @@ use super::operand::{OperandRef, OperandValue};
1717use super :: place:: PlaceRef ;
1818use super :: { FunctionCx , LocalRef } ;
1919
20- use std:: ops:: Range ;
21-
2220pub struct FunctionDebugContext < ' tcx , S , L > {
2321 /// Maps from source code to the corresponding debug info scope.
2422 pub scopes : IndexVec < mir:: SourceScope , DebugScope < S , L > > ,
@@ -36,17 +34,17 @@ pub enum VariableKind {
3634#[ derive( Clone ) ]
3735pub struct PerLocalVarDebugInfo < ' tcx , D > {
3836 pub name : Symbol ,
37+ pub ty : Ty < ' tcx > ,
3938 pub source_info : mir:: SourceInfo ,
4039
4140 /// `DIVariable` returned by `create_dbg_var`.
4241 pub dbg_var : Option < D > ,
4342
44- /// Byte range in the `dbg_var` covered by this fragment,
45- /// if this is a fragment of a composite `VarDebugInfo`.
46- pub fragment : Option < Range < Size > > ,
47-
4843 /// `.place.projection` from `mir::VarDebugInfo`.
49- pub projection : & ' tcx ty:: List < mir:: PlaceElem < ' tcx > > ,
44+ pub projection : & ' tcx [ mir:: PlaceElem < ' tcx > ] ,
45+
46+ /// Projection from fragment debuginfo.
47+ pub fragment : & ' tcx [ mir:: PlaceElem < ' tcx > ] ,
5048}
5149
5250#[ derive( Clone , Copy , Debug ) ]
@@ -149,6 +147,8 @@ struct DebugInfoOffset<T> {
149147 indirect_offsets : Vec < Size > ,
150148 /// The final location debuginfo should point to.
151149 result : T ,
150+ /// Whether the final location is a fragment of a larger contiguous projection.
151+ fragment : bool ,
152152}
153153
154154fn calculate_debuginfo_offset <
@@ -165,17 +165,21 @@ fn calculate_debuginfo_offset<
165165 // FIXME(eddyb) use smallvec here.
166166 let mut indirect_offsets = vec ! [ ] ;
167167 let mut place = base;
168+ let mut fragment = false ;
168169
169170 for elem in projection {
171+ let layout = place. layout ( ) ;
170172 match * elem {
171173 mir:: ProjectionElem :: Deref => {
172174 indirect_offsets. push ( Size :: ZERO ) ;
173175 place = place. deref ( bx) ;
176+ fragment = false ;
174177 }
175178 mir:: ProjectionElem :: Field ( field, _) => {
176179 let offset = indirect_offsets. last_mut ( ) . unwrap_or ( & mut direct_offset) ;
177180 * offset += place. layout ( ) . fields . offset ( field. index ( ) ) ;
178181 place = place. project_field ( bx, field) ;
182+ fragment |= place. layout ( ) . size != layout. size ;
179183 }
180184 mir:: ProjectionElem :: Downcast ( _, variant) => {
181185 place = place. downcast ( bx, variant) ;
@@ -191,16 +195,17 @@ fn calculate_debuginfo_offset<
191195 } ;
192196 * offset += stride * index;
193197 place = place. project_constant_index ( bx, index) ;
198+ fragment |= place. layout ( ) . size != layout. size ;
194199 }
195200 _ => {
196201 // Sanity check for `can_use_in_debuginfo`.
197202 debug_assert ! ( !elem. can_use_in_debuginfo( ) ) ;
198- bug ! ( "unsupported var debuginfo projection `{:?}`" , projection)
203+ bug ! ( "unsupported var debuginfo place `{:?}`" , projection)
199204 }
200205 }
201206 }
202207
203- DebugInfoOffset { direct_offset, indirect_offsets, result : place }
208+ DebugInfoOffset { direct_offset, indirect_offsets, result : place, fragment }
204209}
205210
206211impl < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > FunctionCx < ' a , ' tcx , Bx > {
@@ -295,14 +300,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
295300 } else {
296301 let name = kw:: Empty ;
297302 let decl = & self . mir . local_decls [ local] ;
303+ let arg_ty = self . monomorphize ( decl. ty ) ;
304+
298305 let dbg_var = if full_debug_info {
299306 self . adjusted_span_and_dbg_scope ( decl. source_info ) . map (
300307 |( dbg_scope, _, span) | {
301308 // FIXME(eddyb) is this `+ 1` needed at all?
302309 let kind = VariableKind :: ArgumentVariable ( arg_index + 1 ) ;
303310
304- let arg_ty = self . monomorphize ( decl. ty ) ;
305-
306311 self . cx . create_dbg_var ( name, arg_ty, dbg_scope, kind, span)
307312 } ,
308313 )
@@ -312,10 +317,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
312317
313318 Some ( PerLocalVarDebugInfo {
314319 name,
320+ ty : arg_ty,
315321 source_info : decl. source_info ,
316322 dbg_var,
317- fragment : None ,
318- projection : ty :: List :: empty ( ) ,
323+ fragment : & [ ] ,
324+ projection : & [ ] ,
319325 } )
320326 }
321327 } else {
@@ -397,8 +403,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
397403 let Some ( dbg_var) = var. dbg_var else { return } ;
398404 let Some ( dbg_loc) = self . dbg_loc ( var. source_info ) else { return } ;
399405
400- let DebugInfoOffset { direct_offset, indirect_offsets, result : _ } =
406+ let DebugInfoOffset { mut direct_offset, indirect_offsets, result : _ , fragment : _ } =
401407 calculate_debuginfo_offset ( bx, var. projection , base. layout ) ;
408+ let mut indirect_offsets = & indirect_offsets[ ..] ;
402409
403410 // When targeting MSVC, create extra allocas for arguments instead of pointing multiple
404411 // dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
@@ -415,8 +422,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
415422 && ( direct_offset != Size :: ZERO || !matches ! ( & indirect_offsets[ ..] , [ Size :: ZERO ] | [ ] ) ) ;
416423
417424 if should_create_individual_allocas {
418- let DebugInfoOffset { direct_offset : _, indirect_offsets : _, result : place } =
419- calculate_debuginfo_offset ( bx, var. projection , base) ;
425+ let DebugInfoOffset {
426+ direct_offset : _,
427+ indirect_offsets : _,
428+ fragment : _,
429+ result : place,
430+ } = calculate_debuginfo_offset ( bx, var. projection , base) ;
420431
421432 // Create a variable which will be a pointer to the actual value
422433 let ptr_ty = Ty :: new_ptr (
@@ -431,24 +442,61 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
431442 bx. store ( place. llval , alloca. llval , alloca. align ) ;
432443
433444 // Point the debug info to `*alloca` for the current variable
434- bx. dbg_var_addr (
435- dbg_var,
436- dbg_loc,
437- alloca. llval ,
438- Size :: ZERO ,
439- & [ Size :: ZERO ] ,
440- var. fragment ,
441- ) ;
445+ direct_offset = Size :: ZERO ;
446+ indirect_offsets = & [ Size :: ZERO ] ;
447+ }
448+
449+ self . debug_introduce_place (
450+ bx,
451+ dbg_var,
452+ dbg_loc,
453+ base. llval ,
454+ direct_offset,
455+ indirect_offsets,
456+ var. ty ,
457+ var. fragment ,
458+ ) ;
459+ }
460+
461+ fn debug_introduce_place (
462+ & self ,
463+ bx : & mut Bx ,
464+ dbg_var : Bx :: DIVariable ,
465+ dbg_loc : Bx :: DILocation ,
466+ base : Bx :: Value ,
467+ direct_offset : Size ,
468+ mut indirect_offsets : & [ Size ] ,
469+ ty : Ty < ' tcx > ,
470+ fragment : & [ mir:: PlaceElem < ' tcx > ] ,
471+ ) {
472+ let DebugInfoOffset {
473+ direct_offset : fragment_offset,
474+ indirect_offsets : mut fragment_indirect,
475+ result : fragment_layout,
476+ fragment,
477+ } = calculate_debuginfo_offset ( bx, fragment, bx. layout_of ( ty) ) ;
478+
479+ let fragment = if fragment_layout. size == Size :: ZERO {
480+ return ;
481+ } else if fragment {
482+ Some ( fragment_offset..fragment_offset + fragment_layout. size )
442483 } else {
443- bx. dbg_var_addr (
444- dbg_var,
445- dbg_loc,
446- base. llval ,
447- direct_offset,
448- & indirect_offsets,
449- var. fragment ,
450- ) ;
484+ None
485+ } ;
486+
487+ while let Some ( last_inv) = fragment_indirect. pop ( ) {
488+ if let Some ( ( & last_off, rest) ) = indirect_offsets. split_last ( )
489+ && last_inv == last_off
490+ {
491+ indirect_offsets = rest;
492+ continue ;
493+ } else {
494+ return ;
495+ }
451496 }
497+ assert ! ( fragment_indirect. is_empty( ) ) ;
498+
499+ bx. dbg_var_addr ( dbg_var, dbg_loc, base, direct_offset, indirect_offsets, fragment) ;
452500 }
453501
454502 pub fn debug_introduce_locals ( & self , bx : & mut Bx ) {
@@ -520,32 +568,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
520568 self . cx . create_dbg_var ( var. name , var_ty, dbg_scope, var_kind, span)
521569 } ) ;
522570
523- let fragment = if let Some ( ref fragment) = var. composite {
524- let var_layout = self . cx . layout_of ( var_ty) ;
525-
526- let DebugInfoOffset { direct_offset, indirect_offsets, result : fragment_layout } =
527- calculate_debuginfo_offset ( bx, & fragment. projection , var_layout) ;
528- debug_assert ! ( indirect_offsets. is_empty( ) ) ;
529-
530- if fragment_layout. size == Size :: ZERO {
531- // Fragment is a ZST, so does not represent anything. Avoid generating anything
532- // as this may conflict with a fragment that covers the entire variable.
533- continue ;
534- } else if fragment_layout. size == var_layout. size {
535- // Fragment covers entire variable, so as far as
536- // DWARF is concerned, it's not really a fragment.
537- None
538- } else {
539- Some ( direct_offset..direct_offset + fragment_layout. size )
540- }
541- } else {
542- None
543- } ;
571+ let fragment =
572+ if let Some ( ref fragment) = var. composite { & fragment. projection [ ..] } else { & [ ] } ;
544573
545574 match var. value {
546575 mir:: VarDebugInfoContents :: Place ( place) => {
547576 per_local[ place. local ] . push ( PerLocalVarDebugInfo {
548577 name : var. name ,
578+ ty : var_ty,
549579 source_info : var. source_info ,
550580 dbg_var,
551581 fragment,
@@ -561,7 +591,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
561591 let base =
562592 Self :: spill_operand_to_stack ( operand, Some ( var. name . to_string ( ) ) , bx) ;
563593
564- bx. dbg_var_addr ( dbg_var, dbg_loc, base. llval , Size :: ZERO , & [ ] , fragment) ;
594+ self . debug_introduce_place (
595+ bx,
596+ dbg_var,
597+ dbg_loc,
598+ base. llval ,
599+ Size :: ZERO ,
600+ & [ ] ,
601+ var_ty,
602+ fragment,
603+ ) ;
565604 }
566605 }
567606 }
0 commit comments