@@ -17,8 +17,6 @@ use super::operand::{OperandRef, OperandValue};
17
17
use super :: place:: PlaceRef ;
18
18
use super :: { FunctionCx , LocalRef } ;
19
19
20
- use std:: ops:: Range ;
21
-
22
20
pub struct FunctionDebugContext < ' tcx , S , L > {
23
21
/// Maps from source code to the corresponding debug info scope.
24
22
pub scopes : IndexVec < mir:: SourceScope , DebugScope < S , L > > ,
@@ -36,17 +34,17 @@ pub enum VariableKind {
36
34
#[ derive( Clone ) ]
37
35
pub struct PerLocalVarDebugInfo < ' tcx , D > {
38
36
pub name : Symbol ,
37
+ pub ty : Ty < ' tcx > ,
39
38
pub source_info : mir:: SourceInfo ,
40
39
41
40
/// `DIVariable` returned by `create_dbg_var`.
42
41
pub dbg_var : Option < D > ,
43
42
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
-
48
43
/// `.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 > ] ,
50
48
}
51
49
52
50
#[ derive( Clone , Copy , Debug ) ]
@@ -149,6 +147,8 @@ struct DebugInfoOffset<T> {
149
147
indirect_offsets : Vec < Size > ,
150
148
/// The final location debuginfo should point to.
151
149
result : T ,
150
+ /// Whether the final location is a fragment of a larger contiguous projection.
151
+ fragment : bool ,
152
152
}
153
153
154
154
fn calculate_debuginfo_offset <
@@ -165,17 +165,21 @@ fn calculate_debuginfo_offset<
165
165
// FIXME(eddyb) use smallvec here.
166
166
let mut indirect_offsets = vec ! [ ] ;
167
167
let mut place = base;
168
+ let mut fragment = false ;
168
169
169
170
for elem in projection {
171
+ let layout = place. layout ( ) ;
170
172
match * elem {
171
173
mir:: ProjectionElem :: Deref => {
172
174
indirect_offsets. push ( Size :: ZERO ) ;
173
175
place = place. deref ( bx) ;
176
+ fragment = false ;
174
177
}
175
178
mir:: ProjectionElem :: Field ( field, _) => {
176
179
let offset = indirect_offsets. last_mut ( ) . unwrap_or ( & mut direct_offset) ;
177
180
* offset += place. layout ( ) . fields . offset ( field. index ( ) ) ;
178
181
place = place. project_field ( bx, field) ;
182
+ fragment |= place. layout ( ) . size != layout. size ;
179
183
}
180
184
mir:: ProjectionElem :: Downcast ( _, variant) => {
181
185
place = place. downcast ( bx, variant) ;
@@ -191,16 +195,17 @@ fn calculate_debuginfo_offset<
191
195
} ;
192
196
* offset += stride * index;
193
197
place = place. project_constant_index ( bx, index) ;
198
+ fragment |= place. layout ( ) . size != layout. size ;
194
199
}
195
200
_ => {
196
201
// Sanity check for `can_use_in_debuginfo`.
197
202
debug_assert ! ( !elem. can_use_in_debuginfo( ) ) ;
198
- bug ! ( "unsupported var debuginfo projection `{:?}`" , projection)
203
+ bug ! ( "unsupported var debuginfo place `{:?}`" , projection)
199
204
}
200
205
}
201
206
}
202
207
203
- DebugInfoOffset { direct_offset, indirect_offsets, result : place }
208
+ DebugInfoOffset { direct_offset, indirect_offsets, result : place, fragment }
204
209
}
205
210
206
211
impl < ' 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> {
290
295
} else {
291
296
let name = kw:: Empty ;
292
297
let decl = & self . mir . local_decls [ local] ;
298
+ let arg_ty = self . monomorphize ( decl. ty ) ;
299
+
293
300
let dbg_var = if full_debug_info {
294
301
self . adjusted_span_and_dbg_scope ( decl. source_info ) . map (
295
302
|( dbg_scope, _, span) | {
296
303
// FIXME(eddyb) is this `+ 1` needed at all?
297
304
let kind = VariableKind :: ArgumentVariable ( arg_index + 1 ) ;
298
305
299
- let arg_ty = self . monomorphize ( decl. ty ) ;
300
-
301
306
self . cx . create_dbg_var ( name, arg_ty, dbg_scope, kind, span)
302
307
} ,
303
308
)
@@ -307,10 +312,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
307
312
308
313
Some ( PerLocalVarDebugInfo {
309
314
name,
315
+ ty : arg_ty,
310
316
source_info : decl. source_info ,
311
317
dbg_var,
312
- fragment : None ,
313
- projection : ty :: List :: empty ( ) ,
318
+ fragment : & [ ] ,
319
+ projection : & [ ] ,
314
320
} )
315
321
}
316
322
} else {
@@ -392,8 +398,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
392
398
let Some ( dbg_var) = var. dbg_var else { return } ;
393
399
let Some ( dbg_loc) = self . dbg_loc ( var. source_info ) else { return } ;
394
400
395
- let DebugInfoOffset { direct_offset, indirect_offsets, result : _ } =
401
+ let DebugInfoOffset { mut direct_offset, indirect_offsets, result : _ , fragment : _ } =
396
402
calculate_debuginfo_offset ( bx, var. projection , base. layout ) ;
403
+ let mut indirect_offsets = & indirect_offsets[ ..] ;
397
404
398
405
// When targeting MSVC, create extra allocas for arguments instead of pointing multiple
399
406
// 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> {
410
417
&& ( direct_offset != Size :: ZERO || !matches ! ( & indirect_offsets[ ..] , [ Size :: ZERO ] | [ ] ) ) ;
411
418
412
419
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) ;
415
426
416
427
// Create a variable which will be a pointer to the actual value
417
428
let ptr_ty = Ty :: new_ptr (
@@ -426,24 +437,53 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
426
437
bx. store ( place. llval , alloca. llval , alloca. align ) ;
427
438
428
439
// 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 )
437
478
} 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 ;
446
484
}
485
+
486
+ bx. dbg_var_addr ( dbg_var, dbg_loc, base, direct_offset, indirect_offsets, fragment) ;
447
487
}
448
488
449
489
pub fn debug_introduce_locals ( & self , bx : & mut Bx ) {
@@ -515,32 +555,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
515
555
self . cx . create_dbg_var ( var. name , var_ty, dbg_scope, var_kind, span)
516
556
} ) ;
517
557
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 { & [ ] } ;
539
560
540
561
match var. value {
541
562
mir:: VarDebugInfoContents :: Place ( place) => {
542
563
per_local[ place. local ] . push ( PerLocalVarDebugInfo {
543
564
name : var. name ,
565
+ ty : var_ty,
544
566
source_info : var. source_info ,
545
567
dbg_var,
546
568
fragment,
@@ -556,7 +578,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
556
578
let base =
557
579
Self :: spill_operand_to_stack ( operand, Some ( var. name . to_string ( ) ) , bx) ;
558
580
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
+ ) ;
560
591
}
561
592
}
562
593
}
0 commit comments