Skip to content

Commit 5f4ee36

Browse files
committed
rustc_codegen_ssa: move all set_var_name calls to mir::debuginfo.
1 parent c58e6b5 commit 5f4ee36

File tree

6 files changed

+217
-173
lines changed

6 files changed

+217
-173
lines changed

src/librustc_codegen_ssa/mir/debuginfo.rs

Lines changed: 112 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ use rustc::ty::layout::HasTyCtxt;
77
use rustc_target::abi::{Variants, VariantIdx};
88
use crate::traits::*;
99

10+
use std::fmt;
1011
use syntax_pos::{DUMMY_SP, BytePos, Span};
1112
use syntax::symbol::kw;
1213

1314
use super::{FunctionCx, LocalRef};
15+
use super::OperandValue;
1416

1517
pub enum FunctionDebugContext<D> {
1618
RegularContext(FunctionDebugContextData<D>),
@@ -90,6 +92,29 @@ impl<D> DebugScope<D> {
9092
}
9193
}
9294

95+
// HACK(eddyb) helpers for `set_var_name` calls, move elsewhere?
96+
enum Either<T, U> {
97+
Left(T),
98+
Right(U),
99+
}
100+
101+
impl<T: fmt::Display, U: fmt::Display> fmt::Display for Either<T, U> {
102+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103+
match self {
104+
Either::Left(x) => x.fmt(f),
105+
Either::Right(x) => x.fmt(f),
106+
}
107+
}
108+
}
109+
110+
struct DisplayViaDebug<T>(T);
111+
112+
impl<T: fmt::Debug> fmt::Display for DisplayViaDebug<T> {
113+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
114+
self.0.fmt(f)
115+
}
116+
}
117+
93118
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
94119
pub fn set_debug_loc(
95120
&mut self,
@@ -149,54 +174,107 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
149174
}
150175
}
151176

152-
pub fn debug_declare_locals(&self, bx: &mut Bx) {
153-
let tcx = self.cx.tcx();
177+
/// Apply debuginfo and/or name, after creating the `alloca` for a local,
178+
/// or initializing the local with an operand (whichever applies).
179+
// FIXME(eddyb) use `llvm.dbg.value` (which would work for operands),
180+
// not just `llvm.dbg.declare` (which requires `alloca`).
181+
pub fn debug_introduce_local(&self, bx: &mut Bx, local: mir::Local) {
154182
let upvar_debuginfo = &self.mir.__upvar_debuginfo_codegen_only_do_not_use;
155183

156-
if bx.sess().opts.debuginfo != DebugInfo::Full {
184+
// FIXME(eddyb) maybe name the return place as `_0` or `return`?
185+
if local == mir::RETURN_PLACE {
157186
return;
158187
}
159188

160-
for (local, local_ref) in self.locals.iter_enumerated() {
161-
if local == mir::RETURN_PLACE {
162-
continue;
189+
let decl = &self.mir.local_decls[local];
190+
let (name, kind) = if self.mir.local_kind(local) == mir::LocalKind::Arg {
191+
let arg_index = local.index() - 1;
192+
193+
// Add debuginfo even to unnamed arguments.
194+
// FIXME(eddyb) is this really needed?
195+
let name = if arg_index == 0 && !upvar_debuginfo.is_empty() {
196+
// Hide closure environments from debuginfo.
197+
// FIXME(eddyb) shouldn't `ArgumentVariable` indices
198+
// be offset to account for the hidden environment?
199+
None
200+
} else {
201+
Some(decl.name.unwrap_or(kw::Invalid))
202+
};
203+
(name, VariableKind::ArgumentVariable(arg_index + 1))
204+
} else {
205+
(decl.name, VariableKind::LocalVariable)
206+
};
207+
208+
let local_ref = &self.locals[local];
209+
210+
{
211+
let name = match name {
212+
Some(name) if name != kw::Invalid => Either::Left(name),
213+
_ => Either::Right(DisplayViaDebug(local)),
214+
};
215+
match local_ref {
216+
LocalRef::Place(place) |
217+
LocalRef::UnsizedPlace(place) => {
218+
bx.set_var_name(place.llval, name);
219+
}
220+
LocalRef::Operand(Some(operand)) => match operand.val {
221+
OperandValue::Ref(x, ..) |
222+
OperandValue::Immediate(x) => {
223+
bx.set_var_name(x, name);
224+
}
225+
OperandValue::Pair(a, b) => {
226+
// FIXME(eddyb) these are scalar components,
227+
// maybe extract the high-level fields?
228+
bx.set_var_name(a, format_args!("{}.0", name));
229+
bx.set_var_name(b, format_args!("{}.1", name));
230+
}
231+
}
232+
LocalRef::Operand(None) => {}
233+
}
234+
}
235+
236+
if let Some(name) = name {
237+
if bx.sess().opts.debuginfo != DebugInfo::Full {
238+
return;
163239
}
164240

165241
// FIXME(eddyb) add debuginfo for unsized places too.
166242
let place = match local_ref {
167243
LocalRef::Place(place) => place,
168-
_ => continue,
244+
_ => return,
169245
};
170246

171-
let decl = &self.mir.local_decls[local];
172-
let (name, kind) = if self.mir.local_kind(local) == mir::LocalKind::Arg {
173-
let arg_index = local.index() - 1;
174-
175-
// Add debuginfo even to unnamed arguments.
176-
// FIXME(eddyb) is this really needed?
177-
let name = if arg_index == 0 && !upvar_debuginfo.is_empty() {
178-
// Hide closure environments from debuginfo.
179-
// FIXME(eddyb) shouldn't `ArgumentVariable` indices
180-
// be offset to account for the hidden environment?
181-
None
182-
} else {
183-
Some(decl.name.unwrap_or(kw::Invalid))
184-
};
185-
(name, VariableKind::ArgumentVariable(arg_index + 1))
186-
} else {
187-
(decl.name, VariableKind::LocalVariable)
188-
};
189-
if let Some(name) = name {
190-
let (scope, span) = self.debug_loc(mir::SourceInfo {
191-
span: decl.source_info.span,
192-
scope: decl.visibility_scope,
193-
});
194-
if let Some(scope) = scope {
195-
bx.declare_local(&self.debug_context, name, place.layout.ty, scope,
196-
VariableAccess::DirectVariable { alloca: place.llval },
197-
kind, span);
247+
let (scope, span) = self.debug_loc(mir::SourceInfo {
248+
span: decl.source_info.span,
249+
scope: decl.visibility_scope,
250+
});
251+
if let Some(scope) = scope {
252+
bx.declare_local(&self.debug_context, name, place.layout.ty, scope,
253+
VariableAccess::DirectVariable { alloca: place.llval },
254+
kind, span);
255+
}
256+
}
257+
}
258+
259+
pub fn debug_introduce_locals(&self, bx: &mut Bx) {
260+
let tcx = self.cx.tcx();
261+
let upvar_debuginfo = &self.mir.__upvar_debuginfo_codegen_only_do_not_use;
262+
263+
if bx.sess().opts.debuginfo != DebugInfo::Full {
264+
// HACK(eddyb) figure out a way to perhaps disentangle
265+
// the use of `declare_local` and `set_var_name`.
266+
// Or maybe just running this loop always is not that expensive?
267+
if !bx.sess().fewer_names() {
268+
for local in self.locals.indices() {
269+
self.debug_introduce_local(bx, local);
198270
}
199271
}
272+
273+
return;
274+
}
275+
276+
for local in self.locals.indices() {
277+
self.debug_introduce_local(bx, local);
200278
}
201279

202280
// Declare closure captures as if they were local variables.

src/librustc_codegen_ssa/mir/mod.rs

Lines changed: 5 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -190,31 +190,15 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
190190
return LocalRef::Place(PlaceRef::new_sized(llretptr, layout));
191191
}
192192

193-
let decl_name = decl.name.map(|name| name.as_str());
194-
let decl_name = decl_name.as_ref().map(|name| &name[..]);
195-
let name;
196-
let name = if let Some(name) = decl_name {
197-
name
198-
} else {
199-
// FIXME(eddyb) compute something else for the name so no work is done
200-
// unless LLVM IR names are turned on (e.g. for `--emit=llvm-ir`).
201-
name = format!("{:?}", local);
202-
&name
203-
};
204-
205193
if memory_locals.contains(local) {
206-
debug!("alloc: {:?} ({}) -> place", local, name);
194+
debug!("alloc: {:?} -> place", local);
207195
if layout.is_unsized() {
208-
let indirect_place = PlaceRef::alloca_unsized_indirect(&mut bx, layout);
209-
bx.set_var_name(indirect_place.llval, name);
210-
LocalRef::UnsizedPlace(indirect_place)
196+
LocalRef::UnsizedPlace(PlaceRef::alloca_unsized_indirect(&mut bx, layout))
211197
} else {
212-
let place = PlaceRef::alloca(&mut bx, layout);
213-
bx.set_var_name(place.llval, name);
214-
LocalRef::Place(place)
198+
LocalRef::Place(PlaceRef::alloca(&mut bx, layout))
215199
}
216200
} else {
217-
debug!("alloc: {:?} ({}) -> operand", local, name);
201+
debug!("alloc: {:?} -> operand", local);
218202
LocalRef::new_operand(&mut bx, layout)
219203
}
220204
};
@@ -227,7 +211,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
227211
};
228212

229213
// Apply debuginfo to the newly allocated locals.
230-
fx.debug_declare_locals(&mut bx);
214+
fx.debug_introduce_locals(&mut bx);
231215

232216
// Branch to the START block, if it's not the entry block.
233217
if reentrant_start_block {
@@ -343,13 +327,6 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
343327
mir.args_iter().enumerate().map(|(arg_index, local)| {
344328
let arg_decl = &mir.local_decls[local];
345329

346-
// FIXME(eddyb) don't allocate a `String` unless it gets used.
347-
let name = if let Some(name) = arg_decl.name {
348-
name.as_str().to_string()
349-
} else {
350-
format!("{:?}", local)
351-
};
352-
353330
if Some(local) == mir.spread_arg {
354331
// This argument (e.g., the last argument in the "rust-call" ABI)
355332
// is a tuple that was spread at the ABI level and now we have
@@ -363,7 +340,6 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
363340
};
364341

365342
let place = PlaceRef::alloca(bx, bx.layout_of(arg_ty));
366-
bx.set_var_name(place.llval, name);
367343
for i in 0..tupled_arg_tys.len() {
368344
let arg = &fx.fn_ty.args[idx];
369345
idx += 1;
@@ -381,7 +357,6 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
381357
let arg_ty = fx.monomorphize(&arg_decl.ty);
382358

383359
let va_list = PlaceRef::alloca(bx, bx.layout_of(arg_ty));
384-
bx.set_var_name(va_list.llval, name);
385360
bx.va_start(va_list.llval);
386361

387362
return LocalRef::Place(va_list);
@@ -404,7 +379,6 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
404379
}
405380
PassMode::Direct(_) => {
406381
let llarg = bx.get_param(llarg_idx);
407-
bx.set_var_name(llarg, &name);
408382
llarg_idx += 1;
409383
return local(
410384
OperandRef::from_immediate_or_packed_pair(bx, llarg, arg.layout));
@@ -413,11 +387,6 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
413387
let (a, b) = (bx.get_param(llarg_idx), bx.get_param(llarg_idx + 1));
414388
llarg_idx += 2;
415389

416-
// FIXME(eddyb) these are scalar components,
417-
// maybe extract the high-level fields?
418-
bx.set_var_name(a, format_args!("{}.0", name));
419-
bx.set_var_name(b, format_args!("{}.1", name));
420-
421390
return local(OperandRef {
422391
val: OperandValue::Pair(a, b),
423392
layout: arg.layout
@@ -432,7 +401,6 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
432401
// already put it in a temporary alloca and gave it up.
433402
// FIXME: lifetimes
434403
let llarg = bx.get_param(llarg_idx);
435-
bx.set_var_name(llarg, &name);
436404
llarg_idx += 1;
437405
LocalRef::Place(PlaceRef::new_sized(llarg, arg.layout))
438406
} else if arg.is_unsized_indirect() {
@@ -445,12 +413,10 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
445413
let indirect_operand = OperandValue::Pair(llarg, llextra);
446414

447415
let tmp = PlaceRef::alloca_unsized_indirect(bx, arg.layout);
448-
bx.set_var_name(tmp.llval, name);
449416
indirect_operand.store(bx, tmp);
450417
LocalRef::UnsizedPlace(tmp)
451418
} else {
452419
let tmp = PlaceRef::alloca(bx, arg.layout);
453-
bx.set_var_name(tmp.llval, name);
454420
bx.store_fn_arg(arg, &mut llarg_idx, tmp);
455421
LocalRef::Place(tmp)
456422
}

src/librustc_codegen_ssa/mir/statement.rs

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
2727
}
2828
LocalRef::Operand(None) => {
2929
let (mut bx, operand) = self.codegen_rvalue_operand(bx, rvalue);
30-
if let Some(name) = self.mir.local_decls[index].name {
31-
match operand.val {
32-
OperandValue::Ref(x, ..) |
33-
OperandValue::Immediate(x) => {
34-
bx.set_var_name(x, name);
35-
}
36-
OperandValue::Pair(a, b) => {
37-
// FIXME(eddyb) these are scalar components,
38-
// maybe extract the high-level fields?
39-
bx.set_var_name(a, format_args!("{}.0", name));
40-
bx.set_var_name(b, format_args!("{}.1", name));
41-
}
42-
}
43-
}
4430
self.locals[index] = LocalRef::Operand(Some(operand));
31+
self.debug_introduce_local(&mut bx, index);
4532
bx
4633
}
4734
LocalRef::Operand(Some(op)) => {

src/test/codegen/optimize-attr-1.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
// CHECK-LABEL: define i32 @nothing
1010
// CHECK-SAME: [[NOTHING_ATTRS:#[0-9]+]]
11-
// NO-OPT: ret i32 %1
11+
// NO-OPT: ret i32 %_1.0
1212
// SIZE-OPT: ret i32 4
1313
// SPEEC-OPT: ret i32 4
1414
#[no_mangle]
@@ -18,7 +18,7 @@ pub fn nothing() -> i32 {
1818

1919
// CHECK-LABEL: define i32 @size
2020
// CHECK-SAME: [[SIZE_ATTRS:#[0-9]+]]
21-
// NO-OPT: ret i32 %1
21+
// NO-OPT: ret i32 %_1.0
2222
// SIZE-OPT: ret i32 6
2323
// SPEED-OPT: ret i32 6
2424
#[optimize(size)]
@@ -31,7 +31,7 @@ pub fn size() -> i32 {
3131
// NO-OPT-SAME: [[NOTHING_ATTRS]]
3232
// SPEED-OPT-SAME: [[NOTHING_ATTRS]]
3333
// SIZE-OPT-SAME: [[SPEED_ATTRS:#[0-9]+]]
34-
// NO-OPT: ret i32 %1
34+
// NO-OPT: ret i32 %_1.0
3535
// SIZE-OPT: ret i32 8
3636
// SPEED-OPT: ret i32 8
3737
#[optimize(speed)]

0 commit comments

Comments
 (0)