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_item
;
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
::def_id
::DefId
;
27 use rustc
::ty
::subst
::Substs
;
30 use common
::{self, CrateContext}
;
32 use monomorphize
::Instance
;
33 use rustc
::ty
::{self, Ty}
;
35 use session
::config
::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo}
;
36 use util
::nodemap
::{DefIdMap, FxHashMap, FxHashSet}
;
39 use std
::cell
::{Cell, RefCell}
;
40 use std
::ffi
::CString
;
43 use syntax_pos
::{self, Span, Pos}
;
45 use rustc
::ty
::layout
;
55 pub use self::create_scope_map
::{create_mir_scopes, MirDebugScope}
;
56 pub use self::source_loc
::start_emitting_source_locations
;
57 pub use self::metadata
::create_global_var_metadata
;
58 pub use self::metadata
::extend_scope_to_file
;
59 pub use self::source_loc
::set_source_location
;
61 #[allow(non_upper_case_globals)]
62 const DW_TAG_auto_variable
: c_uint
= 0x100;
63 #[allow(non_upper_case_globals)]
64 const DW_TAG_arg_variable
: c_uint
= 0x101;
66 /// A context object for maintaining all state needed by the debuginfo module.
67 pub struct CrateDebugContext
<'tcx
> {
68 llcontext
: ContextRef
,
69 builder
: DIBuilderRef
,
70 created_files
: RefCell
<FxHashMap
<String
, DIFile
>>,
71 created_enum_disr_types
: RefCell
<FxHashMap
<(DefId
, layout
::Integer
), DIType
>>,
73 type_map
: RefCell
<TypeMap
<'tcx
>>,
74 namespace_map
: RefCell
<DefIdMap
<DIScope
>>,
76 // This collection is used to assert that composite types (structs, enums,
77 // ...) have their members only set once:
78 composite_types_completed
: RefCell
<FxHashSet
<DIType
>>,
81 impl<'tcx
> CrateDebugContext
<'tcx
> {
82 pub fn new(llmod
: ModuleRef
) -> CrateDebugContext
<'tcx
> {
83 debug
!("CrateDebugContext::new");
84 let builder
= unsafe { llvm::LLVMRustDIBuilderCreate(llmod) }
;
85 // DIBuilder inherits context from the module, so we'd better use the same one
86 let llcontext
= unsafe { llvm::LLVMGetModuleContext(llmod) }
;
90 created_files
: RefCell
::new(FxHashMap()),
91 created_enum_disr_types
: RefCell
::new(FxHashMap()),
92 type_map
: RefCell
::new(TypeMap
::new()),
93 namespace_map
: RefCell
::new(DefIdMap()),
94 composite_types_completed
: RefCell
::new(FxHashSet()),
99 pub enum FunctionDebugContext
{
100 RegularContext(FunctionDebugContextData
),
102 FunctionWithoutDebugInfo
,
105 impl FunctionDebugContext
{
106 fn get_ref
<'a
>(&'a
self, span
: Span
) -> &'a FunctionDebugContextData
{
108 FunctionDebugContext
::RegularContext(ref data
) => data
,
109 FunctionDebugContext
::DebugInfoDisabled
=> {
110 span_bug
!(span
, "{}", FunctionDebugContext
::debuginfo_disabled_message());
112 FunctionDebugContext
::FunctionWithoutDebugInfo
=> {
113 span_bug
!(span
, "{}", FunctionDebugContext
::should_be_ignored_message());
118 fn debuginfo_disabled_message() -> &'
static str {
119 "debuginfo: Error trying to access FunctionDebugContext although debug info is disabled!"
122 fn should_be_ignored_message() -> &'
static str {
123 "debuginfo: Error trying to access FunctionDebugContext for function that should be \
124 ignored by debug info!"
128 pub struct FunctionDebugContextData
{
129 fn_metadata
: DISubprogram
,
130 source_locations_enabled
: Cell
<bool
>,
133 pub enum VariableAccess
<'a
> {
134 // The llptr given is an alloca containing the variable's value
135 DirectVariable { alloca: ValueRef }
,
136 // The llptr given is an alloca containing the start of some pointer chain
137 // leading to the variable's content.
138 IndirectVariable { alloca: ValueRef, address_operations: &'a [i64] }
141 pub enum VariableKind
{
142 ArgumentVariable(usize /*index*/),
147 /// Create any deferred debug metadata nodes
148 pub fn finalize(cx
: &CrateContext
) {
149 if cx
.dbg_cx().is_none() {
155 if gdb
::needs_gdb_debug_scripts_section(cx
) {
156 // Add a .debug_gdb_scripts section to this compile-unit. This will
157 // cause GDB to try and load the gdb_load_rust_pretty_printers.py file,
158 // which activates the Rust pretty printers for binary this section is
160 gdb
::get_or_insert_gdb_debug_scripts_section_global(cx
);
164 llvm
::LLVMRustDIBuilderFinalize(DIB(cx
));
165 llvm
::LLVMRustDIBuilderDispose(DIB(cx
));
166 // Debuginfo generation in LLVM by default uses a higher
167 // version of dwarf than macOS currently understands. We can
168 // instruct LLVM to emit an older version of dwarf, however,
169 // for macOS to understand. For more info see #11352
170 // This can be overridden using --llvm-opts -dwarf-version,N.
171 // Android has the same issue (#22398)
172 if cx
.sess().target
.target
.options
.is_like_osx
||
173 cx
.sess().target
.target
.options
.is_like_android
{
174 llvm
::LLVMRustAddModuleFlag(cx
.llmod(),
175 "Dwarf Version\0".as_ptr() as *const _
,
179 // Indicate that we want CodeView debug information on MSVC
180 if cx
.sess().target
.target
.options
.is_like_msvc
{
181 llvm
::LLVMRustAddModuleFlag(cx
.llmod(),
182 "CodeView\0".as_ptr() as *const _
,
186 // Prevent bitcode readers from deleting the debug info.
187 let ptr
= "Debug Info Version\0".as_ptr();
188 llvm
::LLVMRustAddModuleFlag(cx
.llmod(), ptr
as *const _
,
189 llvm
::LLVMRustDebugMetadataVersion());
193 /// Creates the function-specific debug context.
195 /// Returns the FunctionDebugContext for the function which holds state needed
196 /// for debug info creation. The function may also return another variant of the
197 /// FunctionDebugContext enum which indicates why no debuginfo should be created
198 /// for the function.
199 pub fn create_function_debug_context
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>,
200 instance
: Instance
<'tcx
>,
201 sig
: ty
::FnSig
<'tcx
>,
203 mir
: &mir
::Mir
) -> FunctionDebugContext
{
204 if cx
.sess().opts
.debuginfo
== NoDebugInfo
{
205 return FunctionDebugContext
::DebugInfoDisabled
;
208 for attr
in instance
.def
.attrs(cx
.tcx()).iter() {
209 if attr
.check_name("no_debug") {
210 return FunctionDebugContext
::FunctionWithoutDebugInfo
;
214 let containing_scope
= get_containing_scope(cx
, instance
);
217 // This can be the case for functions inlined from another crate
218 if span
== syntax_pos
::DUMMY_SP
{
219 // FIXME(simulacrum): Probably can't happen; remove.
220 return FunctionDebugContext
::FunctionWithoutDebugInfo
;
223 let loc
= span_start(cx
, span
);
224 let file_metadata
= file_metadata(cx
, &loc
.file
.name
, &loc
.file
.abs_path
);
226 let function_type_metadata
= unsafe {
227 let fn_signature
= get_function_signature(cx
, sig
);
228 llvm
::LLVMRustDIBuilderCreateSubroutineType(DIB(cx
), file_metadata
, fn_signature
)
231 // Find the enclosing function, in case this is a closure.
232 let def_key
= cx
.tcx().def_key(instance
.def_id());
233 let mut name
= def_key
.disambiguated_data
.data
.to_string();
234 let name_len
= name
.len();
236 let fn_def_id
= cx
.tcx().closure_base_def_id(instance
.def_id());
238 // Get_template_parameters() will append a `<...>` clause to the function
239 // name if necessary.
240 let generics
= cx
.tcx().item_generics(fn_def_id
);
241 let substs
= instance
.substs
.truncate_to(cx
.tcx(), generics
);
242 let template_parameters
= get_template_parameters(cx
,
248 // Build the linkage_name out of the item path and "template" parameters.
249 let linkage_name
= mangled_name_of_item(cx
, instance
.def_id(), &name
[name_len
..]);
251 let scope_line
= span_start(cx
, span
).line
;
253 let local_id
= cx
.tcx().hir
.as_local_node_id(instance
.def_id());
254 let is_local_to_unit
= local_id
.map_or(false, |id
| is_node_local_to_unit(cx
, id
));
256 let function_name
= CString
::new(name
).unwrap();
257 let linkage_name
= CString
::new(linkage_name
).unwrap();
259 let mut flags
= DIFlags
::FlagPrototyped
;
260 match *cx
.sess().entry_fn
.borrow() {
262 if local_id
== Some(id
) {
263 flags
= flags
| DIFlags
::FlagMainSubprogram
;
269 let fn_metadata
= unsafe {
270 llvm
::LLVMRustDIBuilderCreateFunction(
273 function_name
.as_ptr(),
274 linkage_name
.as_ptr(),
277 function_type_metadata
,
280 scope_line
as c_uint
,
282 cx
.sess().opts
.optimize
!= config
::OptLevel
::No
,
288 // Initialize fn debug context (including scope map and namespace map)
289 let fn_debug_context
= FunctionDebugContextData
{
290 fn_metadata
: fn_metadata
,
291 source_locations_enabled
: Cell
::new(false),
294 return FunctionDebugContext
::RegularContext(fn_debug_context
);
296 fn get_function_signature
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>,
297 sig
: ty
::FnSig
<'tcx
>) -> DIArray
{
298 if cx
.sess().opts
.debuginfo
== LimitedDebugInfo
{
299 return create_DIArray(DIB(cx
), &[]);
302 let mut signature
= Vec
::with_capacity(sig
.inputs().len() + 1);
304 // Return type -- llvm::DIBuilder wants this at index 0
305 signature
.push(match sig
.output().sty
{
306 ty
::TyTuple(ref tys
, _
) if tys
.is_empty() => ptr
::null_mut(),
307 _
=> type_metadata(cx
, sig
.output(), syntax_pos
::DUMMY_SP
)
310 let inputs
= if sig
.abi
== Abi
::RustCall
{
311 &sig
.inputs()[..sig
.inputs().len() - 1]
317 for &argument_type
in inputs
{
318 signature
.push(type_metadata(cx
, argument_type
, syntax_pos
::DUMMY_SP
));
321 if sig
.abi
== Abi
::RustCall
&& !sig
.inputs().is_empty() {
322 if let ty
::TyTuple(args
, _
) = sig
.inputs()[sig
.inputs().len() - 1].sty
{
323 for &argument_type
in args
{
324 signature
.push(type_metadata(cx
, argument_type
, syntax_pos
::DUMMY_SP
));
329 return create_DIArray(DIB(cx
), &signature
[..]);
332 fn get_template_parameters
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>,
333 generics
: &ty
::Generics
,
334 substs
: &Substs
<'tcx
>,
335 file_metadata
: DIFile
,
336 name_to_append_suffix_to
: &mut String
)
339 if substs
.types().next().is_none() {
340 return create_DIArray(DIB(cx
), &[]);
343 name_to_append_suffix_to
.push('
<'
);
344 for (i
, actual_type
) in substs
.types().enumerate() {
346 name_to_append_suffix_to
.push_str(",");
349 let actual_type
= cx
.tcx().normalize_associated_type(&actual_type
);
350 // Add actual type name to <...> clause of function name
351 let actual_type_name
= compute_debuginfo_type_name(cx
,
354 name_to_append_suffix_to
.push_str(&actual_type_name
[..]);
356 name_to_append_suffix_to
.push('
>'
);
358 // Again, only create type information if full debuginfo is enabled
359 let template_params
: Vec
<_
> = if cx
.sess().opts
.debuginfo
== FullDebugInfo
{
360 let names
= get_type_parameter_names(cx
, generics
);
361 substs
.types().zip(names
).map(|(ty
, name
)| {
362 let actual_type
= cx
.tcx().normalize_associated_type(&ty
);
363 let actual_type_metadata
= type_metadata(cx
, actual_type
, syntax_pos
::DUMMY_SP
);
364 let name
= CString
::new(name
.as_str().as_bytes()).unwrap();
366 llvm
::LLVMRustDIBuilderCreateTemplateTypeParameter(
370 actual_type_metadata
,
380 return create_DIArray(DIB(cx
), &template_params
[..]);
383 fn get_type_parameter_names(cx
: &CrateContext
, generics
: &ty
::Generics
) -> Vec
<ast
::Name
> {
384 let mut names
= generics
.parent
.map_or(vec
![], |def_id
| {
385 get_type_parameter_names(cx
, cx
.tcx().item_generics(def_id
))
387 names
.extend(generics
.types
.iter().map(|param
| param
.name
));
391 fn get_containing_scope
<'ccx
, 'tcx
>(cx
: &CrateContext
<'ccx
, 'tcx
>,
392 instance
: Instance
<'tcx
>)
394 // First, let's see if this is a method within an inherent impl. Because
395 // if yes, we want to make the result subroutine DIE a child of the
396 // subroutine's self-type.
397 let self_type
= cx
.tcx().impl_of_method(instance
.def_id()).and_then(|impl_def_id
| {
398 // If the method does *not* belong to a trait, proceed
399 if cx
.tcx().trait_id_of_impl(impl_def_id
).is_none() {
401 common
::def_ty(cx
.shared(), impl_def_id
, instance
.substs
);
403 // Only "class" methods are generally understood by LLVM,
404 // so avoid methods on other types (e.g. `<*mut T>::null`).
405 match impl_self_ty
.sty
{
406 ty
::TyAdt(def
, ..) if !def
.is_box() => {
407 Some(type_metadata(cx
, impl_self_ty
, syntax_pos
::DUMMY_SP
))
412 // For trait method impls we still use the "parallel namespace"
418 self_type
.unwrap_or_else(|| {
419 namespace
::item_namespace(cx
, DefId
{
420 krate
: instance
.def_id().krate
,
422 .def_key(instance
.def_id())
424 .expect("get_containing_scope: missing parent?")
430 pub fn declare_local
<'a
, 'tcx
>(bcx
: &Builder
<'a
, 'tcx
>,
431 dbg_context
: &FunctionDebugContext
,
432 variable_name
: ast
::Name
,
433 variable_type
: Ty
<'tcx
>,
434 scope_metadata
: DIScope
,
435 variable_access
: VariableAccess
,
436 variable_kind
: VariableKind
,
440 let file
= span_start(cx
, span
).file
;
441 let filename
= file
.name
.clone();
442 let file_metadata
= file_metadata(cx
, &filename
[..], &file
.abs_path
);
444 let loc
= span_start(cx
, span
);
445 let type_metadata
= type_metadata(cx
, variable_type
, span
);
447 let (argument_index
, dwarf_tag
) = match variable_kind
{
448 ArgumentVariable(index
) => (index
as c_uint
, DW_TAG_arg_variable
),
450 CapturedVariable
=> (0, DW_TAG_auto_variable
)
452 let align
= cx
.align_of(variable_type
);
454 let name
= CString
::new(variable_name
.as_str().as_bytes()).unwrap();
455 match (variable_access
, &[][..]) {
456 (DirectVariable { alloca }
, address_operations
) |
457 (IndirectVariable {alloca, address_operations}
, _
) => {
458 let metadata
= unsafe {
459 llvm
::LLVMRustDIBuilderCreateVariable(
467 cx
.sess().opts
.optimize
!= config
::OptLevel
::No
,
473 source_loc
::set_debug_location(bcx
,
474 InternalDebugLocation
::new(scope_metadata
, loc
.line
, loc
.col
.to_usize()));
476 let debug_loc
= llvm
::LLVMGetCurrentDebugLocation(bcx
.llbuilder
);
477 let instr
= llvm
::LLVMRustDIBuilderInsertDeclareAtEnd(
481 address_operations
.as_ptr(),
482 address_operations
.len() as c_uint
,
486 llvm
::LLVMSetInstDebugLocation(bcx
.llbuilder
, instr
);
491 match variable_kind
{
492 ArgumentVariable(_
) | CapturedVariable
=> {
493 assert
!(!dbg_context
.get_ref(span
).source_locations_enabled
.get());
494 source_loc
::set_debug_location(bcx
, UnknownLocation
);
496 _
=> { /* nothing to do */ }