1 // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 // See doc.rs for documentation.
14 use self::VariableAccess
::*;
15 use self::VariableKind
::*;
17 use self::utils
::{DIB, span_start, create_DIArray, is_node_local_to_unit}
;
18 use self::namespace
::mangled_name_of_instance
;
19 use self::type_names
::compute_debuginfo_type_name
;
20 use self::metadata
::{type_metadata, file_metadata, TypeMap}
;
21 use self::source_loc
::InternalDebugLocation
::{self, UnknownLocation}
;
24 use llvm
::{ModuleRef, ContextRef, ValueRef}
;
25 use llvm
::debuginfo
::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray, DIFlags}
;
26 use rustc
::hir
::TransFnAttrFlags
;
27 use rustc
::hir
::def_id
::{DefId, CrateNum}
;
28 use rustc
::ty
::subst
::Substs
;
31 use common
::CodegenCx
;
33 use monomorphize
::Instance
;
34 use rustc
::ty
::{self, ParamEnv, Ty, InstanceDef}
;
36 use rustc
::session
::config
::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo}
;
37 use rustc
::util
::nodemap
::{DefIdMap, FxHashMap, FxHashSet}
;
40 use std
::cell
::{Cell, RefCell}
;
41 use std
::ffi
::CString
;
44 use syntax_pos
::{self, Span, Pos}
;
46 use syntax
::symbol
::{Symbol, InternedString}
;
47 use rustc
::ty
::layout
::{self, LayoutOf}
;
57 pub use self::create_scope_map
::{create_mir_scopes, MirDebugScope}
;
58 pub use self::source_loc
::start_emitting_source_locations
;
59 pub use self::metadata
::create_global_var_metadata
;
60 pub use self::metadata
::create_vtable_metadata
;
61 pub use self::metadata
::extend_scope_to_file
;
62 pub use self::source_loc
::set_source_location
;
64 #[allow(non_upper_case_globals)]
65 const DW_TAG_auto_variable
: c_uint
= 0x100;
66 #[allow(non_upper_case_globals)]
67 const DW_TAG_arg_variable
: c_uint
= 0x101;
69 /// A context object for maintaining all state needed by the debuginfo module.
70 pub struct CrateDebugContext
<'tcx
> {
71 llcontext
: ContextRef
,
73 builder
: DIBuilderRef
,
74 created_files
: RefCell
<FxHashMap
<(Symbol
, Symbol
), DIFile
>>,
75 created_enum_disr_types
: RefCell
<FxHashMap
<(DefId
, layout
::Primitive
), DIType
>>,
77 type_map
: RefCell
<TypeMap
<'tcx
>>,
78 namespace_map
: RefCell
<DefIdMap
<DIScope
>>,
80 // This collection is used to assert that composite types (structs, enums,
81 // ...) have their members only set once:
82 composite_types_completed
: RefCell
<FxHashSet
<DIType
>>,
85 impl<'tcx
> CrateDebugContext
<'tcx
> {
86 pub fn new(llmod
: ModuleRef
) -> CrateDebugContext
<'tcx
> {
87 debug
!("CrateDebugContext::new");
88 let builder
= unsafe { llvm::LLVMRustDIBuilderCreate(llmod) }
;
89 // DIBuilder inherits context from the module, so we'd better use the same one
90 let llcontext
= unsafe { llvm::LLVMGetModuleContext(llmod) }
;
95 created_files
: RefCell
::new(FxHashMap()),
96 created_enum_disr_types
: RefCell
::new(FxHashMap()),
97 type_map
: RefCell
::new(TypeMap
::new()),
98 namespace_map
: RefCell
::new(DefIdMap()),
99 composite_types_completed
: RefCell
::new(FxHashSet()),
104 pub enum FunctionDebugContext
{
105 RegularContext(FunctionDebugContextData
),
107 FunctionWithoutDebugInfo
,
110 impl FunctionDebugContext
{
111 pub fn get_ref
<'a
>(&'a
self, span
: Span
) -> &'a FunctionDebugContextData
{
113 FunctionDebugContext
::RegularContext(ref data
) => data
,
114 FunctionDebugContext
::DebugInfoDisabled
=> {
115 span_bug
!(span
, "{}", FunctionDebugContext
::debuginfo_disabled_message());
117 FunctionDebugContext
::FunctionWithoutDebugInfo
=> {
118 span_bug
!(span
, "{}", FunctionDebugContext
::should_be_ignored_message());
123 fn debuginfo_disabled_message() -> &'
static str {
124 "debuginfo: Error trying to access FunctionDebugContext although debug info is disabled!"
127 fn should_be_ignored_message() -> &'
static str {
128 "debuginfo: Error trying to access FunctionDebugContext for function that should be \
129 ignored by debug info!"
133 pub struct FunctionDebugContextData
{
134 fn_metadata
: DISubprogram
,
135 source_locations_enabled
: Cell
<bool
>,
136 pub defining_crate
: CrateNum
,
139 pub enum VariableAccess
<'a
> {
140 // The llptr given is an alloca containing the variable's value
141 DirectVariable { alloca: ValueRef }
,
142 // The llptr given is an alloca containing the start of some pointer chain
143 // leading to the variable's content.
144 IndirectVariable { alloca: ValueRef, address_operations: &'a [i64] }
147 pub enum VariableKind
{
148 ArgumentVariable(usize /*index*/),
153 /// Create any deferred debug metadata nodes
154 pub fn finalize(cx
: &CodegenCx
) {
155 if cx
.dbg_cx
.is_none() {
161 if gdb
::needs_gdb_debug_scripts_section(cx
) {
162 // Add a .debug_gdb_scripts section to this compile-unit. This will
163 // cause GDB to try and load the gdb_load_rust_pretty_printers.py file,
164 // which activates the Rust pretty printers for binary this section is
166 gdb
::get_or_insert_gdb_debug_scripts_section_global(cx
);
170 llvm
::LLVMRustDIBuilderFinalize(DIB(cx
));
171 llvm
::LLVMRustDIBuilderDispose(DIB(cx
));
172 // Debuginfo generation in LLVM by default uses a higher
173 // version of dwarf than macOS currently understands. We can
174 // instruct LLVM to emit an older version of dwarf, however,
175 // for macOS to understand. For more info see #11352
176 // This can be overridden using --llvm-opts -dwarf-version,N.
177 // Android has the same issue (#22398)
178 if cx
.sess().target
.target
.options
.is_like_osx
||
179 cx
.sess().target
.target
.options
.is_like_android
{
180 llvm
::LLVMRustAddModuleFlag(cx
.llmod
,
181 "Dwarf Version\0".as_ptr() as *const _
,
185 // Indicate that we want CodeView debug information on MSVC
186 if cx
.sess().target
.target
.options
.is_like_msvc
{
187 llvm
::LLVMRustAddModuleFlag(cx
.llmod
,
188 "CodeView\0".as_ptr() as *const _
,
192 // Prevent bitcode readers from deleting the debug info.
193 let ptr
= "Debug Info Version\0".as_ptr();
194 llvm
::LLVMRustAddModuleFlag(cx
.llmod
, ptr
as *const _
,
195 llvm
::LLVMRustDebugMetadataVersion());
199 /// Creates the function-specific debug context.
201 /// Returns the FunctionDebugContext for the function which holds state needed
202 /// for debug info creation. The function may also return another variant of the
203 /// FunctionDebugContext enum which indicates why no debuginfo should be created
204 /// for the function.
205 pub fn create_function_debug_context
<'a
, 'tcx
>(cx
: &CodegenCx
<'a
, 'tcx
>,
206 instance
: Instance
<'tcx
>,
207 sig
: ty
::FnSig
<'tcx
>,
209 mir
: &mir
::Mir
) -> FunctionDebugContext
{
210 if cx
.sess().opts
.debuginfo
== NoDebugInfo
{
211 return FunctionDebugContext
::DebugInfoDisabled
;
214 if let InstanceDef
::Item(def_id
) = instance
.def
{
215 if cx
.tcx
.trans_fn_attrs(def_id
).flags
.contains(TransFnAttrFlags
::NO_DEBUG
) {
216 return FunctionDebugContext
::FunctionWithoutDebugInfo
;
222 // This can be the case for functions inlined from another crate
223 if span
== syntax_pos
::DUMMY_SP
{
224 // FIXME(simulacrum): Probably can't happen; remove.
225 return FunctionDebugContext
::FunctionWithoutDebugInfo
;
228 let def_id
= instance
.def_id();
229 let containing_scope
= get_containing_scope(cx
, instance
);
230 let loc
= span_start(cx
, span
);
231 let file_metadata
= file_metadata(cx
, &loc
.file
.name
, def_id
.krate
);
233 let function_type_metadata
= unsafe {
234 let fn_signature
= get_function_signature(cx
, sig
);
235 llvm
::LLVMRustDIBuilderCreateSubroutineType(DIB(cx
), file_metadata
, fn_signature
)
238 // Find the enclosing function, in case this is a closure.
239 let def_key
= cx
.tcx
.def_key(def_id
);
240 let mut name
= def_key
.disambiguated_data
.data
.to_string();
242 let enclosing_fn_def_id
= cx
.tcx
.closure_base_def_id(def_id
);
244 // Get_template_parameters() will append a `<...>` clause to the function
245 // name if necessary.
246 let generics
= cx
.tcx
.generics_of(enclosing_fn_def_id
);
247 let substs
= instance
.substs
.truncate_to(cx
.tcx
, generics
);
248 let template_parameters
= get_template_parameters(cx
,
254 // Get the linkage_name, which is just the symbol name
255 let linkage_name
= mangled_name_of_instance(cx
, instance
);
257 let scope_line
= span_start(cx
, span
).line
;
258 let is_local_to_unit
= is_node_local_to_unit(cx
, def_id
);
260 let function_name
= CString
::new(name
).unwrap();
261 let linkage_name
= CString
::new(linkage_name
.to_string()).unwrap();
263 let mut flags
= DIFlags
::FlagPrototyped
;
265 let local_id
= cx
.tcx
.hir
.as_local_node_id(def_id
);
266 match *cx
.sess().entry_fn
.borrow() {
267 Some((id
, _
, _
)) => {
268 if local_id
== Some(id
) {
269 flags
= flags
| DIFlags
::FlagMainSubprogram
;
274 if cx
.layout_of(sig
.output()).abi
== ty
::layout
::Abi
::Uninhabited
{
275 flags
= flags
| DIFlags
::FlagNoReturn
;
278 let fn_metadata
= unsafe {
279 llvm
::LLVMRustDIBuilderCreateFunction(
282 function_name
.as_ptr(),
283 linkage_name
.as_ptr(),
286 function_type_metadata
,
289 scope_line
as c_uint
,
291 cx
.sess().opts
.optimize
!= config
::OptLevel
::No
,
297 // Initialize fn debug context (including scope map and namespace map)
298 let fn_debug_context
= FunctionDebugContextData
{
300 source_locations_enabled
: Cell
::new(false),
301 defining_crate
: def_id
.krate
,
304 return FunctionDebugContext
::RegularContext(fn_debug_context
);
306 fn get_function_signature
<'a
, 'tcx
>(cx
: &CodegenCx
<'a
, 'tcx
>,
307 sig
: ty
::FnSig
<'tcx
>) -> DIArray
{
308 if cx
.sess().opts
.debuginfo
== LimitedDebugInfo
{
309 return create_DIArray(DIB(cx
), &[]);
312 let mut signature
= Vec
::with_capacity(sig
.inputs().len() + 1);
314 // Return type -- llvm::DIBuilder wants this at index 0
315 signature
.push(match sig
.output().sty
{
316 ty
::TyTuple(ref tys
) if tys
.is_empty() => ptr
::null_mut(),
317 _
=> type_metadata(cx
, sig
.output(), syntax_pos
::DUMMY_SP
)
320 let inputs
= if sig
.abi
== Abi
::RustCall
{
321 &sig
.inputs()[..sig
.inputs().len() - 1]
327 if cx
.sess().target
.target
.options
.is_like_msvc
{
329 // There is a bug in MSDIA that leads to a crash when it encounters
330 // a fixed-size array of `u8` or something zero-sized in a
331 // function-type (see #40477).
332 // As a workaround, we replace those fixed-size arrays with a
333 // pointer-type. So a function `fn foo(a: u8, b: [u8; 4])` would
334 // appear as `fn foo(a: u8, b: *const u8)` in debuginfo,
335 // and a function `fn bar(x: [(); 7])` as `fn bar(x: *const ())`.
336 // This transformed type is wrong, but these function types are
337 // already inaccurate due to ABI adjustments (see #42800).
338 signature
.extend(inputs
.iter().map(|&t
| {
339 let t
= match t
.sty
{
341 if (ct
== cx
.tcx
.types
.u8) || cx
.layout_of(ct
).is_zst() => {
342 cx
.tcx
.mk_imm_ptr(ct
)
346 type_metadata(cx
, t
, syntax_pos
::DUMMY_SP
)
349 signature
.extend(inputs
.iter().map(|t
| {
350 type_metadata(cx
, t
, syntax_pos
::DUMMY_SP
)
354 if sig
.abi
== Abi
::RustCall
&& !sig
.inputs().is_empty() {
355 if let ty
::TyTuple(args
) = sig
.inputs()[sig
.inputs().len() - 1].sty
{
356 for &argument_type
in args
{
357 signature
.push(type_metadata(cx
, argument_type
, syntax_pos
::DUMMY_SP
));
362 return create_DIArray(DIB(cx
), &signature
[..]);
365 fn get_template_parameters
<'a
, 'tcx
>(cx
: &CodegenCx
<'a
, 'tcx
>,
366 generics
: &ty
::Generics
,
367 substs
: &Substs
<'tcx
>,
368 file_metadata
: DIFile
,
369 name_to_append_suffix_to
: &mut String
)
372 if substs
.types().next().is_none() {
373 return create_DIArray(DIB(cx
), &[]);
376 name_to_append_suffix_to
.push('
<'
);
377 for (i
, actual_type
) in substs
.types().enumerate() {
379 name_to_append_suffix_to
.push_str(",");
382 let actual_type
= cx
.tcx
.normalize_erasing_regions(ParamEnv
::reveal_all(), actual_type
);
383 // Add actual type name to <...> clause of function name
384 let actual_type_name
= compute_debuginfo_type_name(cx
,
387 name_to_append_suffix_to
.push_str(&actual_type_name
[..]);
389 name_to_append_suffix_to
.push('
>'
);
391 // Again, only create type information if full debuginfo is enabled
392 let template_params
: Vec
<_
> = if cx
.sess().opts
.debuginfo
== FullDebugInfo
{
393 let names
= get_type_parameter_names(cx
, generics
);
394 substs
.types().zip(names
).map(|(ty
, name
)| {
395 let actual_type
= cx
.tcx
.normalize_erasing_regions(ParamEnv
::reveal_all(), ty
);
396 let actual_type_metadata
= type_metadata(cx
, actual_type
, syntax_pos
::DUMMY_SP
);
397 let name
= CString
::new(name
.as_str().as_bytes()).unwrap();
399 llvm
::LLVMRustDIBuilderCreateTemplateTypeParameter(
403 actual_type_metadata
,
413 return create_DIArray(DIB(cx
), &template_params
[..]);
416 fn get_type_parameter_names(cx
: &CodegenCx
, generics
: &ty
::Generics
) -> Vec
<InternedString
> {
417 let mut names
= generics
.parent
.map_or(vec
![], |def_id
| {
418 get_type_parameter_names(cx
, cx
.tcx
.generics_of(def_id
))
420 names
.extend(generics
.types
.iter().map(|param
| param
.name
));
424 fn get_containing_scope
<'cx
, 'tcx
>(cx
: &CodegenCx
<'cx
, 'tcx
>,
425 instance
: Instance
<'tcx
>)
427 // First, let's see if this is a method within an inherent impl. Because
428 // if yes, we want to make the result subroutine DIE a child of the
429 // subroutine's self-type.
430 let self_type
= cx
.tcx
.impl_of_method(instance
.def_id()).and_then(|impl_def_id
| {
431 // If the method does *not* belong to a trait, proceed
432 if cx
.tcx
.trait_id_of_impl(impl_def_id
).is_none() {
433 let impl_self_ty
= cx
.tcx
.subst_and_normalize_erasing_regions(
435 ty
::ParamEnv
::reveal_all(),
436 &cx
.tcx
.type_of(impl_def_id
),
439 // Only "class" methods are generally understood by LLVM,
440 // so avoid methods on other types (e.g. `<*mut T>::null`).
441 match impl_self_ty
.sty
{
442 ty
::TyAdt(def
, ..) if !def
.is_box() => {
443 Some(type_metadata(cx
, impl_self_ty
, syntax_pos
::DUMMY_SP
))
448 // For trait method impls we still use the "parallel namespace"
454 self_type
.unwrap_or_else(|| {
455 namespace
::item_namespace(cx
, DefId
{
456 krate
: instance
.def_id().krate
,
458 .def_key(instance
.def_id())
460 .expect("get_containing_scope: missing parent?")
466 pub fn declare_local
<'a
, 'tcx
>(bx
: &Builder
<'a
, 'tcx
>,
467 dbg_context
: &FunctionDebugContext
,
468 variable_name
: ast
::Name
,
469 variable_type
: Ty
<'tcx
>,
470 scope_metadata
: DIScope
,
471 variable_access
: VariableAccess
,
472 variable_kind
: VariableKind
,
476 let file
= span_start(cx
, span
).file
;
477 let file_metadata
= file_metadata(cx
,
479 dbg_context
.get_ref(span
).defining_crate
);
481 let loc
= span_start(cx
, span
);
482 let type_metadata
= type_metadata(cx
, variable_type
, span
);
484 let (argument_index
, dwarf_tag
) = match variable_kind
{
485 ArgumentVariable(index
) => (index
as c_uint
, DW_TAG_arg_variable
),
487 CapturedVariable
=> (0, DW_TAG_auto_variable
)
489 let align
= cx
.align_of(variable_type
);
491 let name
= CString
::new(variable_name
.as_str().as_bytes()).unwrap();
492 match (variable_access
, &[][..]) {
493 (DirectVariable { alloca }
, address_operations
) |
494 (IndirectVariable {alloca, address_operations}
, _
) => {
495 let metadata
= unsafe {
496 llvm
::LLVMRustDIBuilderCreateVariable(
504 cx
.sess().opts
.optimize
!= config
::OptLevel
::No
,
510 source_loc
::set_debug_location(bx
,
511 InternalDebugLocation
::new(scope_metadata
, loc
.line
, loc
.col
.to_usize()));
513 let debug_loc
= llvm
::LLVMGetCurrentDebugLocation(bx
.llbuilder
);
514 let instr
= llvm
::LLVMRustDIBuilderInsertDeclareAtEnd(
518 address_operations
.as_ptr(),
519 address_operations
.len() as c_uint
,
523 llvm
::LLVMSetInstDebugLocation(bx
.llbuilder
, instr
);
528 match variable_kind
{
529 ArgumentVariable(_
) | CapturedVariable
=> {
530 assert
!(!dbg_context
.get_ref(span
).source_locations_enabled
.get());
531 source_loc
::set_debug_location(bx
, UnknownLocation
);
533 _
=> { /* nothing to do */ }