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