]> git.lizzy.rs Git - rust.git/blob - src/librustc_codegen_llvm/debuginfo/mod.rs
All Builder methods now take &mut self instead of &self
[rust.git] / src / librustc_codegen_llvm / debuginfo / mod.rs
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.
4 //
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.
10
11 // See doc.rs for documentation.
12 mod doc;
13
14 use rustc_codegen_ssa::debuginfo::VariableAccess::*;
15 use rustc_codegen_ssa::debuginfo::VariableKind::*;
16
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};
22
23 use llvm;
24 use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilder, DISubprogram, DIArray, DIFlags,
25     DILexicalBlock};
26 use rustc::hir::CodegenFnAttrFlags;
27 use rustc::hir::def_id::{DefId, CrateNum};
28 use rustc::ty::subst::{Substs, UnpackedKind};
29
30 use abi::Abi;
31 use common::CodegenCx;
32 use builder::Builder;
33 use monomorphize::Instance;
34 use rustc::ty::{self, ParamEnv, Ty, InstanceDef};
35 use rustc::mir;
36 use rustc::session::config::{self, DebugInfo};
37 use rustc::util::nodemap::{DefIdMap, FxHashMap, FxHashSet};
38 use rustc_data_structures::small_c_str::SmallCStr;
39 use rustc_data_structures::indexed_vec::IndexVec;
40 use value::Value;
41 use rustc_codegen_ssa::debuginfo::{FunctionDebugContext, MirDebugScope, VariableAccess,
42     VariableKind, FunctionDebugContextData};
43
44 use libc::c_uint;
45 use std::cell::{Cell, RefCell};
46 use std::ffi::CString;
47
48 use syntax_pos::{self, Span, Pos};
49 use syntax::ast;
50 use syntax::symbol::{Symbol, InternedString};
51 use rustc::ty::layout::{self, LayoutOf, HasTyCtxt};
52 use rustc_codegen_ssa::interfaces::*;
53
54 pub mod gdb;
55 mod utils;
56 mod namespace;
57 mod type_names;
58 pub mod metadata;
59 mod create_scope_map;
60 mod source_loc;
61
62 pub use self::create_scope_map::{create_mir_scopes};
63 pub use self::metadata::create_global_var_metadata;
64 pub use self::metadata::extend_scope_to_file;
65 pub use self::source_loc::set_source_location;
66
67 #[allow(non_upper_case_globals)]
68 const DW_TAG_auto_variable: c_uint = 0x100;
69 #[allow(non_upper_case_globals)]
70 const DW_TAG_arg_variable: c_uint = 0x101;
71
72 /// A context object for maintaining all state needed by the debuginfo module.
73 pub struct CrateDebugContext<'a, 'tcx> {
74     llcontext: &'a llvm::Context,
75     llmod: &'a llvm::Module,
76     builder: &'a mut DIBuilder<'a>,
77     created_files: RefCell<FxHashMap<(Symbol, Symbol), &'a DIFile>>,
78     created_enum_disr_types: RefCell<FxHashMap<(DefId, layout::Primitive), &'a DIType>>,
79
80     type_map: RefCell<TypeMap<'a, 'tcx>>,
81     namespace_map: RefCell<DefIdMap<&'a DIScope>>,
82
83     // This collection is used to assert that composite types (structs, enums,
84     // ...) have their members only set once:
85     composite_types_completed: RefCell<FxHashSet<&'a DIType>>,
86 }
87
88 impl Drop for CrateDebugContext<'a, 'tcx> {
89     fn drop(&mut self) {
90         unsafe {
91             llvm::LLVMRustDIBuilderDispose(&mut *(self.builder as *mut _));
92         }
93     }
94 }
95
96 impl<'a, 'tcx> CrateDebugContext<'a, 'tcx> {
97     pub fn new(llmod: &'a llvm::Module) -> Self {
98         debug!("CrateDebugContext::new");
99         let builder = unsafe { llvm::LLVMRustDIBuilderCreate(llmod) };
100         // DIBuilder inherits context from the module, so we'd better use the same one
101         let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
102         CrateDebugContext {
103             llcontext,
104             llmod,
105             builder,
106             created_files: Default::default(),
107             created_enum_disr_types: Default::default(),
108             type_map: Default::default(),
109             namespace_map: RefCell::new(DefIdMap()),
110             composite_types_completed: Default::default(),
111         }
112     }
113 }
114
115 /// Create any deferred debug metadata nodes
116 pub fn finalize(cx: &CodegenCx) {
117     if cx.dbg_cx.is_none() {
118         return;
119     }
120
121     debug!("finalize");
122
123     if gdb::needs_gdb_debug_scripts_section(cx) {
124         // Add a .debug_gdb_scripts section to this compile-unit. This will
125         // cause GDB to try and load the gdb_load_rust_pretty_printers.py file,
126         // which activates the Rust pretty printers for binary this section is
127         // contained in.
128         gdb::get_or_insert_gdb_debug_scripts_section_global(cx);
129     }
130
131     unsafe {
132         llvm::LLVMRustDIBuilderFinalize(DIB(cx));
133         // Debuginfo generation in LLVM by default uses a higher
134         // version of dwarf than macOS currently understands. We can
135         // instruct LLVM to emit an older version of dwarf, however,
136         // for macOS to understand. For more info see #11352
137         // This can be overridden using --llvm-opts -dwarf-version,N.
138         // Android has the same issue (#22398)
139         if cx.sess().target.target.options.is_like_osx ||
140            cx.sess().target.target.options.is_like_android {
141             llvm::LLVMRustAddModuleFlag(cx.llmod,
142                                         "Dwarf Version\0".as_ptr() as *const _,
143                                         2)
144         }
145
146         // Indicate that we want CodeView debug information on MSVC
147         if cx.sess().target.target.options.is_like_msvc {
148             llvm::LLVMRustAddModuleFlag(cx.llmod,
149                                         "CodeView\0".as_ptr() as *const _,
150                                         1)
151         }
152
153         // Prevent bitcode readers from deleting the debug info.
154         let ptr = "Debug Info Version\0".as_ptr();
155         llvm::LLVMRustAddModuleFlag(cx.llmod, ptr as *const _,
156                                     llvm::LLVMRustDebugMetadataVersion());
157     };
158 }
159
160 impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
161     fn declare_local(
162         &mut self,
163         dbg_context: &FunctionDebugContext<&'ll DISubprogram>,
164         variable_name: ast::Name,
165         variable_type: Ty<'tcx>,
166         scope_metadata: &'ll DIScope,
167         variable_access: VariableAccess<'_, &'ll Value>,
168         variable_kind: VariableKind,
169         span: Span,
170     ) {
171         assert!(!dbg_context.get_ref(span).source_locations_enabled.get());
172         let cx = self.cx();
173
174         let file = span_start(cx, span).file;
175         let file_metadata = file_metadata(cx,
176                                           &file.name,
177                                           dbg_context.get_ref(span).defining_crate);
178
179         let loc = span_start(cx, span);
180         let type_metadata = type_metadata(cx, variable_type, span);
181
182         let (argument_index, dwarf_tag) = match variable_kind {
183             ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),
184             LocalVariable => (0, DW_TAG_auto_variable)
185         };
186         let align = cx.align_of(variable_type);
187
188         let name = SmallCStr::new(&variable_name.as_str());
189         match (variable_access, &[][..]) {
190             (DirectVariable { alloca }, address_operations) |
191             (IndirectVariable {alloca, address_operations}, _) => {
192                 let metadata = unsafe {
193                     llvm::LLVMRustDIBuilderCreateVariable(
194                         DIB(cx),
195                         dwarf_tag,
196                         scope_metadata,
197                         name.as_ptr(),
198                         file_metadata,
199                         loc.line as c_uint,
200                         type_metadata,
201                         cx.sess().opts.optimize != config::OptLevel::No,
202                         DIFlags::FlagZero,
203                         argument_index,
204                         align.abi() as u32,
205                     )
206                 };
207                 source_loc::set_debug_location(self,
208                     InternalDebugLocation::new(scope_metadata, loc.line, loc.col.to_usize()));
209                 unsafe {
210                     let debug_loc = llvm::LLVMGetCurrentDebugLocation(self.llbuilder);
211                     let instr = llvm::LLVMRustDIBuilderInsertDeclareAtEnd(
212                         DIB(cx),
213                         alloca,
214                         metadata,
215                         address_operations.as_ptr(),
216                         address_operations.len() as c_uint,
217                         debug_loc,
218                         self.llbb());
219
220                     llvm::LLVMSetInstDebugLocation(self.llbuilder, instr);
221                 }
222                 source_loc::set_debug_location(self, UnknownLocation);
223             }
224         }
225     }
226
227     fn set_source_location(
228         &mut self,
229         debug_context: &FunctionDebugContext<&'ll DISubprogram>,
230         scope: Option<&'ll DIScope>,
231         span: Span,
232     ) {
233         set_source_location(debug_context, &self, scope, span)
234     }
235     fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) {
236         gdb::insert_reference_to_gdb_debug_scripts_section_global(self)
237     }
238 }
239
240 impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
241     fn create_function_debug_context(
242         &self,
243         instance: Instance<'tcx>,
244         sig: ty::FnSig<'tcx>,
245         llfn: &'ll Value,
246         mir: &mir::Mir,
247     ) -> FunctionDebugContext<&'ll DISubprogram> {
248         if self.sess().opts.debuginfo == DebugInfo::None {
249             return FunctionDebugContext::DebugInfoDisabled;
250         }
251
252         if let InstanceDef::Item(def_id) = instance.def {
253             if self.tcx().codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NO_DEBUG) {
254                 return FunctionDebugContext::FunctionWithoutDebugInfo;
255             }
256         }
257
258         let span = mir.span;
259
260         // This can be the case for functions inlined from another crate
261         if span.is_dummy() {
262             // FIXME(simulacrum): Probably can't happen; remove.
263             return FunctionDebugContext::FunctionWithoutDebugInfo;
264         }
265
266         let def_id = instance.def_id();
267         let containing_scope = get_containing_scope(self, instance);
268         let loc = span_start(self, span);
269         let file_metadata = file_metadata(self, &loc.file.name, def_id.krate);
270
271         let function_type_metadata = unsafe {
272             let fn_signature = get_function_signature(self, sig);
273             llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(self), file_metadata, fn_signature)
274         };
275
276         // Find the enclosing function, in case this is a closure.
277         let def_key = self.tcx().def_key(def_id);
278         let mut name = def_key.disambiguated_data.data.to_string();
279
280         let enclosing_fn_def_id = self.tcx().closure_base_def_id(def_id);
281
282         // Get_template_parameters() will append a `<...>` clause to the function
283         // name if necessary.
284         let generics = self.tcx().generics_of(enclosing_fn_def_id);
285         let substs = instance.substs.truncate_to(self.tcx(), generics);
286         let template_parameters = get_template_parameters(self,
287                                                           &generics,
288                                                           substs,
289                                                           file_metadata,
290                                                           &mut name);
291
292         // Get the linkage_name, which is just the symbol name
293         let linkage_name = mangled_name_of_instance(self, instance);
294
295         let scope_line = span_start(self, span).line;
296         let is_local_to_unit = is_node_local_to_unit(self, def_id);
297
298         let function_name = CString::new(name).unwrap();
299         let linkage_name = SmallCStr::new(&linkage_name.as_str());
300
301         let mut flags = DIFlags::FlagPrototyped;
302
303         let local_id = self.tcx().hir.as_local_node_id(def_id);
304         if let Some((id, _, _)) = *self.sess().entry_fn.borrow() {
305             if local_id == Some(id) {
306                 flags |= DIFlags::FlagMainSubprogram;
307             }
308         }
309
310         if self.layout_of(sig.output()).abi.is_uninhabited() {
311             flags |= DIFlags::FlagNoReturn;
312         }
313
314         let fn_metadata = unsafe {
315             llvm::LLVMRustDIBuilderCreateFunction(
316                 DIB(self),
317                 containing_scope,
318                 function_name.as_ptr(),
319                 linkage_name.as_ptr(),
320                 file_metadata,
321                 loc.line as c_uint,
322                 function_type_metadata,
323                 is_local_to_unit,
324                 true,
325                 scope_line as c_uint,
326                 flags,
327                 self.sess().opts.optimize != config::OptLevel::No,
328                 llfn,
329                 template_parameters,
330                 None)
331         };
332
333         // Initialize fn debug context (including scope map and namespace map)
334         let fn_debug_context = FunctionDebugContextData {
335             fn_metadata,
336             source_locations_enabled: Cell::new(false),
337             defining_crate: def_id.krate,
338         };
339
340         return FunctionDebugContext::RegularContext(fn_debug_context);
341
342         fn get_function_signature<'ll, 'tcx>(
343             cx: &CodegenCx<'ll, 'tcx>,
344             sig: ty::FnSig<'tcx>,
345         ) -> &'ll DIArray {
346             if cx.sess().opts.debuginfo == DebugInfo::Limited {
347                 return create_DIArray(DIB(cx), &[]);
348             }
349
350             let mut signature = Vec::with_capacity(sig.inputs().len() + 1);
351
352             // Return type -- llvm::DIBuilder wants this at index 0
353             signature.push(match sig.output().sty {
354                 ty::Tuple(ref tys) if tys.is_empty() => None,
355                 _ => Some(type_metadata(cx, sig.output(), syntax_pos::DUMMY_SP))
356             });
357
358             let inputs = if sig.abi == Abi::RustCall {
359                 &sig.inputs()[..sig.inputs().len() - 1]
360             } else {
361                 sig.inputs()
362             };
363
364             // Arguments types
365             if cx.sess().target.target.options.is_like_msvc {
366                 // FIXME(#42800):
367                 // There is a bug in MSDIA that leads to a crash when it encounters
368                 // a fixed-size array of `u8` or something zero-sized in a
369                 // function-type (see #40477).
370                 // As a workaround, we replace those fixed-size arrays with a
371                 // pointer-type. So a function `fn foo(a: u8, b: [u8; 4])` would
372                 // appear as `fn foo(a: u8, b: *const u8)` in debuginfo,
373                 // and a function `fn bar(x: [(); 7])` as `fn bar(x: *const ())`.
374                 // This transformed type is wrong, but these function types are
375                 // already inaccurate due to ABI adjustments (see #42800).
376                 signature.extend(inputs.iter().map(|&t| {
377                     let t = match t.sty {
378                         ty::Array(ct, _)
379                             if (ct == cx.tcx.types.u8) || cx.layout_of(ct).is_zst() => {
380                             cx.tcx.mk_imm_ptr(ct)
381                         }
382                         _ => t
383                     };
384                     Some(type_metadata(cx, t, syntax_pos::DUMMY_SP))
385                 }));
386             } else {
387                 signature.extend(inputs.iter().map(|t| {
388                     Some(type_metadata(cx, t, syntax_pos::DUMMY_SP))
389                 }));
390             }
391
392             if sig.abi == Abi::RustCall && !sig.inputs().is_empty() {
393                 if let ty::Tuple(args) = sig.inputs()[sig.inputs().len() - 1].sty {
394                     signature.extend(
395                         args.iter().map(|argument_type| {
396                             Some(type_metadata(cx, argument_type, syntax_pos::DUMMY_SP))
397                         })
398                     );
399                 }
400             }
401
402             create_DIArray(DIB(cx), &signature[..])
403         }
404
405         fn get_template_parameters<'ll, 'tcx>(
406             cx: &CodegenCx<'ll, 'tcx>,
407             generics: &ty::Generics,
408             substs: &Substs<'tcx>,
409             file_metadata: &'ll DIFile,
410             name_to_append_suffix_to: &mut String,
411         ) -> &'ll DIArray {
412             if substs.types().next().is_none() {
413                 return create_DIArray(DIB(cx), &[]);
414             }
415
416             name_to_append_suffix_to.push('<');
417             for (i, actual_type) in substs.types().enumerate() {
418                 if i != 0 {
419                     name_to_append_suffix_to.push_str(",");
420                 }
421
422                 let actual_type =
423                     cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), actual_type);
424                 // Add actual type name to <...> clause of function name
425                 let actual_type_name = compute_debuginfo_type_name(cx,
426                                                                    actual_type,
427                                                                    true);
428                 name_to_append_suffix_to.push_str(&actual_type_name[..]);
429             }
430             name_to_append_suffix_to.push('>');
431
432             // Again, only create type information if full debuginfo is enabled
433             let template_params: Vec<_> = if cx.sess().opts.debuginfo == DebugInfo::Full {
434                 let names = get_parameter_names(cx, generics);
435                 substs.iter().zip(names).filter_map(|(kind, name)| {
436                     if let UnpackedKind::Type(ty) = kind.unpack() {
437                         let actual_type =
438                             cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
439                         let actual_type_metadata =
440                             type_metadata(cx, actual_type, syntax_pos::DUMMY_SP);
441                         let name = SmallCStr::new(&name.as_str());
442                         Some(unsafe {
443                             Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
444                                 DIB(cx),
445                                 None,
446                                 name.as_ptr(),
447                                 actual_type_metadata,
448                                 file_metadata,
449                                 0,
450                                 0,
451                             ))
452                         })
453                     } else {
454                         None
455                     }
456                 }).collect()
457             } else {
458                 vec![]
459             };
460
461             return create_DIArray(DIB(cx), &template_params[..]);
462         }
463
464         fn get_parameter_names(cx: &CodegenCx,
465                                generics: &ty::Generics)
466                                -> Vec<InternedString> {
467             let mut names = generics.parent.map_or(vec![], |def_id| {
468                 get_parameter_names(cx, cx.tcx.generics_of(def_id))
469             });
470             names.extend(generics.params.iter().map(|param| param.name));
471             names
472         }
473
474         fn get_containing_scope<'ll, 'tcx>(
475             cx: &CodegenCx<'ll, 'tcx>,
476             instance: Instance<'tcx>,
477         ) -> &'ll DIScope {
478             // First, let's see if this is a method within an inherent impl. Because
479             // if yes, we want to make the result subroutine DIE a child of the
480             // subroutine's self-type.
481             let self_type = cx.tcx.impl_of_method(instance.def_id()).and_then(|impl_def_id| {
482                 // If the method does *not* belong to a trait, proceed
483                 if cx.tcx.trait_id_of_impl(impl_def_id).is_none() {
484                     let impl_self_ty = cx.tcx.subst_and_normalize_erasing_regions(
485                         instance.substs,
486                         ty::ParamEnv::reveal_all(),
487                         &cx.tcx.type_of(impl_def_id),
488                     );
489
490                     // Only "class" methods are generally understood by LLVM,
491                     // so avoid methods on other types (e.g. `<*mut T>::null`).
492                     match impl_self_ty.sty {
493                         ty::Adt(def, ..) if !def.is_box() => {
494                             Some(type_metadata(cx, impl_self_ty, syntax_pos::DUMMY_SP))
495                         }
496                         _ => None
497                     }
498                 } else {
499                     // For trait method impls we still use the "parallel namespace"
500                     // strategy
501                     None
502                 }
503             });
504
505             self_type.unwrap_or_else(|| {
506                 namespace::item_namespace(cx, DefId {
507                     krate: instance.def_id().krate,
508                     index: cx.tcx
509                              .def_key(instance.def_id())
510                              .parent
511                              .expect("get_containing_scope: missing parent?")
512                 })
513             })
514         }
515     }
516
517     fn create_vtable_metadata(
518         &self,
519         ty: Ty<'tcx>,
520         vtable: Self::Value,
521     ) {
522         metadata::create_vtable_metadata(self, ty, vtable)
523     }
524
525     fn create_mir_scopes(
526         &self,
527         mir: &mir::Mir,
528         debug_context: &FunctionDebugContext<&'ll DISubprogram>,
529     ) -> IndexVec<mir::SourceScope, MirDebugScope<&'ll DIScope>> {
530         create_scope_map::create_mir_scopes(self, mir, debug_context)
531     }
532
533     fn extend_scope_to_file(
534          &self,
535          scope_metadata: &'ll DIScope,
536          file: &syntax_pos::SourceFile,
537          defining_crate: CrateNum,
538      ) -> &'ll DILexicalBlock {
539          metadata::extend_scope_to_file(&self, scope_metadata, file, defining_crate)
540      }
541
542     fn debuginfo_finalize(&self) {
543         finalize(self)
544     }
545
546     fn debuginfo_upvar_decls_ops_sequence(&self, byte_offset_of_var_in_env: u64) -> [i64; 4] {
547         unsafe {
548             [llvm::LLVMRustDIBuilderCreateOpDeref(),
549              llvm::LLVMRustDIBuilderCreateOpPlusUconst(),
550              byte_offset_of_var_in_env as i64,
551              llvm::LLVMRustDIBuilderCreateOpDeref()]
552         }
553     }
554 }