@@ -5,9 +5,9 @@ use rustc::ty;
5
5
use rustc:: ty:: layout:: { LayoutOf , Size } ;
6
6
use rustc_hir:: def_id:: CrateNum ;
7
7
use rustc_index:: vec:: IndexVec ;
8
-
9
8
use rustc_span:: symbol:: { kw, Symbol } ;
10
9
use rustc_span:: { BytePos , Span } ;
10
+ use std:: ops:: Range ;
11
11
12
12
use super :: OperandValue ;
13
13
use super :: { FunctionCx , LocalRef } ;
@@ -25,14 +25,18 @@ pub enum VariableKind {
25
25
}
26
26
27
27
/// Like `mir::VarDebugInfo`, but within a `mir::Local`.
28
- #[ derive( Copy , Clone ) ]
28
+ #[ derive( Clone ) ]
29
29
pub struct PerLocalVarDebugInfo < ' tcx , D > {
30
30
pub name : Symbol ,
31
31
pub source_info : mir:: SourceInfo ,
32
32
33
33
/// `DIVariable` returned by `create_dbg_var`.
34
34
pub dbg_var : Option < D > ,
35
35
36
+ /// Byte range in the `dbg_var` covered by this fragment,
37
+ /// if this is a fragment of a composite `VarDebugInfo`.
38
+ pub fragment : Option < Range < Size > > ,
39
+
36
40
/// `.place.projection` from `mir::VarDebugInfo`.
37
41
pub projection : & ' tcx ty:: List < mir:: PlaceElem < ' tcx > > ,
38
42
}
@@ -127,7 +131,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
127
131
Some ( per_local) => & per_local[ local] ,
128
132
None => return ,
129
133
} ;
130
- let whole_local_var = vars. iter ( ) . find ( |var| var. projection . is_empty ( ) ) . copied ( ) ;
134
+ let whole_local_var =
135
+ vars. iter ( ) . find ( |var| var. fragment . is_none ( ) && var. projection . is_empty ( ) ) . cloned ( ) ;
131
136
let has_proj = || vars. iter ( ) . any ( |var| !var. projection . is_empty ( ) ) ;
132
137
133
138
let fallback_var = if self . mir . local_kind ( local) == mir:: LocalKind :: Arg {
@@ -173,6 +178,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
173
178
name,
174
179
source_info : decl. source_info ,
175
180
dbg_var,
181
+ fragment : None ,
176
182
projection : ty:: List :: empty ( ) ,
177
183
} )
178
184
}
@@ -183,7 +189,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
183
189
let local_ref = & self . locals [ local] ;
184
190
185
191
if !bx. sess ( ) . fewer_names ( ) {
186
- let name = match whole_local_var. or ( fallback_var) {
192
+ let name = match whole_local_var. or ( fallback_var. clone ( ) ) {
187
193
Some ( var) if var. name != kw:: Invalid => var. name . to_string ( ) ,
188
194
_ => format ! ( "{:?}" , local) ,
189
195
} ;
@@ -221,7 +227,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
221
227
_ => return ,
222
228
} ;
223
229
224
- let vars = vars. iter ( ) . copied ( ) . chain ( fallback_var) ;
230
+ let vars = vars. iter ( ) . cloned ( ) . chain ( fallback_var) ;
225
231
226
232
for var in vars {
227
233
let mut layout = base. layout ;
@@ -270,6 +276,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
270
276
base. llval ,
271
277
direct_offset,
272
278
& indirect_offsets,
279
+ var. fragment ,
273
280
span,
274
281
) ;
275
282
}
@@ -302,25 +309,31 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
302
309
} else {
303
310
( None , var. source_info . span )
304
311
} ;
312
+ let ( var_ty, var_kind) = match var. contents {
313
+ mir:: VarDebugInfoContents :: Compact ( place) => (
314
+ self . monomorphized_place_ty ( place. as_ref ( ) ) ,
315
+ if self . mir . local_kind ( place. local ) == mir:: LocalKind :: Arg
316
+ && place. projection . is_empty ( )
317
+ {
318
+ // FIXME(eddyb, #67586) take `var.source_info.scope` into
319
+ // account to avoid using `ArgumentVariable` more than once
320
+ // per argument local.
321
+
322
+ let arg_index = place. local . index ( ) - 1 ;
323
+
324
+ // FIXME(eddyb) shouldn't `ArgumentVariable` indices be
325
+ // offset in closures to account for the hidden environment?
326
+ // Also, is this `+ 1` needed at all?
327
+ VariableKind :: ArgumentVariable ( arg_index + 1 )
328
+ } else {
329
+ VariableKind :: LocalVariable
330
+ } ,
331
+ ) ,
332
+ mir:: VarDebugInfoContents :: Composite { ty, fragments : _ } => {
333
+ ( self . monomorphize ( & ty) , VariableKind :: LocalVariable )
334
+ }
335
+ } ;
305
336
let dbg_var = scope. map ( |scope| {
306
- let place = var. place ;
307
- let var_ty = self . monomorphized_place_ty ( place. as_ref ( ) ) ;
308
- let var_kind = if self . mir . local_kind ( place. local ) == mir:: LocalKind :: Arg
309
- && place. projection . is_empty ( )
310
- {
311
- // FIXME(eddyb, #67586) take `var.source_info.scope` into
312
- // account to avoid using `ArgumentVariable` more than once
313
- // per argument local.
314
-
315
- let arg_index = place. local . index ( ) - 1 ;
316
-
317
- // FIXME(eddyb) shouldn't `ArgumentVariable` indices be
318
- // offset in closures to account for the hidden environment?
319
- // Also, is this `+ 1` needed at all?
320
- VariableKind :: ArgumentVariable ( arg_index + 1 )
321
- } else {
322
- VariableKind :: LocalVariable
323
- } ;
324
337
self . cx . create_dbg_var (
325
338
self . debug_context . as_ref ( ) . unwrap ( ) ,
326
339
var. name ,
@@ -331,12 +344,54 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
331
344
)
332
345
} ) ;
333
346
334
- per_local[ var. place . local ] . push ( PerLocalVarDebugInfo {
335
- name : var. name ,
336
- source_info : var. source_info ,
337
- dbg_var,
338
- projection : var. place . projection ,
339
- } ) ;
347
+ match & var. contents {
348
+ mir:: VarDebugInfoContents :: Compact ( place) => {
349
+ per_local[ place. local ] . push ( PerLocalVarDebugInfo {
350
+ name : var. name ,
351
+ source_info : var. source_info ,
352
+ dbg_var,
353
+ fragment : None ,
354
+ projection : place. projection ,
355
+ } ) ;
356
+ }
357
+ mir:: VarDebugInfoContents :: Composite { ty : _, fragments } => {
358
+ let var_layout = self . cx . layout_of ( var_ty) ;
359
+ for fragment in fragments {
360
+ let mut fragment_start = Size :: ZERO ;
361
+ let mut fragment_layout = var_layout;
362
+
363
+ for elem in & fragment. projection {
364
+ match * elem {
365
+ mir:: ProjectionElem :: Field ( field, _) => {
366
+ let i = field. index ( ) ;
367
+ fragment_start += fragment_layout. fields . offset ( i) ;
368
+ fragment_layout = fragment_layout. field ( self . cx , i) ;
369
+ }
370
+ _ => span_bug ! (
371
+ var. source_info. span,
372
+ "unsupported fragment projection `{:?}`" ,
373
+ elem,
374
+ ) ,
375
+ }
376
+ }
377
+
378
+ let place = fragment. contents ;
379
+ per_local[ place. local ] . push ( PerLocalVarDebugInfo {
380
+ name : var. name ,
381
+ source_info : var. source_info ,
382
+ dbg_var,
383
+ fragment : if fragment_layout. size == var_layout. size {
384
+ // Fragment covers entire variable, so as far as
385
+ // DWARF is concerned, it's not really a fragment.
386
+ None
387
+ } else {
388
+ Some ( fragment_start..fragment_start + fragment_layout. size )
389
+ } ,
390
+ projection : place. projection ,
391
+ } ) ;
392
+ }
393
+ }
394
+ }
340
395
}
341
396
Some ( per_local)
342
397
}
0 commit comments