@@ -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 > {
@@ -290,14 +295,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
290295 } else {
291296 let name = kw:: Empty ;
292297 let decl = & self . mir . local_decls [ local] ;
298+ let arg_ty = self . monomorphize ( decl. ty ) ;
299+
293300 let dbg_var = if full_debug_info {
294301 self . adjusted_span_and_dbg_scope ( decl. source_info ) . map (
295302 |( dbg_scope, _, span) | {
296303 // FIXME(eddyb) is this `+ 1` needed at all?
297304 let kind = VariableKind :: ArgumentVariable ( arg_index + 1 ) ;
298305
299- let arg_ty = self . monomorphize ( decl. ty ) ;
300-
301306 self . cx . create_dbg_var ( name, arg_ty, dbg_scope, kind, span)
302307 } ,
303308 )
@@ -307,10 +312,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
307312
308313 Some ( PerLocalVarDebugInfo {
309314 name,
315+ ty : arg_ty,
310316 source_info : decl. source_info ,
311317 dbg_var,
312- fragment : None ,
313- projection : ty :: List :: empty ( ) ,
318+ fragment : & [ ] ,
319+ projection : & [ ] ,
314320 } )
315321 }
316322 } else {
@@ -392,8 +398,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
392398 let Some ( dbg_var) = var. dbg_var else { return } ;
393399 let Some ( dbg_loc) = self . dbg_loc ( var. source_info ) else { return } ;
394400
395- let DebugInfoOffset { direct_offset, indirect_offsets, result : _ } =
401+ let DebugInfoOffset { mut direct_offset, indirect_offsets, result : _ , fragment : _ } =
396402 calculate_debuginfo_offset ( bx, var. projection , base. layout ) ;
403+ let mut indirect_offsets = & indirect_offsets[ ..] ;
397404
398405 // When targeting MSVC, create extra allocas for arguments instead of pointing multiple
399406 // dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
@@ -410,8 +417,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
410417 && ( direct_offset != Size :: ZERO || !matches ! ( & indirect_offsets[ ..] , [ Size :: ZERO ] | [ ] ) ) ;
411418
412419 if should_create_individual_allocas {
413- let DebugInfoOffset { direct_offset : _, indirect_offsets : _, result : place } =
414- calculate_debuginfo_offset ( bx, var. projection , base) ;
420+ let DebugInfoOffset {
421+ direct_offset : _,
422+ indirect_offsets : _,
423+ fragment : _,
424+ result : place,
425+ } = calculate_debuginfo_offset ( bx, var. projection , base) ;
415426
416427 // Create a variable which will be a pointer to the actual value
417428 let ptr_ty = Ty :: new_ptr (
@@ -426,24 +437,53 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
426437 bx. store ( place. llval , alloca. llval , alloca. align ) ;
427438
428439 // Point the debug info to `*alloca` for the current variable
429- bx. dbg_var_addr (
430- dbg_var,
431- dbg_loc,
432- alloca. llval ,
433- Size :: ZERO ,
434- & [ Size :: ZERO ] ,
435- var. fragment ,
436- ) ;
440+ direct_offset = Size :: ZERO ;
441+ indirect_offsets = & [ Size :: ZERO ] ;
442+ }
443+
444+ self . debug_introduce_place (
445+ bx,
446+ dbg_var,
447+ dbg_loc,
448+ base. llval ,
449+ direct_offset,
450+ indirect_offsets,
451+ var. ty ,
452+ var. fragment ,
453+ ) ;
454+ }
455+
456+ fn debug_introduce_place (
457+ & self ,
458+ bx : & mut Bx ,
459+ dbg_var : Bx :: DIVariable ,
460+ dbg_loc : Bx :: DILocation ,
461+ base : Bx :: Value ,
462+ direct_offset : Size ,
463+ indirect_offsets : & [ Size ] ,
464+ ty : Ty < ' tcx > ,
465+ fragment : & [ mir:: PlaceElem < ' tcx > ] ,
466+ ) {
467+ let DebugInfoOffset {
468+ direct_offset : fragment_offset,
469+ indirect_offsets : fragment_indirect,
470+ result : fragment_layout,
471+ fragment,
472+ } = calculate_debuginfo_offset ( bx, fragment, bx. layout_of ( ty) ) ;
473+
474+ let fragment = if fragment_layout. size == Size :: ZERO {
475+ return ;
476+ } else if fragment {
477+ Some ( fragment_offset..fragment_offset + fragment_layout. size )
437478 } else {
438- bx. dbg_var_addr (
439- dbg_var,
440- dbg_loc,
441- base. llval ,
442- direct_offset,
443- & indirect_offsets,
444- var. fragment ,
445- ) ;
479+ None
480+ } ;
481+
482+ if !fragment_indirect. is_empty ( ) {
483+ return ;
446484 }
485+
486+ bx. dbg_var_addr ( dbg_var, dbg_loc, base, direct_offset, indirect_offsets, fragment) ;
447487 }
448488
449489 pub fn debug_introduce_locals ( & self , bx : & mut Bx ) {
@@ -515,32 +555,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
515555 self . cx . create_dbg_var ( var. name , var_ty, dbg_scope, var_kind, span)
516556 } ) ;
517557
518- let fragment = if let Some ( ref fragment) = var. composite {
519- let var_layout = self . cx . layout_of ( var_ty) ;
520-
521- let DebugInfoOffset { direct_offset, indirect_offsets, result : fragment_layout } =
522- calculate_debuginfo_offset ( bx, & fragment. projection , var_layout) ;
523- debug_assert ! ( indirect_offsets. is_empty( ) ) ;
524-
525- if fragment_layout. size == Size :: ZERO {
526- // Fragment is a ZST, so does not represent anything. Avoid generating anything
527- // as this may conflict with a fragment that covers the entire variable.
528- continue ;
529- } else if fragment_layout. size == var_layout. size {
530- // Fragment covers entire variable, so as far as
531- // DWARF is concerned, it's not really a fragment.
532- None
533- } else {
534- Some ( direct_offset..direct_offset + fragment_layout. size )
535- }
536- } else {
537- None
538- } ;
558+ let fragment =
559+ if let Some ( ref fragment) = var. composite { & fragment. projection [ ..] } else { & [ ] } ;
539560
540561 match var. value {
541562 mir:: VarDebugInfoContents :: Place ( place) => {
542563 per_local[ place. local ] . push ( PerLocalVarDebugInfo {
543564 name : var. name ,
565+ ty : var_ty,
544566 source_info : var. source_info ,
545567 dbg_var,
546568 fragment,
@@ -556,7 +578,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
556578 let base =
557579 Self :: spill_operand_to_stack ( operand, Some ( var. name . to_string ( ) ) , bx) ;
558580
559- bx. dbg_var_addr ( dbg_var, dbg_loc, base. llval , Size :: ZERO , & [ ] , fragment) ;
581+ self . debug_introduce_place (
582+ bx,
583+ dbg_var,
584+ dbg_loc,
585+ base. llval ,
586+ Size :: ZERO ,
587+ & [ ] ,
588+ var_ty,
589+ fragment,
590+ ) ;
560591 }
561592 }
562593 }
0 commit comments