@@ -6,7 +6,7 @@ use rustc_middle::ty;
6
6
use rustc_session:: config:: DebugInfo ;
7
7
use rustc_span:: symbol:: { kw, Symbol } ;
8
8
use rustc_span:: { BytePos , Span } ;
9
- use rustc_target:: abi:: { LayoutOf , Size } ;
9
+ use rustc_target:: abi:: Size ;
10
10
11
11
use super :: operand:: { OperandRef , OperandValue } ;
12
12
use super :: place:: PlaceRef ;
@@ -265,33 +265,25 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
265
265
None => continue ,
266
266
} ;
267
267
268
- let mut layout = base. layout ;
269
268
let mut direct_offset = Size :: ZERO ;
270
269
// FIXME(eddyb) use smallvec here.
271
270
let mut indirect_offsets = vec ! [ ] ;
271
+ let mut place = base;
272
272
273
273
for elem in & var. projection [ ..] {
274
274
match * elem {
275
275
mir:: ProjectionElem :: Deref => {
276
276
indirect_offsets. push ( Size :: ZERO ) ;
277
- layout = bx. cx ( ) . layout_of (
278
- layout
279
- . ty
280
- . builtin_deref ( true )
281
- . unwrap_or_else ( || {
282
- span_bug ! ( var. source_info. span, "cannot deref `{}`" , layout. ty)
283
- } )
284
- . ty ,
285
- ) ;
277
+ place = place. project_deref ( bx) ;
286
278
}
287
279
mir:: ProjectionElem :: Field ( field, _) => {
288
280
let i = field. index ( ) ;
289
281
let offset = indirect_offsets. last_mut ( ) . unwrap_or ( & mut direct_offset) ;
290
- * offset += layout. fields . offset ( i) ;
291
- layout = layout . field ( bx. cx ( ) , i) ;
282
+ * offset += place . layout . fields . offset ( i) ;
283
+ place = place . project_field ( bx, i) ;
292
284
}
293
285
mir:: ProjectionElem :: Downcast ( _, variant) => {
294
- layout = layout . for_variant ( bx. cx ( ) , variant) ;
286
+ place = place . project_downcast ( bx, variant) ;
295
287
}
296
288
_ => span_bug ! (
297
289
var. source_info. span,
@@ -301,7 +293,39 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
301
293
}
302
294
}
303
295
304
- bx. dbg_var_addr ( dbg_var, dbg_loc, base. llval , direct_offset, & indirect_offsets) ;
296
+ // When targeting MSVC, create extra allocas for arguments instead of pointing multiple
297
+ // dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
298
+ // not DWARF and LLVM doesn't support translating the resulting
299
+ // [DW_OP_deref, DW_OP_plus_uconst, offset, DW_OP_deref] debug info to CodeView.
300
+ // Creating extra allocas on the stack makes the resulting debug info simple enough
301
+ // that LLVM can generate correct CodeView records and thus the values appear in the
302
+ // debugger. (#83709)
303
+ let should_create_individual_allocas = bx. cx ( ) . sess ( ) . target . is_like_msvc
304
+ && self . mir . local_kind ( local) == mir:: LocalKind :: Arg
305
+ // LLVM can handle simple things but anything more complex than just a direct
306
+ // offset or one indirect offset of 0 is too complex for it to generate CV records
307
+ // correctly.
308
+ && ( direct_offset != Size :: ZERO
309
+ || !matches ! ( & indirect_offsets[ ..] , [ Size :: ZERO ] | [ ] ) ) ;
310
+
311
+ if should_create_individual_allocas {
312
+ // Create a variable which will be a pointer to the actual value
313
+ let ptr_ty = bx. tcx ( ) . mk_ty ( ty:: RawPtr ( ty:: TypeAndMut {
314
+ mutbl : mir:: Mutability :: Mut ,
315
+ ty : place. layout . ty ,
316
+ } ) ) ;
317
+ let ptr_layout = bx. layout_of ( ptr_ty) ;
318
+ let alloca = PlaceRef :: alloca ( bx, ptr_layout) ;
319
+ bx. set_var_name ( alloca. llval , & ( var. name . to_string ( ) + ".dbg.spill" ) ) ;
320
+
321
+ // Write the pointer to the variable
322
+ bx. store ( place. llval , alloca. llval , alloca. align ) ;
323
+
324
+ // Point the debug info to `*alloca` for the current variable
325
+ bx. dbg_var_addr ( dbg_var, dbg_loc, alloca. llval , Size :: ZERO , & [ Size :: ZERO ] ) ;
326
+ } else {
327
+ bx. dbg_var_addr ( dbg_var, dbg_loc, base. llval , direct_offset, & indirect_offsets) ;
328
+ }
305
329
}
306
330
}
307
331
0 commit comments