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