@@ -126,6 +126,7 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) {
126126 let scopes = debuginfo:: create_mir_scopes ( fcx) ;
127127
128128 // Allocate variable and temp allocas
129+ let args = arg_value_refs ( & bcx, & mir, & scopes) ;
129130 let vars = mir. var_decls . iter ( )
130131 . map ( |decl| ( bcx. monomorphize ( & decl. ty ) , decl) )
131132 . map ( |( mty, decl) | {
@@ -156,7 +157,6 @@ pub fn trans_mir<'blk, 'tcx: 'blk>(fcx: &'blk FunctionContext<'blk, 'tcx>) {
156157 TempRef :: Operand ( None )
157158 } )
158159 . collect ( ) ;
159- let args = arg_value_refs ( & bcx, & mir, & scopes) ;
160160
161161 // Allocate a `Block` for every basic block
162162 let block_bcxs: Vec < Block < ' blk , ' tcx > > =
@@ -278,15 +278,15 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
278278 let byte_offset_of_var_in_tuple =
279279 machine:: llelement_offset ( bcx. ccx ( ) , lltuplety, i) ;
280280
281- let address_operations = unsafe {
281+ let ops = unsafe {
282282 [ llvm:: LLVMDIBuilderCreateOpDeref ( ) ,
283283 llvm:: LLVMDIBuilderCreateOpPlus ( ) ,
284284 byte_offset_of_var_in_tuple as i64 ]
285285 } ;
286286
287287 let variable_access = VariableAccess :: IndirectVariable {
288288 alloca : lltemp,
289- address_operations : & address_operations
289+ address_operations : & ops
290290 } ;
291291 declare_local ( bcx, token:: special_idents:: invalid. name ,
292292 tupled_arg_ty, scope, variable_access,
@@ -327,10 +327,78 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
327327 lltemp
328328 } ;
329329 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+ }
334402 } ) ) ;
335403 LvalueRef :: new_sized ( llval, LvalueTy :: from_ty ( arg_ty) )
336404 } ) . collect ( )
0 commit comments