@@ -14,6 +14,8 @@ use super::operand::{OperandRef, OperandValue};
1414use super :: place:: PlaceRef ;
1515use super :: { FunctionCx , LocalRef } ;
1616
17+ use std:: ops:: Range ;
18+
1719pub struct FunctionDebugContext < S , L > {
1820 pub scopes : IndexVec < mir:: SourceScope , DebugScope < S , L > > ,
1921}
@@ -25,14 +27,18 @@ pub enum VariableKind {
2527}
2628
2729/// Like `mir::VarDebugInfo`, but within a `mir::Local`.
28- #[ derive( Copy , Clone ) ]
30+ #[ derive( Clone ) ]
2931pub struct PerLocalVarDebugInfo < ' tcx , D > {
3032 pub name : Symbol ,
3133 pub source_info : mir:: SourceInfo ,
3234
3335 /// `DIVariable` returned by `create_dbg_var`.
3436 pub dbg_var : Option < D > ,
3537
38+ /// Byte range in the `dbg_var` covered by this fragment,
39+ /// if this is a fragment of a composite `VarDebugInfo`.
40+ pub fragment : Option < Range < Size > > ,
41+
3642 /// `.place.projection` from `mir::VarDebugInfo`.
3743 pub projection : & ' tcx ty:: List < mir:: PlaceElem < ' tcx > > ,
3844}
@@ -145,7 +151,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
145151 Some ( per_local) => & per_local[ local] ,
146152 None => return ,
147153 } ;
148- let whole_local_var = vars. iter ( ) . find ( |var| var. projection . is_empty ( ) ) . copied ( ) ;
154+ let whole_local_var = vars. iter ( ) . find ( |var| var. projection . is_empty ( ) ) . cloned ( ) ;
149155 let has_proj = || vars. iter ( ) . any ( |var| !var. projection . is_empty ( ) ) ;
150156
151157 let fallback_var = if self . mir . local_kind ( local) == mir:: LocalKind :: Arg {
@@ -187,6 +193,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
187193 name,
188194 source_info : decl. source_info ,
189195 dbg_var,
196+ fragment : None ,
190197 projection : ty:: List :: empty ( ) ,
191198 } )
192199 }
@@ -199,7 +206,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
199206 let name = if bx. sess ( ) . fewer_names ( ) {
200207 None
201208 } else {
202- Some ( match whole_local_var. or ( fallback_var) {
209+ Some ( match whole_local_var. or ( fallback_var. clone ( ) ) {
203210 Some ( var) if var. name != kw:: Empty => var. name . to_string ( ) ,
204211 _ => format ! ( "{:?}" , local) ,
205212 } )
@@ -249,7 +256,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
249256 LocalRef :: UnsizedPlace ( _) => return ,
250257 } ;
251258
252- let vars = vars. iter ( ) . copied ( ) . chain ( fallback_var) ;
259+ let vars = vars. iter ( ) . cloned ( ) . chain ( fallback_var) ;
253260
254261 for var in vars {
255262 let Some ( dbg_var) = var. dbg_var else { continue } ;
@@ -312,9 +319,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
312319 bx. store ( place. llval , alloca. llval , alloca. align ) ;
313320
314321 // Point the debug info to `*alloca` for the current variable
315- bx. dbg_var_addr ( dbg_var, dbg_loc, alloca. llval , Size :: ZERO , & [ Size :: ZERO ] ) ;
322+ bx. dbg_var_addr ( dbg_var, dbg_loc, alloca. llval , Size :: ZERO , & [ Size :: ZERO ] , None ) ;
316323 } else {
317- bx. dbg_var_addr ( dbg_var, dbg_loc, base. llval , direct_offset, & indirect_offsets) ;
324+ bx. dbg_var_addr (
325+ dbg_var,
326+ dbg_loc,
327+ base. llval ,
328+ direct_offset,
329+ & indirect_offsets,
330+ None ,
331+ ) ;
318332 }
319333 }
320334 }
@@ -382,6 +396,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
382396 let ty = self . monomorphize ( c. ty ( ) ) ;
383397 ( ty, VariableKind :: LocalVariable )
384398 }
399+ mir:: VarDebugInfoContents :: Composite { ty, fragments : _ } => {
400+ let ty = self . monomorphize ( ty) ;
401+ ( ty, VariableKind :: LocalVariable )
402+ }
385403 } ;
386404
387405 self . cx . create_dbg_var ( var. name , var_ty, dbg_scope, var_kind, span)
@@ -393,6 +411,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
393411 name : var. name ,
394412 source_info : var. source_info ,
395413 dbg_var,
414+ fragment : None ,
396415 projection : place. projection ,
397416 } ) ;
398417 }
@@ -407,10 +426,48 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
407426 bx,
408427 ) ;
409428
410- bx. dbg_var_addr ( dbg_var, dbg_loc, base. llval , Size :: ZERO , & [ ] ) ;
429+ bx. dbg_var_addr ( dbg_var, dbg_loc, base. llval , Size :: ZERO , & [ ] , None ) ;
411430 }
412431 }
413432 }
433+ mir:: VarDebugInfoContents :: Composite { ty, ref fragments } => {
434+ let var_ty = self . monomorphize ( ty) ;
435+ let var_layout = self . cx . layout_of ( var_ty) ;
436+ for fragment in fragments {
437+ let mut fragment_start = Size :: ZERO ;
438+ let mut fragment_layout = var_layout;
439+
440+ for elem in & fragment. projection {
441+ match * elem {
442+ mir:: ProjectionElem :: Field ( field, _) => {
443+ let i = field. index ( ) ;
444+ fragment_start += fragment_layout. fields . offset ( i) ;
445+ fragment_layout = fragment_layout. field ( self . cx , i) ;
446+ }
447+ _ => span_bug ! (
448+ var. source_info. span,
449+ "unsupported fragment projection `{:?}`" ,
450+ elem,
451+ ) ,
452+ }
453+ }
454+
455+ let place = fragment. contents ;
456+ per_local[ place. local ] . push ( PerLocalVarDebugInfo {
457+ name : var. name ,
458+ source_info : var. source_info ,
459+ dbg_var,
460+ fragment : if fragment_layout. size == var_layout. size {
461+ // Fragment covers entire variable, so as far as
462+ // DWARF is concerned, it's not really a fragment.
463+ None
464+ } else {
465+ Some ( fragment_start..fragment_start + fragment_layout. size )
466+ } ,
467+ projection : place. projection ,
468+ } ) ;
469+ }
470+ }
414471 }
415472 }
416473 Some ( per_local)
0 commit comments