]> git.lizzy.rs Git - rust.git/commitdiff
debuginfo: Make variables captured in unboxed closures available in debuginfo.
authorMichael Woerister <michaelwoerister@posteo>
Thu, 27 Nov 2014 14:52:16 +0000 (15:52 +0100)
committerMichael Woerister <michaelwoerister@posteo>
Thu, 27 Nov 2014 15:38:17 +0000 (16:38 +0100)
src/librustc_trans/trans/closure.rs
src/librustc_trans/trans/debuginfo.rs
src/test/debuginfo/var-captured-in-sendable-closure.rs

index 2f82b8286c2d531da021e90752b4eba7b025b56f..bb4df00bd944a1147ed9f6504767897d6a4b2082 100644 (file)
@@ -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
index c35de3209c61f087566f87ab65495783bdf0c5cd..326adf1f3e7b633c2b2b769b4222ab99bc4c73ca 100644 (file)
@@ -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 {
index df32d385e0e731ffe4f33d7c46436d245a954da1..fca47ed47bd7a1adeeee3503369fc362301a006e 100644 (file)
 // 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) {