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, CrateNum}
;
27 use rustc
::ty
::subst
::Substs
;
30 use common
::{self, CrateContext}
;
32 use monomorphize
::Instance
;
33 use rustc
::ty
::{self, Ty}
;
35 use rustc
::session
::config
::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo}
;
36 use rustc
::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 syntax
::symbol
::Symbol
;
46 use rustc
::ty
::layout
::{self, LayoutTyper}
;
56 pub use self::create_scope_map
::{create_mir_scopes, MirDebugScope}
;
57 pub use self::source_loc
::start_emitting_source_locations
;
58 pub use self::metadata
::create_global_var_metadata
;
59 pub use self::metadata
::extend_scope_to_file
;
60 pub use self::source_loc
::set_source_location
;
62 #[allow(non_upper_case_globals)]
63 const DW_TAG_auto_variable
: c_uint
= 0x100;
64 #[allow(non_upper_case_globals)]
65 const DW_TAG_arg_variable
: c_uint
= 0x101;
67 /// A context object for maintaining all state needed by the debuginfo module.
68 pub struct CrateDebugContext
<'tcx
> {
69 llcontext
: ContextRef
,
71 builder
: DIBuilderRef
,
72 created_files
: RefCell
<FxHashMap
<(Symbol
, Symbol
), DIFile
>>,
73 created_enum_disr_types
: RefCell
<FxHashMap
<(DefId
, layout
::Integer
), DIType
>>,
75 type_map
: RefCell
<TypeMap
<'tcx
>>,
76 namespace_map
: RefCell
<DefIdMap
<DIScope
>>,
78 // This collection is used to assert that composite types (structs, enums,
79 // ...) have their members only set once:
80 composite_types_completed
: RefCell
<FxHashSet
<DIType
>>,
83 impl<'tcx
> CrateDebugContext
<'tcx
> {
84 pub fn new(llmod
: ModuleRef
) -> CrateDebugContext
<'tcx
> {
85 debug
!("CrateDebugContext::new");
86 let builder
= unsafe { llvm::LLVMRustDIBuilderCreate(llmod) }
;
87 // DIBuilder inherits context from the module, so we'd better use the same one
88 let llcontext
= unsafe { llvm::LLVMGetModuleContext(llmod) }
;
93 created_files
: RefCell
::new(FxHashMap()),
94 created_enum_disr_types
: RefCell
::new(FxHashMap()),
95 type_map
: RefCell
::new(TypeMap
::new()),
96 namespace_map
: RefCell
::new(DefIdMap()),
97 composite_types_completed
: RefCell
::new(FxHashSet()),
102 pub enum FunctionDebugContext
{
103 RegularContext(FunctionDebugContextData
),
105 FunctionWithoutDebugInfo
,
108 impl FunctionDebugContext
{
109 pub fn get_ref
<'a
>(&'a
self, span
: Span
) -> &'a FunctionDebugContextData
{
111 FunctionDebugContext
::RegularContext(ref data
) => data
,
112 FunctionDebugContext
::DebugInfoDisabled
=> {
113 span_bug
!(span
, "{}", FunctionDebugContext
::debuginfo_disabled_message());
115 FunctionDebugContext
::FunctionWithoutDebugInfo
=> {
116 span_bug
!(span
, "{}", FunctionDebugContext
::should_be_ignored_message());
121 fn debuginfo_disabled_message() -> &'
static str {
122 "debuginfo: Error trying to access FunctionDebugContext although debug info is disabled!"
125 fn should_be_ignored_message() -> &'
static str {
126 "debuginfo: Error trying to access FunctionDebugContext for function that should be \
127 ignored by debug info!"
131 pub struct FunctionDebugContextData
{
132 fn_metadata
: DISubprogram
,
133 source_locations_enabled
: Cell
<bool
>,
134 pub defining_crate
: CrateNum
,
137 pub enum VariableAccess
<'a
> {
138 // The llptr given is an alloca containing the variable's value
139 DirectVariable { alloca: ValueRef }
,
140 // The llptr given is an alloca containing the start of some pointer chain
141 // leading to the variable's content.
142 IndirectVariable { alloca: ValueRef, address_operations: &'a [i64] }
145 pub enum VariableKind
{
146 ArgumentVariable(usize /*index*/),
151 /// Create any deferred debug metadata nodes
152 pub fn finalize(cx
: &CrateContext
) {
153 if cx
.dbg_cx().is_none() {
159 if gdb
::needs_gdb_debug_scripts_section(cx
) {
160 // Add a .debug_gdb_scripts section to this compile-unit. This will
161 // cause GDB to try and load the gdb_load_rust_pretty_printers.py file,
162 // which activates the Rust pretty printers for binary this section is
164 gdb
::get_or_insert_gdb_debug_scripts_section_global(cx
);
168 llvm
::LLVMRustDIBuilderFinalize(DIB(cx
));
169 llvm
::LLVMRustDIBuilderDispose(DIB(cx
));
170 // Debuginfo generation in LLVM by default uses a higher
171 // version of dwarf than macOS currently understands. We can
172 // instruct LLVM to emit an older version of dwarf, however,
173 // for macOS to understand. For more info see #11352
174 // This can be overridden using --llvm-opts -dwarf-version,N.
175 // Android has the same issue (#22398)
176 if cx
.sess().target
.target
.options
.is_like_osx
||
177 cx
.sess().target
.target
.options
.is_like_android
{
178 llvm
::LLVMRustAddModuleFlag(cx
.llmod(),
179 "Dwarf Version\0".as_ptr() as *const _
,
183 // Indicate that we want CodeView debug information on MSVC
184 if cx
.sess().target
.target
.options
.is_like_msvc
{
185 llvm
::LLVMRustAddModuleFlag(cx
.llmod(),
186 "CodeView\0".as_ptr() as *const _
,
190 // Prevent bitcode readers from deleting the debug info.
191 let ptr
= "Debug Info Version\0".as_ptr();
192 llvm
::LLVMRustAddModuleFlag(cx
.llmod(), ptr
as *const _
,
193 llvm
::LLVMRustDebugMetadataVersion());
197 /// Creates the function-specific debug context.
199 /// Returns the FunctionDebugContext for the function which holds state needed
200 /// for debug info creation. The function may also return another variant of the
201 /// FunctionDebugContext enum which indicates why no debuginfo should be created
202 /// for the function.
203 pub fn create_function_debug_context
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>,
204 instance
: Instance
<'tcx
>,
205 sig
: ty
::FnSig
<'tcx
>,
207 mir
: &mir
::Mir
) -> FunctionDebugContext
{
208 if cx
.sess().opts
.debuginfo
== NoDebugInfo
{
209 return FunctionDebugContext
::DebugInfoDisabled
;
212 for attr
in instance
.def
.attrs(cx
.tcx()).iter() {
213 if attr
.check_name("no_debug") {
214 return FunctionDebugContext
::FunctionWithoutDebugInfo
;
218 let containing_scope
= get_containing_scope(cx
, instance
);
221 // This can be the case for functions inlined from another crate
222 if span
== syntax_pos
::DUMMY_SP
{
223 // FIXME(simulacrum): Probably can't happen; remove.
224 return FunctionDebugContext
::FunctionWithoutDebugInfo
;
227 let def_id
= instance
.def_id();
228 let loc
= span_start(cx
, span
);
229 let file_metadata
= file_metadata(cx
, &loc
.file
.name
, def_id
.krate
);
231 let function_type_metadata
= unsafe {
232 let fn_signature
= get_function_signature(cx
, sig
);
233 llvm
::LLVMRustDIBuilderCreateSubroutineType(DIB(cx
), file_metadata
, fn_signature
)
236 // Find the enclosing function, in case this is a closure.
237 let def_key
= cx
.tcx().def_key(def_id
);
238 let mut name
= def_key
.disambiguated_data
.data
.to_string();
239 let name_len
= name
.len();
241 let enclosing_fn_def_id
= cx
.tcx().closure_base_def_id(def_id
);
243 // Get_template_parameters() will append a `<...>` clause to the function
244 // name if necessary.
245 let generics
= cx
.tcx().generics_of(enclosing_fn_def_id
);
246 let substs
= instance
.substs
.truncate_to(cx
.tcx(), generics
);
247 let template_parameters
= get_template_parameters(cx
,
253 // Build the linkage_name out of the item path and "template" parameters.
254 let linkage_name
= mangled_name_of_item(cx
, instance
.def_id(), &name
[name_len
..]);
256 let scope_line
= span_start(cx
, span
).line
;
258 let local_id
= cx
.tcx().hir
.as_local_node_id(instance
.def_id());
259 let is_local_to_unit
= local_id
.map_or(false, |id
| is_node_local_to_unit(cx
, id
));
261 let function_name
= CString
::new(name
).unwrap();
262 let linkage_name
= CString
::new(linkage_name
).unwrap();
264 let mut flags
= DIFlags
::FlagPrototyped
;
265 match *cx
.sess().entry_fn
.borrow() {
267 if local_id
== Some(id
) {
268 flags
= flags
| DIFlags
::FlagMainSubprogram
;
274 let fn_metadata
= unsafe {
275 llvm
::LLVMRustDIBuilderCreateFunction(
278 function_name
.as_ptr(),
279 linkage_name
.as_ptr(),
282 function_type_metadata
,
285 scope_line
as c_uint
,
287 cx
.sess().opts
.optimize
!= config
::OptLevel
::No
,
293 // Initialize fn debug context (including scope map and namespace map)
294 let fn_debug_context
= FunctionDebugContextData
{
295 fn_metadata
: fn_metadata
,
296 source_locations_enabled
: Cell
::new(false),
297 defining_crate
: def_id
.krate
,
300 return FunctionDebugContext
::RegularContext(fn_debug_context
);
302 fn get_function_signature
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>,
303 sig
: ty
::FnSig
<'tcx
>) -> DIArray
{
304 if cx
.sess().opts
.debuginfo
== LimitedDebugInfo
{
305 return create_DIArray(DIB(cx
), &[]);
308 let mut signature
= Vec
::with_capacity(sig
.inputs().len() + 1);
310 // Return type -- llvm::DIBuilder wants this at index 0
311 signature
.push(match sig
.output().sty
{
312 ty
::TyTuple(ref tys
, _
) if tys
.is_empty() => ptr
::null_mut(),
313 _
=> type_metadata(cx
, sig
.output(), syntax_pos
::DUMMY_SP
)
316 let inputs
= if sig
.abi
== Abi
::RustCall
{
317 &sig
.inputs()[..sig
.inputs().len() - 1]
323 if cx
.sess().target
.target
.options
.is_like_msvc
{
325 // There is a bug in MSDIA that leads to a crash when it encounters
326 // a fixed-size array of `u8` or something zero-sized in a
327 // function-type (see #40477).
328 // As a workaround, we replace those fixed-size arrays with a
329 // pointer-type. So a function `fn foo(a: u8, b: [u8; 4])` would
330 // appear as `fn foo(a: u8, b: *const u8)` in debuginfo,
331 // and a function `fn bar(x: [(); 7])` as `fn bar(x: *const ())`.
332 // This transformed type is wrong, but these function types are
333 // already inaccurate due to ABI adjustments (see #42800).
334 signature
.extend(inputs
.iter().map(|&t
| {
335 let t
= match t
.sty
{
337 if (ct
== cx
.tcx().types
.u8) ||
338 (cx
.layout_of(ct
).size(cx
).bytes() == 0) => {
339 cx
.tcx().mk_imm_ptr(ct
)
343 type_metadata(cx
, t
, syntax_pos
::DUMMY_SP
)
346 signature
.extend(inputs
.iter().map(|t
| {
347 type_metadata(cx
, t
, syntax_pos
::DUMMY_SP
)
351 if sig
.abi
== Abi
::RustCall
&& !sig
.inputs().is_empty() {
352 if let ty
::TyTuple(args
, _
) = sig
.inputs()[sig
.inputs().len() - 1].sty
{
353 for &argument_type
in args
{
354 signature
.push(type_metadata(cx
, argument_type
, syntax_pos
::DUMMY_SP
));
359 return create_DIArray(DIB(cx
), &signature
[..]);
362 fn get_template_parameters
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>,
363 generics
: &ty
::Generics
,
364 substs
: &Substs
<'tcx
>,
365 file_metadata
: DIFile
,
366 name_to_append_suffix_to
: &mut String
)
369 if substs
.types().next().is_none() {
370 return create_DIArray(DIB(cx
), &[]);
373 name_to_append_suffix_to
.push('
<'
);
374 for (i
, actual_type
) in substs
.types().enumerate() {
376 name_to_append_suffix_to
.push_str(",");
379 let actual_type
= cx
.tcx().normalize_associated_type(&actual_type
);
380 // Add actual type name to <...> clause of function name
381 let actual_type_name
= compute_debuginfo_type_name(cx
,
384 name_to_append_suffix_to
.push_str(&actual_type_name
[..]);
386 name_to_append_suffix_to
.push('
>'
);
388 // Again, only create type information if full debuginfo is enabled
389 let template_params
: Vec
<_
> = if cx
.sess().opts
.debuginfo
== FullDebugInfo
{
390 let names
= get_type_parameter_names(cx
, generics
);
391 substs
.types().zip(names
).map(|(ty
, name
)| {
392 let actual_type
= cx
.tcx().normalize_associated_type(&ty
);
393 let actual_type_metadata
= type_metadata(cx
, actual_type
, syntax_pos
::DUMMY_SP
);
394 let name
= CString
::new(name
.as_str().as_bytes()).unwrap();
396 llvm
::LLVMRustDIBuilderCreateTemplateTypeParameter(
400 actual_type_metadata
,
410 return create_DIArray(DIB(cx
), &template_params
[..]);
413 fn get_type_parameter_names(cx
: &CrateContext
, generics
: &ty
::Generics
) -> Vec
<ast
::Name
> {
414 let mut names
= generics
.parent
.map_or(vec
![], |def_id
| {
415 get_type_parameter_names(cx
, cx
.tcx().generics_of(def_id
))
417 names
.extend(generics
.types
.iter().map(|param
| param
.name
));
421 fn get_containing_scope
<'ccx
, 'tcx
>(cx
: &CrateContext
<'ccx
, 'tcx
>,
422 instance
: Instance
<'tcx
>)
424 // First, let's see if this is a method within an inherent impl. Because
425 // if yes, we want to make the result subroutine DIE a child of the
426 // subroutine's self-type.
427 let self_type
= cx
.tcx().impl_of_method(instance
.def_id()).and_then(|impl_def_id
| {
428 // If the method does *not* belong to a trait, proceed
429 if cx
.tcx().trait_id_of_impl(impl_def_id
).is_none() {
431 common
::def_ty(cx
.shared(), impl_def_id
, instance
.substs
);
433 // Only "class" methods are generally understood by LLVM,
434 // so avoid methods on other types (e.g. `<*mut T>::null`).
435 match impl_self_ty
.sty
{
436 ty
::TyAdt(def
, ..) if !def
.is_box() => {
437 Some(type_metadata(cx
, impl_self_ty
, syntax_pos
::DUMMY_SP
))
442 // For trait method impls we still use the "parallel namespace"
448 self_type
.unwrap_or_else(|| {
449 namespace
::item_namespace(cx
, DefId
{
450 krate
: instance
.def_id().krate
,
452 .def_key(instance
.def_id())
454 .expect("get_containing_scope: missing parent?")
460 pub fn declare_local
<'a
, 'tcx
>(bcx
: &Builder
<'a
, 'tcx
>,
461 dbg_context
: &FunctionDebugContext
,
462 variable_name
: ast
::Name
,
463 variable_type
: Ty
<'tcx
>,
464 scope_metadata
: DIScope
,
465 variable_access
: VariableAccess
,
466 variable_kind
: VariableKind
,
470 let file
= span_start(cx
, span
).file
;
471 let file_metadata
= file_metadata(cx
,
473 dbg_context
.get_ref(span
).defining_crate
);
475 let loc
= span_start(cx
, span
);
476 let type_metadata
= type_metadata(cx
, variable_type
, span
);
478 let (argument_index
, dwarf_tag
) = match variable_kind
{
479 ArgumentVariable(index
) => (index
as c_uint
, DW_TAG_arg_variable
),
481 CapturedVariable
=> (0, DW_TAG_auto_variable
)
483 let align
= cx
.align_of(variable_type
);
485 let name
= CString
::new(variable_name
.as_str().as_bytes()).unwrap();
486 match (variable_access
, &[][..]) {
487 (DirectVariable { alloca }
, address_operations
) |
488 (IndirectVariable {alloca, address_operations}
, _
) => {
489 let metadata
= unsafe {
490 llvm
::LLVMRustDIBuilderCreateVariable(
498 cx
.sess().opts
.optimize
!= config
::OptLevel
::No
,
504 source_loc
::set_debug_location(bcx
,
505 InternalDebugLocation
::new(scope_metadata
, loc
.line
, loc
.col
.to_usize()));
507 let debug_loc
= llvm
::LLVMGetCurrentDebugLocation(bcx
.llbuilder
);
508 let instr
= llvm
::LLVMRustDIBuilderInsertDeclareAtEnd(
512 address_operations
.as_ptr(),
513 address_operations
.len() as c_uint
,
517 llvm
::LLVMSetInstDebugLocation(bcx
.llbuilder
, instr
);
522 match variable_kind
{
523 ArgumentVariable(_
) | CapturedVariable
=> {
524 assert
!(!dbg_context
.get_ref(span
).source_locations_enabled
.get());
525 source_loc
::set_debug_location(bcx
, UnknownLocation
);
527 _
=> { /* nothing to do */ }