@@ -126,6 +126,7 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) {
126
126
let scopes = debuginfo:: create_mir_scopes ( fcx) ;
127
127
128
128
// Allocate variable and temp allocas
129
+ let args = arg_value_refs ( & bcx, & mir, & scopes) ;
129
130
let vars = mir. var_decls . iter ( )
130
131
. map ( |decl| ( bcx. monomorphize ( & decl. ty ) , decl) )
131
132
. map ( |( mty, decl) | {
@@ -156,7 +157,6 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) {
156
157
TempRef :: Operand ( None )
157
158
} )
158
159
. collect ( ) ;
159
- let args = arg_value_refs ( & bcx, & mir, & scopes) ;
160
160
161
161
// Allocate a `Block` for every basic block
162
162
let block_bcxs: Vec < Block < ' blk , ' tcx > > =
@@ -278,15 +278,15 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
278
278
let byte_offset_of_var_in_tuple =
279
279
machine:: llelement_offset ( bcx. ccx ( ) , lltuplety, i) ;
280
280
281
- let address_operations = unsafe {
281
+ let ops = unsafe {
282
282
[ llvm:: LLVMDIBuilderCreateOpDeref ( ) ,
283
283
llvm:: LLVMDIBuilderCreateOpPlus ( ) ,
284
284
byte_offset_of_var_in_tuple as i64 ]
285
285
} ;
286
286
287
287
let variable_access = VariableAccess :: IndirectVariable {
288
288
alloca : lltemp,
289
- address_operations : & address_operations
289
+ address_operations : & ops
290
290
} ;
291
291
declare_local ( bcx, token:: special_idents:: invalid. name ,
292
292
tupled_arg_ty, scope, variable_access,
@@ -327,10 +327,78 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
327
327
lltemp
328
328
} ;
329
329
bcx. with_block ( |bcx| arg_scope. map ( |scope| {
330
- declare_local ( bcx, token:: special_idents:: invalid. name , arg_ty, scope,
331
- VariableAccess :: DirectVariable { alloca : llval } ,
332
- VariableKind :: ArgumentVariable ( arg_index + 1 ) ,
333
- bcx. fcx ( ) . span . unwrap_or ( DUMMY_SP ) ) ;
330
+ // Is this a regular argument?
331
+ if arg_index > 0 || mir. upvar_decls . is_empty ( ) {
332
+ declare_local ( bcx, arg_decl. debug_name , arg_ty, scope,
333
+ VariableAccess :: DirectVariable { alloca : llval } ,
334
+ VariableKind :: ArgumentVariable ( arg_index + 1 ) ,
335
+ bcx. fcx ( ) . span . unwrap_or ( DUMMY_SP ) ) ;
336
+ return ;
337
+ }
338
+
339
+ // Or is it the closure environment?
340
+ let ( closure_ty, env_ref) = if let ty:: TyRef ( _, mt) = arg_ty. sty {
341
+ ( mt. ty , true )
342
+ } else {
343
+ ( arg_ty, false )
344
+ } ;
345
+ let upvar_tys = if let ty:: TyClosure ( _, ref substs) = closure_ty. sty {
346
+ & substs. upvar_tys [ ..]
347
+ } else {
348
+ bug ! ( "upvar_decls with non-closure arg0 type `{}`" , closure_ty) ;
349
+ } ;
350
+
351
+ // Store the pointer to closure data in an alloca for debuginfo
352
+ // because that's what the llvm.dbg.declare intrinsic expects.
353
+
354
+ // FIXME(eddyb) this shouldn't be necessary but SROA seems to
355
+ // mishandle DW_OP_plus not preceded by DW_OP_deref, i.e. it
356
+ // doesn't actually strip the offset when splitting the closure
357
+ // environment into its components so it ends up out of bounds.
358
+ let env_ptr = if !env_ref {
359
+ use base:: * ;
360
+ use build:: * ;
361
+ use common:: * ;
362
+ let alloc = alloca ( bcx, val_ty ( llval) , "__debuginfo_env_ptr" ) ;
363
+ Store ( bcx, llval, alloc) ;
364
+ alloc
365
+ } else {
366
+ llval
367
+ } ;
368
+
369
+ let llclosurety = type_of:: type_of ( bcx. ccx ( ) , closure_ty) ;
370
+ for ( i, ( decl, ty) ) in mir. upvar_decls . iter ( ) . zip ( upvar_tys) . enumerate ( ) {
371
+ let byte_offset_of_var_in_env =
372
+ machine:: llelement_offset ( bcx. ccx ( ) , llclosurety, i) ;
373
+
374
+ let ops = unsafe {
375
+ [ llvm:: LLVMDIBuilderCreateOpDeref ( ) ,
376
+ llvm:: LLVMDIBuilderCreateOpPlus ( ) ,
377
+ byte_offset_of_var_in_env as i64 ,
378
+ llvm:: LLVMDIBuilderCreateOpDeref ( ) ]
379
+ } ;
380
+
381
+ // The environment and the capture can each be indirect.
382
+
383
+ // FIXME(eddyb) see above why we have to keep
384
+ // a pointer in an alloca for debuginfo atm.
385
+ let mut ops = if env_ref || true { & ops[ ..] } else { & ops[ 1 ..] } ;
386
+
387
+ let ty = if let ( true , & ty:: TyRef ( _, mt) ) = ( decl. by_ref , & ty. sty ) {
388
+ mt. ty
389
+ } else {
390
+ ops = & ops[ ..ops. len ( ) - 1 ] ;
391
+ ty
392
+ } ;
393
+
394
+ let variable_access = VariableAccess :: IndirectVariable {
395
+ alloca : env_ptr,
396
+ address_operations : & ops
397
+ } ;
398
+ declare_local ( bcx, decl. debug_name , ty, scope, variable_access,
399
+ VariableKind :: CapturedVariable ,
400
+ bcx. fcx ( ) . span . unwrap_or ( DUMMY_SP ) ) ;
401
+ }
334
402
} ) ) ;
335
403
LvalueRef :: new_sized ( llval, LvalueTy :: from_ty ( arg_ty) )
336
404
} ) . collect ( )
0 commit comments