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:
commit
fb52e69a50
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user