Skip to content

Commit fb52e69

Browse files
committed
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).
2 parents 832dc61 + 251386c commit fb52e69

File tree

3 files changed

+60
-18
lines changed

3 files changed

+60
-18
lines changed

src/librustc_trans/trans/closure.rs

+37-9
Original file line numberDiff line numberDiff line change
@@ -272,21 +272,24 @@ fn load_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
272272
let mut i = 0u;
273273
for freevar in freevars.iter() {
274274
let mut upvarptr = GEPi(bcx, llcdata, &[0u, i]);
275-
match store {
276-
ty::RegionTraitStore(..) => { upvarptr = Load(bcx, upvarptr); }
277-
ty::UniqTraitStore => {}
278-
}
275+
let captured_by_ref = match store {
276+
ty::RegionTraitStore(..) => {
277+
upvarptr = Load(bcx, upvarptr);
278+
true
279+
}
280+
ty::UniqTraitStore => false
281+
};
279282
let def_id = freevar.def.def_id();
280283

281284
bcx.fcx.llupvars.borrow_mut().insert(def_id.node, upvarptr);
282-
for &env_pointer_alloca in env_pointer_alloca.iter() {
285+
if let Some(env_pointer_alloca) = env_pointer_alloca {
283286
debuginfo::create_captured_var_metadata(
284287
bcx,
285288
def_id.node,
286289
cdata_ty,
287290
env_pointer_alloca,
288291
i,
289-
store,
292+
captured_by_ref,
290293
freevar.span);
291294
}
292295

@@ -320,11 +323,25 @@ fn load_unboxed_closure_environment<'blk, 'tcx>(
320323
bcx.fcx.llenv.unwrap()
321324
};
322325

326+
// Store the pointer to closure data in an alloca for debug info because that's what the
327+
// llvm.dbg.declare intrinsic expects
328+
let env_pointer_alloca = if bcx.sess().opts.debuginfo == FullDebugInfo {
329+
let alloc = alloc_ty(bcx, ty::mk_mut_ptr(bcx.tcx(), self_type), "__debuginfo_env_ptr");
330+
Store(bcx, llenv, alloc);
331+
Some(alloc)
332+
} else {
333+
None
334+
};
335+
323336
for (i, freevar) in freevars.iter().enumerate() {
324337
let mut upvar_ptr = GEPi(bcx, llenv, &[0, i]);
325-
if freevar_mode == ast::CaptureByRef {
326-
upvar_ptr = Load(bcx, upvar_ptr);
327-
}
338+
let captured_by_ref = match freevar_mode {
339+
ast::CaptureByRef => {
340+
upvar_ptr = Load(bcx, upvar_ptr);
341+
true
342+
}
343+
ast::CaptureByValue => false
344+
};
328345
let def_id = freevar.def.def_id();
329346
bcx.fcx.llupvars.borrow_mut().insert(def_id.node, upvar_ptr);
330347

@@ -333,6 +350,17 @@ fn load_unboxed_closure_environment<'blk, 'tcx>(
333350
upvar_ptr,
334351
node_id_type(bcx, def_id.node))
335352
}
353+
354+
if let Some(env_pointer_alloca) = env_pointer_alloca {
355+
debuginfo::create_captured_var_metadata(
356+
bcx,
357+
def_id.node,
358+
self_type,
359+
env_pointer_alloca,
360+
i,
361+
captured_by_ref,
362+
freevar.span);
363+
}
336364
}
337365

338366
bcx

src/librustc_trans/trans/debuginfo.rs

+5-8
Original file line numberDiff line numberDiff line change
@@ -885,7 +885,7 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
885885
env_data_type: Ty<'tcx>,
886886
env_pointer: ValueRef,
887887
env_index: uint,
888-
closure_store: ty::TraitStore,
888+
captured_by_ref: bool,
889889
span: Span) {
890890
if fn_should_be_ignored(bcx.fcx) {
891891
return;
@@ -940,13 +940,10 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
940940
llvm::LLVMDIBuilderCreateOpDeref(Type::i64(cx).to_ref())]
941941
};
942942

943-
let address_op_count = match closure_store {
944-
ty::RegionTraitStore(..) => {
945-
address_operations.len()
946-
}
947-
ty::UniqTraitStore => {
948-
address_operations.len() - 1
949-
}
943+
let address_op_count = if captured_by_ref {
944+
address_operations.len()
945+
} else {
946+
address_operations.len() - 1
950947
};
951948

952949
let variable_access = IndirectVariable {

src/test/debuginfo/var-captured-in-sendable-closure.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@
2323
// gdb-check:$2 = {a = -2, b = 3.5, c = 4}
2424
// gdb-command:print *owned
2525
// gdb-check:$3 = 5
26+
// gdb-command:continue
2627

28+
// gdb-command:print constant2
29+
// gdb-check:$4 = 6
30+
// gdb-command:continue
2731

2832
// === LLDB TESTS ==================================================================================
2933

@@ -37,6 +41,7 @@
3741
// lldb-check:[...]$2 = 5
3842

3943
#![allow(unused_variables)]
44+
#![feature(unboxed_closures)]
4045

4146
struct Struct {
4247
a: int,
@@ -55,12 +60,24 @@ fn main() {
5560

5661
let owned = box 5;
5762

58-
let closure: proc() = proc() {
63+
let closure = move |:| {
5964
zzz(); // #break
6065
do_something(&constant, &a_struct.a, &*owned);
6166
};
6267

6368
closure();
69+
70+
let constant2 = 6u;
71+
72+
// The `self` argument of the following closure should be passed by value
73+
// to FnOnce::call_once(self, args), which gets translated a bit differently
74+
// than the regular case. Let's make sure this is supported too.
75+
let immedate_env = move |:| {
76+
zzz(); // #break
77+
return constant2;
78+
};
79+
80+
immedate_env();
6481
}
6582

6683
fn do_something(_: &int, _:&int, _:&int) {

0 commit comments

Comments
 (0)