Skip to content

Commit b6690a8

Browse files
committed
Auto merge of #68961 - eddyb:dbg-stack-dunk, r=nagisa
rustc_codegen_ssa: only "spill" SSA-like values to the stack for debuginfo. This is an implementation of the idea described in #68817 (comment). In short, instead of debuginfo forcing otherwise-SSA-like MIR locals into `alloca`s, and requiring a `load` for each use (or two, for scalar pairs), the `alloca` is now *only* used for attaching debuginfo with `llvm.dbg.declare`: the `OperandRef` is stored to the `alloca`, but *never loaded* from it. Outside of `debug_introduce_local`, nothing cares about the debuginfo-only `alloca`, and instead works with `OperandRef` the same as MIR locals without debuginfo before this PR. This should have some of the benefits of `llvm.dbg.value`, while working today. cc @nagisa @nikomatsakis
2 parents dc4242d + 1a8f5ef commit b6690a8

File tree

5 files changed

+41
-38
lines changed

5 files changed

+41
-38
lines changed

src/librustc_codegen_ssa/mir/analyze.rs

-19
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use rustc::mir::visit::{
88
MutatingUseContext, NonMutatingUseContext, NonUseContext, PlaceContext, Visitor,
99
};
1010
use rustc::mir::{self, Location, TerminatorKind};
11-
use rustc::session::config::DebugInfo;
1211
use rustc::ty;
1312
use rustc::ty::layout::{HasTyCtxt, LayoutOf};
1413
use rustc_data_structures::graph::dominators::Dominators;
@@ -24,15 +23,6 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
2423
analyzer.visit_body(mir);
2524

2625
for (local, decl) in mir.local_decls.iter_enumerated() {
27-
// FIXME(eddyb): We should figure out how to use llvm.dbg.value instead
28-
// of putting everything in allocas just so we can use llvm.dbg.declare.
29-
if fx.cx.sess().opts.debuginfo == DebugInfo::Full {
30-
if fx.mir.local_kind(local) == mir::LocalKind::Arg {
31-
analyzer.not_ssa(local);
32-
continue;
33-
}
34-
}
35-
3626
let ty = fx.monomorphize(&decl.ty);
3727
debug!("local {:?} has type `{}`", local, ty);
3828
let layout = fx.cx.spanned_layout_of(ty, decl.source_info.span);
@@ -281,15 +271,6 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
281271
self.assign(local, location);
282272
}
283273

284-
PlaceContext::NonUse(NonUseContext::VarDebugInfo) => {
285-
// We need to keep locals in `alloca`s for debuginfo.
286-
// FIXME(eddyb): We should figure out how to use `llvm.dbg.value` instead
287-
// of putting everything in allocas just so we can use `llvm.dbg.declare`.
288-
if self.fx.cx.sess().opts.debuginfo == DebugInfo::Full {
289-
self.not_ssa(local);
290-
}
291-
}
292-
293274
PlaceContext::NonUse(_) | PlaceContext::MutatingUse(MutatingUseContext::Retag) => {}
294275

295276
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy)

src/librustc_codegen_ssa/mir/block.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1145,6 +1145,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
11451145
let op = bx.load_operand(place);
11461146
place.storage_dead(bx);
11471147
self.locals[index] = LocalRef::Operand(Some(op));
1148+
self.debug_introduce_local(bx, index);
11481149
}
11491150
LocalRef::Operand(Some(op)) => {
11501151
assert!(op.layout.is_zst(), "assigning to initialized SSAtemp");
@@ -1186,6 +1187,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
11861187
let op = bx.load_operand(tmp);
11871188
tmp.storage_dead(bx);
11881189
self.locals[index] = LocalRef::Operand(Some(op));
1190+
self.debug_introduce_local(bx, index);
11891191
}
11901192
DirectOperand(index) => {
11911193
// If there is a cast, we have to store and reload.
@@ -1200,6 +1202,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
12001202
OperandRef::from_immediate_or_packed_pair(bx, llval, ret_abi.layout)
12011203
};
12021204
self.locals[index] = LocalRef::Operand(Some(op));
1205+
self.debug_introduce_local(bx, index);
12031206
}
12041207
}
12051208
}

src/librustc_codegen_ssa/mir/debuginfo.rs

+34-13
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ use rustc_index::vec::IndexVec;
99
use rustc_span::symbol::{kw, Symbol};
1010
use rustc_span::{BytePos, Span};
1111

12-
use super::OperandValue;
12+
use super::operand::OperandValue;
13+
use super::place::PlaceRef;
1314
use super::{FunctionCx, LocalRef};
1415

1516
pub struct FunctionDebugContext<D> {
@@ -111,8 +112,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
111112

112113
/// Apply debuginfo and/or name, after creating the `alloca` for a local,
113114
/// or initializing the local with an operand (whichever applies).
114-
// FIXME(eddyb) use `llvm.dbg.value` (which would work for operands),
115-
// not just `llvm.dbg.declare` (which requires `alloca`).
116115
pub fn debug_introduce_local(&self, bx: &mut Bx, local: mir::Local) {
117116
let full_debug_info = bx.sess().opts.debuginfo == DebugInfo::Full;
118117

@@ -180,38 +179,60 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
180179

181180
let local_ref = &self.locals[local];
182181

183-
if !bx.sess().fewer_names() {
184-
let name = match whole_local_var.or(fallback_var) {
182+
let name = if bx.sess().fewer_names() {
183+
None
184+
} else {
185+
Some(match whole_local_var.or(fallback_var) {
185186
Some(var) if var.name != kw::Invalid => var.name.to_string(),
186187
_ => format!("{:?}", local),
187-
};
188+
})
189+
};
190+
191+
if let Some(name) = &name {
188192
match local_ref {
189193
LocalRef::Place(place) | LocalRef::UnsizedPlace(place) => {
190-
bx.set_var_name(place.llval, &name);
194+
bx.set_var_name(place.llval, name);
191195
}
192196
LocalRef::Operand(Some(operand)) => match operand.val {
193197
OperandValue::Ref(x, ..) | OperandValue::Immediate(x) => {
194-
bx.set_var_name(x, &name);
198+
bx.set_var_name(x, name);
195199
}
196200
OperandValue::Pair(a, b) => {
197201
// FIXME(eddyb) these are scalar components,
198202
// maybe extract the high-level fields?
199203
bx.set_var_name(a, &(name.clone() + ".0"));
200-
bx.set_var_name(b, &(name + ".1"));
204+
bx.set_var_name(b, &(name.clone() + ".1"));
201205
}
202206
},
203207
LocalRef::Operand(None) => {}
204208
}
205209
}
206210

207-
if !full_debug_info {
211+
if !full_debug_info || vars.is_empty() && fallback_var.is_none() {
208212
return;
209213
}
210214

211-
// FIXME(eddyb) add debuginfo for unsized places too.
212215
let base = match local_ref {
213-
LocalRef::Place(place) => place,
214-
_ => return,
216+
LocalRef::Operand(None) => return,
217+
218+
LocalRef::Operand(Some(operand)) => {
219+
// "Spill" the value onto the stack, for debuginfo,
220+
// without forcing non-debuginfo uses of the local
221+
// to also load from the stack every single time.
222+
// FIXME(#68817) use `llvm.dbg.value` instead,
223+
// at least for the cases which LLVM handles correctly.
224+
let spill_slot = PlaceRef::alloca(bx, operand.layout);
225+
if let Some(name) = name {
226+
bx.set_var_name(spill_slot.llval, &(name + ".dbg.spill"));
227+
}
228+
operand.val.store(bx, spill_slot);
229+
spill_slot
230+
}
231+
232+
LocalRef::Place(place) => *place,
233+
234+
// FIXME(eddyb) add debuginfo for unsized places too.
235+
LocalRef::UnsizedPlace(_) => return,
215236
};
216237

217238
let vars = vars.iter().copied().chain(fallback_var);

src/test/codegen/naked-functions.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// ignore-tidy-linelength
2-
31
// compile-flags: -C no-prepopulate-passes
42

53
#![crate_type = "lib"]
@@ -61,19 +59,19 @@ pub fn naked_recursive() {
6159

6260
naked_empty();
6361

64-
// CHECK-NEXT: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_return()
62+
// CHECK-NEXT: %_4 = call i{{[0-9]+}} @naked_with_return()
6563

6664
// FIXME(#39685) Avoid one block per call.
6765
// CHECK-NEXT: br label %bb2
6866
// CHECK: bb2:
6967

70-
// CHECK-NEXT: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}} %{{[0-9]+}})
68+
// CHECK-NEXT: %_3 = call i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}} %_4)
7169

7270
// FIXME(#39685) Avoid one block per call.
7371
// CHECK-NEXT: br label %bb3
7472
// CHECK: bb3:
7573

76-
// CHECK-NEXT: call void @naked_with_args(i{{[0-9]+}} %{{[0-9]+}})
74+
// CHECK-NEXT: call void @naked_with_args(i{{[0-9]+}} %_3)
7775

7876
// FIXME(#39685) Avoid one block per call.
7977
// CHECK-NEXT: br label %bb4

src/test/debuginfo/issue-12886.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
// gdb-command:run
88
// gdb-command:next
9-
// gdb-check:[...]25[...]s
9+
// gdb-check:[...]24[...]let s = Some(5).unwrap(); // #break
1010
// gdb-command:continue
1111

1212
#![feature(omit_gdb_pretty_printer_section)]

0 commit comments

Comments
 (0)