1
Fork 0

debuginfo: Make variables captured in unboxed closures available in debuginfo.

This commit is contained in:
Michael Woerister 2014-11-27 15:52:16 +01:00
parent 82fc1aa875
commit 251386c605
3 changed files with 60 additions and 18 deletions

View file

@ -272,21 +272,24 @@ fn load_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let mut i = 0u; let mut i = 0u;
for freevar in freevars.iter() { for freevar in freevars.iter() {
let mut upvarptr = GEPi(bcx, llcdata, &[0u, i]); let mut upvarptr = GEPi(bcx, llcdata, &[0u, i]);
match store { let captured_by_ref = match store {
ty::RegionTraitStore(..) => { upvarptr = Load(bcx, upvarptr); } ty::RegionTraitStore(..) => {
ty::UniqTraitStore => {} upvarptr = Load(bcx, upvarptr);
true
} }
ty::UniqTraitStore => false
};
let def_id = freevar.def.def_id(); let def_id = freevar.def.def_id();
bcx.fcx.llupvars.borrow_mut().insert(def_id.node, upvarptr); 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( debuginfo::create_captured_var_metadata(
bcx, bcx,
def_id.node, def_id.node,
cdata_ty, cdata_ty,
env_pointer_alloca, env_pointer_alloca,
i, i,
store, captured_by_ref,
freevar.span); freevar.span);
} }
@ -320,11 +323,25 @@ fn load_unboxed_closure_environment<'blk, 'tcx>(
bcx.fcx.llenv.unwrap() 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() { for (i, freevar) in freevars.iter().enumerate() {
let mut upvar_ptr = GEPi(bcx, llenv, &[0, i]); let mut upvar_ptr = GEPi(bcx, llenv, &[0, i]);
if freevar_mode == ast::CaptureByRef { let captured_by_ref = match freevar_mode {
ast::CaptureByRef => {
upvar_ptr = Load(bcx, upvar_ptr); upvar_ptr = Load(bcx, upvar_ptr);
true
} }
ast::CaptureByValue => false
};
let def_id = freevar.def.def_id(); let def_id = freevar.def.def_id();
bcx.fcx.llupvars.borrow_mut().insert(def_id.node, upvar_ptr); bcx.fcx.llupvars.borrow_mut().insert(def_id.node, upvar_ptr);
@ -333,6 +350,17 @@ fn load_unboxed_closure_environment<'blk, 'tcx>(
upvar_ptr, upvar_ptr,
node_id_type(bcx, def_id.node)) 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 bcx

View file

@ -885,7 +885,7 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
env_data_type: Ty<'tcx>, env_data_type: Ty<'tcx>,
env_pointer: ValueRef, env_pointer: ValueRef,
env_index: uint, env_index: uint,
closure_store: ty::TraitStore, captured_by_ref: bool,
span: Span) { span: Span) {
if fn_should_be_ignored(bcx.fcx) { if fn_should_be_ignored(bcx.fcx) {
return; return;
@ -940,13 +940,10 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
llvm::LLVMDIBuilderCreateOpDeref(Type::i64(cx).to_ref())] llvm::LLVMDIBuilderCreateOpDeref(Type::i64(cx).to_ref())]
}; };
let address_op_count = match closure_store { let address_op_count = if captured_by_ref {
ty::RegionTraitStore(..) => {
address_operations.len() address_operations.len()
} } else {
ty::UniqTraitStore => {
address_operations.len() - 1 address_operations.len() - 1
}
}; };
let variable_access = IndirectVariable { let variable_access = IndirectVariable {

View file

@ -23,7 +23,11 @@
// gdb-check:$2 = {a = -2, b = 3.5, c = 4} // gdb-check:$2 = {a = -2, b = 3.5, c = 4}
// gdb-command:print *owned // gdb-command:print *owned
// gdb-check:$3 = 5 // gdb-check:$3 = 5
// gdb-command:continue
// gdb-command:print constant2
// gdb-check:$4 = 6
// gdb-command:continue
// === LLDB TESTS ================================================================================== // === LLDB TESTS ==================================================================================
@ -37,6 +41,7 @@
// lldb-check:[...]$2 = 5 // lldb-check:[...]$2 = 5
#![allow(unused_variables)] #![allow(unused_variables)]
#![feature(unboxed_closures)]
struct Struct { struct Struct {
a: int, a: int,
@ -55,12 +60,24 @@ fn main() {
let owned = box 5; let owned = box 5;
let closure: proc() = proc() { let closure = move |:| {
zzz(); // #break zzz(); // #break
do_something(&constant, &a_struct.a, &*owned); do_something(&constant, &a_struct.a, &*owned);
}; };
closure(); 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) { fn do_something(_: &int, _:&int, _:&int) {