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