]>
Commit | Line | Data |
---|---|---|
cdc7bbd5 | 1 | #![doc = include_str!("doc.md")] |
d9579d0f | 2 | |
e74abb32 | 3 | use rustc_codegen_ssa::mir::debuginfo::VariableKind::*; |
d9579d0f | 4 | |
29967ef6 XL |
5 | use self::metadata::{file_metadata, type_metadata, TypeMap}; |
6 | use self::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER}; | |
ff7c6d11 | 7 | use self::namespace::mangled_name_of_instance; |
ba9703b0 | 8 | use self::utils::{create_DIArray, is_node_local_to_unit, DIB}; |
d9579d0f | 9 | |
ba9703b0 XL |
10 | use crate::abi::FnAbi; |
11 | use crate::builder::Builder; | |
12 | use crate::common::CodegenCx; | |
9fa01778 | 13 | use crate::llvm; |
dfeec247 | 14 | use crate::llvm::debuginfo::{ |
29967ef6 XL |
15 | DIArray, DIBuilder, DIFile, DIFlags, DILexicalBlock, DILocation, DISPFlags, DIScope, DIType, |
16 | DIVariable, | |
dfeec247 | 17 | }; |
9fa01778 | 18 | use crate::value::Value; |
ba9703b0 | 19 | |
dfeec247 XL |
20 | use rustc_codegen_ssa::debuginfo::type_names; |
21 | use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind}; | |
ba9703b0 | 22 | use rustc_codegen_ssa::traits::*; |
dfeec247 | 23 | use rustc_data_structures::fx::{FxHashMap, FxHashSet}; |
29967ef6 | 24 | use rustc_data_structures::sync::Lrc; |
17df50a5 | 25 | use rustc_hir::def_id::{DefId, DefIdMap}; |
e74abb32 | 26 | use rustc_index::vec::IndexVec; |
ba9703b0 | 27 | use rustc_middle::mir; |
5099ac24 | 28 | use rustc_middle::ty::layout::LayoutOf; |
ba9703b0 | 29 | use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; |
3dfed10e | 30 | use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeFoldable}; |
ba9703b0 | 31 | use rustc_session::config::{self, DebugInfo}; |
c295e0f8 | 32 | use rustc_session::Session; |
ba9703b0 | 33 | use rustc_span::symbol::Symbol; |
29967ef6 | 34 | use rustc_span::{self, BytePos, Pos, SourceFile, SourceFileAndLine, Span}; |
c295e0f8 | 35 | use rustc_target::abi::{Primitive, Size}; |
d9579d0f AL |
36 | |
37 | use libc::c_uint; | |
e74abb32 | 38 | use smallvec::SmallVec; |
ba9703b0 | 39 | use std::cell::RefCell; |
cdc7bbd5 | 40 | use std::iter; |
3dfed10e | 41 | use tracing::debug; |
d9579d0f | 42 | |
dfeec247 | 43 | mod create_scope_map; |
d9579d0f | 44 | pub mod gdb; |
5bcae85e | 45 | pub mod metadata; |
dfeec247 | 46 | mod namespace; |
dfeec247 | 47 | mod utils; |
d9579d0f | 48 | |
e74abb32 | 49 | pub use self::create_scope_map::compute_mir_scopes; |
d9579d0f | 50 | pub use self::metadata::create_global_var_metadata; |
9e0c209e | 51 | pub use self::metadata::extend_scope_to_file; |
d9579d0f AL |
52 | |
53 | #[allow(non_upper_case_globals)] | |
54 | const DW_TAG_auto_variable: c_uint = 0x100; | |
55 | #[allow(non_upper_case_globals)] | |
56 | const DW_TAG_arg_variable: c_uint = 0x101; | |
57 | ||
58 | /// A context object for maintaining all state needed by the debuginfo module. | |
b7449926 XL |
59 | pub struct CrateDebugContext<'a, 'tcx> { |
60 | llcontext: &'a llvm::Context, | |
61 | llmod: &'a llvm::Module, | |
62 | builder: &'a mut DIBuilder<'a>, | |
dc9dc135 | 63 | created_files: RefCell<FxHashMap<(Option<String>, Option<String>), &'a DIFile>>, |
ba9703b0 | 64 | created_enum_disr_types: RefCell<FxHashMap<(DefId, Primitive), &'a DIType>>, |
d9579d0f | 65 | |
b7449926 XL |
66 | type_map: RefCell<TypeMap<'a, 'tcx>>, |
67 | namespace_map: RefCell<DefIdMap<&'a DIScope>>, | |
d9579d0f AL |
68 | |
69 | // This collection is used to assert that composite types (structs, enums, | |
70 | // ...) have their members only set once: | |
b7449926 | 71 | composite_types_completed: RefCell<FxHashSet<&'a DIType>>, |
d9579d0f AL |
72 | } |
73 | ||
a2a8927a | 74 | impl Drop for CrateDebugContext<'_, '_> { |
b7449926 XL |
75 | fn drop(&mut self) { |
76 | unsafe { | |
77 | llvm::LLVMRustDIBuilderDispose(&mut *(self.builder as *mut _)); | |
78 | } | |
79 | } | |
80 | } | |
81 | ||
82 | impl<'a, 'tcx> CrateDebugContext<'a, 'tcx> { | |
83 | pub fn new(llmod: &'a llvm::Module) -> Self { | |
d9579d0f | 84 | debug!("CrateDebugContext::new"); |
5bcae85e | 85 | let builder = unsafe { llvm::LLVMRustDIBuilderCreate(llmod) }; |
d9579d0f AL |
86 | // DIBuilder inherits context from the module, so we'd better use the same one |
87 | let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) }; | |
32a655c1 | 88 | CrateDebugContext { |
3b2f2976 XL |
89 | llcontext, |
90 | llmod, | |
91 | builder, | |
0bf4aa26 XL |
92 | created_files: Default::default(), |
93 | created_enum_disr_types: Default::default(), | |
94 | type_map: Default::default(), | |
a1dfa0c6 | 95 | namespace_map: RefCell::new(Default::default()), |
0bf4aa26 | 96 | composite_types_completed: Default::default(), |
32a655c1 | 97 | } |
d9579d0f | 98 | } |
d9579d0f | 99 | |
c295e0f8 XL |
100 | pub fn finalize(&self, sess: &Session) { |
101 | unsafe { | |
102 | llvm::LLVMRustDIBuilderFinalize(self.builder); | |
103 | ||
104 | // Debuginfo generation in LLVM by default uses a higher | |
105 | // version of dwarf than macOS currently understands. We can | |
106 | // instruct LLVM to emit an older version of dwarf, however, | |
107 | // for macOS to understand. For more info see #11352 | |
108 | // This can be overridden using --llvm-opts -dwarf-version,N. | |
109 | // Android has the same issue (#22398) | |
110 | if let Some(version) = sess.target.dwarf_version { | |
5099ac24 FG |
111 | llvm::LLVMRustAddModuleFlag( |
112 | self.llmod, | |
113 | llvm::LLVMModFlagBehavior::Warning, | |
114 | "Dwarf Version\0".as_ptr().cast(), | |
115 | version, | |
116 | ) | |
c295e0f8 | 117 | } |
d9579d0f | 118 | |
c295e0f8 XL |
119 | // Indicate that we want CodeView debug information on MSVC |
120 | if sess.target.is_like_msvc { | |
5099ac24 FG |
121 | llvm::LLVMRustAddModuleFlag( |
122 | self.llmod, | |
123 | llvm::LLVMModFlagBehavior::Warning, | |
124 | "CodeView\0".as_ptr().cast(), | |
125 | 1, | |
126 | ) | |
c295e0f8 | 127 | } |
d9579d0f | 128 | |
c295e0f8 XL |
129 | // Prevent bitcode readers from deleting the debug info. |
130 | let ptr = "Debug Info Version\0".as_ptr(); | |
131 | llvm::LLVMRustAddModuleFlag( | |
132 | self.llmod, | |
5099ac24 | 133 | llvm::LLVMModFlagBehavior::Warning, |
c295e0f8 XL |
134 | ptr.cast(), |
135 | llvm::LLVMRustDebugMetadataVersion(), | |
136 | ); | |
d9579d0f | 137 | } |
c295e0f8 XL |
138 | } |
139 | } | |
d9579d0f | 140 | |
c295e0f8 XL |
141 | /// Creates any deferred debug metadata nodes |
142 | pub fn finalize(cx: &CodegenCx<'_, '_>) { | |
143 | if let Some(dbg_cx) = &cx.dbg_cx { | |
144 | debug!("finalize"); | |
145 | ||
146 | if gdb::needs_gdb_debug_scripts_section(cx) { | |
147 | // Add a .debug_gdb_scripts section to this compile-unit. This will | |
148 | // cause GDB to try and load the gdb_load_rust_pretty_printers.py file, | |
149 | // which activates the Rust pretty printers for binary this section is | |
150 | // contained in. | |
151 | gdb::get_or_insert_gdb_debug_scripts_section_global(cx); | |
7453a54e SL |
152 | } |
153 | ||
c295e0f8 XL |
154 | dbg_cx.finalize(cx.sess()); |
155 | } | |
d9579d0f AL |
156 | } |
157 | ||
a2a8927a | 158 | impl<'ll> DebugInfoBuilderMethods for Builder<'_, 'll, '_> { |
74b04a01 XL |
159 | // FIXME(eddyb) find a common convention for all of the debuginfo-related |
160 | // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.). | |
161 | fn dbg_var_addr( | |
a1dfa0c6 | 162 | &mut self, |
74b04a01 | 163 | dbg_var: &'ll DIVariable, |
29967ef6 | 164 | dbg_loc: &'ll DILocation, |
e74abb32 XL |
165 | variable_alloca: Self::Value, |
166 | direct_offset: Size, | |
167 | indirect_offsets: &[Size], | |
a1dfa0c6 | 168 | ) { |
e74abb32 | 169 | // Convert the direct and indirect offsets to address ops. |
74b04a01 XL |
170 | // FIXME(eddyb) use `const`s instead of getting the values via FFI, |
171 | // the values should match the ones in the DWARF standard anyway. | |
e74abb32 XL |
172 | let op_deref = || unsafe { llvm::LLVMRustDIBuilderCreateOpDeref() }; |
173 | let op_plus_uconst = || unsafe { llvm::LLVMRustDIBuilderCreateOpPlusUconst() }; | |
a2a8927a | 174 | let mut addr_ops = SmallVec::<[u64; 8]>::new(); |
e74abb32 XL |
175 | |
176 | if direct_offset.bytes() > 0 { | |
177 | addr_ops.push(op_plus_uconst()); | |
a2a8927a | 178 | addr_ops.push(direct_offset.bytes() as u64); |
e74abb32 XL |
179 | } |
180 | for &offset in indirect_offsets { | |
181 | addr_ops.push(op_deref()); | |
182 | if offset.bytes() > 0 { | |
183 | addr_ops.push(op_plus_uconst()); | |
a2a8927a | 184 | addr_ops.push(offset.bytes() as u64); |
a1dfa0c6 XL |
185 | } |
186 | } | |
e74abb32 | 187 | |
e74abb32 | 188 | unsafe { |
74b04a01 XL |
189 | // FIXME(eddyb) replace `llvm.dbg.declare` with `llvm.dbg.addr`. |
190 | llvm::LLVMRustDIBuilderInsertDeclareAtEnd( | |
29967ef6 | 191 | DIB(self.cx()), |
e74abb32 | 192 | variable_alloca, |
74b04a01 | 193 | dbg_var, |
e74abb32 XL |
194 | addr_ops.as_ptr(), |
195 | addr_ops.len() as c_uint, | |
74b04a01 | 196 | dbg_loc, |
dfeec247 XL |
197 | self.llbb(), |
198 | ); | |
e74abb32 | 199 | } |
a1dfa0c6 XL |
200 | } |
201 | ||
29967ef6 | 202 | fn set_dbg_loc(&mut self, dbg_loc: &'ll DILocation) { |
74b04a01 | 203 | unsafe { |
29967ef6 XL |
204 | let dbg_loc_as_llval = llvm::LLVMRustMetadataAsValue(self.cx().llcx, dbg_loc); |
205 | llvm::LLVMSetCurrentDebugLocation(self.llbuilder, dbg_loc_as_llval); | |
74b04a01 | 206 | } |
d9579d0f | 207 | } |
29967ef6 | 208 | |
a1dfa0c6 XL |
209 | fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) { |
210 | gdb::insert_reference_to_gdb_debug_scripts_section_global(self) | |
211 | } | |
532ac7d7 | 212 | |
e74abb32 | 213 | fn set_var_name(&mut self, value: &'ll Value, name: &str) { |
e1599b0c XL |
214 | // Avoid wasting time if LLVM value names aren't even enabled. |
215 | if self.sess().fewer_names() { | |
216 | return; | |
217 | } | |
218 | ||
219 | // Only function parameters and instructions are local to a function, | |
220 | // don't change the name of anything else (e.g. globals). | |
221 | let param_or_inst = unsafe { | |
dfeec247 | 222 | llvm::LLVMIsAArgument(value).is_some() || llvm::LLVMIsAInstruction(value).is_some() |
e1599b0c XL |
223 | }; |
224 | if !param_or_inst { | |
225 | return; | |
226 | } | |
227 | ||
60c5eb7d XL |
228 | // Avoid replacing the name if it already exists. |
229 | // While we could combine the names somehow, it'd | |
230 | // get noisy quick, and the usefulness is dubious. | |
231 | if llvm::get_value_name(value).is_empty() { | |
232 | llvm::set_value_name(value, name.as_bytes()); | |
532ac7d7 XL |
233 | } |
234 | } | |
a1dfa0c6 | 235 | } |
d9579d0f | 236 | |
29967ef6 XL |
237 | /// A source code location used to generate debug information. |
238 | // FIXME(eddyb) rename this to better indicate it's a duplicate of | |
239 | // `rustc_span::Loc` rather than `DILocation`, perhaps by making | |
240 | // `lookup_char_pos` return the right information instead. | |
241 | pub struct DebugLoc { | |
242 | /// Information about the original source file. | |
243 | pub file: Lrc<SourceFile>, | |
244 | /// The (1-based) line number. | |
6a06907d | 245 | pub line: u32, |
29967ef6 | 246 | /// The (1-based) column number. |
6a06907d | 247 | pub col: u32, |
29967ef6 XL |
248 | } |
249 | ||
a2a8927a | 250 | impl CodegenCx<'_, '_> { |
29967ef6 XL |
251 | /// Looks up debug source information about a `BytePos`. |
252 | // FIXME(eddyb) rename this to better indicate it's a duplicate of | |
253 | // `lookup_char_pos` rather than `dbg_loc`, perhaps by making | |
254 | // `lookup_char_pos` return the right information instead. | |
255 | pub fn lookup_debug_loc(&self, pos: BytePos) -> DebugLoc { | |
256 | let (file, line, col) = match self.sess().source_map().lookup_line(pos) { | |
257 | Ok(SourceFileAndLine { sf: file, line }) => { | |
258 | let line_pos = file.line_begin_pos(pos); | |
259 | ||
260 | // Use 1-based indexing. | |
261 | let line = (line + 1) as u32; | |
262 | let col = (pos - line_pos).to_u32() + 1; | |
263 | ||
6a06907d | 264 | (file, line, col) |
29967ef6 | 265 | } |
6a06907d | 266 | Err(file) => (file, UNKNOWN_LINE_NUMBER, UNKNOWN_COLUMN_NUMBER), |
29967ef6 XL |
267 | }; |
268 | ||
269 | // For MSVC, omit the column number. | |
270 | // Otherwise, emit it. This mimics clang behaviour. | |
271 | // See discussion in https://github.com/rust-lang/rust/issues/42921 | |
272 | if self.sess().target.is_like_msvc { | |
6a06907d | 273 | DebugLoc { file, line, col: UNKNOWN_COLUMN_NUMBER } |
29967ef6 XL |
274 | } else { |
275 | DebugLoc { file, line, col } | |
276 | } | |
277 | } | |
278 | } | |
279 | ||
a2a8927a | 280 | impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { |
a1dfa0c6 XL |
281 | fn create_function_debug_context( |
282 | &self, | |
283 | instance: Instance<'tcx>, | |
60c5eb7d | 284 | fn_abi: &FnAbi<'tcx, Ty<'tcx>>, |
a1dfa0c6 | 285 | llfn: &'ll Value, |
29967ef6 XL |
286 | mir: &mir::Body<'tcx>, |
287 | ) -> Option<FunctionDebugContext<&'ll DIScope, &'ll DILocation>> { | |
a1dfa0c6 | 288 | if self.sess().opts.debuginfo == DebugInfo::None { |
e74abb32 | 289 | return None; |
a1dfa0c6 XL |
290 | } |
291 | ||
29967ef6 XL |
292 | // Initialize fn debug context (including scopes). |
293 | // FIXME(eddyb) figure out a way to not need `Option` for `dbg_scope`. | |
294 | let empty_scope = DebugScope { | |
295 | dbg_scope: None, | |
296 | inlined_at: None, | |
297 | file_start_pos: BytePos(0), | |
298 | file_end_pos: BytePos(0), | |
299 | }; | |
300 | let mut fn_debug_context = | |
301 | FunctionDebugContext { scopes: IndexVec::from_elem(empty_scope, &mir.source_scopes) }; | |
d9579d0f | 302 | |
29967ef6 XL |
303 | // Fill in all the scopes, with the information from the MIR body. |
304 | compute_mir_scopes( | |
305 | self, | |
306 | instance, | |
307 | mir, | |
308 | self.dbg_scope_fn(instance, fn_abi, Some(llfn)), | |
309 | &mut fn_debug_context, | |
310 | ); | |
311 | ||
312 | Some(fn_debug_context) | |
313 | } | |
d9579d0f | 314 | |
29967ef6 XL |
315 | fn dbg_scope_fn( |
316 | &self, | |
317 | instance: Instance<'tcx>, | |
318 | fn_abi: &FnAbi<'tcx, Ty<'tcx>>, | |
319 | maybe_definition_llfn: Option<&'ll Value>, | |
320 | ) -> &'ll DIScope { | |
5099ac24 FG |
321 | let tcx = self.tcx; |
322 | ||
a1dfa0c6 XL |
323 | let def_id = instance.def_id(); |
324 | let containing_scope = get_containing_scope(self, instance); | |
5099ac24 | 325 | let span = tcx.def_span(def_id); |
ba9703b0 | 326 | let loc = self.lookup_debug_loc(span.lo()); |
29967ef6 | 327 | let file_metadata = file_metadata(self, &loc.file); |
d9579d0f | 328 | |
a1dfa0c6 | 329 | let function_type_metadata = unsafe { |
60c5eb7d | 330 | let fn_signature = get_function_signature(self, fn_abi); |
f9f354fc | 331 | llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(self), fn_signature) |
a1dfa0c6 | 332 | }; |
d9579d0f | 333 | |
136023e0 | 334 | let mut name = String::new(); |
5099ac24 | 335 | type_names::push_item_name(tcx, def_id, false, &mut name); |
476ff2be | 336 | |
136023e0 | 337 | // Find the enclosing function, in case this is a closure. |
5099ac24 FG |
338 | let enclosing_fn_def_id = tcx.typeck_root_def_id(def_id); |
339 | ||
340 | // We look up the generics of the enclosing function and truncate the substs | |
341 | // to their length in order to cut off extra stuff that might be in there for | |
342 | // closures or generators. | |
343 | let generics = tcx.generics_of(enclosing_fn_def_id); | |
344 | let substs = instance.substs.truncate_to(tcx, generics); | |
345 | ||
346 | type_names::push_generic_params( | |
347 | tcx, | |
348 | tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substs), | |
349 | &mut name, | |
350 | ); | |
a7813a04 | 351 | |
5099ac24 | 352 | let template_parameters = get_template_parameters(self, generics, substs); |
a7813a04 | 353 | |
3dfed10e | 354 | let linkage_name = &mangled_name_of_instance(self, instance).name; |
f035d41b XL |
355 | // Omit the linkage_name if it is the same as subprogram name. |
356 | let linkage_name = if &name == linkage_name { "" } else { linkage_name }; | |
d9579d0f | 357 | |
74b04a01 XL |
358 | // FIXME(eddyb) does this need to be separate from `loc.line` for some reason? |
359 | let scope_line = loc.line; | |
a7813a04 | 360 | |
a1dfa0c6 | 361 | let mut flags = DIFlags::FlagPrototyped; |
0531ce1d | 362 | |
60c5eb7d | 363 | if fn_abi.ret.layout.abi.is_uninhabited() { |
a1dfa0c6 XL |
364 | flags |= DIFlags::FlagNoReturn; |
365 | } | |
8bb4bdeb | 366 | |
9fa01778 XL |
367 | let mut spflags = DISPFlags::SPFlagDefinition; |
368 | if is_node_local_to_unit(self, def_id) { | |
369 | spflags |= DISPFlags::SPFlagLocalToUnit; | |
370 | } | |
371 | if self.sess().opts.optimize != config::OptLevel::No { | |
372 | spflags |= DISPFlags::SPFlagOptimized; | |
373 | } | |
5099ac24 | 374 | if let Some((id, _)) = tcx.entry_fn(()) { |
cdc7bbd5 | 375 | if id == def_id { |
532ac7d7 XL |
376 | spflags |= DISPFlags::SPFlagMainSubprogram; |
377 | } | |
378 | } | |
9fa01778 | 379 | |
29967ef6 XL |
380 | unsafe { |
381 | return llvm::LLVMRustDIBuilderCreateFunction( | |
a1dfa0c6 XL |
382 | DIB(self), |
383 | containing_scope, | |
74b04a01 XL |
384 | name.as_ptr().cast(), |
385 | name.len(), | |
386 | linkage_name.as_ptr().cast(), | |
387 | linkage_name.len(), | |
a1dfa0c6 | 388 | file_metadata, |
6a06907d | 389 | loc.line, |
a1dfa0c6 | 390 | function_type_metadata, |
6a06907d | 391 | scope_line, |
a1dfa0c6 | 392 | flags, |
9fa01778 | 393 | spflags, |
29967ef6 | 394 | maybe_definition_llfn, |
a1dfa0c6 | 395 | template_parameters, |
dfeec247 | 396 | None, |
29967ef6 XL |
397 | ); |
398 | } | |
d9579d0f | 399 | |
a1dfa0c6 XL |
400 | fn get_function_signature<'ll, 'tcx>( |
401 | cx: &CodegenCx<'ll, 'tcx>, | |
60c5eb7d | 402 | fn_abi: &FnAbi<'tcx, Ty<'tcx>>, |
a1dfa0c6 XL |
403 | ) -> &'ll DIArray { |
404 | if cx.sess().opts.debuginfo == DebugInfo::Limited { | |
405 | return create_DIArray(DIB(cx), &[]); | |
406 | } | |
d9579d0f | 407 | |
60c5eb7d | 408 | let mut signature = Vec::with_capacity(fn_abi.args.len() + 1); |
c1a9b12d | 409 | |
a1dfa0c6 | 410 | // Return type -- llvm::DIBuilder wants this at index 0 |
60c5eb7d XL |
411 | signature.push(if fn_abi.ret.is_ignore() { |
412 | None | |
a1dfa0c6 | 413 | } else { |
5099ac24 | 414 | Some(type_metadata(cx, fn_abi.ret.layout.ty)) |
60c5eb7d | 415 | }); |
d9579d0f | 416 | |
a1dfa0c6 | 417 | // Arguments types |
29967ef6 | 418 | if cx.sess().target.is_like_msvc { |
a1dfa0c6 XL |
419 | // FIXME(#42800): |
420 | // There is a bug in MSDIA that leads to a crash when it encounters | |
421 | // a fixed-size array of `u8` or something zero-sized in a | |
422 | // function-type (see #40477). | |
423 | // As a workaround, we replace those fixed-size arrays with a | |
424 | // pointer-type. So a function `fn foo(a: u8, b: [u8; 4])` would | |
425 | // appear as `fn foo(a: u8, b: *const u8)` in debuginfo, | |
426 | // and a function `fn bar(x: [(); 7])` as `fn bar(x: *const ())`. | |
427 | // This transformed type is wrong, but these function types are | |
428 | // already inaccurate due to ABI adjustments (see #42800). | |
60c5eb7d XL |
429 | signature.extend(fn_abi.args.iter().map(|arg| { |
430 | let t = arg.layout.ty; | |
1b1a35ee | 431 | let t = match t.kind() { |
a1dfa0c6 | 432 | ty::Array(ct, _) |
5099ac24 | 433 | if (*ct == cx.tcx.types.u8) || cx.layout_of(*ct).is_zst() => |
dfeec247 | 434 | { |
5099ac24 | 435 | cx.tcx.mk_imm_ptr(*ct) |
a1dfa0c6 | 436 | } |
dfeec247 | 437 | _ => t, |
a1dfa0c6 | 438 | }; |
5099ac24 | 439 | Some(type_metadata(cx, t)) |
a1dfa0c6 XL |
440 | })); |
441 | } else { | |
5099ac24 FG |
442 | signature |
443 | .extend(fn_abi.args.iter().map(|arg| Some(type_metadata(cx, arg.layout.ty)))); | |
a1dfa0c6 | 444 | } |
d9579d0f | 445 | |
a1dfa0c6 | 446 | create_DIArray(DIB(cx), &signature[..]) |
54a0048b SL |
447 | } |
448 | ||
a1dfa0c6 XL |
449 | fn get_template_parameters<'ll, 'tcx>( |
450 | cx: &CodegenCx<'ll, 'tcx>, | |
451 | generics: &ty::Generics, | |
532ac7d7 | 452 | substs: SubstsRef<'tcx>, |
a1dfa0c6 XL |
453 | ) -> &'ll DIArray { |
454 | if substs.types().next().is_none() { | |
455 | return create_DIArray(DIB(cx), &[]); | |
456 | } | |
d9579d0f | 457 | |
a1dfa0c6 XL |
458 | // Again, only create type information if full debuginfo is enabled |
459 | let template_params: Vec<_> = if cx.sess().opts.debuginfo == DebugInfo::Full { | |
460 | let names = get_parameter_names(cx, generics); | |
cdc7bbd5 | 461 | iter::zip(substs, names) |
dfeec247 XL |
462 | .filter_map(|(kind, name)| { |
463 | if let GenericArgKind::Type(ty) = kind.unpack() { | |
464 | let actual_type = | |
465 | cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); | |
5099ac24 | 466 | let actual_type_metadata = type_metadata(cx, actual_type); |
74b04a01 | 467 | let name = name.as_str(); |
dfeec247 XL |
468 | Some(unsafe { |
469 | Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( | |
470 | DIB(cx), | |
471 | None, | |
74b04a01 XL |
472 | name.as_ptr().cast(), |
473 | name.len(), | |
dfeec247 | 474 | actual_type_metadata, |
dfeec247 XL |
475 | )) |
476 | }) | |
477 | } else { | |
478 | None | |
479 | } | |
480 | }) | |
481 | .collect() | |
a1dfa0c6 XL |
482 | } else { |
483 | vec![] | |
484 | }; | |
485 | ||
a2a8927a | 486 | create_DIArray(DIB(cx), &template_params) |
a1dfa0c6 | 487 | } |
9e0c209e | 488 | |
dfeec247 | 489 | fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec<Symbol> { |
6a06907d XL |
490 | let mut names = generics.parent.map_or_else(Vec::new, |def_id| { |
491 | get_parameter_names(cx, cx.tcx.generics_of(def_id)) | |
492 | }); | |
a1dfa0c6 XL |
493 | names.extend(generics.params.iter().map(|param| param.name)); |
494 | names | |
a7813a04 | 495 | } |
a1dfa0c6 XL |
496 | |
497 | fn get_containing_scope<'ll, 'tcx>( | |
498 | cx: &CodegenCx<'ll, 'tcx>, | |
499 | instance: Instance<'tcx>, | |
500 | ) -> &'ll DIScope { | |
501 | // First, let's see if this is a method within an inherent impl. Because | |
502 | // if yes, we want to make the result subroutine DIE a child of the | |
503 | // subroutine's self-type. | |
504 | let self_type = cx.tcx.impl_of_method(instance.def_id()).and_then(|impl_def_id| { | |
505 | // If the method does *not* belong to a trait, proceed | |
506 | if cx.tcx.trait_id_of_impl(impl_def_id).is_none() { | |
507 | let impl_self_ty = cx.tcx.subst_and_normalize_erasing_regions( | |
508 | instance.substs, | |
509 | ty::ParamEnv::reveal_all(), | |
fc512014 | 510 | cx.tcx.type_of(impl_def_id), |
a1dfa0c6 XL |
511 | ); |
512 | ||
513 | // Only "class" methods are generally understood by LLVM, | |
0731742a | 514 | // so avoid methods on other types (e.g., `<*mut T>::null`). |
1b1a35ee | 515 | match impl_self_ty.kind() { |
a1dfa0c6 | 516 | ty::Adt(def, ..) if !def.is_box() => { |
ba9703b0 | 517 | // Again, only create type information if full debuginfo is enabled |
3dfed10e | 518 | if cx.sess().opts.debuginfo == DebugInfo::Full |
5099ac24 | 519 | && !impl_self_ty.needs_subst() |
3dfed10e | 520 | { |
5099ac24 | 521 | Some(type_metadata(cx, impl_self_ty)) |
ba9703b0 XL |
522 | } else { |
523 | Some(namespace::item_namespace(cx, def.did)) | |
524 | } | |
a1dfa0c6 | 525 | } |
dfeec247 | 526 | _ => None, |
a1dfa0c6 | 527 | } |
94b46f34 | 528 | } else { |
a1dfa0c6 XL |
529 | // For trait method impls we still use the "parallel namespace" |
530 | // strategy | |
94b46f34 | 531 | None |
a7813a04 | 532 | } |
a1dfa0c6 XL |
533 | }); |
534 | ||
535 | self_type.unwrap_or_else(|| { | |
dfeec247 XL |
536 | namespace::item_namespace( |
537 | cx, | |
538 | DefId { | |
539 | krate: instance.def_id().krate, | |
540 | index: cx | |
541 | .tcx | |
542 | .def_key(instance.def_id()) | |
543 | .parent | |
544 | .expect("get_containing_scope: missing parent?"), | |
545 | }, | |
546 | ) | |
a1dfa0c6 XL |
547 | }) |
548 | } | |
549 | } | |
a7813a04 | 550 | |
29967ef6 XL |
551 | fn dbg_loc( |
552 | &self, | |
553 | scope: &'ll DIScope, | |
554 | inlined_at: Option<&'ll DILocation>, | |
555 | span: Span, | |
556 | ) -> &'ll DILocation { | |
557 | let DebugLoc { line, col, .. } = self.lookup_debug_loc(span.lo()); | |
558 | ||
6a06907d | 559 | unsafe { llvm::LLVMRustDIBuilderCreateDebugLocation(line, col, scope, inlined_at) } |
29967ef6 XL |
560 | } |
561 | ||
c295e0f8 XL |
562 | fn create_vtable_metadata( |
563 | &self, | |
564 | ty: Ty<'tcx>, | |
565 | trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>, | |
566 | vtable: Self::Value, | |
567 | ) { | |
568 | metadata::create_vtable_metadata(self, ty, trait_ref, vtable) | |
a7813a04 XL |
569 | } |
570 | ||
a1dfa0c6 | 571 | fn extend_scope_to_file( |
dfeec247 XL |
572 | &self, |
573 | scope_metadata: &'ll DIScope, | |
574 | file: &rustc_span::SourceFile, | |
dfeec247 | 575 | ) -> &'ll DILexicalBlock { |
c295e0f8 | 576 | metadata::extend_scope_to_file(self, scope_metadata, file) |
dfeec247 | 577 | } |
a1dfa0c6 XL |
578 | |
579 | fn debuginfo_finalize(&self) { | |
580 | finalize(self) | |
d9579d0f | 581 | } |
74b04a01 XL |
582 | |
583 | // FIXME(eddyb) find a common convention for all of the debuginfo-related | |
584 | // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.). | |
585 | fn create_dbg_var( | |
586 | &self, | |
f9f354fc | 587 | variable_name: Symbol, |
74b04a01 XL |
588 | variable_type: Ty<'tcx>, |
589 | scope_metadata: &'ll DIScope, | |
590 | variable_kind: VariableKind, | |
591 | span: Span, | |
592 | ) -> &'ll DIVariable { | |
ba9703b0 | 593 | let loc = self.lookup_debug_loc(span.lo()); |
29967ef6 | 594 | let file_metadata = file_metadata(self, &loc.file); |
74b04a01 | 595 | |
5099ac24 | 596 | let type_metadata = type_metadata(self, variable_type); |
74b04a01 XL |
597 | |
598 | let (argument_index, dwarf_tag) = match variable_kind { | |
599 | ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable), | |
600 | LocalVariable => (0, DW_TAG_auto_variable), | |
601 | }; | |
602 | let align = self.align_of(variable_type); | |
603 | ||
604 | let name = variable_name.as_str(); | |
605 | unsafe { | |
606 | llvm::LLVMRustDIBuilderCreateVariable( | |
607 | DIB(self), | |
608 | dwarf_tag, | |
609 | scope_metadata, | |
610 | name.as_ptr().cast(), | |
611 | name.len(), | |
612 | file_metadata, | |
6a06907d | 613 | loc.line, |
74b04a01 XL |
614 | type_metadata, |
615 | true, | |
616 | DIFlags::FlagZero, | |
617 | argument_index, | |
618 | align.bytes() as u32, | |
619 | ) | |
620 | } | |
621 | } | |
d9579d0f | 622 | } |