]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
New upstream version 1.65.0+dfsg1
[rustc.git] / compiler / rustc_codegen_llvm / src / debuginfo / metadata.rs
CommitLineData
5e7ed085
FG
1use self::type_map::DINodeCreationResult;
2use self::type_map::Stub;
3use self::type_map::UniqueTypeId;
1a4d82fc 4
0531ce1d 5use super::namespace::mangled_name_of_instance;
c295e0f8 6use super::type_names::{compute_debuginfo_type_name, compute_debuginfo_vtable_name};
dfeec247 7use super::utils::{
ba9703b0 8 create_DIArray, debug_context, get_namespace_for_item, is_node_local_to_unit, DIB,
dfeec247 9};
5e7ed085 10use super::CodegenUnitDebugContext;
d9579d0f 11
60c5eb7d
XL
12use crate::abi;
13use crate::common::CodegenCx;
5e7ed085 14use crate::debuginfo::metadata::type_map::build_type_with_children;
5099ac24
FG
15use crate::debuginfo::utils::fat_pointer_kind;
16use crate::debuginfo::utils::FatPtrKind;
9fa01778 17use crate::llvm;
dfeec247 18use crate::llvm::debuginfo::{
5e7ed085 19 DIDescriptor, DIFile, DIFlags, DILexicalBlock, DIScope, DIType, DebugEmissionKind,
dfeec247 20};
60c5eb7d 21use crate::value::Value;
d9579d0f 22
6a06907d 23use cstr::cstr;
a2a8927a 24use rustc_codegen_ssa::debuginfo::type_names::cpp_like_debuginfo;
5099ac24 25use rustc_codegen_ssa::debuginfo::type_names::VTableNameKind;
dfeec247 26use rustc_codegen_ssa::traits::*;
dfeec247
XL
27use rustc_fs_util::path_to_c_string;
28use rustc_hir::def::CtorKind;
29967ef6 29use rustc_hir::def_id::{DefId, LOCAL_CRATE};
dfeec247 30use rustc_index::vec::{Idx, IndexVec};
5099ac24 31use rustc_middle::bug;
136023e0 32use rustc_middle::mir::{self, GeneratorLayout};
923072b8 33use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
f035d41b 34use rustc_middle::ty::subst::GenericArgKind;
923072b8
FG
35use rustc_middle::ty::{
36 self, AdtKind, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt, Visibility,
37};
38use rustc_session::config::{self, DebugInfo, Lto};
c295e0f8 39use rustc_span::symbol::Symbol;
923072b8
FG
40use rustc_span::FileName;
41use rustc_span::{self, FileNameDisplayPreference, SourceFile};
42use rustc_symbol_mangling::typeid_for_trait_ref;
5e7ed085
FG
43use rustc_target::abi::{Align, Size};
44use smallvec::smallvec;
1a4d82fc 45
923072b8 46use libc::{c_char, c_longlong, c_uint};
5e7ed085 47use std::borrow::Cow;
b7449926
XL
48use std::fmt::{self, Write};
49use std::hash::{Hash, Hasher};
8faf50e0 50use std::iter;
ff7c6d11 51use std::path::{Path, PathBuf};
dfeec247 52use std::ptr;
1a4d82fc 53
b7449926
XL
54impl PartialEq for llvm::Metadata {
55 fn eq(&self, other: &Self) -> bool {
0731742a 56 ptr::eq(self, other)
b7449926
XL
57 }
58}
59
60impl Eq for llvm::Metadata {}
61
62impl Hash for llvm::Metadata {
63 fn hash<H: Hasher>(&self, hasher: &mut H) {
64 (self as *const Self).hash(hasher);
65 }
66}
67
68impl fmt::Debug for llvm::Metadata {
9fa01778 69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
b7449926
XL
70 (self as *const Self).fmt(f)
71 }
72}
c30ab7b3 73
54a0048b 74// From DWARF 5.
60c5eb7d 75// See http://www.dwarfstd.org/ShowIssue.php?issue=140129.1.
54a0048b 76const DW_LANG_RUST: c_uint = 0x1c;
1a4d82fc
JJ
77#[allow(non_upper_case_globals)]
78const DW_ATE_boolean: c_uint = 0x02;
79#[allow(non_upper_case_globals)]
80const DW_ATE_float: c_uint = 0x04;
81#[allow(non_upper_case_globals)]
82const DW_ATE_signed: c_uint = 0x05;
83#[allow(non_upper_case_globals)]
84const DW_ATE_unsigned: c_uint = 0x07;
85#[allow(non_upper_case_globals)]
5e7ed085 86const DW_ATE_UTF: c_uint = 0x10;
1a4d82fc 87
5e7ed085
FG
88pub(super) const UNKNOWN_LINE_NUMBER: c_uint = 0;
89pub(super) const UNKNOWN_COLUMN_NUMBER: c_uint = 0;
5099ac24 90
5e7ed085
FG
91const NO_SCOPE_METADATA: Option<&DIScope> = None;
92/// A function that returns an empty list of generic parameter debuginfo nodes.
93const NO_GENERICS: for<'ll> fn(&CodegenCx<'ll, '_>) -> SmallVec<&'ll DIType> = |_| SmallVec::new();
d9579d0f 94
5e7ed085
FG
95// SmallVec is used quite a bit in this module, so create a shorthand.
96// The actual number of elements is not so important.
97pub type SmallVec<T> = smallvec::SmallVec<[T; 16]>;
d9579d0f 98
5e7ed085
FG
99mod enums;
100mod type_map;
d9579d0f 101
5e7ed085 102pub(crate) use type_map::TypeMap;
d9579d0f 103
5e7ed085 104/// Returns from the enclosing function if the type debuginfo node with the given
60c5eb7d 105/// unique ID can be found in the type map.
5e7ed085 106macro_rules! return_if_di_node_created_in_meantime {
dfeec247 107 ($cx: expr, $unique_type_id: expr) => {
5e7ed085
FG
108 if let Some(di_node) = debug_context($cx).type_map.di_node_for_unique_id($unique_type_id) {
109 return DINodeCreationResult::new(di_node, true);
b039eaaf 110 }
dfeec247 111 };
1a4d82fc
JJ
112}
113
5e7ed085 114/// Extract size and alignment from a TyAndLayout.
f2b60f7d 115#[inline]
5e7ed085
FG
116fn size_and_align_of<'tcx>(ty_and_layout: TyAndLayout<'tcx>) -> (Size, Align) {
117 (ty_and_layout.size, ty_and_layout.align.abi)
118}
119
5099ac24 120/// Creates debuginfo for a fixed size array (e.g. `[u64; 123]`).
5e7ed085
FG
121/// For slices (that is, "arrays" of unknown size) use [build_slice_type_di_node].
122fn build_fixed_size_array_di_node<'ll, 'tcx>(
b7449926 123 cx: &CodegenCx<'ll, 'tcx>,
5e7ed085 124 unique_type_id: UniqueTypeId<'tcx>,
5099ac24 125 array_type: Ty<'tcx>,
5e7ed085 126) -> DINodeCreationResult<'ll> {
5099ac24 127 let ty::Array(element_type, len) = array_type.kind() else {
5e7ed085 128 bug!("build_fixed_size_array_di_node() called with non-ty::Array type `{:?}`", array_type)
5099ac24
FG
129 };
130
5e7ed085 131 let element_type_di_node = type_di_node(cx, *element_type);
d9579d0f 132
5e7ed085 133 return_if_di_node_created_in_meantime!(cx, unique_type_id);
1a4d82fc 134
5099ac24 135 let (size, align) = cx.size_and_align_of(array_type);
1a4d82fc 136
5099ac24 137 let upper_bound = len.eval_usize(cx.tcx, ty::ParamEnv::reveal_all()) as c_longlong;
1a4d82fc 138
dfeec247
XL
139 let subrange =
140 unsafe { Some(llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)) };
1a4d82fc 141
d9579d0f 142 let subscripts = create_DIArray(DIB(cx), &[subrange]);
5e7ed085 143 let di_node = unsafe {
5bcae85e 144 llvm::LLVMRustDIBuilderCreateArrayType(
d9579d0f 145 DIB(cx),
ff7c6d11 146 size.bits(),
a1dfa0c6 147 align.bits() as u32,
5e7ed085 148 element_type_di_node,
dfeec247
XL
149 subscripts,
150 )
d9579d0f 151 };
1a4d82fc 152
5e7ed085 153 DINodeCreationResult::new(di_node, false)
1a4d82fc
JJ
154}
155
5099ac24
FG
156/// Creates debuginfo for built-in pointer-like things:
157///
158/// - ty::Ref
159/// - ty::RawPtr
160/// - ty::Adt in the case it's Box
161///
162/// At some point we might want to remove the special handling of Box
163/// and treat it the same as other smart pointers (like Rc, Arc, ...).
5e7ed085 164fn build_pointer_or_reference_di_node<'ll, 'tcx>(
b7449926 165 cx: &CodegenCx<'ll, 'tcx>,
5099ac24
FG
166 ptr_type: Ty<'tcx>,
167 pointee_type: Ty<'tcx>,
5e7ed085
FG
168 unique_type_id: UniqueTypeId<'tcx>,
169) -> DINodeCreationResult<'ll> {
170 // The debuginfo generated by this function is only valid if `ptr_type` is really just
171 // a (fat) pointer. Make sure it is not called for e.g. `Box<T, NonZSTAllocator>`.
172 debug_assert_eq!(
173 cx.size_and_align_of(ptr_type),
174 cx.size_and_align_of(cx.tcx.mk_mut_ptr(pointee_type))
175 );
176
177 let pointee_type_di_node = type_di_node(cx, pointee_type);
1a4d82fc 178
5e7ed085 179 return_if_di_node_created_in_meantime!(cx, unique_type_id);
1a4d82fc 180
5099ac24
FG
181 let (thin_pointer_size, thin_pointer_align) =
182 cx.size_and_align_of(cx.tcx.mk_imm_ptr(cx.tcx.types.unit));
183 let ptr_type_debuginfo_name = compute_debuginfo_type_name(cx.tcx, ptr_type, true);
1a4d82fc 184
5e7ed085 185 match fat_pointer_kind(cx, pointee_type) {
5099ac24
FG
186 None => {
187 // This is a thin pointer. Create a regular pointer type and give it the correct name.
188 debug_assert_eq!(
189 (thin_pointer_size, thin_pointer_align),
5e7ed085
FG
190 cx.size_and_align_of(ptr_type),
191 "ptr_type={}, pointee_type={}",
192 ptr_type,
193 pointee_type,
5099ac24 194 );
1a4d82fc 195
5e7ed085 196 let di_node = unsafe {
5099ac24
FG
197 llvm::LLVMRustDIBuilderCreatePointerType(
198 DIB(cx),
5e7ed085 199 pointee_type_di_node,
5099ac24
FG
200 thin_pointer_size.bits(),
201 thin_pointer_align.bits() as u32,
202 0, // Ignore DWARF address space.
203 ptr_type_debuginfo_name.as_ptr().cast(),
204 ptr_type_debuginfo_name.len(),
205 )
5e7ed085
FG
206 };
207
208 DINodeCreationResult { di_node, already_stored_in_typemap: false }
5099ac24
FG
209 }
210 Some(fat_pointer_kind) => {
5e7ed085
FG
211 type_map::build_type_with_children(
212 cx,
213 type_map::stub(
214 cx,
215 Stub::Struct,
216 unique_type_id,
217 &ptr_type_debuginfo_name,
218 cx.size_and_align_of(ptr_type),
219 NO_SCOPE_METADATA,
220 DIFlags::FlagZero,
221 ),
222 |cx, owner| {
223 // FIXME: If this fat pointer is a `Box` then we don't want to use its
224 // type layout and instead use the layout of the raw pointer inside
225 // of it.
226 // The proper way to handle this is to not treat Box as a pointer
227 // at all and instead emit regular struct debuginfo for it. We just
228 // need to make sure that we don't break existing debuginfo consumers
229 // by doing that (at least not without a warning period).
230 let layout_type =
231 if ptr_type.is_box() { cx.tcx.mk_mut_ptr(pointee_type) } else { ptr_type };
232
233 let layout = cx.layout_of(layout_type);
234 let addr_field = layout.field(cx, abi::FAT_PTR_ADDR);
235 let extra_field = layout.field(cx, abi::FAT_PTR_EXTRA);
236
237 let (addr_field_name, extra_field_name) = match fat_pointer_kind {
238 FatPtrKind::Dyn => ("pointer", "vtable"),
239 FatPtrKind::Slice => ("data_ptr", "length"),
240 };
5099ac24 241
5e7ed085
FG
242 debug_assert_eq!(abi::FAT_PTR_ADDR, 0);
243 debug_assert_eq!(abi::FAT_PTR_EXTRA, 1);
5099ac24 244
5e7ed085
FG
245 // The data pointer type is a regular, thin pointer, regardless of whether this
246 // is a slice or a trait object.
247 let data_ptr_type_di_node = unsafe {
248 llvm::LLVMRustDIBuilderCreatePointerType(
249 DIB(cx),
250 pointee_type_di_node,
251 addr_field.size.bits(),
252 addr_field.align.abi.bits() as u32,
253 0, // Ignore DWARF address space.
254 std::ptr::null(),
255 0,
256 )
257 };
5099ac24 258
5e7ed085
FG
259 smallvec![
260 build_field_di_node(
261 cx,
262 owner,
263 addr_field_name,
264 (addr_field.size, addr_field.align.abi),
265 layout.fields.offset(abi::FAT_PTR_ADDR),
266 DIFlags::FlagZero,
267 data_ptr_type_di_node,
268 ),
269 build_field_di_node(
270 cx,
271 owner,
272 extra_field_name,
273 (extra_field.size, extra_field.align.abi),
274 layout.fields.offset(abi::FAT_PTR_EXTRA),
275 DIFlags::FlagZero,
276 type_di_node(cx, extra_field.ty),
277 ),
278 ]
5099ac24 279 },
5e7ed085 280 NO_GENERICS,
5099ac24
FG
281 )
282 }
5e7ed085 283 }
d9579d0f 284}
1a4d82fc 285
5e7ed085 286fn build_subroutine_type_di_node<'ll, 'tcx>(
b7449926 287 cx: &CodegenCx<'ll, 'tcx>,
5e7ed085
FG
288 unique_type_id: UniqueTypeId<'tcx>,
289) -> DINodeCreationResult<'ll> {
290 // It's possible to create a self-referential
291 // type in Rust by using 'impl trait':
292 //
293 // fn foo() -> impl Copy { foo }
294 //
295 // Unfortunately LLVM's API does not allow us to create recursive subroutine types.
296 // In order to work around that restriction we place a marker type in the type map,
297 // before creating the actual type. If the actual type is recursive, it will hit the
298 // marker type. So we end up with a type that looks like
299 //
300 // fn foo() -> <recursive_type>
301 //
302 // Once that is created, we replace the marker in the typemap with the actual type.
303 debug_context(cx)
304 .type_map
305 .unique_id_to_di_node
306 .borrow_mut()
307 .insert(unique_type_id, recursion_marker_type_di_node(cx));
1a4d82fc 308
5e7ed085
FG
309 let fn_ty = unique_type_id.expect_ty();
310 let signature = cx
311 .tcx
312 .normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), fn_ty.fn_sig(cx.tcx));
313
314 let signature_di_nodes: SmallVec<_> = iter::once(
8faf50e0 315 // return type
1b1a35ee 316 match signature.output().kind() {
5e7ed085
FG
317 ty::Tuple(tys) if tys.is_empty() => {
318 // this is a "void" function
319 None
320 }
321 _ => Some(type_di_node(cx, signature.output())),
dfeec247
XL
322 },
323 )
324 .chain(
8faf50e0 325 // regular arguments
5e7ed085 326 signature.inputs().iter().map(|&argument_type| Some(type_di_node(cx, argument_type))),
dfeec247
XL
327 )
328 .collect();
1a4d82fc 329
5e7ed085 330 debug_context(cx).type_map.unique_id_to_di_node.borrow_mut().remove(&unique_type_id);
1a4d82fc 331
5e7ed085
FG
332 let fn_di_node = unsafe {
333 llvm::LLVMRustDIBuilderCreateSubroutineType(
334 DIB(cx),
335 create_DIArray(DIB(cx), &signature_di_nodes[..]),
336 )
337 };
338
339 // This is actually a function pointer, so wrap it in pointer DI.
340 let name = compute_debuginfo_type_name(cx.tcx, fn_ty, false);
341 let di_node = unsafe {
342 llvm::LLVMRustDIBuilderCreatePointerType(
343 DIB(cx),
344 fn_di_node,
345 cx.tcx.data_layout.pointer_size.bits(),
346 cx.tcx.data_layout.pointer_align.abi.bits() as u32,
347 0, // Ignore DWARF address space.
348 name.as_ptr().cast(),
349 name.len(),
350 )
351 };
352
353 DINodeCreationResult::new(di_node, false)
1a4d82fc
JJ
354}
355
5099ac24
FG
356/// Create debuginfo for `dyn SomeTrait` types. Currently these are empty structs
357/// we with the correct type name (e.g. "dyn SomeTrait<Foo, Item=u32> + Sync").
5e7ed085 358fn build_dyn_type_di_node<'ll, 'tcx>(
b7449926 359 cx: &CodegenCx<'ll, 'tcx>,
5099ac24 360 dyn_type: Ty<'tcx>,
5e7ed085
FG
361 unique_type_id: UniqueTypeId<'tcx>,
362) -> DINodeCreationResult<'ll> {
5099ac24
FG
363 if let ty::Dynamic(..) = dyn_type.kind() {
364 let type_name = compute_debuginfo_type_name(cx.tcx, dyn_type, true);
5e7ed085
FG
365 type_map::build_type_with_children(
366 cx,
367 type_map::stub(
368 cx,
369 Stub::Struct,
370 unique_type_id,
371 &type_name,
372 cx.size_and_align_of(dyn_type),
373 NO_SCOPE_METADATA,
374 DIFlags::FlagZero,
375 ),
376 |_, _| smallvec![],
377 NO_GENERICS,
378 )
5099ac24 379 } else {
5e7ed085
FG
380 bug!(
381 "Only ty::Dynamic is valid for build_dyn_type_di_node(). Found {:?} instead.",
382 dyn_type
383 )
5099ac24
FG
384 }
385}
1a4d82fc 386
5099ac24
FG
387/// Create debuginfo for `[T]` and `str`. These are unsized.
388///
389/// NOTE: We currently emit just emit the debuginfo for the element type here
390/// (i.e. `T` for slices and `u8` for `str`), so that we end up with
391/// `*const T` for the `data_ptr` field of the corresponding fat-pointer
392/// debuginfo of `&[T]`.
393///
394/// It would be preferable and more accurate if we emitted a DIArray of T
395/// without an upper bound instead. That is, LLVM already supports emitting
396/// debuginfo of arrays of unknown size. But GDB currently seems to end up
397/// in an infinite loop when confronted with such a type.
398///
399/// As a side effect of the current encoding every instance of a type like
400/// `struct Foo { unsized_field: [u8] }` will look like
401/// `struct Foo { unsized_field: u8 }` in debuginfo. If the length of the
402/// slice is zero, then accessing `unsized_field` in the debugger would
403/// result in an out-of-bounds access.
5e7ed085 404fn build_slice_type_di_node<'ll, 'tcx>(
5099ac24
FG
405 cx: &CodegenCx<'ll, 'tcx>,
406 slice_type: Ty<'tcx>,
5e7ed085
FG
407 unique_type_id: UniqueTypeId<'tcx>,
408) -> DINodeCreationResult<'ll> {
5099ac24
FG
409 let element_type = match slice_type.kind() {
410 ty::Slice(element_type) => *element_type,
411 ty::Str => cx.tcx.types.u8,
412 _ => {
413 bug!(
5e7ed085 414 "Only ty::Slice is valid for build_slice_type_di_node(). Found {:?} instead.",
5099ac24
FG
415 slice_type
416 )
417 }
136023e0 418 };
1a4d82fc 419
5e7ed085
FG
420 let element_type_di_node = type_di_node(cx, element_type);
421 return_if_di_node_created_in_meantime!(cx, unique_type_id);
422 DINodeCreationResult { di_node: element_type_di_node, already_stored_in_typemap: false }
1a4d82fc
JJ
423}
424
5e7ed085
FG
425/// Get the debuginfo node for the given type.
426///
427/// This function will look up the debuginfo node in the TypeMap. If it can't find it, it
428/// will create the node by dispatching to the corresponding `build_*_di_node()` function.
429pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
430 let unique_type_id = UniqueTypeId::for_ty(cx.tcx, t);
431
432 if let Some(existing_di_node) = debug_context(cx).type_map.di_node_for_unique_id(unique_type_id)
433 {
434 return existing_di_node;
435 }
1a4d82fc 436
5e7ed085 437 debug!("type_di_node: {:?}", t);
1a4d82fc 438
5e7ed085 439 let DINodeCreationResult { di_node, already_stored_in_typemap } = match *t.kind() {
dfeec247 440 ty::Never | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) => {
04454e1e 441 build_basic_type_di_node(cx, t)
1a4d82fc 442 }
04454e1e 443 ty::Tuple(elements) if elements.is_empty() => build_basic_type_di_node(cx, t),
5e7ed085
FG
444 ty::Array(..) => build_fixed_size_array_di_node(cx, unique_type_id, t),
445 ty::Slice(_) | ty::Str => build_slice_type_di_node(cx, t, unique_type_id),
446 ty::Dynamic(..) => build_dyn_type_di_node(cx, t, unique_type_id),
447 ty::Foreign(..) => build_foreign_type_di_node(cx, t, unique_type_id),
5099ac24 448 ty::RawPtr(ty::TypeAndMut { ty: pointee_type, .. }) | ty::Ref(_, pointee_type, _) => {
5e7ed085 449 build_pointer_or_reference_di_node(cx, t, pointee_type, unique_type_id)
1a4d82fc 450 }
5e7ed085
FG
451 // Box<T, A> may have a non-ZST allocator A. In that case, we
452 // cannot treat Box<T, A> as just an owned alias of `*mut T`.
453 ty::Adt(def, substs) if def.is_box() && cx.layout_of(substs.type_at(1)).is_zst() => {
454 build_pointer_or_reference_di_node(cx, t, t.boxed_ty(), unique_type_id)
ea8adc8c 455 }
5e7ed085
FG
456 ty::FnDef(..) | ty::FnPtr(_) => build_subroutine_type_di_node(cx, unique_type_id),
457 ty::Closure(..) => build_closure_env_di_node(cx, unique_type_id),
458 ty::Generator(..) => enums::build_generator_di_node(cx, unique_type_id),
b7449926 459 ty::Adt(def, ..) => match def.adt_kind() {
5e7ed085
FG
460 AdtKind::Struct => build_struct_type_di_node(cx, unique_type_id),
461 AdtKind::Union => build_union_type_di_node(cx, unique_type_id),
462 AdtKind::Enum => enums::build_enum_type_di_node(cx, unique_type_id),
9e0c209e 463 },
5e7ed085 464 ty::Tuple(_) => build_tuple_type_di_node(cx, unique_type_id),
3dfed10e 465 // Type parameters from polymorphized functions.
5e7ed085
FG
466 ty::Param(_) => build_param_type_di_node(cx, t),
467 _ => bug!("debuginfo: unexpected type in type_di_node(): {:?}", t),
1a4d82fc
JJ
468 };
469
470 {
1a4d82fc 471 if already_stored_in_typemap {
5e7ed085
FG
472 // Make sure that we really do have a `TypeMap` entry for the unique type ID.
473 let di_node_for_uid =
474 match debug_context(cx).type_map.di_node_for_unique_id(unique_type_id) {
475 Some(di_node) => di_node,
476 None => {
5099ac24 477 bug!(
5e7ed085
FG
478 "expected type debuginfo node for unique \
479 type ID '{:?}' to already be in \
480 the `debuginfo::TypeMap` but it \
481 was not.",
482 unique_type_id,
dfeec247 483 );
1a4d82fc 484 }
5e7ed085
FG
485 };
486
487 debug_assert_eq!(di_node_for_uid as *const _, di_node as *const _);
1a4d82fc 488 } else {
5e7ed085 489 debug_context(cx).type_map.insert(unique_type_id, di_node);
1a4d82fc
JJ
490 }
491 }
492
5e7ed085
FG
493 di_node
494}
495
496// FIXME(mw): Cache this via a regular UniqueTypeId instead of an extra field in the debug context.
497fn recursion_marker_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> &'ll DIType {
498 *debug_context(cx).recursion_marker_type.get_or_init(move || {
499 unsafe {
500 // The choice of type here is pretty arbitrary -
501 // anything reading the debuginfo for a recursive
502 // type is going to see *something* weird - the only
503 // question is what exactly it will see.
504 //
505 // FIXME: the name `<recur_type>` does not fit the naming scheme
506 // of other types.
507 //
508 // FIXME: it might make sense to use an actual pointer type here
509 // so that debuggers can show the address.
510 let name = "<recur_type>";
511 llvm::LLVMRustDIBuilderCreateBasicType(
512 DIB(cx),
513 name.as_ptr().cast(),
514 name.len(),
515 cx.tcx.data_layout.pointer_size.bits(),
516 DW_ATE_unsigned,
517 )
518 }
519 })
1a4d82fc
JJ
520}
521
ba9703b0
XL
522fn hex_encode(data: &[u8]) -> String {
523 let mut hex_string = String::with_capacity(data.len() * 2);
524 for byte in data.iter() {
525 write!(&mut hex_string, "{:02x}", byte).unwrap();
526 }
527 hex_string
528}
529
a2a8927a 530pub fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) -> &'ll DIFile {
923072b8
FG
531 let cache_key = Some((source_file.name_hash, source_file.src_hash));
532 return debug_context(cx)
533 .created_files
534 .borrow_mut()
535 .entry(cache_key)
536 .or_insert_with(|| alloc_new_file_metadata(cx, source_file));
537
538 #[instrument(skip(cx, source_file), level = "debug")]
539 fn alloc_new_file_metadata<'ll>(
540 cx: &CodegenCx<'ll, '_>,
541 source_file: &SourceFile,
542 ) -> &'ll DIFile {
543 debug!(?source_file.name);
544
545 let (directory, file_name) = match &source_file.name {
546 FileName::Real(filename) => {
547 let working_directory = &cx.sess().opts.working_dir;
548 debug!(?working_directory);
549
550 let filename = cx
551 .sess()
552 .source_map()
553 .path_mapping()
554 .to_embeddable_absolute_path(filename.clone(), working_directory);
555
556 // Construct the absolute path of the file
557 let abs_path = filename.remapped_path_if_available();
558 debug!(?abs_path);
559
560 if let Ok(rel_path) =
561 abs_path.strip_prefix(working_directory.remapped_path_if_available())
562 {
563 // If the compiler's working directory (which also is the DW_AT_comp_dir of
564 // the compilation unit) is a prefix of the path we are about to emit, then
565 // only emit the part relative to the working directory.
566 // Because of path remapping we sometimes see strange things here: `abs_path`
567 // might actually look like a relative path
568 // (e.g. `<crate-name-and-version>/src/lib.rs`), so if we emit it without
569 // taking the working directory into account, downstream tooling will
570 // interpret it as `<working-directory>/<crate-name-and-version>/src/lib.rs`,
571 // which makes no sense. Usually in such cases the working directory will also
572 // be remapped to `<crate-name-and-version>` or some other prefix of the path
573 // we are remapping, so we end up with
574 // `<crate-name-and-version>/<crate-name-and-version>/src/lib.rs`.
575 // By moving the working directory portion into the `directory` part of the
576 // DIFile, we allow LLVM to emit just the relative path for DWARF, while
577 // still emitting the correct absolute path for CodeView.
578 (
579 working_directory.to_string_lossy(FileNameDisplayPreference::Remapped),
580 rel_path.to_string_lossy().into_owned(),
581 )
582 } else {
583 ("".into(), abs_path.to_string_lossy().into_owned())
ba9703b0 584 }
923072b8
FG
585 }
586 other => ("".into(), other.prefer_remapped().to_string_lossy().into_owned()),
587 };
ba9703b0 588
923072b8
FG
589 let hash_kind = match source_file.src_hash.kind {
590 rustc_span::SourceFileHashAlgorithm::Md5 => llvm::ChecksumKind::MD5,
591 rustc_span::SourceFileHashAlgorithm::Sha1 => llvm::ChecksumKind::SHA1,
592 rustc_span::SourceFileHashAlgorithm::Sha256 => llvm::ChecksumKind::SHA256,
593 };
594 let hash_value = hex_encode(source_file.src_hash.hash_bytes());
7cac9316 595
923072b8
FG
596 unsafe {
597 llvm::LLVMRustDIBuilderCreateFile(
598 DIB(cx),
599 file_name.as_ptr().cast(),
600 file_name.len(),
601 directory.as_ptr().cast(),
602 directory.len(),
603 hash_kind,
604 hash_value.as_ptr().cast(),
605 hash_value.len(),
606 )
dc9dc135 607 }
e9174d1e 608 }
d9579d0f
AL
609}
610
923072b8
FG
611pub fn unknown_file_metadata<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile {
612 debug_context(cx).created_files.borrow_mut().entry(None).or_insert_with(|| unsafe {
613 let file_name = "<unknown>";
614 let directory = "";
615 let hash_value = "";
616
617 llvm::LLVMRustDIBuilderCreateFile(
618 DIB(cx),
619 file_name.as_ptr().cast(),
620 file_name.len(),
621 directory.as_ptr().cast(),
622 directory.len(),
623 llvm::ChecksumKind::None,
624 hash_value.as_ptr().cast(),
625 hash_value.len(),
626 )
627 })
628}
629
f035d41b
XL
630trait MsvcBasicName {
631 fn msvc_basic_name(self) -> &'static str;
632}
633
5869c6ff 634impl MsvcBasicName for ty::IntTy {
f035d41b
XL
635 fn msvc_basic_name(self) -> &'static str {
636 match self {
5869c6ff
XL
637 ty::IntTy::Isize => "ptrdiff_t",
638 ty::IntTy::I8 => "__int8",
639 ty::IntTy::I16 => "__int16",
640 ty::IntTy::I32 => "__int32",
641 ty::IntTy::I64 => "__int64",
642 ty::IntTy::I128 => "__int128",
f035d41b
XL
643 }
644 }
645}
646
5869c6ff 647impl MsvcBasicName for ty::UintTy {
f035d41b
XL
648 fn msvc_basic_name(self) -> &'static str {
649 match self {
5869c6ff
XL
650 ty::UintTy::Usize => "size_t",
651 ty::UintTy::U8 => "unsigned __int8",
652 ty::UintTy::U16 => "unsigned __int16",
653 ty::UintTy::U32 => "unsigned __int32",
654 ty::UintTy::U64 => "unsigned __int64",
655 ty::UintTy::U128 => "unsigned __int128",
f035d41b
XL
656 }
657 }
658}
659
5869c6ff 660impl MsvcBasicName for ty::FloatTy {
f035d41b
XL
661 fn msvc_basic_name(self) -> &'static str {
662 match self {
5869c6ff
XL
663 ty::FloatTy::F32 => "float",
664 ty::FloatTy::F64 => "double",
f035d41b
XL
665 }
666 }
667}
668
04454e1e
FG
669fn build_basic_type_di_node<'ll, 'tcx>(
670 cx: &CodegenCx<'ll, 'tcx>,
671 t: Ty<'tcx>,
672) -> DINodeCreationResult<'ll> {
5e7ed085 673 debug!("build_basic_type_di_node: {:?}", t);
d9579d0f 674
f035d41b
XL
675 // When targeting MSVC, emit MSVC style type names for compatibility with
676 // .natvis visualizers (and perhaps other existing native debuggers?)
a2a8927a 677 let cpp_like_debuginfo = cpp_like_debuginfo(cx.tcx);
f035d41b 678
1b1a35ee 679 let (name, encoding) = match t.kind() {
b7449926 680 ty::Never => ("!", DW_ATE_unsigned),
04454e1e
FG
681 ty::Tuple(elements) if elements.is_empty() => {
682 if cpp_like_debuginfo {
683 return build_tuple_type_di_node(cx, UniqueTypeId::for_ty(cx.tcx, t));
684 } else {
685 ("()", DW_ATE_unsigned)
686 }
687 }
b7449926 688 ty::Bool => ("bool", DW_ATE_boolean),
5e7ed085 689 ty::Char => ("char", DW_ATE_UTF),
a2a8927a
XL
690 ty::Int(int_ty) if cpp_like_debuginfo => (int_ty.msvc_basic_name(), DW_ATE_signed),
691 ty::Uint(uint_ty) if cpp_like_debuginfo => (uint_ty.msvc_basic_name(), DW_ATE_unsigned),
692 ty::Float(float_ty) if cpp_like_debuginfo => (float_ty.msvc_basic_name(), DW_ATE_float),
dfeec247
XL
693 ty::Int(int_ty) => (int_ty.name_str(), DW_ATE_signed),
694 ty::Uint(uint_ty) => (uint_ty.name_str(), DW_ATE_unsigned),
695 ty::Float(float_ty) => (float_ty.name_str(), DW_ATE_float),
5e7ed085 696 _ => bug!("debuginfo::build_basic_type_di_node - `t` is invalid type"),
d9579d0f
AL
697 };
698
5e7ed085 699 let ty_di_node = unsafe {
5bcae85e 700 llvm::LLVMRustDIBuilderCreateBasicType(
d9579d0f 701 DIB(cx),
74b04a01
XL
702 name.as_ptr().cast(),
703 name.len(),
f9f354fc 704 cx.size_of(t).bits(),
dfeec247
XL
705 encoding,
706 )
d9579d0f
AL
707 };
708
a2a8927a 709 if !cpp_like_debuginfo {
04454e1e 710 return DINodeCreationResult::new(ty_di_node, false);
f035d41b
XL
711 }
712
1b1a35ee 713 let typedef_name = match t.kind() {
f035d41b
XL
714 ty::Int(int_ty) => int_ty.name_str(),
715 ty::Uint(uint_ty) => uint_ty.name_str(),
716 ty::Float(float_ty) => float_ty.name_str(),
04454e1e 717 _ => return DINodeCreationResult::new(ty_di_node, false),
f035d41b
XL
718 };
719
5e7ed085 720 let typedef_di_node = unsafe {
f035d41b
XL
721 llvm::LLVMRustDIBuilderCreateTypedef(
722 DIB(cx),
5e7ed085 723 ty_di_node,
f035d41b
XL
724 typedef_name.as_ptr().cast(),
725 typedef_name.len(),
726 unknown_file_metadata(cx),
727 0,
728 None,
729 )
730 };
731
04454e1e 732 DINodeCreationResult::new(typedef_di_node, false)
d9579d0f
AL
733}
734
5e7ed085 735fn build_foreign_type_di_node<'ll, 'tcx>(
b7449926
XL
736 cx: &CodegenCx<'ll, 'tcx>,
737 t: Ty<'tcx>,
5e7ed085
FG
738 unique_type_id: UniqueTypeId<'tcx>,
739) -> DINodeCreationResult<'ll> {
740 debug!("build_foreign_type_di_node: {:?}", t);
741
742 let &ty::Foreign(def_id) = unique_type_id.expect_ty().kind() else {
743 bug!("build_foreign_type_di_node() called with unexpected type: {:?}", unique_type_id.expect_ty());
744 };
abe05a73 745
5e7ed085 746 build_type_with_children(
5099ac24 747 cx,
5e7ed085
FG
748 type_map::stub(
749 cx,
750 Stub::Struct,
751 unique_type_id,
752 &compute_debuginfo_type_name(cx.tcx, t, false),
753 cx.size_and_align_of(t),
754 Some(get_namespace_for_item(cx, def_id)),
755 DIFlags::FlagZero,
756 ),
757 |_, _| smallvec![],
758 NO_GENERICS,
5099ac24 759 )
d9579d0f
AL
760}
761
5e7ed085
FG
762fn build_param_type_di_node<'ll, 'tcx>(
763 cx: &CodegenCx<'ll, 'tcx>,
764 t: Ty<'tcx>,
765) -> DINodeCreationResult<'ll> {
766 debug!("build_param_type_di_node: {:?}", t);
3dfed10e 767 let name = format!("{:?}", t);
5e7ed085
FG
768 DINodeCreationResult {
769 di_node: unsafe {
770 llvm::LLVMRustDIBuilderCreateBasicType(
771 DIB(cx),
772 name.as_ptr().cast(),
773 name.len(),
774 Size::ZERO.bits(),
775 DW_ATE_unsigned,
776 )
777 },
778 already_stored_in_typemap: false,
3dfed10e
XL
779 }
780}
781
5e7ed085 782pub fn build_compile_unit_di_node<'ll, 'tcx>(
a2a8927a 783 tcx: TyCtxt<'tcx>,
dc9dc135 784 codegen_unit_name: &str,
5e7ed085 785 debug_context: &CodegenUnitDebugContext<'ll, 'tcx>,
dc9dc135 786) -> &'ll DIDescriptor {
2c00a5a8 787 let mut name_in_debuginfo = match tcx.sess.local_crate_source_file {
7cac9316 788 Some(ref path) => path.clone(),
a2a8927a 789 None => PathBuf::from(tcx.crate_name(LOCAL_CRATE).as_str()),
d9579d0f
AL
790 };
791
a2a8927a
XL
792 // To avoid breaking split DWARF, we need to ensure that each codegen unit
793 // has a unique `DW_AT_name`. This is because there's a remote chance that
794 // different codegen units for the same module will have entirely
795 // identical DWARF entries for the purpose of the DWO ID, which would
796 // violate Appendix F ("Split Dwarf Object Files") of the DWARF 5
797 // specification. LLVM uses the algorithm specified in section 7.32 "Type
798 // Signature Computation" to compute the DWO ID, which does not include
799 // any fields that would distinguish compilation units. So we must embed
800 // the codegen unit name into the `DW_AT_name`. (Issue #88521.)
801 //
802 // Additionally, the OSX linker has an idiosyncrasy where it will ignore
803 // some debuginfo if multiple object files with the same `DW_AT_name` are
804 // linked together.
805 //
806 // As a workaround for these two issues, we generate unique names for each
807 // object file. Those do not correspond to an actual source file but that
808 // is harmless.
809 name_in_debuginfo.push("@");
810 name_in_debuginfo.push(codegen_unit_name);
7cac9316 811
5e7ed085 812 debug!("build_compile_unit_di_node: {:?}", name_in_debuginfo);
dfeec247
XL
813 let rustc_producer =
814 format!("rustc version {}", option_env!("CFG_VERSION").expect("CFG_VERSION"),);
cc61c64b 815 // FIXME(#41252) Remove "clang LLVM" if we can get GDB and LLVM to play nice.
416331ca 816 let producer = format!("clang LLVM ({})", rustc_producer);
d9579d0f 817
b7449926 818 let name_in_debuginfo = name_in_debuginfo.to_string_lossy();
94222f64 819 let work_dir = tcx.sess.opts.working_dir.to_string_lossy(FileNameDisplayPreference::Remapped);
d9579d0f 820 let flags = "\0";
17df50a5 821 let output_filenames = tcx.output_filenames(());
5869c6ff 822 let split_name = if tcx.sess.target_can_use_split_dwarf() {
17df50a5 823 output_filenames
a2a8927a
XL
824 .split_dwarf_path(
825 tcx.sess.split_debuginfo(),
064997fb 826 tcx.sess.opts.unstable_opts.split_dwarf_kind,
a2a8927a
XL
827 Some(codegen_unit_name),
828 )
829 // We get a path relative to the working directory from split_dwarf_path
830 .map(|f| tcx.sess.source_map().path_mapping().map_prefix(f).0)
5869c6ff
XL
831 } else {
832 None
833 }
834 .unwrap_or_default();
fc512014 835 let split_name = split_name.to_str().unwrap();
48663c56
XL
836
837 // FIXME(#60020):
838 //
839 // This should actually be
840 //
60c5eb7d 841 // let kind = DebugEmissionKind::from_generic(tcx.sess.opts.debuginfo);
48663c56 842 //
60c5eb7d 843 // That is, we should set LLVM's emission kind to `LineTablesOnly` if
48663c56
XL
844 // we are compiling with "limited" debuginfo. However, some of the
845 // existing tools relied on slightly more debuginfo being generated than
846 // would be the case with `LineTablesOnly`, and we did not want to break
847 // these tools in a "drive-by fix", without a good idea or plan about
848 // what limited debuginfo should exactly look like. So for now we keep
849 // the emission kind as `FullDebug`.
850 //
851 // See https://github.com/rust-lang/rust/issues/60020 for details.
852 let kind = DebugEmissionKind::FullDebug;
853 assert!(tcx.sess.opts.debuginfo != DebugInfo::None);
8bb4bdeb
XL
854
855 unsafe {
6a06907d 856 let compile_unit_file = llvm::LLVMRustDIBuilderCreateFile(
dfeec247 857 debug_context.builder,
74b04a01
XL
858 name_in_debuginfo.as_ptr().cast(),
859 name_in_debuginfo.len(),
6a06907d
XL
860 work_dir.as_ptr().cast(),
861 work_dir.len(),
ba9703b0
XL
862 llvm::ChecksumKind::None,
863 ptr::null(),
864 0,
dfeec247 865 );
8bb4bdeb 866
041b39d2 867 let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit(
5bcae85e 868 debug_context.builder,
d9579d0f 869 DW_LANG_RUST,
6a06907d 870 compile_unit_file,
74b04a01
XL
871 producer.as_ptr().cast(),
872 producer.len(),
2c00a5a8 873 tcx.sess.opts.optimize != config::OptLevel::No,
e74abb32 874 flags.as_ptr().cast(),
d9579d0f 875 0,
6a06907d
XL
876 // NB: this doesn't actually have any perceptible effect, it seems. LLVM will instead
877 // put the path supplied to `MCSplitDwarfFile` into the debug info of the final
878 // output(s).
e74abb32 879 split_name.as_ptr().cast(),
74b04a01 880 split_name.len(),
dfeec247 881 kind,
fc512014 882 0,
064997fb 883 tcx.sess.opts.unstable_opts.split_dwarf_inlining,
dfeec247 884 );
041b39d2 885
064997fb 886 if tcx.sess.opts.unstable_opts.profile {
dfeec247
XL
887 let cu_desc_metadata =
888 llvm::LLVMRustMetadataAsValue(debug_context.llcontext, unit_metadata);
17df50a5 889 let default_gcda_path = &output_filenames.with_extension("gcda");
f9f354fc 890 let gcda_path =
064997fb 891 tcx.sess.opts.unstable_opts.profile_emit.as_ref().unwrap_or(default_gcda_path);
041b39d2
XL
892
893 let gcov_cu_info = [
17df50a5 894 path_to_mdstring(debug_context.llcontext, &output_filenames.with_extension("gcno")),
c295e0f8 895 path_to_mdstring(debug_context.llcontext, gcda_path),
041b39d2
XL
896 cu_desc_metadata,
897 ];
dfeec247
XL
898 let gcov_metadata = llvm::LLVMMDNodeInContext(
899 debug_context.llcontext,
900 gcov_cu_info.as_ptr(),
901 gcov_cu_info.len() as c_uint,
902 );
041b39d2 903
6a06907d 904 let llvm_gcov_ident = cstr!("llvm.gcov");
dfeec247
XL
905 llvm::LLVMAddNamedMetadataOperand(
906 debug_context.llmod,
907 llvm_gcov_ident.as_ptr(),
908 gcov_metadata,
909 );
041b39d2
XL
910 }
911
cdc7bbd5 912 // Insert `llvm.ident` metadata on the wasm targets since that will
416331ca 913 // get hooked up to the "producer" sections `processed-by` information.
cdc7bbd5 914 if tcx.sess.target.is_like_wasm {
416331ca
XL
915 let name_metadata = llvm::LLVMMDStringInContext(
916 debug_context.llcontext,
e74abb32 917 rustc_producer.as_ptr().cast(),
416331ca
XL
918 rustc_producer.as_bytes().len() as c_uint,
919 );
920 llvm::LLVMAddNamedMetadataOperand(
921 debug_context.llmod,
6a06907d 922 cstr!("llvm.ident").as_ptr(),
416331ca
XL
923 llvm::LLVMMDNodeInContext(debug_context.llcontext, &name_metadata, 1),
924 );
925 }
926
041b39d2 927 return unit_metadata;
d9579d0f 928 };
041b39d2 929
a2a8927a 930 fn path_to_mdstring<'ll>(llcx: &'ll llvm::Context, path: &Path) -> &'ll Value {
a1dfa0c6 931 let path_str = path_to_c_string(path);
041b39d2 932 unsafe {
dfeec247
XL
933 llvm::LLVMMDStringInContext(
934 llcx,
935 path_str.as_ptr(),
936 path_str.as_bytes().len() as c_uint,
937 )
041b39d2
XL
938 }
939 }
d9579d0f
AL
940}
941
5e7ed085
FG
942/// Creates a `DW_TAG_member` entry inside the DIE represented by the given `type_di_node`.
943fn build_field_di_node<'ll, 'tcx>(
944 cx: &CodegenCx<'ll, 'tcx>,
945 owner: &'ll DIScope,
946 name: &str,
947 size_and_align: (Size, Align),
ff7c6d11 948 offset: Size,
476ff2be 949 flags: DIFlags,
5e7ed085
FG
950 type_di_node: &'ll DIType,
951) -> &'ll DIType {
952 unsafe {
953 llvm::LLVMRustDIBuilderCreateMemberType(
954 DIB(cx),
955 owner,
956 name.as_ptr().cast(),
957 name.len(),
958 unknown_file_metadata(cx),
959 UNKNOWN_LINE_NUMBER,
960 size_and_align.0.bits(),
961 size_and_align.1.bits() as u32,
962 offset.bits(),
963 flags,
964 type_di_node,
965 )
48663c56
XL
966 }
967}
968
5e7ed085
FG
969/// Creates the debuginfo node for a Rust struct type. Maybe be a regular struct or a tuple-struct.
970fn build_struct_type_di_node<'ll, 'tcx>(
971 cx: &CodegenCx<'ll, 'tcx>,
972 unique_type_id: UniqueTypeId<'tcx>,
973) -> DINodeCreationResult<'ll> {
974 let struct_type = unique_type_id.expect_ty();
975 let ty::Adt(adt_def, _) = struct_type.kind() else {
976 bug!("build_struct_type_di_node() called with non-struct-type: {:?}", struct_type);
977 };
978 debug_assert!(adt_def.is_struct());
979 let containing_scope = get_namespace_for_item(cx, adt_def.did());
980 let struct_type_and_layout = cx.layout_of(struct_type);
981 let variant_def = adt_def.non_enum_variant();
d9579d0f 982
5e7ed085
FG
983 type_map::build_type_with_children(
984 cx,
985 type_map::stub(
986 cx,
987 Stub::Struct,
988 unique_type_id,
989 &compute_debuginfo_type_name(cx.tcx, struct_type, false),
990 size_and_align_of(struct_type_and_layout),
991 Some(containing_scope),
992 DIFlags::FlagZero,
993 ),
994 // Fields:
995 |cx, owner| {
996 variant_def
997 .fields
998 .iter()
999 .enumerate()
1000 .map(|(i, f)| {
1001 let field_name = if variant_def.ctor_kind == CtorKind::Fn {
1002 // This is a tuple struct
1003 tuple_field_name(i)
1004 } else {
1005 // This is struct with named fields
1006 Cow::Borrowed(f.name.as_str())
1007 };
1008 let field_layout = struct_type_and_layout.field(cx, i);
1009 build_field_di_node(
1010 cx,
1011 owner,
1012 &field_name[..],
1013 (field_layout.size, field_layout.align.abi),
1014 struct_type_and_layout.fields.offset(i),
1015 DIFlags::FlagZero,
1016 type_di_node(cx, field_layout.ty),
1017 )
1018 })
1019 .collect()
1020 },
1021 |cx| build_generic_type_param_di_nodes(cx, struct_type),
1022 )
d9579d0f
AL
1023}
1024
1025//=-----------------------------------------------------------------------------
5e7ed085 1026// Tuples
d9579d0f
AL
1027//=-----------------------------------------------------------------------------
1028
5e7ed085
FG
1029/// Returns names of captured upvars for closures and generators.
1030///
1031/// Here are some examples:
1032/// - `name__field1__field2` when the upvar is captured by value.
1033/// - `_ref__name__field` when the upvar is captured by reference.
1034///
1035/// For generators this only contains upvars that are shared by all states.
1036fn closure_saved_names_of_captured_variables(tcx: TyCtxt<'_>, def_id: DefId) -> SmallVec<String> {
1037 let body = tcx.optimized_mir(def_id);
94222f64
XL
1038
1039 body.var_debug_info
1040 .iter()
1041 .filter_map(|var| {
1042 let is_ref = match var.value {
1043 mir::VarDebugInfoContents::Place(place) if place.local == mir::Local::new(1) => {
1044 // The projection is either `[.., Field, Deref]` or `[.., Field]`. It
1045 // implies whether the variable is captured by value or by reference.
1046 matches!(place.projection.last().unwrap(), mir::ProjectionElem::Deref)
1047 }
1048 _ => return None,
1049 };
1050 let prefix = if is_ref { "_ref__" } else { "" };
a2a8927a 1051 Some(prefix.to_owned() + var.name.as_str())
94222f64 1052 })
5e7ed085 1053 .collect()
94222f64
XL
1054}
1055
5e7ed085
FG
1056/// Builds the DW_TAG_member debuginfo nodes for the upvars of a closure or generator.
1057/// For a generator, this will handle upvars shared by all states.
1058fn build_upvar_field_di_nodes<'ll, 'tcx>(
1059 cx: &CodegenCx<'ll, 'tcx>,
1060 closure_or_generator_ty: Ty<'tcx>,
1061 closure_or_generator_di_node: &'ll DIType,
1062) -> SmallVec<&'ll DIType> {
1063 let (&def_id, up_var_tys) = match closure_or_generator_ty.kind() {
1064 ty::Generator(def_id, substs, _) => {
1065 let upvar_tys: SmallVec<_> = substs.as_generator().prefix_tys().collect();
1066 (def_id, upvar_tys)
1067 }
1068 ty::Closure(def_id, substs) => {
1069 let upvar_tys: SmallVec<_> = substs.as_closure().upvar_tys().collect();
1070 (def_id, upvar_tys)
1071 }
1072 _ => {
1073 bug!(
1074 "build_upvar_field_di_nodes() called with non-closure-or-generator-type: {:?}",
1075 closure_or_generator_ty
1076 )
1077 }
1078 };
1a4d82fc 1079
5e7ed085
FG
1080 debug_assert!(
1081 up_var_tys
dfeec247 1082 .iter()
5e7ed085
FG
1083 .all(|&t| t == cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t))
1084 );
1085
1086 let capture_names = closure_saved_names_of_captured_variables(cx.tcx, def_id);
1087 let layout = cx.layout_of(closure_or_generator_ty);
1088
1089 up_var_tys
1090 .into_iter()
1091 .zip(capture_names.iter())
1092 .enumerate()
1093 .map(|(index, (up_var_ty, capture_name))| {
1094 build_field_di_node(
1095 cx,
1096 closure_or_generator_di_node,
1097 capture_name,
1098 cx.size_and_align_of(up_var_ty),
1099 layout.fields.offset(index),
1100 DIFlags::FlagZero,
1101 type_di_node(cx, up_var_ty),
1102 )
1103 })
1104 .collect()
1a4d82fc
JJ
1105}
1106
5e7ed085
FG
1107/// Builds the DW_TAG_structure_type debuginfo node for a Rust tuple type.
1108fn build_tuple_type_di_node<'ll, 'tcx>(
b7449926 1109 cx: &CodegenCx<'ll, 'tcx>,
5e7ed085
FG
1110 unique_type_id: UniqueTypeId<'tcx>,
1111) -> DINodeCreationResult<'ll> {
1112 let tuple_type = unique_type_id.expect_ty();
1113 let &ty::Tuple(component_types) = tuple_type.kind() else {
1114 bug!("build_tuple_type_di_node() called with non-tuple-type: {:?}", tuple_type)
1115 };
a1dfa0c6 1116
5e7ed085
FG
1117 let tuple_type_and_layout = cx.layout_of(tuple_type);
1118 let type_name = compute_debuginfo_type_name(cx.tcx, tuple_type, false);
1119
1120 type_map::build_type_with_children(
d9579d0f 1121 cx,
5e7ed085
FG
1122 type_map::stub(
1123 cx,
1124 Stub::Struct,
1125 unique_type_id,
1126 &type_name,
1127 size_and_align_of(tuple_type_and_layout),
1128 NO_SCOPE_METADATA,
1129 DIFlags::FlagZero,
1130 ),
1131 // Fields:
1132 |cx, tuple_di_node| {
1133 component_types
1134 .into_iter()
1135 .enumerate()
1136 .map(|(index, component_type)| {
1137 build_field_di_node(
1138 cx,
1139 tuple_di_node,
1140 &tuple_field_name(index),
1141 cx.size_and_align_of(component_type),
1142 tuple_type_and_layout.fields.offset(index),
1143 DIFlags::FlagZero,
1144 type_di_node(cx, component_type),
1145 )
1146 })
1147 .collect()
1148 },
1149 NO_GENERICS,
d9579d0f 1150 )
1a4d82fc
JJ
1151}
1152
5e7ed085
FG
1153/// Builds the debuginfo node for a closure environment.
1154fn build_closure_env_di_node<'ll, 'tcx>(
1155 cx: &CodegenCx<'ll, 'tcx>,
1156 unique_type_id: UniqueTypeId<'tcx>,
1157) -> DINodeCreationResult<'ll> {
1158 let closure_env_type = unique_type_id.expect_ty();
1159 let &ty::Closure(def_id, _substs) = closure_env_type.kind() else {
1160 bug!("build_closure_env_di_node() called with non-closure-type: {:?}", closure_env_type)
1161 };
1162 let containing_scope = get_namespace_for_item(cx, def_id);
1163 let type_name = compute_debuginfo_type_name(cx.tcx, closure_env_type, false);
9e0c209e 1164
5e7ed085
FG
1165 type_map::build_type_with_children(
1166 cx,
1167 type_map::stub(
1168 cx,
1169 Stub::Struct,
1170 unique_type_id,
1171 &type_name,
1172 cx.size_and_align_of(closure_env_type),
1173 Some(containing_scope),
1174 DIFlags::FlagZero,
1175 ),
1176 // Fields:
1177 |cx, owner| build_upvar_field_di_nodes(cx, closure_env_type, owner),
1178 NO_GENERICS,
1179 )
9e0c209e
SL
1180}
1181
5e7ed085
FG
1182/// Build the debuginfo node for a Rust `union` type.
1183fn build_union_type_di_node<'ll, 'tcx>(
b7449926 1184 cx: &CodegenCx<'ll, 'tcx>,
5e7ed085
FG
1185 unique_type_id: UniqueTypeId<'tcx>,
1186) -> DINodeCreationResult<'ll> {
1187 let union_type = unique_type_id.expect_ty();
1188 let (union_def_id, variant_def) = match union_type.kind() {
1189 ty::Adt(def, _) => (def.did(), def.non_enum_variant()),
1190 _ => bug!("build_union_type_di_node on a non-ADT"),
9e0c209e 1191 };
041b39d2 1192 let containing_scope = get_namespace_for_item(cx, union_def_id);
5e7ed085
FG
1193 let union_ty_and_layout = cx.layout_of(union_type);
1194 let type_name = compute_debuginfo_type_name(cx.tcx, union_type, false);
9e0c209e 1195
5e7ed085 1196 type_map::build_type_with_children(
9e0c209e 1197 cx,
5e7ed085
FG
1198 type_map::stub(
1199 cx,
1200 Stub::Union,
1201 unique_type_id,
1202 &type_name,
1203 size_and_align_of(union_ty_and_layout),
1204 Some(containing_scope),
1205 DIFlags::FlagZero,
1206 ),
1207 // Fields:
1208 |cx, owner| {
1209 variant_def
1210 .fields
1211 .iter()
1212 .enumerate()
1213 .map(|(i, f)| {
1214 let field_layout = union_ty_and_layout.field(cx, i);
1215 build_field_di_node(
1216 cx,
1217 owner,
1218 f.name.as_str(),
1219 size_and_align_of(field_layout),
1220 Size::ZERO,
1221 DIFlags::FlagZero,
1222 type_di_node(cx, field_layout.ty),
1223 )
1224 })
1225 .collect()
1226 },
1227 // Generics:
1228 |cx| build_generic_type_param_di_nodes(cx, union_type),
9e0c209e
SL
1229 )
1230}
1a4d82fc 1231
60c5eb7d
XL
1232// FIXME(eddyb) maybe precompute this? Right now it's computed once
1233// per generator monomorphization, but it doesn't depend on substs.
a2a8927a 1234fn generator_layout_and_saved_local_names<'tcx>(
60c5eb7d
XL
1235 tcx: TyCtxt<'tcx>,
1236 def_id: DefId,
f9f354fc 1237) -> (&'tcx GeneratorLayout<'tcx>, IndexVec<mir::GeneratorSavedLocal, Option<Symbol>>) {
60c5eb7d 1238 let body = tcx.optimized_mir(def_id);
6a06907d 1239 let generator_layout = body.generator_layout().unwrap();
dfeec247 1240 let mut generator_saved_local_names = IndexVec::from_elem(None, &generator_layout.field_tys);
60c5eb7d 1241
dfeec247 1242 let state_arg = mir::Local::new(1);
60c5eb7d 1243 for var in &body.var_debug_info {
5099ac24 1244 let mir::VarDebugInfoContents::Place(place) = &var.value else { continue };
fc512014 1245 if place.local != state_arg {
60c5eb7d
XL
1246 continue;
1247 }
fc512014 1248 match place.projection[..] {
60c5eb7d
XL
1249 [
1250 // Deref of the `Pin<&mut Self>` state argument.
1251 mir::ProjectionElem::Field(..),
1252 mir::ProjectionElem::Deref,
60c5eb7d
XL
1253 // Field of a variant of the state.
1254 mir::ProjectionElem::Downcast(_, variant),
1255 mir::ProjectionElem::Field(field, _),
1256 ] => {
a2a8927a
XL
1257 let name = &mut generator_saved_local_names
1258 [generator_layout.variant_fields[variant][field]];
60c5eb7d
XL
1259 if name.is_none() {
1260 name.replace(var.name);
1261 }
1262 }
1263 _ => {}
1264 }
1265 }
1266 (generator_layout, generator_saved_local_names)
1267}
1268
60c5eb7d 1269/// Computes the type parameters for a type, if any, for the given metadata.
5e7ed085
FG
1270fn build_generic_type_param_di_nodes<'ll, 'tcx>(
1271 cx: &CodegenCx<'ll, 'tcx>,
1272 ty: Ty<'tcx>,
1273) -> SmallVec<&'ll DIType> {
1b1a35ee 1274 if let ty::Adt(def, substs) = *ty.kind() {
74b04a01 1275 if substs.types().next().is_some() {
5e7ed085 1276 let generics = cx.tcx.generics_of(def.did());
a1dfa0c6 1277 let names = get_parameter_names(cx, generics);
5e7ed085 1278 let template_params: SmallVec<_> = iter::zip(substs, names)
dfeec247
XL
1279 .filter_map(|(kind, name)| {
1280 if let GenericArgKind::Type(ty) = kind.unpack() {
1281 let actual_type =
1282 cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
5e7ed085 1283 let actual_type_di_node = type_di_node(cx, actual_type);
a2a8927a 1284 let name = name.as_str();
dfeec247 1285 Some(unsafe {
5e7ed085 1286 llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
dfeec247
XL
1287 DIB(cx),
1288 None,
74b04a01
XL
1289 name.as_ptr().cast(),
1290 name.len(),
5e7ed085
FG
1291 actual_type_di_node,
1292 )
dfeec247
XL
1293 })
1294 } else {
1295 None
1296 }
1297 })
1298 .collect();
a1dfa0c6 1299
5e7ed085 1300 return template_params;
a1dfa0c6
XL
1301 }
1302 }
5e7ed085
FG
1303
1304 return smallvec![];
a1dfa0c6 1305
dfeec247
XL
1306 fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec<Symbol> {
1307 let mut names = generics
1308 .parent
6a06907d 1309 .map_or_else(Vec::new, |def_id| get_parameter_names(cx, cx.tcx.generics_of(def_id)));
a1dfa0c6
XL
1310 names.extend(generics.params.iter().map(|param| param.name));
1311 names
d9579d0f
AL
1312 }
1313}
1a4d82fc 1314
d9579d0f
AL
1315/// Creates debug information for the given global variable.
1316///
5e7ed085
FG
1317/// Adds the created debuginfo nodes directly to the crate's IR.
1318pub fn build_global_var_di_node<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId, global: &'ll Value) {
2c00a5a8 1319 if cx.dbg_cx.is_none() {
d9579d0f
AL
1320 return;
1321 }
1a4d82fc 1322
ba9703b0
XL
1323 // Only create type information if full debuginfo is enabled
1324 if cx.sess().opts.debuginfo != DebugInfo::Full {
1325 return;
1326 }
1327
2c00a5a8 1328 let tcx = cx.tcx;
0531ce1d 1329
60c5eb7d
XL
1330 // We may want to remove the namespace scope if we're in an extern block (see
1331 // https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952).
0531ce1d
XL
1332 let var_scope = get_namespace_for_item(cx, def_id);
1333 let span = tcx.def_span(def_id);
1a4d82fc 1334
8faf50e0 1335 let (file_metadata, line_number) = if !span.is_dummy() {
ba9703b0 1336 let loc = cx.lookup_debug_loc(span.lo());
29967ef6 1337 (file_metadata(cx, &loc.file), loc.line)
d9579d0f 1338 } else {
6a06907d 1339 (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
d9579d0f 1340 };
1a4d82fc 1341
0531ce1d 1342 let is_local_to_unit = is_node_local_to_unit(cx, def_id);
3dfed10e 1343 let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx, ty::ParamEnv::reveal_all());
5e7ed085 1344 let type_di_node = type_di_node(cx, variable_type);
a2a8927a
XL
1345 let var_name = tcx.item_name(def_id);
1346 let var_name = var_name.as_str();
3dfed10e 1347 let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id)).name;
74b04a01
XL
1348 // When empty, linkage_name field is omitted,
1349 // which is what we want for no_mangle statics
f035d41b 1350 let linkage_name = if var_name == linkage_name { "" } else { linkage_name };
476ff2be 1351
cc61c64b 1352 let global_align = cx.align_of(variable_type);
476ff2be 1353
d9579d0f 1354 unsafe {
dfeec247
XL
1355 llvm::LLVMRustDIBuilderCreateStaticVariable(
1356 DIB(cx),
1357 Some(var_scope),
74b04a01
XL
1358 var_name.as_ptr().cast(),
1359 var_name.len(),
1360 linkage_name.as_ptr().cast(),
1361 linkage_name.len(),
dfeec247 1362 file_metadata,
6a06907d 1363 line_number,
5e7ed085 1364 type_di_node,
dfeec247
XL
1365 is_local_to_unit,
1366 global,
1367 None,
923072b8 1368 global_align.bits() as u32,
476ff2be 1369 );
d9579d0f
AL
1370 }
1371}
1a4d82fc 1372
c295e0f8 1373/// Generates LLVM debuginfo for a vtable.
5099ac24
FG
1374///
1375/// The vtable type looks like a struct with a field for each function pointer and super-trait
1376/// pointer it contains (plus the `size` and `align` fields).
1377///
1378/// Except for `size`, `align`, and `drop_in_place`, the field names don't try to mirror
1379/// the name of the method they implement. This can be implemented in the future once there
1380/// is a proper disambiguation scheme for dealing with methods from different traits that have
1381/// the same name.
5e7ed085 1382fn build_vtable_type_di_node<'ll, 'tcx>(
c295e0f8
XL
1383 cx: &CodegenCx<'ll, 'tcx>,
1384 ty: Ty<'tcx>,
1385 poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
1386) -> &'ll DIType {
1387 let tcx = cx.tcx;
1388
1389 let vtable_entries = if let Some(poly_trait_ref) = poly_trait_ref {
1390 let trait_ref = poly_trait_ref.with_self_ty(tcx, ty);
1391 let trait_ref = tcx.erase_regions(trait_ref);
1392
1393 tcx.vtable_entries(trait_ref)
1394 } else {
923072b8 1395 TyCtxt::COMMON_VTABLE_ENTRIES
c295e0f8
XL
1396 };
1397
5099ac24
FG
1398 // All function pointers are described as opaque pointers. This could be improved in the future
1399 // by describing them as actual function pointers.
1400 let void_pointer_ty = tcx.mk_imm_ptr(tcx.types.unit);
5e7ed085
FG
1401 let void_pointer_type_di_node = type_di_node(cx, void_pointer_ty);
1402 let usize_di_node = type_di_node(cx, tcx.types.usize);
5099ac24
FG
1403 let (pointer_size, pointer_align) = cx.size_and_align_of(void_pointer_ty);
1404 // If `usize` is not pointer-sized and -aligned then the size and alignment computations
1405 // for the vtable as a whole would be wrong. Let's make sure this holds even on weird
1406 // platforms.
1407 assert_eq!(cx.size_and_align_of(tcx.types.usize), (pointer_size, pointer_align));
1408
1409 let vtable_type_name =
1410 compute_debuginfo_vtable_name(cx.tcx, ty, poly_trait_ref, VTableNameKind::Type);
5e7ed085 1411 let unique_type_id = UniqueTypeId::for_vtable_ty(tcx, ty, poly_trait_ref);
5099ac24
FG
1412 let size = pointer_size * vtable_entries.len() as u64;
1413
1414 // This gets mapped to a DW_AT_containing_type attribute which allows GDB to correlate
1415 // the vtable to the type it is for.
5e7ed085 1416 let vtable_holder = type_di_node(cx, ty);
5099ac24 1417
5e7ed085 1418 build_type_with_children(
5099ac24 1419 cx,
5e7ed085
FG
1420 type_map::stub(
1421 cx,
064997fb 1422 Stub::VTableTy { vtable_holder },
5e7ed085
FG
1423 unique_type_id,
1424 &vtable_type_name,
1425 (size, pointer_align),
1426 NO_SCOPE_METADATA,
1427 DIFlags::FlagArtificial,
1428 ),
1429 |cx, vtable_type_di_node| {
1430 vtable_entries
1431 .iter()
1432 .enumerate()
1433 .filter_map(|(index, vtable_entry)| {
1434 let (field_name, field_type_di_node) = match vtable_entry {
1435 ty::VtblEntry::MetadataDropInPlace => {
1436 ("drop_in_place".to_string(), void_pointer_type_di_node)
1437 }
1438 ty::VtblEntry::Method(_) => {
1439 // Note: This code does not try to give a proper name to each method
1440 // because their might be multiple methods with the same name
1441 // (coming from different traits).
1442 (format!("__method{}", index), void_pointer_type_di_node)
1443 }
1444 ty::VtblEntry::TraitVPtr(_) => {
1445 (format!("__super_trait_ptr{}", index), void_pointer_type_di_node)
1446 }
1447 ty::VtblEntry::MetadataAlign => ("align".to_string(), usize_di_node),
1448 ty::VtblEntry::MetadataSize => ("size".to_string(), usize_di_node),
1449 ty::VtblEntry::Vacant => return None,
1450 };
5099ac24 1451
5e7ed085 1452 let field_offset = pointer_size * index as u64;
c295e0f8 1453
5e7ed085
FG
1454 Some(build_field_di_node(
1455 cx,
1456 vtable_type_di_node,
1457 &field_name,
1458 (pointer_size, pointer_align),
1459 field_offset,
1460 DIFlags::FlagZero,
1461 field_type_di_node,
1462 ))
1463 })
1464 .collect()
1465 },
1466 NO_GENERICS,
1467 )
1468 .di_node
c295e0f8
XL
1469}
1470
923072b8
FG
1471fn vcall_visibility_metadata<'ll, 'tcx>(
1472 cx: &CodegenCx<'ll, 'tcx>,
1473 ty: Ty<'tcx>,
1474 trait_ref: Option<PolyExistentialTraitRef<'tcx>>,
1475 vtable: &'ll Value,
1476) {
1477 enum VCallVisibility {
1478 Public = 0,
1479 LinkageUnit = 1,
1480 TranslationUnit = 2,
1481 }
1482
1483 let Some(trait_ref) = trait_ref else { return };
1484
1485 let trait_ref_self = trait_ref.with_self_ty(cx.tcx, ty);
1486 let trait_ref_self = cx.tcx.erase_regions(trait_ref_self);
1487 let trait_def_id = trait_ref_self.def_id();
1488 let trait_vis = cx.tcx.visibility(trait_def_id);
1489
1490 let cgus = cx.sess().codegen_units();
1491 let single_cgu = cgus == 1;
1492
1493 let lto = cx.sess().lto();
1494
1495 // Since LLVM requires full LTO for the virtual function elimination optimization to apply,
1496 // only the `Lto::Fat` cases are relevant currently.
1497 let vcall_visibility = match (lto, trait_vis, single_cgu) {
1498 // If there is not LTO and the visibility in public, we have to assume that the vtable can
1499 // be seen from anywhere. With multiple CGUs, the vtable is quasi-public.
1500 (Lto::No | Lto::ThinLocal, Visibility::Public, _)
f2b60f7d 1501 | (Lto::No, Visibility::Restricted(_), false) => VCallVisibility::Public,
923072b8
FG
1502 // With LTO and a quasi-public visibility, the usages of the functions of the vtable are
1503 // all known by the `LinkageUnit`.
1504 // FIXME: LLVM only supports this optimization for `Lto::Fat` currently. Once it also
1505 // supports `Lto::Thin` the `VCallVisibility` may have to be adjusted for those.
1506 (Lto::Fat | Lto::Thin, Visibility::Public, _)
f2b60f7d
FG
1507 | (Lto::ThinLocal | Lto::Thin | Lto::Fat, Visibility::Restricted(_), false) => {
1508 VCallVisibility::LinkageUnit
1509 }
923072b8
FG
1510 // If there is only one CGU, private vtables can only be seen by that CGU/translation unit
1511 // and therefore we know of all usages of functions in the vtable.
f2b60f7d 1512 (_, Visibility::Restricted(_), true) => VCallVisibility::TranslationUnit,
923072b8
FG
1513 };
1514
1515 let trait_ref_typeid = typeid_for_trait_ref(cx.tcx, trait_ref);
1516
1517 unsafe {
1518 let typeid = llvm::LLVMMDStringInContext(
1519 cx.llcx,
1520 trait_ref_typeid.as_ptr() as *const c_char,
1521 trait_ref_typeid.as_bytes().len() as c_uint,
1522 );
1523 let v = [cx.const_usize(0), typeid];
1524 llvm::LLVMRustGlobalAddMetadata(
1525 vtable,
1526 llvm::MD_type as c_uint,
1527 llvm::LLVMValueAsMetadata(llvm::LLVMMDNodeInContext(
1528 cx.llcx,
1529 v.as_ptr(),
1530 v.len() as c_uint,
1531 )),
1532 );
1533 let vcall_visibility = llvm::LLVMValueAsMetadata(cx.const_u64(vcall_visibility as u64));
1534 let vcall_visibility_metadata = llvm::LLVMMDNodeInContext2(cx.llcx, &vcall_visibility, 1);
1535 llvm::LLVMGlobalSetMetadata(
1536 vtable,
1537 llvm::MetadataType::MD_vcall_visibility as c_uint,
1538 vcall_visibility_metadata,
1539 );
1540 }
1541}
1542
abe05a73
XL
1543/// Creates debug information for the given vtable, which is for the
1544/// given type.
1545///
1546/// Adds the created metadata nodes directly to the crate's IR.
5e7ed085 1547pub fn create_vtable_di_node<'ll, 'tcx>(
c295e0f8
XL
1548 cx: &CodegenCx<'ll, 'tcx>,
1549 ty: Ty<'tcx>,
1550 poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
1551 vtable: &'ll Value,
1552) {
923072b8
FG
1553 // FIXME(flip1995): The virtual function elimination optimization only works with full LTO in
1554 // LLVM at the moment.
064997fb 1555 if cx.sess().opts.unstable_opts.virtual_function_elimination && cx.sess().lto() == Lto::Fat {
923072b8
FG
1556 vcall_visibility_metadata(cx, ty, poly_trait_ref, vtable);
1557 }
1558
2c00a5a8 1559 if cx.dbg_cx.is_none() {
abe05a73
XL
1560 return;
1561 }
1562
ba9703b0
XL
1563 // Only create type information if full debuginfo is enabled
1564 if cx.sess().opts.debuginfo != DebugInfo::Full {
1565 return;
1566 }
1567
5099ac24
FG
1568 let vtable_name =
1569 compute_debuginfo_vtable_name(cx.tcx, ty, poly_trait_ref, VTableNameKind::GlobalVariable);
5e7ed085 1570 let vtable_type_di_node = build_vtable_type_di_node(cx, ty, poly_trait_ref);
5099ac24 1571 let linkage_name = "";
abe05a73
XL
1572
1573 unsafe {
dfeec247
XL
1574 llvm::LLVMRustDIBuilderCreateStaticVariable(
1575 DIB(cx),
1576 NO_SCOPE_METADATA,
c295e0f8
XL
1577 vtable_name.as_ptr().cast(),
1578 vtable_name.len(),
74b04a01
XL
1579 linkage_name.as_ptr().cast(),
1580 linkage_name.len(),
dfeec247
XL
1581 unknown_file_metadata(cx),
1582 UNKNOWN_LINE_NUMBER,
5e7ed085 1583 vtable_type_di_node,
dfeec247
XL
1584 true,
1585 vtable,
1586 None,
1587 0,
1588 );
abe05a73
XL
1589 }
1590}
a1dfa0c6 1591
60c5eb7d 1592/// Creates an "extension" of an existing `DIScope` into another file.
a2a8927a 1593pub fn extend_scope_to_file<'ll>(
a1dfa0c6
XL
1594 cx: &CodegenCx<'ll, '_>,
1595 scope_metadata: &'ll DIScope,
29967ef6 1596 file: &SourceFile,
a1dfa0c6 1597) -> &'ll DILexicalBlock {
29967ef6 1598 let file_metadata = file_metadata(cx, file);
dfeec247 1599 unsafe { llvm::LLVMRustDIBuilderCreateLexicalBlockFile(DIB(cx), scope_metadata, file_metadata) }
a1dfa0c6 1600}
5e7ed085
FG
1601
1602pub fn tuple_field_name(field_index: usize) -> Cow<'static, str> {
1603 const TUPLE_FIELD_NAMES: [&'static str; 16] = [
1604 "__0", "__1", "__2", "__3", "__4", "__5", "__6", "__7", "__8", "__9", "__10", "__11",
1605 "__12", "__13", "__14", "__15",
1606 ];
1607 TUPLE_FIELD_NAMES
1608 .get(field_index)
1609 .map(|s| Cow::from(*s))
1610 .unwrap_or_else(|| Cow::from(format!("__{}", field_index)))
1611}