1 // See doc.rs for documentation.
4 use rustc_codegen_ssa
::mir
::debuginfo
::VariableKind
::*;
6 use self::utils
::{DIB, span_start, create_DIArray, is_node_local_to_unit}
;
7 use self::namespace
::mangled_name_of_instance
;
8 use self::type_names
::compute_debuginfo_type_name
;
9 use self::metadata
::{type_metadata, file_metadata, TypeMap}
;
10 use self::source_loc
::InternalDebugLocation
::{self, UnknownLocation}
;
13 use crate::llvm
::debuginfo
::{DIFile
, DIType
, DIScope
, DIBuilder
, DIArray
, DIFlags
,
14 DISPFlags
, DILexicalBlock
};
15 use rustc
::hir
::CodegenFnAttrFlags
;
16 use rustc
::hir
::def_id
::{DefId, CrateNum, LOCAL_CRATE}
;
17 use rustc
::ty
::subst
::{SubstsRef, GenericArgKind}
;
19 use crate::abi
::FnAbi
;
20 use crate::common
::CodegenCx
;
21 use crate::builder
::Builder
;
22 use crate::value
::Value
;
23 use rustc
::ty
::{self, ParamEnv, Ty, InstanceDef, Instance}
;
25 use rustc
::session
::config
::{self, DebugInfo}
;
26 use rustc
::util
::nodemap
::{DefIdMap, FxHashMap, FxHashSet}
;
27 use rustc_data_structures
::small_c_str
::SmallCStr
;
28 use rustc_index
::vec
::IndexVec
;
29 use rustc_codegen_ssa
::debuginfo
::type_names
;
30 use rustc_codegen_ssa
::mir
::debuginfo
::{FunctionDebugContext
, DebugScope
,
34 use std
::cell
::RefCell
;
35 use std
::ffi
::CString
;
38 use smallvec
::SmallVec
;
39 use syntax_pos
::{self, BytePos, Span, Pos}
;
41 use syntax
::symbol
::Symbol
;
42 use rustc
::ty
::layout
::{self, LayoutOf, HasTyCtxt, Size}
;
43 use rustc_codegen_ssa
::traits
::*;
52 pub use self::create_scope_map
::compute_mir_scopes
;
53 pub use self::metadata
::create_global_var_metadata
;
54 pub use self::metadata
::extend_scope_to_file
;
55 pub use self::source_loc
::set_source_location
;
57 #[allow(non_upper_case_globals)]
58 const DW_TAG_auto_variable
: c_uint
= 0x100;
59 #[allow(non_upper_case_globals)]
60 const DW_TAG_arg_variable
: c_uint
= 0x101;
62 /// A context object for maintaining all state needed by the debuginfo module.
63 pub struct CrateDebugContext
<'a
, 'tcx
> {
64 llcontext
: &'a llvm
::Context
,
65 llmod
: &'a llvm
::Module
,
66 builder
: &'a
mut DIBuilder
<'a
>,
67 created_files
: RefCell
<FxHashMap
<(Option
<String
>, Option
<String
>), &'a DIFile
>>,
68 created_enum_disr_types
: RefCell
<FxHashMap
<(DefId
, layout
::Primitive
), &'a DIType
>>,
70 type_map
: RefCell
<TypeMap
<'a
, 'tcx
>>,
71 namespace_map
: RefCell
<DefIdMap
<&'a DIScope
>>,
73 // This collection is used to assert that composite types (structs, enums,
74 // ...) have their members only set once:
75 composite_types_completed
: RefCell
<FxHashSet
<&'a DIType
>>,
78 impl Drop
for CrateDebugContext
<'a
, 'tcx
> {
81 llvm
::LLVMRustDIBuilderDispose(&mut *(self.builder
as *mut _
));
86 impl<'a
, 'tcx
> CrateDebugContext
<'a
, 'tcx
> {
87 pub fn new(llmod
: &'a llvm
::Module
) -> Self {
88 debug
!("CrateDebugContext::new");
89 let builder
= unsafe { llvm::LLVMRustDIBuilderCreate(llmod) }
;
90 // DIBuilder inherits context from the module, so we'd better use the same one
91 let llcontext
= unsafe { llvm::LLVMGetModuleContext(llmod) }
;
96 created_files
: Default
::default(),
97 created_enum_disr_types
: Default
::default(),
98 type_map
: Default
::default(),
99 namespace_map
: RefCell
::new(Default
::default()),
100 composite_types_completed
: Default
::default(),
105 /// Creates any deferred debug metadata nodes
106 pub fn finalize(cx
: &CodegenCx
<'_
, '_
>) {
107 if cx
.dbg_cx
.is_none() {
113 if gdb
::needs_gdb_debug_scripts_section(cx
) {
114 // Add a .debug_gdb_scripts section to this compile-unit. This will
115 // cause GDB to try and load the gdb_load_rust_pretty_printers.py file,
116 // which activates the Rust pretty printers for binary this section is
118 gdb
::get_or_insert_gdb_debug_scripts_section_global(cx
);
122 llvm
::LLVMRustDIBuilderFinalize(DIB(cx
));
123 // Debuginfo generation in LLVM by default uses a higher
124 // version of dwarf than macOS currently understands. We can
125 // instruct LLVM to emit an older version of dwarf, however,
126 // for macOS to understand. For more info see #11352
127 // This can be overridden using --llvm-opts -dwarf-version,N.
128 // Android has the same issue (#22398)
129 if cx
.sess().target
.target
.options
.is_like_osx
||
130 cx
.sess().target
.target
.options
.is_like_android
{
131 llvm
::LLVMRustAddModuleFlag(cx
.llmod
,
132 "Dwarf Version\0".as_ptr().cast(),
136 // Indicate that we want CodeView debug information on MSVC
137 if cx
.sess().target
.target
.options
.is_like_msvc
{
138 llvm
::LLVMRustAddModuleFlag(cx
.llmod
,
139 "CodeView\0".as_ptr().cast(),
143 // Prevent bitcode readers from deleting the debug info.
144 let ptr
= "Debug Info Version\0".as_ptr();
145 llvm
::LLVMRustAddModuleFlag(cx
.llmod
, ptr
.cast(),
146 llvm
::LLVMRustDebugMetadataVersion());
150 impl DebugInfoBuilderMethods
<'tcx
> for Builder
<'a
, 'll
, 'tcx
> {
153 dbg_context
: &FunctionDebugContext
<&'ll DIScope
>,
154 variable_name
: ast
::Name
,
155 variable_type
: Ty
<'tcx
>,
156 scope_metadata
: &'ll DIScope
,
157 variable_alloca
: Self::Value
,
159 indirect_offsets
: &[Size
],
160 variable_kind
: VariableKind
,
163 assert
!(!dbg_context
.source_locations_enabled
);
166 let file
= span_start(cx
, span
).file
;
167 let file_metadata
= file_metadata(cx
,
169 dbg_context
.defining_crate
);
171 let loc
= span_start(cx
, span
);
172 let type_metadata
= type_metadata(cx
, variable_type
, span
);
174 let (argument_index
, dwarf_tag
) = match variable_kind
{
175 ArgumentVariable(index
) => (index
as c_uint
, DW_TAG_arg_variable
),
176 LocalVariable
=> (0, DW_TAG_auto_variable
)
178 let align
= cx
.align_of(variable_type
);
180 // Convert the direct and indirect offsets to address ops.
181 let op_deref
= || unsafe { llvm::LLVMRustDIBuilderCreateOpDeref() }
;
182 let op_plus_uconst
= || unsafe { llvm::LLVMRustDIBuilderCreateOpPlusUconst() }
;
183 let mut addr_ops
= SmallVec
::<[_
; 8]>::new();
185 if direct_offset
.bytes() > 0 {
186 addr_ops
.push(op_plus_uconst());
187 addr_ops
.push(direct_offset
.bytes() as i64);
189 for &offset
in indirect_offsets
{
190 addr_ops
.push(op_deref());
191 if offset
.bytes() > 0 {
192 addr_ops
.push(op_plus_uconst());
193 addr_ops
.push(offset
.bytes() as i64);
197 let name
= SmallCStr
::new(&variable_name
.as_str());
198 let metadata
= unsafe {
199 llvm
::LLVMRustDIBuilderCreateVariable(
207 cx
.sess().opts
.optimize
!= config
::OptLevel
::No
,
210 align
.bytes() as u32,
213 source_loc
::set_debug_location(self,
214 InternalDebugLocation
::new(scope_metadata
, loc
.line
, loc
.col
.to_usize()));
216 let debug_loc
= llvm
::LLVMGetCurrentDebugLocation(self.llbuilder
);
217 let instr
= llvm
::LLVMRustDIBuilderInsertDeclareAtEnd(
222 addr_ops
.len() as c_uint
,
226 llvm
::LLVMSetInstDebugLocation(self.llbuilder
, instr
);
228 source_loc
::set_debug_location(self, UnknownLocation
);
231 fn set_source_location(
233 debug_context
: &mut FunctionDebugContext
<&'ll DIScope
>,
237 set_source_location(debug_context
, &self, scope
, span
)
239 fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) {
240 gdb
::insert_reference_to_gdb_debug_scripts_section_global(self)
243 fn set_var_name(&mut self, value
: &'ll Value
, name
: &str) {
244 // Avoid wasting time if LLVM value names aren't even enabled.
245 if self.sess().fewer_names() {
249 // Only function parameters and instructions are local to a function,
250 // don't change the name of anything else (e.g. globals).
251 let param_or_inst
= unsafe {
252 llvm
::LLVMIsAArgument(value
).is_some() ||
253 llvm
::LLVMIsAInstruction(value
).is_some()
259 // Avoid replacing the name if it already exists.
260 // While we could combine the names somehow, it'd
261 // get noisy quick, and the usefulness is dubious.
262 if llvm
::get_value_name(value
).is_empty() {
263 llvm
::set_value_name(value
, name
.as_bytes());
268 impl DebugInfoMethods
<'tcx
> for CodegenCx
<'ll
, 'tcx
> {
269 fn create_function_debug_context(
271 instance
: Instance
<'tcx
>,
272 fn_abi
: &FnAbi
<'tcx
, Ty
<'tcx
>>,
275 ) -> Option
<FunctionDebugContext
<&'ll DIScope
>> {
276 if self.sess().opts
.debuginfo
== DebugInfo
::None
{
280 if let InstanceDef
::Item(def_id
) = instance
.def
{
281 if self.tcx().codegen_fn_attrs(def_id
).flags
.contains(CodegenFnAttrFlags
::NO_DEBUG
) {
288 // This can be the case for functions inlined from another crate
290 // FIXME(simulacrum): Probably can't happen; remove.
294 let def_id
= instance
.def_id();
295 let containing_scope
= get_containing_scope(self, instance
);
296 let loc
= span_start(self, span
);
297 let file_metadata
= file_metadata(self, &loc
.file
.name
, def_id
.krate
);
299 let function_type_metadata
= unsafe {
300 let fn_signature
= get_function_signature(self, fn_abi
);
301 llvm
::LLVMRustDIBuilderCreateSubroutineType(DIB(self), file_metadata
, fn_signature
)
304 // Find the enclosing function, in case this is a closure.
305 let def_key
= self.tcx().def_key(def_id
);
306 let mut name
= def_key
.disambiguated_data
.data
.to_string();
308 let enclosing_fn_def_id
= self.tcx().closure_base_def_id(def_id
);
310 // Get_template_parameters() will append a `<...>` clause to the function
311 // name if necessary.
312 let generics
= self.tcx().generics_of(enclosing_fn_def_id
);
313 let substs
= instance
.substs
.truncate_to(self.tcx(), generics
);
314 let template_parameters
= get_template_parameters(self,
320 // Get the linkage_name, which is just the symbol name
321 let linkage_name
= mangled_name_of_instance(self, instance
);
323 let scope_line
= span_start(self, span
).line
;
325 let function_name
= CString
::new(name
).unwrap();
326 let linkage_name
= SmallCStr
::new(&linkage_name
.name
.as_str());
328 let mut flags
= DIFlags
::FlagPrototyped
;
330 if fn_abi
.ret
.layout
.abi
.is_uninhabited() {
331 flags
|= DIFlags
::FlagNoReturn
;
334 let mut spflags
= DISPFlags
::SPFlagDefinition
;
335 if is_node_local_to_unit(self, def_id
) {
336 spflags
|= DISPFlags
::SPFlagLocalToUnit
;
338 if self.sess().opts
.optimize
!= config
::OptLevel
::No
{
339 spflags
|= DISPFlags
::SPFlagOptimized
;
341 if let Some((id
, _
)) = self.tcx
.entry_fn(LOCAL_CRATE
) {
343 spflags
|= DISPFlags
::SPFlagMainSubprogram
;
347 let fn_metadata
= unsafe {
348 llvm
::LLVMRustDIBuilderCreateFunction(
351 function_name
.as_ptr(),
352 linkage_name
.as_ptr(),
355 function_type_metadata
,
356 scope_line
as c_uint
,
364 // Initialize fn debug context (including scopes).
365 // FIXME(eddyb) figure out a way to not need `Option` for `scope_metadata`.
366 let null_scope
= DebugScope
{
367 scope_metadata
: None
,
368 file_start_pos
: BytePos(0),
369 file_end_pos
: BytePos(0)
371 let mut fn_debug_context
= FunctionDebugContext
{
372 scopes
: IndexVec
::from_elem(null_scope
, &mir
.source_scopes
),
373 source_locations_enabled
: false,
374 defining_crate
: def_id
.krate
,
377 // Fill in all the scopes, with the information from the MIR body.
378 compute_mir_scopes(self, mir
, fn_metadata
, &mut fn_debug_context
);
380 return Some(fn_debug_context
);
382 fn get_function_signature
<'ll
, 'tcx
>(
383 cx
: &CodegenCx
<'ll
, 'tcx
>,
384 fn_abi
: &FnAbi
<'tcx
, Ty
<'tcx
>>,
386 if cx
.sess().opts
.debuginfo
== DebugInfo
::Limited
{
387 return create_DIArray(DIB(cx
), &[]);
390 let mut signature
= Vec
::with_capacity(fn_abi
.args
.len() + 1);
392 // Return type -- llvm::DIBuilder wants this at index 0
393 signature
.push(if fn_abi
.ret
.is_ignore() {
396 Some(type_metadata(cx
, fn_abi
.ret
.layout
.ty
, syntax_pos
::DUMMY_SP
))
400 if cx
.sess().target
.target
.options
.is_like_msvc
{
402 // There is a bug in MSDIA that leads to a crash when it encounters
403 // a fixed-size array of `u8` or something zero-sized in a
404 // function-type (see #40477).
405 // As a workaround, we replace those fixed-size arrays with a
406 // pointer-type. So a function `fn foo(a: u8, b: [u8; 4])` would
407 // appear as `fn foo(a: u8, b: *const u8)` in debuginfo,
408 // and a function `fn bar(x: [(); 7])` as `fn bar(x: *const ())`.
409 // This transformed type is wrong, but these function types are
410 // already inaccurate due to ABI adjustments (see #42800).
411 signature
.extend(fn_abi
.args
.iter().map(|arg
| {
412 let t
= arg
.layout
.ty
;
413 let t
= match t
.kind
{
415 if (ct
== cx
.tcx
.types
.u8) || cx
.layout_of(ct
).is_zst() => {
416 cx
.tcx
.mk_imm_ptr(ct
)
420 Some(type_metadata(cx
, t
, syntax_pos
::DUMMY_SP
))
423 signature
.extend(fn_abi
.args
.iter().map(|arg
| {
424 Some(type_metadata(cx
, arg
.layout
.ty
, syntax_pos
::DUMMY_SP
))
428 create_DIArray(DIB(cx
), &signature
[..])
431 fn get_template_parameters
<'ll
, 'tcx
>(
432 cx
: &CodegenCx
<'ll
, 'tcx
>,
433 generics
: &ty
::Generics
,
434 substs
: SubstsRef
<'tcx
>,
435 file_metadata
: &'ll DIFile
,
436 name_to_append_suffix_to
: &mut String
,
438 if substs
.types().next().is_none() {
439 return create_DIArray(DIB(cx
), &[]);
442 name_to_append_suffix_to
.push('
<'
);
443 for (i
, actual_type
) in substs
.types().enumerate() {
445 name_to_append_suffix_to
.push_str(",");
449 cx
.tcx
.normalize_erasing_regions(ParamEnv
::reveal_all(), actual_type
);
450 // Add actual type name to <...> clause of function name
451 let actual_type_name
= compute_debuginfo_type_name(cx
.tcx(),
454 name_to_append_suffix_to
.push_str(&actual_type_name
[..]);
456 name_to_append_suffix_to
.push('
>'
);
458 // Again, only create type information if full debuginfo is enabled
459 let template_params
: Vec
<_
> = if cx
.sess().opts
.debuginfo
== DebugInfo
::Full
{
460 let names
= get_parameter_names(cx
, generics
);
461 substs
.iter().zip(names
).filter_map(|(kind
, name
)| {
462 if let GenericArgKind
::Type(ty
) = kind
.unpack() {
464 cx
.tcx
.normalize_erasing_regions(ParamEnv
::reveal_all(), ty
);
465 let actual_type_metadata
=
466 type_metadata(cx
, actual_type
, syntax_pos
::DUMMY_SP
);
467 let name
= SmallCStr
::new(&name
.as_str());
469 Some(llvm
::LLVMRustDIBuilderCreateTemplateTypeParameter(
473 actual_type_metadata
,
487 return create_DIArray(DIB(cx
), &template_params
[..]);
490 fn get_parameter_names(cx
: &CodegenCx
<'_
, '_
>,
491 generics
: &ty
::Generics
)
493 let mut names
= generics
.parent
.map_or(vec
![], |def_id
| {
494 get_parameter_names(cx
, cx
.tcx
.generics_of(def_id
))
496 names
.extend(generics
.params
.iter().map(|param
| param
.name
));
500 fn get_containing_scope
<'ll
, 'tcx
>(
501 cx
: &CodegenCx
<'ll
, 'tcx
>,
502 instance
: Instance
<'tcx
>,
504 // First, let's see if this is a method within an inherent impl. Because
505 // if yes, we want to make the result subroutine DIE a child of the
506 // subroutine's self-type.
507 let self_type
= cx
.tcx
.impl_of_method(instance
.def_id()).and_then(|impl_def_id
| {
508 // If the method does *not* belong to a trait, proceed
509 if cx
.tcx
.trait_id_of_impl(impl_def_id
).is_none() {
510 let impl_self_ty
= cx
.tcx
.subst_and_normalize_erasing_regions(
512 ty
::ParamEnv
::reveal_all(),
513 &cx
.tcx
.type_of(impl_def_id
),
516 // Only "class" methods are generally understood by LLVM,
517 // so avoid methods on other types (e.g., `<*mut T>::null`).
518 match impl_self_ty
.kind
{
519 ty
::Adt(def
, ..) if !def
.is_box() => {
520 Some(type_metadata(cx
, impl_self_ty
, syntax_pos
::DUMMY_SP
))
525 // For trait method impls we still use the "parallel namespace"
531 self_type
.unwrap_or_else(|| {
532 namespace
::item_namespace(cx
, DefId
{
533 krate
: instance
.def_id().krate
,
535 .def_key(instance
.def_id())
537 .expect("get_containing_scope: missing parent?")
543 fn create_vtable_metadata(
548 metadata
::create_vtable_metadata(self, ty
, vtable
)
551 fn extend_scope_to_file(
553 scope_metadata
: &'ll DIScope
,
554 file
: &syntax_pos
::SourceFile
,
555 defining_crate
: CrateNum
,
556 ) -> &'ll DILexicalBlock
{
557 metadata
::extend_scope_to_file(&self, scope_metadata
, file
, defining_crate
)
560 fn debuginfo_finalize(&self) {