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