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);
}
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);
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
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;
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 {
// 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 ==================================================================================
// lldb-check:[...]$2 = 5
#![allow(unused_variables)]
+#![feature(unboxed_closures)]
struct Struct {
a: int,
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) {