@@ -44,8 +44,11 @@ pub struct PerLocalVarDebugInfo<'tcx, D> {
44
44
/// if this is a fragment of a composite `VarDebugInfo`.
45
45
pub fragment : Option < Range < Size > > ,
46
46
47
- /// `.place.projection` from `mir::VarDebugInfo`.
48
- pub projection : & ' tcx ty:: List < mir:: PlaceElem < ' tcx > > ,
47
+ /// `.place.direct_projection` from `mir::VarDebugInfo`.
48
+ pub direct_projection : & ' tcx ty:: List < mir:: PlaceElem < ' tcx > > ,
49
+
50
+ /// `.place.projection_chain` from `mir::VarDebugInfo`.
51
+ pub projection_chain : & ' tcx ty:: List < mir:: ProjectionFragment < ' tcx > > ,
49
52
}
50
53
51
54
/// Information needed to emit a constant.
@@ -168,46 +171,68 @@ fn calculate_debuginfo_offset<
168
171
L : DebugInfoOffsetLocation < ' tcx , Bx > ,
169
172
> (
170
173
bx : & mut Bx ,
171
- projection : & [ mir:: PlaceElem < ' tcx > ] ,
174
+ direct_projection : & [ mir:: PlaceElem < ' tcx > ] ,
175
+ projection_chain : & [ mir:: ProjectionFragment < ' tcx > ] ,
172
176
base : L ,
173
177
) -> DebugInfoOffset < L > {
174
- let mut direct_offset = Size :: ZERO ;
175
- // FIXME(eddyb) use smallvec here.
176
- let mut indirect_offsets = vec ! [ ] ;
177
- let mut place = base;
178
-
179
- for elem in projection {
180
- match * elem {
181
- mir:: ProjectionElem :: Deref => {
182
- indirect_offsets. push ( Size :: ZERO ) ;
183
- place = place. deref ( bx) ;
184
- }
178
+ let project_direct = |bx : & mut Bx , place : L , offset, elem| {
179
+ let ( new_place, new_offset) = match elem {
185
180
mir:: ProjectionElem :: Field ( field, _) => {
186
- let offset = indirect_offsets. last_mut ( ) . unwrap_or ( & mut direct_offset) ;
187
- * offset += place. layout ( ) . fields . offset ( field. index ( ) ) ;
188
- place = place. project_field ( bx, field) ;
189
- }
190
- mir:: ProjectionElem :: Downcast ( _, variant) => {
191
- place = place. downcast ( bx, variant) ;
181
+ let offset = place. layout ( ) . fields . offset ( field. index ( ) ) ;
182
+ let place = place. project_field ( bx, field) ;
183
+
184
+ ( place, offset)
192
185
}
186
+ mir:: ProjectionElem :: Downcast ( _, variant) => ( place. downcast ( bx, variant) , Size :: ZERO ) ,
193
187
mir:: ProjectionElem :: ConstantIndex {
194
188
offset : index,
195
189
min_length : _,
196
190
from_end : false ,
197
191
} => {
198
- let offset = indirect_offsets. last_mut ( ) . unwrap_or ( & mut direct_offset) ;
199
192
let FieldsShape :: Array { stride, count : _ } = place. layout ( ) . fields else {
200
193
bug ! ( "ConstantIndex on non-array type {:?}" , place. layout( ) )
201
194
} ;
202
- * offset += stride * index;
203
- place = place. project_constant_index ( bx, index) ;
195
+ let offset = stride * index;
196
+ let place = place. project_constant_index ( bx, index) ;
197
+
198
+ ( place, offset)
199
+ }
200
+
201
+ mir:: ProjectionElem :: Deref => {
202
+ // derefs handled separately
203
+ bug ! (
204
+ "unexpected deref in var debuginfo projection `{direct_projection:?} {projection_chain:?}`"
205
+ )
204
206
}
205
207
_ => {
206
208
// Sanity check for `can_use_in_debuginfo`.
207
209
assert ! ( !elem. can_use_in_debuginfo( ) ) ;
208
- bug ! ( "unsupported var debuginfo projection `{:?}`" , projection)
210
+ bug ! (
211
+ "unsupported var debuginfo projection `{direct_projection:?} {projection_chain:?}`"
212
+ )
209
213
}
210
- }
214
+ } ;
215
+ ( new_place, offset + new_offset)
216
+ } ;
217
+
218
+ let ( mut place, direct_offset) = direct_projection
219
+ . iter ( )
220
+ . fold ( ( base, Size :: ZERO ) , |( place, offset) , & elem| project_direct ( bx, place, offset, elem) ) ;
221
+
222
+ // FIXME(eddyb) use smallvec here.
223
+ let mut indirect_offsets = vec ! [ ] ;
224
+
225
+ for projection in projection_chain {
226
+ debug_assert_eq ! ( projection[ 0 ] , mir:: ProjectionElem :: Deref ) ;
227
+ let pointee = place. deref ( bx) ;
228
+
229
+ let ( projected, offset) =
230
+ projection[ 1 ..] . iter ( ) . fold ( ( pointee, Size :: ZERO ) , |( place, offset) , & elem| {
231
+ project_direct ( bx, place, offset, elem)
232
+ } ) ;
233
+
234
+ place = projected;
235
+ indirect_offsets. push ( offset) ;
211
236
}
212
237
213
238
DebugInfoOffset { direct_offset, indirect_offsets, result : place }
@@ -262,8 +287,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
262
287
Some ( per_local) => & per_local[ local] ,
263
288
None => return ,
264
289
} ;
265
- let whole_local_var = vars. iter ( ) . find ( |var| var. projection . is_empty ( ) ) . cloned ( ) ;
266
- let has_proj = || vars. iter ( ) . any ( |var| !var. projection . is_empty ( ) ) ;
290
+ let whole_local_var = vars
291
+ . iter ( )
292
+ . find ( |var| var. direct_projection . is_empty ( ) && var. projection_chain . is_empty ( ) )
293
+ . cloned ( ) ;
294
+ let has_proj = || {
295
+ vars. iter ( )
296
+ . any ( |var| !var. direct_projection . is_empty ( ) || !var. projection_chain . is_empty ( ) )
297
+ } ;
267
298
268
299
let fallback_var = if self . mir . local_kind ( local) == mir:: LocalKind :: Arg {
269
300
let arg_index = local. index ( ) - 1 ;
@@ -305,7 +336,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
305
336
source_info : decl. source_info ,
306
337
dbg_var,
307
338
fragment : None ,
308
- projection : ty:: List :: empty ( ) ,
339
+ direct_projection : ty:: List :: empty ( ) ,
340
+ projection_chain : ty:: List :: empty ( ) ,
309
341
} )
310
342
}
311
343
} else {
@@ -388,7 +420,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
388
420
let Some ( dbg_loc) = self . dbg_loc ( var. source_info ) else { return } ;
389
421
390
422
let DebugInfoOffset { direct_offset, indirect_offsets, result : _ } =
391
- calculate_debuginfo_offset ( bx, var. projection , base. layout ) ;
423
+ calculate_debuginfo_offset (
424
+ bx,
425
+ var. direct_projection ,
426
+ var. projection_chain ,
427
+ base. layout ,
428
+ ) ;
392
429
393
430
// When targeting MSVC, create extra allocas for arguments instead of pointing multiple
394
431
// dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
@@ -406,7 +443,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
406
443
407
444
if should_create_individual_allocas {
408
445
let DebugInfoOffset { direct_offset : _, indirect_offsets : _, result : place } =
409
- calculate_debuginfo_offset ( bx, var. projection , base) ;
446
+ calculate_debuginfo_offset ( bx, var. direct_projection , var . projection_chain , base) ;
410
447
411
448
// Create a variable which will be a pointer to the actual value
412
449
let ptr_ty = Ty :: new_mut_ptr ( bx. tcx ( ) , place. layout . ty ) ;
@@ -543,7 +580,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
543
580
let var_layout = self . cx . layout_of ( var_ty) ;
544
581
545
582
let DebugInfoOffset { direct_offset, indirect_offsets, result : fragment_layout } =
546
- calculate_debuginfo_offset ( bx, & fragment. projection , var_layout) ;
583
+ calculate_debuginfo_offset ( bx, & fragment. projection , & [ ] , var_layout) ;
547
584
assert ! ( indirect_offsets. is_empty( ) ) ;
548
585
549
586
if fragment_layout. size == Size :: ZERO {
@@ -562,16 +599,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
562
599
} ;
563
600
564
601
match var. value {
565
- mir:: VarDebugInfoContents :: Place ( place) => {
566
- per_local[ place. local ] . push ( PerLocalVarDebugInfo {
602
+ mir:: VarDebugInfoContents :: Place ( mir:: CompoundPlace {
603
+ local,
604
+ direct_projection,
605
+ projection_chain,
606
+ } ) => {
607
+ per_local[ local] . push ( PerLocalVarDebugInfo {
567
608
name : var. name ,
568
609
source_info : var. source_info ,
569
610
dbg_var,
570
611
fragment,
571
- // FIXME change field to be projection chain
572
- projection : bx
573
- . tcx ( )
574
- . mk_place_elems_from_iter ( place. iter_projection_elems ( ) ) ,
612
+ direct_projection,
613
+ projection_chain,
575
614
} ) ;
576
615
}
577
616
mir:: VarDebugInfoContents :: Const ( c) => {
0 commit comments