Skip to content

Commit 01e5d91

Browse files
committed
Auto merge of #65718 - eddyb:codegen-var-debuginfo, r=nikomatsakis
rustc_codegen_ssa: introduce MIR VarDebugInfo, but only for codegen. These are all the codegen changes necessary for #56231. The refactors were performed locally to codegen, and in several steps, to ease reviewing and avoid introducing changes in behavior (as I'm not sure our debuginfo tests cover enough). r? @michaelwoerister cc @nagisa @rkruppe @oli-obk
2 parents 253fc0e + 60a2266 commit 01e5d91

File tree

14 files changed

+655
-653
lines changed

14 files changed

+655
-653
lines changed

src/librustc_codegen_llvm/debuginfo/create_scope_map.rs

+21-37
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_codegen_ssa::debuginfo::{FunctionDebugContext, FunctionDebugContextData, MirDebugScope};
1+
use rustc_codegen_ssa::mir::debuginfo::{FunctionDebugContext, DebugScope};
22
use super::metadata::file_metadata;
33
use super::utils::{DIB, span_start};
44

@@ -12,34 +12,20 @@ use libc::c_uint;
1212
use syntax_pos::Pos;
1313

1414
use rustc_index::bit_set::BitSet;
15-
use rustc_index::vec::{Idx, IndexVec};
16-
17-
use syntax_pos::BytePos;
15+
use rustc_index::vec::Idx;
1816

1917
/// Produces DIScope DIEs for each MIR Scope which has variables defined in it.
20-
/// If debuginfo is disabled, the returned vector is empty.
21-
pub fn create_mir_scopes(
18+
pub fn compute_mir_scopes(
2219
cx: &CodegenCx<'ll, '_>,
2320
mir: &Body<'_>,
24-
debug_context: &FunctionDebugContext<&'ll DISubprogram>,
25-
) -> IndexVec<SourceScope, MirDebugScope<&'ll DIScope>> {
26-
let null_scope = MirDebugScope {
27-
scope_metadata: None,
28-
file_start_pos: BytePos(0),
29-
file_end_pos: BytePos(0)
30-
};
31-
let mut scopes = IndexVec::from_elem(null_scope, &mir.source_scopes);
32-
33-
let debug_context = match *debug_context {
34-
FunctionDebugContext::RegularContext(ref data) => data,
35-
FunctionDebugContext::DebugInfoDisabled |
36-
FunctionDebugContext::FunctionWithoutDebugInfo => {
37-
return scopes;
38-
}
39-
};
40-
21+
fn_metadata: &'ll DISubprogram,
22+
debug_context: &mut FunctionDebugContext<&'ll DIScope>,
23+
) {
4124
// Find all the scopes with variables defined in them.
4225
let mut has_variables = BitSet::new_empty(mir.source_scopes.len());
26+
// FIXME(eddyb) base this on `decl.name`, or even better, on debuginfo.
27+
// FIXME(eddyb) take into account that arguments always have debuginfo,
28+
// irrespective of their name (assuming full debuginfo is enabled).
4329
for var in mir.vars_iter() {
4430
let decl = &mir.local_decls[var];
4531
has_variables.insert(decl.visibility_scope);
@@ -48,31 +34,29 @@ pub fn create_mir_scopes(
4834
// Instantiate all scopes.
4935
for idx in 0..mir.source_scopes.len() {
5036
let scope = SourceScope::new(idx);
51-
make_mir_scope(cx, &mir, &has_variables, debug_context, scope, &mut scopes);
37+
make_mir_scope(cx, &mir, fn_metadata, &has_variables, debug_context, scope);
5238
}
53-
54-
scopes
5539
}
5640

5741
fn make_mir_scope(cx: &CodegenCx<'ll, '_>,
5842
mir: &Body<'_>,
43+
fn_metadata: &'ll DISubprogram,
5944
has_variables: &BitSet<SourceScope>,
60-
debug_context: &FunctionDebugContextData<&'ll DISubprogram>,
61-
scope: SourceScope,
62-
scopes: &mut IndexVec<SourceScope, MirDebugScope<&'ll DIScope>>) {
63-
if scopes[scope].is_valid() {
45+
debug_context: &mut FunctionDebugContext<&'ll DISubprogram>,
46+
scope: SourceScope) {
47+
if debug_context.scopes[scope].is_valid() {
6448
return;
6549
}
6650

6751
let scope_data = &mir.source_scopes[scope];
6852
let parent_scope = if let Some(parent) = scope_data.parent_scope {
69-
make_mir_scope(cx, mir, has_variables, debug_context, parent, scopes);
70-
scopes[parent]
53+
make_mir_scope(cx, mir, fn_metadata, has_variables, debug_context, parent);
54+
debug_context.scopes[parent]
7155
} else {
7256
// The root is the function itself.
7357
let loc = span_start(cx, mir.span);
74-
scopes[scope] = MirDebugScope {
75-
scope_metadata: Some(debug_context.fn_metadata),
58+
debug_context.scopes[scope] = DebugScope {
59+
scope_metadata: Some(fn_metadata),
7660
file_start_pos: loc.file.start_pos,
7761
file_end_pos: loc.file.end_pos,
7862
};
@@ -86,8 +70,8 @@ fn make_mir_scope(cx: &CodegenCx<'ll, '_>,
8670
// However, we don't skip creating a nested scope if
8771
// our parent is the root, because we might want to
8872
// put arguments in the root and not have shadowing.
89-
if parent_scope.scope_metadata.unwrap() != debug_context.fn_metadata {
90-
scopes[scope] = parent_scope;
73+
if parent_scope.scope_metadata.unwrap() != fn_metadata {
74+
debug_context.scopes[scope] = parent_scope;
9175
return;
9276
}
9377
}
@@ -105,7 +89,7 @@ fn make_mir_scope(cx: &CodegenCx<'ll, '_>,
10589
loc.line as c_uint,
10690
loc.col.to_usize() as c_uint))
10791
};
108-
scopes[scope] = MirDebugScope {
92+
debug_context.scopes[scope] = DebugScope {
10993
scope_metadata,
11094
file_start_pos: loc.file.start_pos,
11195
file_end_pos: loc.file.end_pos,

src/librustc_codegen_llvm/debuginfo/mod.rs

+83-76
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
// See doc.rs for documentation.
22
mod doc;
33

4-
use rustc_codegen_ssa::debuginfo::VariableAccess::*;
5-
use rustc_codegen_ssa::debuginfo::VariableKind::*;
4+
use rustc_codegen_ssa::mir::debuginfo::VariableKind::*;
65

76
use self::utils::{DIB, span_start, create_DIArray, is_node_local_to_unit};
87
use self::namespace::mangled_name_of_instance;
@@ -11,7 +10,7 @@ use self::metadata::{type_metadata, file_metadata, TypeMap};
1110
use self::source_loc::InternalDebugLocation::{self, UnknownLocation};
1211

1312
use crate::llvm;
14-
use crate::llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilder, DISubprogram, DIArray, DIFlags,
13+
use crate::llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilder, DIArray, DIFlags,
1514
DISPFlags, DILexicalBlock};
1615
use rustc::hir::CodegenFnAttrFlags;
1716
use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
@@ -27,17 +26,19 @@ use rustc::session::config::{self, DebugInfo};
2726
use rustc::util::nodemap::{DefIdMap, FxHashMap, FxHashSet};
2827
use rustc_data_structures::small_c_str::SmallCStr;
2928
use rustc_index::vec::IndexVec;
30-
use rustc_codegen_ssa::debuginfo::{FunctionDebugContext, MirDebugScope, VariableAccess,
31-
VariableKind, FunctionDebugContextData, type_names};
29+
use rustc_codegen_ssa::debuginfo::type_names;
30+
use rustc_codegen_ssa::mir::debuginfo::{FunctionDebugContext, DebugScope,
31+
VariableKind};
3232

3333
use libc::c_uint;
3434
use std::cell::RefCell;
3535
use std::ffi::{CStr, CString};
3636

37-
use syntax_pos::{self, Span, Pos};
37+
use smallvec::SmallVec;
38+
use syntax_pos::{self, BytePos, Span, Pos};
3839
use syntax::ast;
3940
use syntax::symbol::Symbol;
40-
use rustc::ty::layout::{self, LayoutOf, HasTyCtxt};
41+
use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, Size};
4142
use rustc_codegen_ssa::traits::*;
4243

4344
pub mod gdb;
@@ -47,7 +48,7 @@ pub mod metadata;
4748
mod create_scope_map;
4849
mod source_loc;
4950

50-
pub use self::create_scope_map::{create_mir_scopes};
51+
pub use self::create_scope_map::compute_mir_scopes;
5152
pub use self::metadata::create_global_var_metadata;
5253
pub use self::metadata::extend_scope_to_file;
5354
pub use self::source_loc::set_source_location;
@@ -148,21 +149,23 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
148149
impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
149150
fn declare_local(
150151
&mut self,
151-
dbg_context: &FunctionDebugContext<&'ll DISubprogram>,
152+
dbg_context: &FunctionDebugContext<&'ll DIScope>,
152153
variable_name: ast::Name,
153154
variable_type: Ty<'tcx>,
154155
scope_metadata: &'ll DIScope,
155-
variable_access: VariableAccess<'_, &'ll Value>,
156+
variable_alloca: Self::Value,
157+
direct_offset: Size,
158+
indirect_offsets: &[Size],
156159
variable_kind: VariableKind,
157160
span: Span,
158161
) {
159-
assert!(!dbg_context.get_ref(span).source_locations_enabled);
162+
assert!(!dbg_context.source_locations_enabled);
160163
let cx = self.cx();
161164

162165
let file = span_start(cx, span).file;
163166
let file_metadata = file_metadata(cx,
164167
&file.name,
165-
dbg_context.get_ref(span).defining_crate);
168+
dbg_context.defining_crate);
166169

167170
let loc = span_start(cx, span);
168171
let type_metadata = type_metadata(cx, variable_type, span);
@@ -173,49 +176,61 @@ impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
173176
};
174177
let align = cx.align_of(variable_type);
175178

176-
let name = SmallCStr::new(&variable_name.as_str());
177-
match (variable_access, &[][..]) {
178-
(DirectVariable { alloca }, address_operations) |
179-
(IndirectVariable {alloca, address_operations}, _) => {
180-
let metadata = unsafe {
181-
llvm::LLVMRustDIBuilderCreateVariable(
182-
DIB(cx),
183-
dwarf_tag,
184-
scope_metadata,
185-
name.as_ptr(),
186-
file_metadata,
187-
loc.line as c_uint,
188-
type_metadata,
189-
cx.sess().opts.optimize != config::OptLevel::No,
190-
DIFlags::FlagZero,
191-
argument_index,
192-
align.bytes() as u32,
193-
)
194-
};
195-
source_loc::set_debug_location(self,
196-
InternalDebugLocation::new(scope_metadata, loc.line, loc.col.to_usize()));
197-
unsafe {
198-
let debug_loc = llvm::LLVMGetCurrentDebugLocation(self.llbuilder);
199-
let instr = llvm::LLVMRustDIBuilderInsertDeclareAtEnd(
200-
DIB(cx),
201-
alloca,
202-
metadata,
203-
address_operations.as_ptr(),
204-
address_operations.len() as c_uint,
205-
debug_loc,
206-
self.llbb());
207-
208-
llvm::LLVMSetInstDebugLocation(self.llbuilder, instr);
209-
}
210-
source_loc::set_debug_location(self, UnknownLocation);
179+
// Convert the direct and indirect offsets to address ops.
180+
let op_deref = || unsafe { llvm::LLVMRustDIBuilderCreateOpDeref() };
181+
let op_plus_uconst = || unsafe { llvm::LLVMRustDIBuilderCreateOpPlusUconst() };
182+
let mut addr_ops = SmallVec::<[_; 8]>::new();
183+
184+
if direct_offset.bytes() > 0 {
185+
addr_ops.push(op_plus_uconst());
186+
addr_ops.push(direct_offset.bytes() as i64);
187+
}
188+
for &offset in indirect_offsets {
189+
addr_ops.push(op_deref());
190+
if offset.bytes() > 0 {
191+
addr_ops.push(op_plus_uconst());
192+
addr_ops.push(offset.bytes() as i64);
211193
}
212194
}
195+
196+
let name = SmallCStr::new(&variable_name.as_str());
197+
let metadata = unsafe {
198+
llvm::LLVMRustDIBuilderCreateVariable(
199+
DIB(cx),
200+
dwarf_tag,
201+
scope_metadata,
202+
name.as_ptr(),
203+
file_metadata,
204+
loc.line as c_uint,
205+
type_metadata,
206+
cx.sess().opts.optimize != config::OptLevel::No,
207+
DIFlags::FlagZero,
208+
argument_index,
209+
align.bytes() as u32,
210+
)
211+
};
212+
source_loc::set_debug_location(self,
213+
InternalDebugLocation::new(scope_metadata, loc.line, loc.col.to_usize()));
214+
unsafe {
215+
let debug_loc = llvm::LLVMGetCurrentDebugLocation(self.llbuilder);
216+
let instr = llvm::LLVMRustDIBuilderInsertDeclareAtEnd(
217+
DIB(cx),
218+
variable_alloca,
219+
metadata,
220+
addr_ops.as_ptr(),
221+
addr_ops.len() as c_uint,
222+
debug_loc,
223+
self.llbb());
224+
225+
llvm::LLVMSetInstDebugLocation(self.llbuilder, instr);
226+
}
227+
source_loc::set_debug_location(self, UnknownLocation);
213228
}
214229

215230
fn set_source_location(
216231
&mut self,
217-
debug_context: &mut FunctionDebugContext<&'ll DISubprogram>,
218-
scope: Option<&'ll DIScope>,
232+
debug_context: &mut FunctionDebugContext<&'ll DIScope>,
233+
scope: &'ll DIScope,
219234
span: Span,
220235
) {
221236
set_source_location(debug_context, &self, scope, span)
@@ -224,7 +239,7 @@ impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
224239
gdb::insert_reference_to_gdb_debug_scripts_section_global(self)
225240
}
226241

227-
fn set_var_name(&mut self, value: &'ll Value, name: impl ToString) {
242+
fn set_var_name(&mut self, value: &'ll Value, name: &str) {
228243
// Avoid wasting time if LLVM value names aren't even enabled.
229244
if self.sess().fewer_names() {
230245
return;
@@ -254,7 +269,7 @@ impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
254269
Err(_) => return,
255270
}
256271

257-
let cname = CString::new(name.to_string()).unwrap();
272+
let cname = SmallCStr::new(name);
258273
unsafe {
259274
llvm::LLVMSetValueName(value, cname.as_ptr());
260275
}
@@ -268,14 +283,14 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
268283
sig: ty::FnSig<'tcx>,
269284
llfn: &'ll Value,
270285
mir: &mir::Body<'_>,
271-
) -> FunctionDebugContext<&'ll DISubprogram> {
286+
) -> Option<FunctionDebugContext<&'ll DIScope>> {
272287
if self.sess().opts.debuginfo == DebugInfo::None {
273-
return FunctionDebugContext::DebugInfoDisabled;
288+
return None;
274289
}
275290

276291
if let InstanceDef::Item(def_id) = instance.def {
277292
if self.tcx().codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NO_DEBUG) {
278-
return FunctionDebugContext::FunctionWithoutDebugInfo;
293+
return None;
279294
}
280295
}
281296

@@ -284,7 +299,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
284299
// This can be the case for functions inlined from another crate
285300
if span.is_dummy() {
286301
// FIXME(simulacrum): Probably can't happen; remove.
287-
return FunctionDebugContext::FunctionWithoutDebugInfo;
302+
return None;
288303
}
289304

290305
let def_id = instance.def_id();
@@ -357,14 +372,23 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
357372
None)
358373
};
359374

360-
// Initialize fn debug context (including scope map and namespace map)
361-
let fn_debug_context = FunctionDebugContextData {
362-
fn_metadata,
375+
// Initialize fn debug context (including scopes).
376+
// FIXME(eddyb) figure out a way to not need `Option` for `scope_metadata`.
377+
let null_scope = DebugScope {
378+
scope_metadata: None,
379+
file_start_pos: BytePos(0),
380+
file_end_pos: BytePos(0)
381+
};
382+
let mut fn_debug_context = FunctionDebugContext {
383+
scopes: IndexVec::from_elem(null_scope, &mir.source_scopes),
363384
source_locations_enabled: false,
364385
defining_crate: def_id.krate,
365386
};
366387

367-
return FunctionDebugContext::RegularContext(fn_debug_context);
388+
// Fill in all the scopes, with the information from the MIR body.
389+
compute_mir_scopes(self, mir, fn_metadata, &mut fn_debug_context);
390+
391+
return Some(fn_debug_context);
368392

369393
fn get_function_signature<'ll, 'tcx>(
370394
cx: &CodegenCx<'ll, 'tcx>,
@@ -549,14 +573,6 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
549573
metadata::create_vtable_metadata(self, ty, vtable)
550574
}
551575

552-
fn create_mir_scopes(
553-
&self,
554-
mir: &mir::Body<'_>,
555-
debug_context: &mut FunctionDebugContext<&'ll DISubprogram>,
556-
) -> IndexVec<mir::SourceScope, MirDebugScope<&'ll DIScope>> {
557-
create_scope_map::create_mir_scopes(self, mir, debug_context)
558-
}
559-
560576
fn extend_scope_to_file(
561577
&self,
562578
scope_metadata: &'ll DIScope,
@@ -569,13 +585,4 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
569585
fn debuginfo_finalize(&self) {
570586
finalize(self)
571587
}
572-
573-
fn debuginfo_upvar_ops_sequence(&self, byte_offset_of_var_in_env: u64) -> [i64; 4] {
574-
unsafe {
575-
[llvm::LLVMRustDIBuilderCreateOpDeref(),
576-
llvm::LLVMRustDIBuilderCreateOpPlusUconst(),
577-
byte_offset_of_var_in_env as i64,
578-
llvm::LLVMRustDIBuilderCreateOpDeref()]
579-
}
580-
}
581588
}

0 commit comments

Comments
 (0)