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
,
27 use rustc
::hir
::def_id
::DefId
;
28 use rustc
::hir
::map
::DefPathData
;
29 use rustc
::ty
::subst
::Substs
;
32 use common
::{CrateContext, FunctionContext, Block, BlockAndBuilder}
;
33 use monomorphize
::{self, Instance}
;
34 use rustc
::ty
::{self, Ty}
;
35 use rustc
::mir
::repr
as mir
;
36 use session
::config
::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo}
;
37 use util
::nodemap
::{DefIdMap, FnvHashMap, FnvHashSet}
;
40 use std
::cell
::{Cell, RefCell}
;
41 use std
::ffi
::CString
;
44 use syntax_pos
::{self, Span, Pos}
;
46 use rustc
::ty
::layout
;
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
;
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 current_debug_location
: Cell
<InternalDebugLocation
>,
71 created_files
: RefCell
<FnvHashMap
<String
, DIFile
>>,
72 created_enum_disr_types
: RefCell
<FnvHashMap
<(DefId
, layout
::Integer
), DIType
>>,
74 type_map
: RefCell
<TypeMap
<'tcx
>>,
75 namespace_map
: RefCell
<DefIdMap
<DIScope
>>,
77 // This collection is used to assert that composite types (structs, enums,
78 // ...) have their members only set once:
79 composite_types_completed
: RefCell
<FnvHashSet
<DIType
>>,
82 impl<'tcx
> CrateDebugContext
<'tcx
> {
83 pub fn new(llmod
: ModuleRef
) -> CrateDebugContext
<'tcx
> {
84 debug
!("CrateDebugContext::new");
85 let builder
= unsafe { llvm::LLVMRustDIBuilderCreate(llmod) }
;
86 // DIBuilder inherits context from the module, so we'd better use the same one
87 let llcontext
= unsafe { llvm::LLVMGetModuleContext(llmod) }
;
88 return CrateDebugContext
{
91 current_debug_location
: Cell
::new(InternalDebugLocation
::UnknownLocation
),
92 created_files
: RefCell
::new(FnvHashMap()),
93 created_enum_disr_types
: RefCell
::new(FnvHashMap()),
94 type_map
: RefCell
::new(TypeMap
::new()),
95 namespace_map
: RefCell
::new(DefIdMap()),
96 composite_types_completed
: RefCell
::new(FnvHashSet()),
101 pub enum FunctionDebugContext
{
102 RegularContext(Box
<FunctionDebugContextData
>),
104 FunctionWithoutDebugInfo
,
107 impl FunctionDebugContext
{
108 fn get_ref
<'a
>(&'a
self,
110 -> &'a FunctionDebugContextData
{
112 FunctionDebugContext
::RegularContext(box ref data
) => data
,
113 FunctionDebugContext
::DebugInfoDisabled
=> {
116 FunctionDebugContext
::debuginfo_disabled_message());
118 FunctionDebugContext
::FunctionWithoutDebugInfo
=> {
121 FunctionDebugContext
::should_be_ignored_message());
126 fn debuginfo_disabled_message() -> &'
static str {
127 "debuginfo: Error trying to access FunctionDebugContext although debug info is disabled!"
130 fn should_be_ignored_message() -> &'
static str {
131 "debuginfo: Error trying to access FunctionDebugContext for function that should be \
132 ignored by debug info!"
136 pub struct FunctionDebugContextData
{
137 fn_metadata
: DISubprogram
,
138 source_locations_enabled
: Cell
<bool
>,
139 source_location_override
: Cell
<bool
>,
142 pub enum VariableAccess
<'a
> {
143 // The llptr given is an alloca containing the variable's value
144 DirectVariable { alloca: ValueRef }
,
145 // The llptr given is an alloca containing the start of some pointer chain
146 // leading to the variable's content.
147 IndirectVariable { alloca: ValueRef, address_operations: &'a [i64] }
150 pub enum VariableKind
{
151 ArgumentVariable(usize /*index*/),
156 /// Create any deferred debug metadata nodes
157 pub fn finalize(cx
: &CrateContext
) {
158 if cx
.dbg_cx().is_none() {
164 if gdb
::needs_gdb_debug_scripts_section(cx
) {
165 // Add a .debug_gdb_scripts section to this compile-unit. This will
166 // cause GDB to try and load the gdb_load_rust_pretty_printers.py file,
167 // which activates the Rust pretty printers for binary this section is
169 gdb
::get_or_insert_gdb_debug_scripts_section_global(cx
);
173 llvm
::LLVMRustDIBuilderFinalize(DIB(cx
));
174 llvm
::LLVMRustDIBuilderDispose(DIB(cx
));
175 // Debuginfo generation in LLVM by default uses a higher
176 // version of dwarf than OS X currently understands. We can
177 // instruct LLVM to emit an older version of dwarf, however,
178 // for OS X to understand. For more info see #11352
179 // This can be overridden using --llvm-opts -dwarf-version,N.
180 // Android has the same issue (#22398)
181 if cx
.sess().target
.target
.options
.is_like_osx
||
182 cx
.sess().target
.target
.options
.is_like_android
{
183 llvm
::LLVMRustAddModuleFlag(cx
.llmod(),
184 "Dwarf Version\0".as_ptr() as *const _
,
188 // Indicate that we want CodeView debug information on MSVC
189 if cx
.sess().target
.target
.options
.is_like_msvc
{
190 llvm
::LLVMRustAddModuleFlag(cx
.llmod(),
191 "CodeView\0".as_ptr() as *const _
,
195 // Prevent bitcode readers from deleting the debug info.
196 let ptr
= "Debug Info Version\0".as_ptr();
197 llvm
::LLVMRustAddModuleFlag(cx
.llmod(), ptr
as *const _
,
198 llvm
::LLVMRustDebugMetadataVersion());
202 /// Creates a function-specific debug context for a function w/o debuginfo.
203 pub fn empty_function_debug_context
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>)
204 -> FunctionDebugContext
{
205 if cx
.sess().opts
.debuginfo
== NoDebugInfo
{
206 return FunctionDebugContext
::DebugInfoDisabled
;
209 // Clear the debug location so we don't assign them in the function prelude.
210 source_loc
::set_debug_location(cx
, None
, UnknownLocation
);
211 FunctionDebugContext
::FunctionWithoutDebugInfo
214 /// Creates the function-specific debug context.
216 /// Returns the FunctionDebugContext for the function which holds state needed
217 /// for debug info creation. The function may also return another variant of the
218 /// FunctionDebugContext enum which indicates why no debuginfo should be created
219 /// for the function.
220 pub fn create_function_debug_context
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>,
221 instance
: Instance
<'tcx
>,
222 sig
: &ty
::FnSig
<'tcx
>,
225 mir
: &mir
::Mir
) -> FunctionDebugContext
{
226 if cx
.sess().opts
.debuginfo
== NoDebugInfo
{
227 return FunctionDebugContext
::DebugInfoDisabled
;
230 // Clear the debug location so we don't assign them in the function prelude.
231 // Do this here already, in case we do an early exit from this function.
232 source_loc
::set_debug_location(cx
, None
, UnknownLocation
);
234 let containing_scope
= get_containing_scope(cx
, instance
);
237 // This can be the case for functions inlined from another crate
238 if span
== syntax_pos
::DUMMY_SP
{
239 return FunctionDebugContext
::FunctionWithoutDebugInfo
;
242 let loc
= span_start(cx
, span
);
243 let file_metadata
= file_metadata(cx
, &loc
.file
.name
, &loc
.file
.abs_path
);
245 let function_type_metadata
= unsafe {
246 let fn_signature
= get_function_signature(cx
, sig
, abi
);
247 llvm
::LLVMRustDIBuilderCreateSubroutineType(DIB(cx
), file_metadata
, fn_signature
)
250 // Find the enclosing function, in case this is a closure.
251 let mut fn_def_id
= instance
.def
;
252 let mut def_key
= cx
.tcx().def_key(fn_def_id
);
253 let mut name
= def_key
.disambiguated_data
.data
.to_string();
254 let name_len
= name
.len();
255 while def_key
.disambiguated_data
.data
== DefPathData
::ClosureExpr
{
256 fn_def_id
.index
= def_key
.parent
.expect("closure without a parent?");
257 def_key
= cx
.tcx().def_key(fn_def_id
);
260 // Get_template_parameters() will append a `<...>` clause to the function
261 // name if necessary.
262 let generics
= cx
.tcx().lookup_generics(fn_def_id
);
263 let template_parameters
= get_template_parameters(cx
,
269 // Build the linkage_name out of the item path and "template" parameters.
270 let linkage_name
= mangled_name_of_item(cx
, instance
.def
, &name
[name_len
..]);
272 let scope_line
= span_start(cx
, span
).line
;
274 let local_id
= cx
.tcx().map
.as_local_node_id(instance
.def
);
275 let is_local_to_unit
= local_id
.map_or(false, |id
| is_node_local_to_unit(cx
, id
));
277 let function_name
= CString
::new(name
).unwrap();
278 let linkage_name
= CString
::new(linkage_name
).unwrap();
280 let fn_metadata
= unsafe {
281 llvm
::LLVMRustDIBuilderCreateFunction(
284 function_name
.as_ptr(),
285 linkage_name
.as_ptr(),
288 function_type_metadata
,
291 scope_line
as c_uint
,
292 FlagPrototyped
as c_uint
,
293 cx
.sess().opts
.optimize
!= config
::OptLevel
::No
,
299 // Initialize fn debug context (including scope map and namespace map)
300 let fn_debug_context
= box FunctionDebugContextData
{
301 fn_metadata
: fn_metadata
,
302 source_locations_enabled
: Cell
::new(false),
303 source_location_override
: Cell
::new(false),
306 return FunctionDebugContext
::RegularContext(fn_debug_context
);
308 fn get_function_signature
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>,
309 sig
: &ty
::FnSig
<'tcx
>,
310 abi
: Abi
) -> DIArray
{
311 if cx
.sess().opts
.debuginfo
== LimitedDebugInfo
{
312 return create_DIArray(DIB(cx
), &[]);
315 let mut signature
= Vec
::with_capacity(sig
.inputs
.len() + 1);
317 // Return type -- llvm::DIBuilder wants this at index 0
318 signature
.push(match sig
.output
.sty
{
319 ty
::TyTuple(ref tys
) if tys
.is_empty() => ptr
::null_mut(),
320 _
=> type_metadata(cx
, sig
.output
, syntax_pos
::DUMMY_SP
)
323 let inputs
= if abi
== Abi
::RustCall
{
324 &sig
.inputs
[..sig
.inputs
.len()-1]
330 for &argument_type
in inputs
{
331 signature
.push(type_metadata(cx
, argument_type
, syntax_pos
::DUMMY_SP
));
334 if abi
== Abi
::RustCall
&& !sig
.inputs
.is_empty() {
335 if let ty
::TyTuple(args
) = sig
.inputs
[sig
.inputs
.len() - 1].sty
{
336 for &argument_type
in args
{
337 signature
.push(type_metadata(cx
, argument_type
, syntax_pos
::DUMMY_SP
));
342 return create_DIArray(DIB(cx
), &signature
[..]);
345 fn get_template_parameters
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>,
346 generics
: &ty
::Generics
<'tcx
>,
347 substs
: &Substs
<'tcx
>,
348 file_metadata
: DIFile
,
349 name_to_append_suffix_to
: &mut String
)
352 if substs
.types().next().is_none() {
353 return create_DIArray(DIB(cx
), &[]);
356 name_to_append_suffix_to
.push('
<'
);
357 for (i
, actual_type
) in substs
.types().enumerate() {
359 name_to_append_suffix_to
.push_str(",");
362 let actual_type
= cx
.tcx().normalize_associated_type(&actual_type
);
363 // Add actual type name to <...> clause of function name
364 let actual_type_name
= compute_debuginfo_type_name(cx
,
367 name_to_append_suffix_to
.push_str(&actual_type_name
[..]);
369 name_to_append_suffix_to
.push('
>'
);
371 // Again, only create type information if full debuginfo is enabled
372 let template_params
: Vec
<_
> = if cx
.sess().opts
.debuginfo
== FullDebugInfo
{
373 let names
= get_type_parameter_names(cx
, generics
);
374 substs
.types().zip(names
).map(|(ty
, name
)| {
375 let actual_type
= cx
.tcx().normalize_associated_type(&ty
);
376 let actual_type_metadata
= type_metadata(cx
, actual_type
, syntax_pos
::DUMMY_SP
);
377 let name
= CString
::new(name
.as_str().as_bytes()).unwrap();
379 llvm
::LLVMRustDIBuilderCreateTemplateTypeParameter(
383 actual_type_metadata
,
393 return create_DIArray(DIB(cx
), &template_params
[..]);
396 fn get_type_parameter_names
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>,
397 generics
: &ty
::Generics
<'tcx
>)
399 let mut names
= generics
.parent
.map_or(vec
![], |def_id
| {
400 get_type_parameter_names(cx
, cx
.tcx().lookup_generics(def_id
))
402 names
.extend(generics
.types
.iter().map(|param
| param
.name
));
406 fn get_containing_scope
<'ccx
, 'tcx
>(cx
: &CrateContext
<'ccx
, 'tcx
>,
407 instance
: Instance
<'tcx
>)
409 // First, let's see if this is a method within an inherent impl. Because
410 // if yes, we want to make the result subroutine DIE a child of the
411 // subroutine's self-type.
412 let self_type
= cx
.tcx().impl_of_method(instance
.def
).and_then(|impl_def_id
| {
413 // If the method does *not* belong to a trait, proceed
414 if cx
.tcx().trait_id_of_impl(impl_def_id
).is_none() {
415 let impl_self_ty
= cx
.tcx().lookup_item_type(impl_def_id
).ty
;
416 let impl_self_ty
= cx
.tcx().erase_regions(&impl_self_ty
);
417 let impl_self_ty
= monomorphize
::apply_param_substs(cx
.shared(),
421 // Only "class" methods are generally understood by LLVM,
422 // so avoid methods on other types (e.g. `<*mut T>::null`).
423 match impl_self_ty
.sty
{
425 Some(type_metadata(cx
, impl_self_ty
, syntax_pos
::DUMMY_SP
))
430 // For trait method impls we still use the "parallel namespace"
436 self_type
.unwrap_or_else(|| {
437 namespace
::item_namespace(cx
, DefId
{
438 krate
: instance
.def
.krate
,
440 .def_key(instance
.def
)
442 .expect("get_containing_scope: missing parent?")
448 pub fn declare_local
<'blk
, 'tcx
>(bcx
: Block
<'blk
, 'tcx
>,
449 variable_name
: ast
::Name
,
450 variable_type
: Ty
<'tcx
>,
451 scope_metadata
: DIScope
,
452 variable_access
: VariableAccess
,
453 variable_kind
: VariableKind
,
455 let cx
: &CrateContext
= bcx
.ccx();
457 let file
= span_start(cx
, span
).file
;
458 let filename
= file
.name
.clone();
459 let file_metadata
= file_metadata(cx
, &filename
[..], &file
.abs_path
);
461 let loc
= span_start(cx
, span
);
462 let type_metadata
= type_metadata(cx
, variable_type
, span
);
464 let (argument_index
, dwarf_tag
) = match variable_kind
{
465 ArgumentVariable(index
) => (index
as c_uint
, DW_TAG_arg_variable
),
467 CapturedVariable
=> (0, DW_TAG_auto_variable
)
470 let name
= CString
::new(variable_name
.as_str().as_bytes()).unwrap();
471 match (variable_access
, &[][..]) {
472 (DirectVariable { alloca }
, address_operations
) |
473 (IndirectVariable {alloca, address_operations}
, _
) => {
474 let metadata
= unsafe {
475 llvm
::LLVMRustDIBuilderCreateVariable(
483 cx
.sess().opts
.optimize
!= config
::OptLevel
::No
,
485 address_operations
.as_ptr(),
486 address_operations
.len() as c_uint
,
489 source_loc
::set_debug_location(cx
, None
,
490 InternalDebugLocation
::new(scope_metadata
, loc
.line
, loc
.col
.to_usize()));
492 let debug_loc
= llvm
::LLVMGetCurrentDebugLocation(cx
.raw_builder());
493 let instr
= llvm
::LLVMRustDIBuilderInsertDeclareAtEnd(
497 address_operations
.as_ptr(),
498 address_operations
.len() as c_uint
,
502 llvm
::LLVMSetInstDebugLocation(::build
::B(bcx
).llbuilder
, instr
);
507 match variable_kind
{
508 ArgumentVariable(_
) | CapturedVariable
=> {
512 .source_locations_enabled
514 source_loc
::set_debug_location(cx
, None
, UnknownLocation
);
516 _
=> { /* nothing to do */ }
520 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
522 ScopeAt(DIScope
, Span
),
527 pub fn apply(self, fcx
: &FunctionContext
) {
528 source_loc
::set_source_location(fcx
, None
, self);
531 pub fn apply_to_bcx(self, bcx
: &BlockAndBuilder
) {
532 source_loc
::set_source_location(bcx
.fcx(), Some(bcx
), self);