auto merge of #19363 : michaelwoerister/rust/support-unboxed-closures, r=alexcrichton

This PR lets `rustc` generate debuginfo for variables captured by unboxed closures. 

Fixes #19356

@nikomatsakis This PR will probably conflict with #19338. If this gets merged before, you should be able to just leave the test case as it is (maybe remove the `#![feature(unboxed_closures)]` directive).
This commit is contained in:
bors 2014-11-28 09:31:24 +00:00
commit fb52e69a50
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;
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

View 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 {

View File

@ -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) {