@@ -14,6 +14,8 @@ use super::operand::{OperandRef, OperandValue};
14
14
use super :: place:: PlaceRef ;
15
15
use super :: { FunctionCx , LocalRef } ;
16
16
17
+ use std:: ops:: Range ;
18
+
17
19
pub struct FunctionDebugContext < S , L > {
18
20
pub scopes : IndexVec < mir:: SourceScope , DebugScope < S , L > > ,
19
21
}
@@ -25,14 +27,18 @@ pub enum VariableKind {
25
27
}
26
28
27
29
/// Like `mir::VarDebugInfo`, but within a `mir::Local`.
28
- #[ derive( Copy , Clone ) ]
30
+ #[ derive( Clone ) ]
29
31
pub struct PerLocalVarDebugInfo < ' tcx , D > {
30
32
pub name : Symbol ,
31
33
pub source_info : mir:: SourceInfo ,
32
34
33
35
/// `DIVariable` returned by `create_dbg_var`.
34
36
pub dbg_var : Option < D > ,
35
37
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
+
36
42
/// `.place.projection` from `mir::VarDebugInfo`.
37
43
pub projection : & ' tcx ty:: List < mir:: PlaceElem < ' tcx > > ,
38
44
}
@@ -145,7 +151,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
145
151
Some ( per_local) => & per_local[ local] ,
146
152
None => return ,
147
153
} ;
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 ( ) ;
149
155
let has_proj = || vars. iter ( ) . any ( |var| !var. projection . is_empty ( ) ) ;
150
156
151
157
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> {
187
193
name,
188
194
source_info : decl. source_info ,
189
195
dbg_var,
196
+ fragment : None ,
190
197
projection : ty:: List :: empty ( ) ,
191
198
} )
192
199
}
@@ -199,7 +206,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
199
206
let name = if bx. sess ( ) . fewer_names ( ) {
200
207
None
201
208
} else {
202
- Some ( match whole_local_var. or ( fallback_var) {
209
+ Some ( match whole_local_var. or ( fallback_var. clone ( ) ) {
203
210
Some ( var) if var. name != kw:: Empty => var. name . to_string ( ) ,
204
211
_ => format ! ( "{:?}" , local) ,
205
212
} )
@@ -249,7 +256,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
249
256
LocalRef :: UnsizedPlace ( _) => return ,
250
257
} ;
251
258
252
- let vars = vars. iter ( ) . copied ( ) . chain ( fallback_var) ;
259
+ let vars = vars. iter ( ) . cloned ( ) . chain ( fallback_var) ;
253
260
254
261
for var in vars {
255
262
let Some ( dbg_var) = var. dbg_var else { continue } ;
@@ -312,9 +319,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
312
319
bx. store ( place. llval , alloca. llval , alloca. align ) ;
313
320
314
321
// 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 ) ;
316
323
} 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
+ ) ;
318
332
}
319
333
}
320
334
}
@@ -382,6 +396,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
382
396
let ty = self . monomorphize ( c. ty ( ) ) ;
383
397
( ty, VariableKind :: LocalVariable )
384
398
}
399
+ mir:: VarDebugInfoContents :: Composite { ty, fragments : _ } => {
400
+ let ty = self . monomorphize ( ty) ;
401
+ ( ty, VariableKind :: LocalVariable )
402
+ }
385
403
} ;
386
404
387
405
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> {
393
411
name : var. name ,
394
412
source_info : var. source_info ,
395
413
dbg_var,
414
+ fragment : None ,
396
415
projection : place. projection ,
397
416
} ) ;
398
417
}
@@ -407,10 +426,48 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
407
426
bx,
408
427
) ;
409
428
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 ) ;
411
430
}
412
431
}
413
432
}
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
+ }
414
471
}
415
472
}
416
473
Some ( per_local)
0 commit comments