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