@@ -3,7 +3,6 @@ use rustc_data_structures::fx::FxHashMap;
33use rustc_index:: IndexVec ;
44use rustc_middle:: middle:: codegen_fn_attrs:: CodegenFnAttrFlags ;
55use rustc_middle:: mir;
6- use rustc_middle:: ty;
76use rustc_middle:: ty:: layout:: TyAndLayout ;
87use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf } ;
98use rustc_middle:: ty:: Instance ;
@@ -17,8 +16,6 @@ use super::operand::{OperandRef, OperandValue};
1716use super :: place:: PlaceRef ;
1817use super :: { FunctionCx , LocalRef } ;
1918
20- use std:: ops:: Range ;
21-
2219pub struct FunctionDebugContext < ' tcx , S , L > {
2320 /// Maps from source code to the corresponding debug info scope.
2421 pub scopes : IndexVec < mir:: SourceScope , DebugScope < S , L > > ,
@@ -36,17 +33,17 @@ pub enum VariableKind {
3633#[ derive( Clone ) ]
3734pub struct PerLocalVarDebugInfo < ' tcx , D > {
3835 pub name : Symbol ,
36+ pub ty : Ty < ' tcx > ,
3937 pub source_info : mir:: SourceInfo ,
4038
4139 /// `DIVariable` returned by `create_dbg_var`.
4240 pub dbg_var : Option < D > ,
4341
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-
4842 /// `.place.projection` from `mir::VarDebugInfo`.
49- pub projection : & ' tcx ty:: List < mir:: PlaceElem < ' tcx > > ,
43+ pub projection : & ' tcx [ mir:: PlaceElem < ' tcx > ] ,
44+
45+ /// Projection from fragment debuginfo.
46+ pub fragment : & ' tcx [ mir:: PlaceElem < ' tcx > ] ,
5047}
5148
5249#[ derive( Clone , Copy , Debug ) ]
@@ -149,6 +146,8 @@ struct DebugInfoOffset<T> {
149146 indirect_offsets : Vec < Size > ,
150147 /// The final location debuginfo should point to.
151148 result : T ,
149+ /// Whether the final location is a fragment of a larger contiguous projection.
150+ fragment : bool ,
152151}
153152
154153fn calculate_debuginfo_offset <
@@ -165,17 +164,21 @@ fn calculate_debuginfo_offset<
165164 // FIXME(eddyb) use smallvec here.
166165 let mut indirect_offsets = vec ! [ ] ;
167166 let mut place = base;
167+ let mut fragment = false ;
168168
169169 for elem in projection {
170+ let layout = place. layout ( ) ;
170171 match * elem {
171172 mir:: ProjectionElem :: Deref => {
172173 indirect_offsets. push ( Size :: ZERO ) ;
173174 place = place. deref ( bx) ;
175+ fragment = false ;
174176 }
175177 mir:: ProjectionElem :: Field ( field, _) => {
176178 let offset = indirect_offsets. last_mut ( ) . unwrap_or ( & mut direct_offset) ;
177179 * offset += place. layout ( ) . fields . offset ( field. index ( ) ) ;
178180 place = place. project_field ( bx, field) ;
181+ fragment |= place. layout ( ) . size != layout. size ;
179182 }
180183 mir:: ProjectionElem :: Downcast ( _, variant) => {
181184 place = place. downcast ( bx, variant) ;
@@ -191,16 +194,17 @@ fn calculate_debuginfo_offset<
191194 } ;
192195 * offset += stride * index;
193196 place = place. project_constant_index ( bx, index) ;
197+ fragment |= place. layout ( ) . size != layout. size ;
194198 }
195199 _ => {
196200 // Sanity check for `can_use_in_debuginfo`.
197201 debug_assert ! ( !elem. can_use_in_debuginfo( ) ) ;
198- bug ! ( "unsupported var debuginfo projection `{:?}`" , projection)
202+ bug ! ( "unsupported var debuginfo place `{:?}`" , projection)
199203 }
200204 }
201205 }
202206
203- DebugInfoOffset { direct_offset, indirect_offsets, result : place }
207+ DebugInfoOffset { direct_offset, indirect_offsets, result : place, fragment }
204208}
205209
206210impl < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > FunctionCx < ' a , ' tcx , Bx > {
@@ -290,14 +294,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
290294 } else {
291295 let name = kw:: Empty ;
292296 let decl = & self . mir . local_decls [ local] ;
297+ let arg_ty = self . monomorphize ( decl. ty ) ;
298+
293299 let dbg_var = if full_debug_info {
294300 self . adjusted_span_and_dbg_scope ( decl. source_info ) . map (
295301 |( dbg_scope, _, span) | {
296302 // FIXME(eddyb) is this `+ 1` needed at all?
297303 let kind = VariableKind :: ArgumentVariable ( arg_index + 1 ) ;
298304
299- let arg_ty = self . monomorphize ( decl. ty ) ;
300-
301305 self . cx . create_dbg_var ( name, arg_ty, dbg_scope, kind, span)
302306 } ,
303307 )
@@ -307,10 +311,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
307311
308312 Some ( PerLocalVarDebugInfo {
309313 name,
314+ ty : arg_ty,
310315 source_info : decl. source_info ,
311316 dbg_var,
312- fragment : None ,
313- projection : ty :: List :: empty ( ) ,
317+ fragment : & [ ] ,
318+ projection : & [ ] ,
314319 } )
315320 }
316321 } else {
@@ -392,8 +397,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
392397 let Some ( dbg_var) = var. dbg_var else { return } ;
393398 let Some ( dbg_loc) = self . dbg_loc ( var. source_info ) else { return } ;
394399
395- let DebugInfoOffset { direct_offset, indirect_offsets, result : _ } =
400+ let DebugInfoOffset { mut direct_offset, indirect_offsets, result : _ , fragment : _ } =
396401 calculate_debuginfo_offset ( bx, var. projection , base. layout ) ;
402+ let mut indirect_offsets = & indirect_offsets[ ..] ;
397403
398404 // When targeting MSVC, create extra allocas for arguments instead of pointing multiple
399405 // dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
@@ -410,8 +416,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
410416 && ( direct_offset != Size :: ZERO || !matches ! ( & indirect_offsets[ ..] , [ Size :: ZERO ] | [ ] ) ) ;
411417
412418 if should_create_individual_allocas {
413- let DebugInfoOffset { direct_offset : _, indirect_offsets : _, result : place } =
414- calculate_debuginfo_offset ( bx, var. projection , base) ;
419+ let DebugInfoOffset {
420+ direct_offset : _,
421+ indirect_offsets : _,
422+ fragment : _,
423+ result : place,
424+ } = calculate_debuginfo_offset ( bx, var. projection , base) ;
415425
416426 // Create a variable which will be a pointer to the actual value
417427 let ptr_ty = Ty :: new_mut_ptr ( bx. tcx ( ) , place. layout . ty ) ;
@@ -423,24 +433,53 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
423433 bx. store ( place. llval , alloca. llval , alloca. align ) ;
424434
425435 // Point the debug info to `*alloca` for the current variable
426- bx. dbg_var_addr (
427- dbg_var,
428- dbg_loc,
429- alloca. llval ,
430- Size :: ZERO ,
431- & [ Size :: ZERO ] ,
432- var. fragment ,
433- ) ;
436+ direct_offset = Size :: ZERO ;
437+ indirect_offsets = & [ Size :: ZERO ] ;
438+ }
439+
440+ self . debug_introduce_place (
441+ bx,
442+ dbg_var,
443+ dbg_loc,
444+ base. llval ,
445+ direct_offset,
446+ indirect_offsets,
447+ var. ty ,
448+ var. fragment ,
449+ ) ;
450+ }
451+
452+ fn debug_introduce_place (
453+ & self ,
454+ bx : & mut Bx ,
455+ dbg_var : Bx :: DIVariable ,
456+ dbg_loc : Bx :: DILocation ,
457+ base : Bx :: Value ,
458+ direct_offset : Size ,
459+ indirect_offsets : & [ Size ] ,
460+ ty : Ty < ' tcx > ,
461+ fragment : & [ mir:: PlaceElem < ' tcx > ] ,
462+ ) {
463+ let DebugInfoOffset {
464+ direct_offset : fragment_offset,
465+ indirect_offsets : fragment_indirect,
466+ result : fragment_layout,
467+ fragment,
468+ } = calculate_debuginfo_offset ( bx, fragment, bx. layout_of ( ty) ) ;
469+
470+ let fragment = if fragment_layout. size == Size :: ZERO {
471+ return ;
472+ } else if fragment {
473+ Some ( fragment_offset..fragment_offset + fragment_layout. size )
434474 } else {
435- bx. dbg_var_addr (
436- dbg_var,
437- dbg_loc,
438- base. llval ,
439- direct_offset,
440- & indirect_offsets,
441- var. fragment ,
442- ) ;
475+ None
476+ } ;
477+
478+ if !fragment_indirect. is_empty ( ) {
479+ return ;
443480 }
481+
482+ bx. dbg_var_addr ( dbg_var, dbg_loc, base, direct_offset, indirect_offsets, fragment) ;
444483 }
445484
446485 pub fn debug_introduce_locals ( & self , bx : & mut Bx ) {
@@ -512,32 +551,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
512551 self . cx . create_dbg_var ( var. name , var_ty, dbg_scope, var_kind, span)
513552 } ) ;
514553
515- let fragment = if let Some ( ref fragment) = var. composite {
516- let var_layout = self . cx . layout_of ( var_ty) ;
517-
518- let DebugInfoOffset { direct_offset, indirect_offsets, result : fragment_layout } =
519- calculate_debuginfo_offset ( bx, & fragment. projection , var_layout) ;
520- debug_assert ! ( indirect_offsets. is_empty( ) ) ;
521-
522- if fragment_layout. size == Size :: ZERO {
523- // Fragment is a ZST, so does not represent anything. Avoid generating anything
524- // as this may conflict with a fragment that covers the entire variable.
525- continue ;
526- } else if fragment_layout. size == var_layout. size {
527- // Fragment covers entire variable, so as far as
528- // DWARF is concerned, it's not really a fragment.
529- None
530- } else {
531- Some ( direct_offset..direct_offset + fragment_layout. size )
532- }
533- } else {
534- None
535- } ;
554+ let fragment =
555+ if let Some ( ref fragment) = var. composite { & fragment. projection [ ..] } else { & [ ] } ;
536556
537557 match var. value {
538558 mir:: VarDebugInfoContents :: Place ( place) => {
539559 per_local[ place. local ] . push ( PerLocalVarDebugInfo {
540560 name : var. name ,
561+ ty : var_ty,
541562 source_info : var. source_info ,
542563 dbg_var,
543564 fragment,
@@ -553,7 +574,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
553574 let base =
554575 Self :: spill_operand_to_stack ( operand, Some ( var. name . to_string ( ) ) , bx) ;
555576
556- bx. dbg_var_addr ( dbg_var, dbg_loc, base. llval , Size :: ZERO , & [ ] , fragment) ;
577+ self . debug_introduce_place (
578+ bx,
579+ dbg_var,
580+ dbg_loc,
581+ base. llval ,
582+ Size :: ZERO ,
583+ & [ ] ,
584+ var_ty,
585+ fragment,
586+ ) ;
557587 }
558588 }
559589 }
0 commit comments