@@ -6,7 +6,7 @@ use rustc_middle::ty;
66use rustc_session:: config:: DebugInfo ;
77use rustc_span:: symbol:: { kw, Symbol } ;
88use rustc_span:: { BytePos , Span } ;
9- use rustc_target:: abi:: { LayoutOf , Size } ;
9+ use rustc_target:: abi:: Size ;
1010
1111use super :: operand:: { OperandRef , OperandValue } ;
1212use super :: place:: PlaceRef ;
@@ -265,33 +265,25 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
265265 None => continue ,
266266 } ;
267267
268- let mut layout = base. layout ;
269268 let mut direct_offset = Size :: ZERO ;
270269 // FIXME(eddyb) use smallvec here.
271270 let mut indirect_offsets = vec ! [ ] ;
271+ let mut place = base;
272272
273273 for elem in & var. projection [ ..] {
274274 match * elem {
275275 mir:: ProjectionElem :: Deref => {
276276 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) ;
286278 }
287279 mir:: ProjectionElem :: Field ( field, _) => {
288280 let i = field. index ( ) ;
289281 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) ;
292284 }
293285 mir:: ProjectionElem :: Downcast ( _, variant) => {
294- layout = layout . for_variant ( bx. cx ( ) , variant) ;
286+ place = place . project_downcast ( bx, variant) ;
295287 }
296288 _ => span_bug ! (
297289 var. source_info. span,
@@ -301,7 +293,39 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
301293 }
302294 }
303295
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+ }
305329 }
306330 }
307331
0 commit comments