From 251386c6055f44f064df27d604ae8f9ed55aad09 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 27 Nov 2014 15:52:16 +0100 Subject: [PATCH] debuginfo: Make variables captured in unboxed closures available in debuginfo. --- src/librustc_trans/trans/closure.rs | 46 +++++++++++++++---- src/librustc_trans/trans/debuginfo.rs | 13 ++---- .../var-captured-in-sendable-closure.rs | 19 +++++++- 3 files changed, 60 insertions(+), 18 deletions(-) diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs index 2f82b8286c2..bb4df00bd94 100644 --- a/src/librustc_trans/trans/closure.rs +++ b/src/librustc_trans/trans/closure.rs @@ -272,21 +272,24 @@ fn load_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let mut i = 0u; for freevar in freevars.iter() { let mut upvarptr = GEPi(bcx, llcdata, &[0u, i]); - match store { - ty::RegionTraitStore(..) => { upvarptr = Load(bcx, upvarptr); } - ty::UniqTraitStore => {} - } + let captured_by_ref = match store { + ty::RegionTraitStore(..) => { + upvarptr = Load(bcx, upvarptr); + true + } + ty::UniqTraitStore => false + }; let def_id = freevar.def.def_id(); bcx.fcx.llupvars.borrow_mut().insert(def_id.node, upvarptr); - for &env_pointer_alloca in env_pointer_alloca.iter() { + if let Some(env_pointer_alloca) = env_pointer_alloca { debuginfo::create_captured_var_metadata( bcx, def_id.node, cdata_ty, env_pointer_alloca, i, - store, + captured_by_ref, freevar.span); } @@ -320,11 +323,25 @@ fn load_unboxed_closure_environment<'blk, 'tcx>( bcx.fcx.llenv.unwrap() }; + // Store the pointer to closure data in an alloca for debug info because that's what the + // llvm.dbg.declare intrinsic expects + let env_pointer_alloca = if bcx.sess().opts.debuginfo == FullDebugInfo { + let alloc = alloc_ty(bcx, ty::mk_mut_ptr(bcx.tcx(), self_type), "__debuginfo_env_ptr"); + Store(bcx, llenv, alloc); + Some(alloc) + } else { + None + }; + for (i, freevar) in freevars.iter().enumerate() { let mut upvar_ptr = GEPi(bcx, llenv, &[0, i]); - if freevar_mode == ast::CaptureByRef { - upvar_ptr = Load(bcx, upvar_ptr); - } + let captured_by_ref = match freevar_mode { + ast::CaptureByRef => { + upvar_ptr = Load(bcx, upvar_ptr); + true + } + ast::CaptureByValue => false + }; let def_id = freevar.def.def_id(); bcx.fcx.llupvars.borrow_mut().insert(def_id.node, upvar_ptr); @@ -333,6 +350,17 @@ fn load_unboxed_closure_environment<'blk, 'tcx>( upvar_ptr, node_id_type(bcx, def_id.node)) } + + if let Some(env_pointer_alloca) = env_pointer_alloca { + debuginfo::create_captured_var_metadata( + bcx, + def_id.node, + self_type, + env_pointer_alloca, + i, + captured_by_ref, + freevar.span); + } } bcx diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index c35de3209c6..326adf1f3e7 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -885,7 +885,7 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, env_data_type: Ty<'tcx>, env_pointer: ValueRef, env_index: uint, - closure_store: ty::TraitStore, + captured_by_ref: bool, span: Span) { if fn_should_be_ignored(bcx.fcx) { return; @@ -940,13 +940,10 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, llvm::LLVMDIBuilderCreateOpDeref(Type::i64(cx).to_ref())] }; - let address_op_count = match closure_store { - ty::RegionTraitStore(..) => { - address_operations.len() - } - ty::UniqTraitStore => { - address_operations.len() - 1 - } + let address_op_count = if captured_by_ref { + address_operations.len() + } else { + address_operations.len() - 1 }; let variable_access = IndirectVariable { diff --git a/src/test/debuginfo/var-captured-in-sendable-closure.rs b/src/test/debuginfo/var-captured-in-sendable-closure.rs index df32d385e0e..fca47ed47bd 100644 --- a/src/test/debuginfo/var-captured-in-sendable-closure.rs +++ b/src/test/debuginfo/var-captured-in-sendable-closure.rs @@ -23,7 +23,11 @@ // gdb-check:$2 = {a = -2, b = 3.5, c = 4} // gdb-command:print *owned // gdb-check:$3 = 5 +// gdb-command:continue +// gdb-command:print constant2 +// gdb-check:$4 = 6 +// gdb-command:continue // === LLDB TESTS ================================================================================== @@ -37,6 +41,7 @@ // lldb-check:[...]$2 = 5 #![allow(unused_variables)] +#![feature(unboxed_closures)] struct Struct { a: int, @@ -55,12 +60,24 @@ fn main() { let owned = box 5; - let closure: proc() = proc() { + let closure = move |:| { zzz(); // #break do_something(&constant, &a_struct.a, &*owned); }; closure(); + + let constant2 = 6u; + + // The `self` argument of the following closure should be passed by value + // to FnOnce::call_once(self, args), which gets translated a bit differently + // than the regular case. Let's make sure this is supported too. + let immedate_env = move |:| { + zzz(); // #break + return constant2; + }; + + immedate_env(); } fn do_something(_: &int, _:&int, _:&int) {