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