]> git.lizzy.rs Git - rust.git/blob - src/librustc_codegen_llvm/debuginfo/mod.rs
rustc_codegen_llvm: remove InternalDebugLocation and simplify dbg_var_addr.
[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 pub use self::source_loc::set_source_location;
55
56 #[allow(non_upper_case_globals)]
57 const DW_TAG_auto_variable: c_uint = 0x100;
58 #[allow(non_upper_case_globals)]
59 const DW_TAG_arg_variable: c_uint = 0x101;
60
61 /// A context object for maintaining all state needed by the debuginfo module.
62 pub struct CrateDebugContext<'a, 'tcx> {
63     llcontext: &'a llvm::Context,
64     llmod: &'a llvm::Module,
65     builder: &'a mut DIBuilder<'a>,
66     created_files: RefCell<FxHashMap<(Option<String>, Option<String>), &'a DIFile>>,
67     created_enum_disr_types: RefCell<FxHashMap<(DefId, layout::Primitive), &'a DIType>>,
68
69     type_map: RefCell<TypeMap<'a, 'tcx>>,
70     namespace_map: RefCell<DefIdMap<&'a DIScope>>,
71
72     // This collection is used to assert that composite types (structs, enums,
73     // ...) have their members only set once:
74     composite_types_completed: RefCell<FxHashSet<&'a DIType>>,
75 }
76
77 impl Drop for CrateDebugContext<'a, 'tcx> {
78     fn drop(&mut self) {
79         unsafe {
80             llvm::LLVMRustDIBuilderDispose(&mut *(self.builder as *mut _));
81         }
82     }
83 }
84
85 impl<'a, 'tcx> CrateDebugContext<'a, 'tcx> {
86     pub fn new(llmod: &'a llvm::Module) -> Self {
87         debug!("CrateDebugContext::new");
88         let builder = unsafe { llvm::LLVMRustDIBuilderCreate(llmod) };
89         // DIBuilder inherits context from the module, so we'd better use the same one
90         let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
91         CrateDebugContext {
92             llcontext,
93             llmod,
94             builder,
95             created_files: Default::default(),
96             created_enum_disr_types: Default::default(),
97             type_map: Default::default(),
98             namespace_map: RefCell::new(Default::default()),
99             composite_types_completed: Default::default(),
100         }
101     }
102 }
103
104 /// Creates any deferred debug metadata nodes
105 pub fn finalize(cx: &CodegenCx<'_, '_>) {
106     if cx.dbg_cx.is_none() {
107         return;
108     }
109
110     debug!("finalize");
111
112     if gdb::needs_gdb_debug_scripts_section(cx) {
113         // Add a .debug_gdb_scripts section to this compile-unit. This will
114         // cause GDB to try and load the gdb_load_rust_pretty_printers.py file,
115         // which activates the Rust pretty printers for binary this section is
116         // contained in.
117         gdb::get_or_insert_gdb_debug_scripts_section_global(cx);
118     }
119
120     unsafe {
121         llvm::LLVMRustDIBuilderFinalize(DIB(cx));
122         // Debuginfo generation in LLVM by default uses a higher
123         // version of dwarf than macOS currently understands. We can
124         // instruct LLVM to emit an older version of dwarf, however,
125         // for macOS to understand. For more info see #11352
126         // This can be overridden using --llvm-opts -dwarf-version,N.
127         // Android has the same issue (#22398)
128         if cx.sess().target.target.options.is_like_osx
129             || cx.sess().target.target.options.is_like_android
130         {
131             llvm::LLVMRustAddModuleFlag(cx.llmod, "Dwarf Version\0".as_ptr().cast(), 2)
132         }
133
134         // Indicate that we want CodeView debug information on MSVC
135         if cx.sess().target.target.options.is_like_msvc {
136             llvm::LLVMRustAddModuleFlag(cx.llmod, "CodeView\0".as_ptr().cast(), 1)
137         }
138
139         // Prevent bitcode readers from deleting the debug info.
140         let ptr = "Debug Info Version\0".as_ptr();
141         llvm::LLVMRustAddModuleFlag(cx.llmod, ptr.cast(), llvm::LLVMRustDebugMetadataVersion());
142     };
143 }
144
145 impl DebugInfoBuilderMethods for Builder<'a, 'll, 'tcx> {
146     // FIXME(eddyb) find a common convention for all of the debuginfo-related
147     // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
148     fn dbg_var_addr(
149         &mut self,
150         dbg_var: &'ll DIVariable,
151         scope_metadata: &'ll DIScope,
152         variable_alloca: Self::Value,
153         direct_offset: Size,
154         indirect_offsets: &[Size],
155         span: Span,
156     ) {
157         let cx = self.cx();
158
159         // Convert the direct and indirect offsets to address ops.
160         // FIXME(eddyb) use `const`s instead of getting the values via FFI,
161         // the values should match the ones in the DWARF standard anyway.
162         let op_deref = || unsafe { llvm::LLVMRustDIBuilderCreateOpDeref() };
163         let op_plus_uconst = || unsafe { llvm::LLVMRustDIBuilderCreateOpPlusUconst() };
164         let mut addr_ops = SmallVec::<[_; 8]>::new();
165
166         if direct_offset.bytes() > 0 {
167             addr_ops.push(op_plus_uconst());
168             addr_ops.push(direct_offset.bytes() as i64);
169         }
170         for &offset in indirect_offsets {
171             addr_ops.push(op_deref());
172             if offset.bytes() > 0 {
173                 addr_ops.push(op_plus_uconst());
174                 addr_ops.push(offset.bytes() as i64);
175             }
176         }
177
178         // FIXME(eddyb) maybe this information could be extracted from `dbg_var`,
179         // to avoid having to pass it down in both places?
180         // NB: `var` doesn't seem to know about the column, so that's a limitation.
181         let dbg_loc = cx.create_debug_loc(scope_metadata, span);
182         unsafe {
183             // FIXME(eddyb) replace `llvm.dbg.declare` with `llvm.dbg.addr`.
184             llvm::LLVMRustDIBuilderInsertDeclareAtEnd(
185                 DIB(cx),
186                 variable_alloca,
187                 dbg_var,
188                 addr_ops.as_ptr(),
189                 addr_ops.len() as c_uint,
190                 dbg_loc,
191                 self.llbb(),
192             );
193         }
194     }
195
196     fn set_source_location(
197         &mut self,
198         debug_context: &mut FunctionDebugContext<&'ll DIScope>,
199         scope: &'ll DIScope,
200         span: Span,
201     ) {
202         set_source_location(debug_context, &self, scope, span)
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             source_locations_enabled: false,
337             defining_crate: def_id.krate,
338         };
339
340         // Fill in all the scopes, with the information from the MIR body.
341         compute_mir_scopes(self, mir, fn_metadata, &mut fn_debug_context);
342
343         return Some(fn_debug_context);
344
345         fn get_function_signature<'ll, 'tcx>(
346             cx: &CodegenCx<'ll, 'tcx>,
347             fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
348         ) -> &'ll DIArray {
349             if cx.sess().opts.debuginfo == DebugInfo::Limited {
350                 return create_DIArray(DIB(cx), &[]);
351             }
352
353             let mut signature = Vec::with_capacity(fn_abi.args.len() + 1);
354
355             // Return type -- llvm::DIBuilder wants this at index 0
356             signature.push(if fn_abi.ret.is_ignore() {
357                 None
358             } else {
359                 Some(type_metadata(cx, fn_abi.ret.layout.ty, rustc_span::DUMMY_SP))
360             });
361
362             // Arguments types
363             if cx.sess().target.target.options.is_like_msvc {
364                 // FIXME(#42800):
365                 // There is a bug in MSDIA that leads to a crash when it encounters
366                 // a fixed-size array of `u8` or something zero-sized in a
367                 // function-type (see #40477).
368                 // As a workaround, we replace those fixed-size arrays with a
369                 // pointer-type. So a function `fn foo(a: u8, b: [u8; 4])` would
370                 // appear as `fn foo(a: u8, b: *const u8)` in debuginfo,
371                 // and a function `fn bar(x: [(); 7])` as `fn bar(x: *const ())`.
372                 // This transformed type is wrong, but these function types are
373                 // already inaccurate due to ABI adjustments (see #42800).
374                 signature.extend(fn_abi.args.iter().map(|arg| {
375                     let t = arg.layout.ty;
376                     let t = match t.kind {
377                         ty::Array(ct, _)
378                             if (ct == cx.tcx.types.u8) || cx.layout_of(ct).is_zst() =>
379                         {
380                             cx.tcx.mk_imm_ptr(ct)
381                         }
382                         _ => t,
383                     };
384                     Some(type_metadata(cx, t, rustc_span::DUMMY_SP))
385                 }));
386             } else {
387                 signature.extend(
388                     fn_abi
389                         .args
390                         .iter()
391                         .map(|arg| Some(type_metadata(cx, arg.layout.ty, rustc_span::DUMMY_SP))),
392                 );
393             }
394
395             create_DIArray(DIB(cx), &signature[..])
396         }
397
398         fn get_template_parameters<'ll, 'tcx>(
399             cx: &CodegenCx<'ll, 'tcx>,
400             generics: &ty::Generics,
401             substs: SubstsRef<'tcx>,
402             file_metadata: &'ll DIFile,
403             name_to_append_suffix_to: &mut String,
404         ) -> &'ll DIArray {
405             if substs.types().next().is_none() {
406                 return create_DIArray(DIB(cx), &[]);
407             }
408
409             name_to_append_suffix_to.push('<');
410             for (i, actual_type) in substs.types().enumerate() {
411                 if i != 0 {
412                     name_to_append_suffix_to.push_str(",");
413                 }
414
415                 let actual_type =
416                     cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), actual_type);
417                 // Add actual type name to <...> clause of function name
418                 let actual_type_name = compute_debuginfo_type_name(cx.tcx(), actual_type, true);
419                 name_to_append_suffix_to.push_str(&actual_type_name[..]);
420             }
421             name_to_append_suffix_to.push('>');
422
423             // Again, only create type information if full debuginfo is enabled
424             let template_params: Vec<_> = if cx.sess().opts.debuginfo == DebugInfo::Full {
425                 let names = get_parameter_names(cx, generics);
426                 substs
427                     .iter()
428                     .zip(names)
429                     .filter_map(|(kind, name)| {
430                         if let GenericArgKind::Type(ty) = kind.unpack() {
431                             let actual_type =
432                                 cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
433                             let actual_type_metadata =
434                                 type_metadata(cx, actual_type, rustc_span::DUMMY_SP);
435                             let name = SmallCStr::new(&name.as_str());
436                             Some(unsafe {
437                                 Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
438                                     DIB(cx),
439                                     None,
440                                     name.as_ptr(),
441                                     actual_type_metadata,
442                                     file_metadata,
443                                     0,
444                                     0,
445                                 ))
446                             })
447                         } else {
448                             None
449                         }
450                     })
451                     .collect()
452             } else {
453                 vec![]
454             };
455
456             return create_DIArray(DIB(cx), &template_params[..]);
457         }
458
459         fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec<Symbol> {
460             let mut names = generics
461                 .parent
462                 .map_or(vec![], |def_id| get_parameter_names(cx, cx.tcx.generics_of(def_id)));
463             names.extend(generics.params.iter().map(|param| param.name));
464             names
465         }
466
467         fn get_containing_scope<'ll, 'tcx>(
468             cx: &CodegenCx<'ll, 'tcx>,
469             instance: Instance<'tcx>,
470         ) -> &'ll DIScope {
471             // First, let's see if this is a method within an inherent impl. Because
472             // if yes, we want to make the result subroutine DIE a child of the
473             // subroutine's self-type.
474             let self_type = cx.tcx.impl_of_method(instance.def_id()).and_then(|impl_def_id| {
475                 // If the method does *not* belong to a trait, proceed
476                 if cx.tcx.trait_id_of_impl(impl_def_id).is_none() {
477                     let impl_self_ty = cx.tcx.subst_and_normalize_erasing_regions(
478                         instance.substs,
479                         ty::ParamEnv::reveal_all(),
480                         &cx.tcx.type_of(impl_def_id),
481                     );
482
483                     // Only "class" methods are generally understood by LLVM,
484                     // so avoid methods on other types (e.g., `<*mut T>::null`).
485                     match impl_self_ty.kind {
486                         ty::Adt(def, ..) if !def.is_box() => {
487                             Some(type_metadata(cx, impl_self_ty, rustc_span::DUMMY_SP))
488                         }
489                         _ => None,
490                     }
491                 } else {
492                     // For trait method impls we still use the "parallel namespace"
493                     // strategy
494                     None
495                 }
496             });
497
498             self_type.unwrap_or_else(|| {
499                 namespace::item_namespace(
500                     cx,
501                     DefId {
502                         krate: instance.def_id().krate,
503                         index: cx
504                             .tcx
505                             .def_key(instance.def_id())
506                             .parent
507                             .expect("get_containing_scope: missing parent?"),
508                     },
509                 )
510             })
511         }
512     }
513
514     fn create_vtable_metadata(&self, ty: Ty<'tcx>, vtable: Self::Value) {
515         metadata::create_vtable_metadata(self, ty, vtable)
516     }
517
518     fn extend_scope_to_file(
519         &self,
520         scope_metadata: &'ll DIScope,
521         file: &rustc_span::SourceFile,
522         defining_crate: CrateNum,
523     ) -> &'ll DILexicalBlock {
524         metadata::extend_scope_to_file(&self, scope_metadata, file, defining_crate)
525     }
526
527     fn debuginfo_finalize(&self) {
528         finalize(self)
529     }
530
531     // FIXME(eddyb) find a common convention for all of the debuginfo-related
532     // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
533     fn create_dbg_var(
534         &self,
535         dbg_context: &FunctionDebugContext<&'ll DIScope>,
536         variable_name: ast::Name,
537         variable_type: Ty<'tcx>,
538         scope_metadata: &'ll DIScope,
539         variable_kind: VariableKind,
540         span: Span,
541     ) -> &'ll DIVariable {
542         let loc = span_start(self, span);
543         let file_metadata = file_metadata(self, &loc.file.name, dbg_context.defining_crate);
544
545         let type_metadata = type_metadata(self, variable_type, span);
546
547         let (argument_index, dwarf_tag) = match variable_kind {
548             ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),
549             LocalVariable => (0, DW_TAG_auto_variable),
550         };
551         let align = self.align_of(variable_type);
552
553         let name = SmallCStr::new(&variable_name.as_str());
554         unsafe {
555             llvm::LLVMRustDIBuilderCreateVariable(
556                 DIB(self),
557                 dwarf_tag,
558                 scope_metadata,
559                 name.as_ptr(),
560                 file_metadata,
561                 loc.line as c_uint,
562                 type_metadata,
563                 self.sess().opts.optimize != config::OptLevel::No,
564                 DIFlags::FlagZero,
565                 argument_index,
566                 align.bytes() as u32,
567             )
568         }
569     }
570 }