1 use self::type_map
::DINodeCreationResult
;
2 use self::type_map
::Stub
;
3 use self::type_map
::UniqueTypeId
;
5 use super::namespace
::mangled_name_of_instance
;
6 use super::type_names
::{compute_debuginfo_type_name, compute_debuginfo_vtable_name}
;
8 create_DIArray
, debug_context
, get_namespace_for_item
, is_node_local_to_unit
, DIB
,
10 use super::CodegenUnitDebugContext
;
13 use crate::common
::CodegenCx
;
14 use crate::debuginfo
::metadata
::type_map
::build_type_with_children
;
15 use crate::debuginfo
::utils
::fat_pointer_kind
;
16 use crate::debuginfo
::utils
::FatPtrKind
;
18 use crate::llvm
::debuginfo
::{
19 DIDescriptor
, DIFile
, DIFlags
, DILexicalBlock
, DIScope
, DIType
, DebugEmissionKind
,
21 use crate::value
::Value
;
24 use rustc_codegen_ssa
::debuginfo
::type_names
::cpp_like_debuginfo
;
25 use rustc_codegen_ssa
::debuginfo
::type_names
::VTableNameKind
;
26 use rustc_codegen_ssa
::traits
::*;
27 use rustc_fs_util
::path_to_c_string
;
28 use rustc_hir
::def
::CtorKind
;
29 use rustc_hir
::def_id
::{DefId, LOCAL_CRATE}
;
30 use rustc_index
::vec
::{Idx, IndexVec}
;
31 use rustc_middle
::bug
;
32 use rustc_middle
::mir
::{self, GeneratorLayout}
;
33 use rustc_middle
::ty
::layout
::{LayoutOf, TyAndLayout}
;
34 use rustc_middle
::ty
::subst
::GenericArgKind
;
35 use rustc_middle
::ty
::{
36 self, AdtKind
, Instance
, ParamEnv
, PolyExistentialTraitRef
, Ty
, TyCtxt
, Visibility
,
38 use rustc_session
::config
::{self, DebugInfo, Lto}
;
39 use rustc_span
::symbol
::Symbol
;
40 use rustc_span
::FileName
;
41 use rustc_span
::{self, FileNameDisplayPreference, SourceFile}
;
42 use rustc_symbol_mangling
::typeid_for_trait_ref
;
43 use rustc_target
::abi
::{Align, Size}
;
44 use smallvec
::smallvec
;
47 use libc
::{c_char, c_longlong, c_uint}
;
49 use std
::fmt
::{self, Write}
;
50 use std
::hash
::{Hash, Hasher}
;
52 use std
::path
::{Path, PathBuf}
;
54 use tracing
::instrument
;
56 impl PartialEq
for llvm
::Metadata
{
57 fn eq(&self, other
: &Self) -> bool
{
62 impl Eq
for llvm
::Metadata {}
64 impl Hash
for llvm
::Metadata
{
65 fn hash
<H
: Hasher
>(&self, hasher
: &mut H
) {
66 (self as *const Self).hash(hasher
);
70 impl fmt
::Debug
for llvm
::Metadata
{
71 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
72 (self as *const Self).fmt(f
)
77 // See http://www.dwarfstd.org/ShowIssue.php?issue=140129.1.
78 const DW_LANG_RUST
: c_uint
= 0x1c;
79 #[allow(non_upper_case_globals)]
80 const DW_ATE_boolean
: c_uint
= 0x02;
81 #[allow(non_upper_case_globals)]
82 const DW_ATE_float
: c_uint
= 0x04;
83 #[allow(non_upper_case_globals)]
84 const DW_ATE_signed
: c_uint
= 0x05;
85 #[allow(non_upper_case_globals)]
86 const DW_ATE_unsigned
: c_uint
= 0x07;
87 #[allow(non_upper_case_globals)]
88 const DW_ATE_UTF
: c_uint
= 0x10;
90 pub(super) const UNKNOWN_LINE_NUMBER
: c_uint
= 0;
91 pub(super) const UNKNOWN_COLUMN_NUMBER
: c_uint
= 0;
93 const NO_SCOPE_METADATA
: Option
<&DIScope
> = None
;
94 /// A function that returns an empty list of generic parameter debuginfo nodes.
95 const NO_GENERICS
: for<'ll
> fn(&CodegenCx
<'ll
, '_
>) -> SmallVec
<&'ll DIType
> = |_
| SmallVec
::new();
97 // SmallVec is used quite a bit in this module, so create a shorthand.
98 // The actual number of elements is not so important.
99 pub type SmallVec
<T
> = smallvec
::SmallVec
<[T
; 16]>;
104 pub(crate) use type_map
::TypeMap
;
106 /// Returns from the enclosing function if the type debuginfo node with the given
107 /// unique ID can be found in the type map.
108 macro_rules
! return_if_di_node_created_in_meantime
{
109 ($cx
: expr
, $unique_type_id
: expr
) => {
110 if let Some(di_node
) = debug_context($cx
).type_map
.di_node_for_unique_id($unique_type_id
) {
111 return DINodeCreationResult
::new(di_node
, true);
116 /// Extract size and alignment from a TyAndLayout.
117 fn size_and_align_of
<'tcx
>(ty_and_layout
: TyAndLayout
<'tcx
>) -> (Size
, Align
) {
118 (ty_and_layout
.size
, ty_and_layout
.align
.abi
)
121 /// Creates debuginfo for a fixed size array (e.g. `[u64; 123]`).
122 /// For slices (that is, "arrays" of unknown size) use [build_slice_type_di_node].
123 fn build_fixed_size_array_di_node
<'ll
, 'tcx
>(
124 cx
: &CodegenCx
<'ll
, 'tcx
>,
125 unique_type_id
: UniqueTypeId
<'tcx
>,
126 array_type
: Ty
<'tcx
>,
127 ) -> DINodeCreationResult
<'ll
> {
128 let ty
::Array(element_type
, len
) = array_type
.kind() else {
129 bug
!("build_fixed_size_array_di_node() called with non-ty::Array type `{:?}`", array_type
)
132 let element_type_di_node
= type_di_node(cx
, *element_type
);
134 return_if_di_node_created_in_meantime
!(cx
, unique_type_id
);
136 let (size
, align
) = cx
.size_and_align_of(array_type
);
138 let upper_bound
= len
.eval_usize(cx
.tcx
, ty
::ParamEnv
::reveal_all()) as c_longlong
;
141 unsafe { Some(llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)) }
;
143 let subscripts
= create_DIArray(DIB(cx
), &[subrange
]);
144 let di_node
= unsafe {
145 llvm
::LLVMRustDIBuilderCreateArrayType(
149 element_type_di_node
,
154 DINodeCreationResult
::new(di_node
, false)
157 /// Creates debuginfo for built-in pointer-like things:
161 /// - ty::Adt in the case it's Box
163 /// At some point we might want to remove the special handling of Box
164 /// and treat it the same as other smart pointers (like Rc, Arc, ...).
165 fn build_pointer_or_reference_di_node
<'ll
, 'tcx
>(
166 cx
: &CodegenCx
<'ll
, 'tcx
>,
168 pointee_type
: Ty
<'tcx
>,
169 unique_type_id
: UniqueTypeId
<'tcx
>,
170 ) -> DINodeCreationResult
<'ll
> {
171 // The debuginfo generated by this function is only valid if `ptr_type` is really just
172 // a (fat) pointer. Make sure it is not called for e.g. `Box<T, NonZSTAllocator>`.
174 cx
.size_and_align_of(ptr_type
),
175 cx
.size_and_align_of(cx
.tcx
.mk_mut_ptr(pointee_type
))
178 let pointee_type_di_node
= type_di_node(cx
, pointee_type
);
180 return_if_di_node_created_in_meantime
!(cx
, unique_type_id
);
182 let (thin_pointer_size
, thin_pointer_align
) =
183 cx
.size_and_align_of(cx
.tcx
.mk_imm_ptr(cx
.tcx
.types
.unit
));
184 let ptr_type_debuginfo_name
= compute_debuginfo_type_name(cx
.tcx
, ptr_type
, true);
186 match fat_pointer_kind(cx
, pointee_type
) {
188 // This is a thin pointer. Create a regular pointer type and give it the correct name.
190 (thin_pointer_size
, thin_pointer_align
),
191 cx
.size_and_align_of(ptr_type
),
192 "ptr_type={}, pointee_type={}",
197 let di_node
= unsafe {
198 llvm
::LLVMRustDIBuilderCreatePointerType(
200 pointee_type_di_node
,
201 thin_pointer_size
.bits(),
202 thin_pointer_align
.bits() as u32,
203 0, // Ignore DWARF address space.
204 ptr_type_debuginfo_name
.as_ptr().cast(),
205 ptr_type_debuginfo_name
.len(),
209 DINodeCreationResult { di_node, already_stored_in_typemap: false }
211 Some(fat_pointer_kind
) => {
212 type_map
::build_type_with_children(
218 &ptr_type_debuginfo_name
,
219 cx
.size_and_align_of(ptr_type
),
224 // FIXME: If this fat pointer is a `Box` then we don't want to use its
225 // type layout and instead use the layout of the raw pointer inside
227 // The proper way to handle this is to not treat Box as a pointer
228 // at all and instead emit regular struct debuginfo for it. We just
229 // need to make sure that we don't break existing debuginfo consumers
230 // by doing that (at least not without a warning period).
232 if ptr_type
.is_box() { cx.tcx.mk_mut_ptr(pointee_type) }
else { ptr_type }
;
234 let layout
= cx
.layout_of(layout_type
);
235 let addr_field
= layout
.field(cx
, abi
::FAT_PTR_ADDR
);
236 let extra_field
= layout
.field(cx
, abi
::FAT_PTR_EXTRA
);
238 let (addr_field_name
, extra_field_name
) = match fat_pointer_kind
{
239 FatPtrKind
::Dyn
=> ("pointer", "vtable"),
240 FatPtrKind
::Slice
=> ("data_ptr", "length"),
243 debug_assert_eq
!(abi
::FAT_PTR_ADDR
, 0);
244 debug_assert_eq
!(abi
::FAT_PTR_EXTRA
, 1);
246 // The data pointer type is a regular, thin pointer, regardless of whether this
247 // is a slice or a trait object.
248 let data_ptr_type_di_node
= unsafe {
249 llvm
::LLVMRustDIBuilderCreatePointerType(
251 pointee_type_di_node
,
252 addr_field
.size
.bits(),
253 addr_field
.align
.abi
.bits() as u32,
254 0, // Ignore DWARF address space.
265 (addr_field
.size
, addr_field
.align
.abi
),
266 layout
.fields
.offset(abi
::FAT_PTR_ADDR
),
268 data_ptr_type_di_node
,
274 (extra_field
.size
, extra_field
.align
.abi
),
275 layout
.fields
.offset(abi
::FAT_PTR_EXTRA
),
277 type_di_node(cx
, extra_field
.ty
),
287 fn build_subroutine_type_di_node
<'ll
, 'tcx
>(
288 cx
: &CodegenCx
<'ll
, 'tcx
>,
289 unique_type_id
: UniqueTypeId
<'tcx
>,
290 ) -> DINodeCreationResult
<'ll
> {
291 // It's possible to create a self-referential
292 // type in Rust by using 'impl trait':
294 // fn foo() -> impl Copy { foo }
296 // Unfortunately LLVM's API does not allow us to create recursive subroutine types.
297 // In order to work around that restriction we place a marker type in the type map,
298 // before creating the actual type. If the actual type is recursive, it will hit the
299 // marker type. So we end up with a type that looks like
301 // fn foo() -> <recursive_type>
303 // Once that is created, we replace the marker in the typemap with the actual type.
306 .unique_id_to_di_node
308 .insert(unique_type_id
, recursion_marker_type_di_node(cx
));
310 let fn_ty
= unique_type_id
.expect_ty();
313 .normalize_erasing_late_bound_regions(ty
::ParamEnv
::reveal_all(), fn_ty
.fn_sig(cx
.tcx
));
315 let signature_di_nodes
: SmallVec
<_
> = iter
::once(
317 match signature
.output().kind() {
318 ty
::Tuple(tys
) if tys
.is_empty() => {
319 // this is a "void" function
322 _
=> Some(type_di_node(cx
, signature
.output())),
327 signature
.inputs().iter().map(|&argument_type
| Some(type_di_node(cx
, argument_type
))),
331 debug_context(cx
).type_map
.unique_id_to_di_node
.borrow_mut().remove(&unique_type_id
);
333 let fn_di_node
= unsafe {
334 llvm
::LLVMRustDIBuilderCreateSubroutineType(
336 create_DIArray(DIB(cx
), &signature_di_nodes
[..]),
340 // This is actually a function pointer, so wrap it in pointer DI.
341 let name
= compute_debuginfo_type_name(cx
.tcx
, fn_ty
, false);
342 let di_node
= unsafe {
343 llvm
::LLVMRustDIBuilderCreatePointerType(
346 cx
.tcx
.data_layout
.pointer_size
.bits(),
347 cx
.tcx
.data_layout
.pointer_align
.abi
.bits() as u32,
348 0, // Ignore DWARF address space.
349 name
.as_ptr().cast(),
354 DINodeCreationResult
::new(di_node
, false)
357 /// Create debuginfo for `dyn SomeTrait` types. Currently these are empty structs
358 /// we with the correct type name (e.g. "dyn SomeTrait<Foo, Item=u32> + Sync").
359 fn build_dyn_type_di_node
<'ll
, 'tcx
>(
360 cx
: &CodegenCx
<'ll
, 'tcx
>,
362 unique_type_id
: UniqueTypeId
<'tcx
>,
363 ) -> DINodeCreationResult
<'ll
> {
364 if let ty
::Dynamic(..) = dyn_type
.kind() {
365 let type_name
= compute_debuginfo_type_name(cx
.tcx
, dyn_type
, true);
366 type_map
::build_type_with_children(
373 cx
.size_and_align_of(dyn_type
),
382 "Only ty::Dynamic is valid for build_dyn_type_di_node(). Found {:?} instead.",
388 /// Create debuginfo for `[T]` and `str`. These are unsized.
390 /// NOTE: We currently emit just emit the debuginfo for the element type here
391 /// (i.e. `T` for slices and `u8` for `str`), so that we end up with
392 /// `*const T` for the `data_ptr` field of the corresponding fat-pointer
393 /// debuginfo of `&[T]`.
395 /// It would be preferable and more accurate if we emitted a DIArray of T
396 /// without an upper bound instead. That is, LLVM already supports emitting
397 /// debuginfo of arrays of unknown size. But GDB currently seems to end up
398 /// in an infinite loop when confronted with such a type.
400 /// As a side effect of the current encoding every instance of a type like
401 /// `struct Foo { unsized_field: [u8] }` will look like
402 /// `struct Foo { unsized_field: u8 }` in debuginfo. If the length of the
403 /// slice is zero, then accessing `unsized_field` in the debugger would
404 /// result in an out-of-bounds access.
405 fn build_slice_type_di_node
<'ll
, 'tcx
>(
406 cx
: &CodegenCx
<'ll
, 'tcx
>,
407 slice_type
: Ty
<'tcx
>,
408 unique_type_id
: UniqueTypeId
<'tcx
>,
409 ) -> DINodeCreationResult
<'ll
> {
410 let element_type
= match slice_type
.kind() {
411 ty
::Slice(element_type
) => *element_type
,
412 ty
::Str
=> cx
.tcx
.types
.u8,
415 "Only ty::Slice is valid for build_slice_type_di_node(). Found {:?} instead.",
421 let element_type_di_node
= type_di_node(cx
, element_type
);
422 return_if_di_node_created_in_meantime
!(cx
, unique_type_id
);
423 DINodeCreationResult { di_node: element_type_di_node, already_stored_in_typemap: false }
426 /// Get the debuginfo node for the given type.
428 /// This function will look up the debuginfo node in the TypeMap. If it can't find it, it
429 /// will create the node by dispatching to the corresponding `build_*_di_node()` function.
430 pub fn type_di_node
<'ll
, 'tcx
>(cx
: &CodegenCx
<'ll
, 'tcx
>, t
: Ty
<'tcx
>) -> &'ll DIType
{
431 let unique_type_id
= UniqueTypeId
::for_ty(cx
.tcx
, t
);
433 if let Some(existing_di_node
) = debug_context(cx
).type_map
.di_node_for_unique_id(unique_type_id
)
435 return existing_di_node
;
438 debug
!("type_di_node: {:?}", t
);
440 let DINodeCreationResult { di_node, already_stored_in_typemap }
= match *t
.kind() {
441 ty
::Never
| ty
::Bool
| ty
::Char
| ty
::Int(_
) | ty
::Uint(_
) | ty
::Float(_
) => {
442 build_basic_type_di_node(cx
, t
)
444 ty
::Tuple(elements
) if elements
.is_empty() => build_basic_type_di_node(cx
, t
),
445 ty
::Array(..) => build_fixed_size_array_di_node(cx
, unique_type_id
, t
),
446 ty
::Slice(_
) | ty
::Str
=> build_slice_type_di_node(cx
, t
, unique_type_id
),
447 ty
::Dynamic(..) => build_dyn_type_di_node(cx
, t
, unique_type_id
),
448 ty
::Foreign(..) => build_foreign_type_di_node(cx
, t
, unique_type_id
),
449 ty
::RawPtr(ty
::TypeAndMut { ty: pointee_type, .. }
) | ty
::Ref(_
, pointee_type
, _
) => {
450 build_pointer_or_reference_di_node(cx
, t
, pointee_type
, unique_type_id
)
452 // Box<T, A> may have a non-ZST allocator A. In that case, we
453 // cannot treat Box<T, A> as just an owned alias of `*mut T`.
454 ty
::Adt(def
, substs
) if def
.is_box() && cx
.layout_of(substs
.type_at(1)).is_zst() => {
455 build_pointer_or_reference_di_node(cx
, t
, t
.boxed_ty(), unique_type_id
)
457 ty
::FnDef(..) | ty
::FnPtr(_
) => build_subroutine_type_di_node(cx
, unique_type_id
),
458 ty
::Closure(..) => build_closure_env_di_node(cx
, unique_type_id
),
459 ty
::Generator(..) => enums
::build_generator_di_node(cx
, unique_type_id
),
460 ty
::Adt(def
, ..) => match def
.adt_kind() {
461 AdtKind
::Struct
=> build_struct_type_di_node(cx
, unique_type_id
),
462 AdtKind
::Union
=> build_union_type_di_node(cx
, unique_type_id
),
463 AdtKind
::Enum
=> enums
::build_enum_type_di_node(cx
, unique_type_id
),
465 ty
::Tuple(_
) => build_tuple_type_di_node(cx
, unique_type_id
),
466 // Type parameters from polymorphized functions.
467 ty
::Param(_
) => build_param_type_di_node(cx
, t
),
468 _
=> bug
!("debuginfo: unexpected type in type_di_node(): {:?}", t
),
472 if already_stored_in_typemap
{
473 // Make sure that we really do have a `TypeMap` entry for the unique type ID.
474 let di_node_for_uid
=
475 match debug_context(cx
).type_map
.di_node_for_unique_id(unique_type_id
) {
476 Some(di_node
) => di_node
,
479 "expected type debuginfo node for unique \
480 type ID '{:?}' to already be in \
481 the `debuginfo::TypeMap` but it \
488 debug_assert_eq
!(di_node_for_uid
as *const _
, di_node
as *const _
);
490 debug_context(cx
).type_map
.insert(unique_type_id
, di_node
);
497 // FIXME(mw): Cache this via a regular UniqueTypeId instead of an extra field in the debug context.
498 fn recursion_marker_type_di_node
<'ll
, 'tcx
>(cx
: &CodegenCx
<'ll
, 'tcx
>) -> &'ll DIType
{
499 *debug_context(cx
).recursion_marker_type
.get_or_init(move || {
501 // The choice of type here is pretty arbitrary -
502 // anything reading the debuginfo for a recursive
503 // type is going to see *something* weird - the only
504 // question is what exactly it will see.
506 // FIXME: the name `<recur_type>` does not fit the naming scheme
509 // FIXME: it might make sense to use an actual pointer type here
510 // so that debuggers can show the address.
511 let name
= "<recur_type>";
512 llvm
::LLVMRustDIBuilderCreateBasicType(
514 name
.as_ptr().cast(),
516 cx
.tcx
.data_layout
.pointer_size
.bits(),
523 fn hex_encode(data
: &[u8]) -> String
{
524 let mut hex_string
= String
::with_capacity(data
.len() * 2);
525 for byte
in data
.iter() {
526 write
!(&mut hex_string
, "{:02x}", byte
).unwrap();
531 pub fn file_metadata
<'ll
>(cx
: &CodegenCx
<'ll
, '_
>, source_file
: &SourceFile
) -> &'ll DIFile
{
532 let cache_key
= Some((source_file
.name_hash
, source_file
.src_hash
));
533 return debug_context(cx
)
537 .or_insert_with(|| alloc_new_file_metadata(cx
, source_file
));
539 #[instrument(skip(cx, source_file), level = "debug")]
540 fn alloc_new_file_metadata
<'ll
>(
541 cx
: &CodegenCx
<'ll
, '_
>,
542 source_file
: &SourceFile
,
544 debug
!(?source_file
.name
);
546 let (directory
, file_name
) = match &source_file
.name
{
547 FileName
::Real(filename
) => {
548 let working_directory
= &cx
.sess().opts
.working_dir
;
549 debug
!(?working_directory
);
555 .to_embeddable_absolute_path(filename
.clone(), working_directory
);
557 // Construct the absolute path of the file
558 let abs_path
= filename
.remapped_path_if_available();
561 if let Ok(rel_path
) =
562 abs_path
.strip_prefix(working_directory
.remapped_path_if_available())
564 // If the compiler's working directory (which also is the DW_AT_comp_dir of
565 // the compilation unit) is a prefix of the path we are about to emit, then
566 // only emit the part relative to the working directory.
567 // Because of path remapping we sometimes see strange things here: `abs_path`
568 // might actually look like a relative path
569 // (e.g. `<crate-name-and-version>/src/lib.rs`), so if we emit it without
570 // taking the working directory into account, downstream tooling will
571 // interpret it as `<working-directory>/<crate-name-and-version>/src/lib.rs`,
572 // which makes no sense. Usually in such cases the working directory will also
573 // be remapped to `<crate-name-and-version>` or some other prefix of the path
574 // we are remapping, so we end up with
575 // `<crate-name-and-version>/<crate-name-and-version>/src/lib.rs`.
576 // By moving the working directory portion into the `directory` part of the
577 // DIFile, we allow LLVM to emit just the relative path for DWARF, while
578 // still emitting the correct absolute path for CodeView.
580 working_directory
.to_string_lossy(FileNameDisplayPreference
::Remapped
),
581 rel_path
.to_string_lossy().into_owned(),
584 ("".into(), abs_path
.to_string_lossy().into_owned())
587 other
=> ("".into(), other
.prefer_remapped().to_string_lossy().into_owned()),
590 let hash_kind
= match source_file
.src_hash
.kind
{
591 rustc_span
::SourceFileHashAlgorithm
::Md5
=> llvm
::ChecksumKind
::MD5
,
592 rustc_span
::SourceFileHashAlgorithm
::Sha1
=> llvm
::ChecksumKind
::SHA1
,
593 rustc_span
::SourceFileHashAlgorithm
::Sha256
=> llvm
::ChecksumKind
::SHA256
,
595 let hash_value
= hex_encode(source_file
.src_hash
.hash_bytes());
598 llvm
::LLVMRustDIBuilderCreateFile(
600 file_name
.as_ptr().cast(),
602 directory
.as_ptr().cast(),
605 hash_value
.as_ptr().cast(),
612 pub fn unknown_file_metadata
<'ll
>(cx
: &CodegenCx
<'ll
, '_
>) -> &'ll DIFile
{
613 debug_context(cx
).created_files
.borrow_mut().entry(None
).or_insert_with(|| unsafe {
614 let file_name
= "<unknown>";
618 llvm
::LLVMRustDIBuilderCreateFile(
620 file_name
.as_ptr().cast(),
622 directory
.as_ptr().cast(),
624 llvm
::ChecksumKind
::None
,
625 hash_value
.as_ptr().cast(),
631 trait MsvcBasicName
{
632 fn msvc_basic_name(self) -> &'
static str;
635 impl MsvcBasicName
for ty
::IntTy
{
636 fn msvc_basic_name(self) -> &'
static str {
638 ty
::IntTy
::Isize
=> "ptrdiff_t",
639 ty
::IntTy
::I8
=> "__int8",
640 ty
::IntTy
::I16
=> "__int16",
641 ty
::IntTy
::I32
=> "__int32",
642 ty
::IntTy
::I64
=> "__int64",
643 ty
::IntTy
::I128
=> "__int128",
648 impl MsvcBasicName
for ty
::UintTy
{
649 fn msvc_basic_name(self) -> &'
static str {
651 ty
::UintTy
::Usize
=> "size_t",
652 ty
::UintTy
::U8
=> "unsigned __int8",
653 ty
::UintTy
::U16
=> "unsigned __int16",
654 ty
::UintTy
::U32
=> "unsigned __int32",
655 ty
::UintTy
::U64
=> "unsigned __int64",
656 ty
::UintTy
::U128
=> "unsigned __int128",
661 impl MsvcBasicName
for ty
::FloatTy
{
662 fn msvc_basic_name(self) -> &'
static str {
664 ty
::FloatTy
::F32
=> "float",
665 ty
::FloatTy
::F64
=> "double",
670 fn build_basic_type_di_node
<'ll
, 'tcx
>(
671 cx
: &CodegenCx
<'ll
, 'tcx
>,
673 ) -> DINodeCreationResult
<'ll
> {
674 debug
!("build_basic_type_di_node: {:?}", t
);
676 // When targeting MSVC, emit MSVC style type names for compatibility with
677 // .natvis visualizers (and perhaps other existing native debuggers?)
678 let cpp_like_debuginfo
= cpp_like_debuginfo(cx
.tcx
);
680 let (name
, encoding
) = match t
.kind() {
681 ty
::Never
=> ("!", DW_ATE_unsigned
),
682 ty
::Tuple(elements
) if elements
.is_empty() => {
683 if cpp_like_debuginfo
{
684 return build_tuple_type_di_node(cx
, UniqueTypeId
::for_ty(cx
.tcx
, t
));
686 ("()", DW_ATE_unsigned
)
689 ty
::Bool
=> ("bool", DW_ATE_boolean
),
690 ty
::Char
=> ("char", DW_ATE_UTF
),
691 ty
::Int(int_ty
) if cpp_like_debuginfo
=> (int_ty
.msvc_basic_name(), DW_ATE_signed
),
692 ty
::Uint(uint_ty
) if cpp_like_debuginfo
=> (uint_ty
.msvc_basic_name(), DW_ATE_unsigned
),
693 ty
::Float(float_ty
) if cpp_like_debuginfo
=> (float_ty
.msvc_basic_name(), DW_ATE_float
),
694 ty
::Int(int_ty
) => (int_ty
.name_str(), DW_ATE_signed
),
695 ty
::Uint(uint_ty
) => (uint_ty
.name_str(), DW_ATE_unsigned
),
696 ty
::Float(float_ty
) => (float_ty
.name_str(), DW_ATE_float
),
697 _
=> bug
!("debuginfo::build_basic_type_di_node - `t` is invalid type"),
700 let ty_di_node
= unsafe {
701 llvm
::LLVMRustDIBuilderCreateBasicType(
703 name
.as_ptr().cast(),
705 cx
.size_of(t
).bits(),
710 if !cpp_like_debuginfo
{
711 return DINodeCreationResult
::new(ty_di_node
, false);
714 let typedef_name
= match t
.kind() {
715 ty
::Int(int_ty
) => int_ty
.name_str(),
716 ty
::Uint(uint_ty
) => uint_ty
.name_str(),
717 ty
::Float(float_ty
) => float_ty
.name_str(),
718 _
=> return DINodeCreationResult
::new(ty_di_node
, false),
721 let typedef_di_node
= unsafe {
722 llvm
::LLVMRustDIBuilderCreateTypedef(
725 typedef_name
.as_ptr().cast(),
727 unknown_file_metadata(cx
),
733 DINodeCreationResult
::new(typedef_di_node
, false)
736 fn build_foreign_type_di_node
<'ll
, 'tcx
>(
737 cx
: &CodegenCx
<'ll
, 'tcx
>,
739 unique_type_id
: UniqueTypeId
<'tcx
>,
740 ) -> DINodeCreationResult
<'ll
> {
741 debug
!("build_foreign_type_di_node: {:?}", t
);
743 let &ty
::Foreign(def_id
) = unique_type_id
.expect_ty().kind() else {
744 bug
!("build_foreign_type_di_node() called with unexpected type: {:?}", unique_type_id
.expect_ty());
747 build_type_with_children(
753 &compute_debuginfo_type_name(cx
.tcx
, t
, false),
754 cx
.size_and_align_of(t
),
755 Some(get_namespace_for_item(cx
, def_id
)),
763 fn build_param_type_di_node
<'ll
, 'tcx
>(
764 cx
: &CodegenCx
<'ll
, 'tcx
>,
766 ) -> DINodeCreationResult
<'ll
> {
767 debug
!("build_param_type_di_node: {:?}", t
);
768 let name
= format
!("{:?}", t
);
769 DINodeCreationResult
{
771 llvm
::LLVMRustDIBuilderCreateBasicType(
773 name
.as_ptr().cast(),
779 already_stored_in_typemap
: false,
783 pub fn build_compile_unit_di_node
<'ll
, 'tcx
>(
785 codegen_unit_name
: &str,
786 debug_context
: &CodegenUnitDebugContext
<'ll
, 'tcx
>,
787 ) -> &'ll DIDescriptor
{
788 let mut name_in_debuginfo
= match tcx
.sess
.local_crate_source_file
{
789 Some(ref path
) => path
.clone(),
790 None
=> PathBuf
::from(tcx
.crate_name(LOCAL_CRATE
).as_str()),
793 // To avoid breaking split DWARF, we need to ensure that each codegen unit
794 // has a unique `DW_AT_name`. This is because there's a remote chance that
795 // different codegen units for the same module will have entirely
796 // identical DWARF entries for the purpose of the DWO ID, which would
797 // violate Appendix F ("Split Dwarf Object Files") of the DWARF 5
798 // specification. LLVM uses the algorithm specified in section 7.32 "Type
799 // Signature Computation" to compute the DWO ID, which does not include
800 // any fields that would distinguish compilation units. So we must embed
801 // the codegen unit name into the `DW_AT_name`. (Issue #88521.)
803 // Additionally, the OSX linker has an idiosyncrasy where it will ignore
804 // some debuginfo if multiple object files with the same `DW_AT_name` are
807 // As a workaround for these two issues, we generate unique names for each
808 // object file. Those do not correspond to an actual source file but that
810 name_in_debuginfo
.push("@");
811 name_in_debuginfo
.push(codegen_unit_name
);
813 debug
!("build_compile_unit_di_node: {:?}", name_in_debuginfo
);
815 format
!("rustc version {}", option_env
!("CFG_VERSION").expect("CFG_VERSION"),);
816 // FIXME(#41252) Remove "clang LLVM" if we can get GDB and LLVM to play nice.
817 let producer
= format
!("clang LLVM ({})", rustc_producer
);
819 let name_in_debuginfo
= name_in_debuginfo
.to_string_lossy();
820 let work_dir
= tcx
.sess
.opts
.working_dir
.to_string_lossy(FileNameDisplayPreference
::Remapped
);
822 let output_filenames
= tcx
.output_filenames(());
823 let split_name
= if tcx
.sess
.target_can_use_split_dwarf() {
826 tcx
.sess
.split_debuginfo(),
827 tcx
.sess
.opts
.debugging_opts
.split_dwarf_kind
,
828 Some(codegen_unit_name
),
830 // We get a path relative to the working directory from split_dwarf_path
831 .map(|f
| tcx
.sess
.source_map().path_mapping().map_prefix(f
).0)
835 .unwrap_or_default();
836 let split_name
= split_name
.to_str().unwrap();
840 // This should actually be
842 // let kind = DebugEmissionKind::from_generic(tcx.sess.opts.debuginfo);
844 // That is, we should set LLVM's emission kind to `LineTablesOnly` if
845 // we are compiling with "limited" debuginfo. However, some of the
846 // existing tools relied on slightly more debuginfo being generated than
847 // would be the case with `LineTablesOnly`, and we did not want to break
848 // these tools in a "drive-by fix", without a good idea or plan about
849 // what limited debuginfo should exactly look like. So for now we keep
850 // the emission kind as `FullDebug`.
852 // See https://github.com/rust-lang/rust/issues/60020 for details.
853 let kind
= DebugEmissionKind
::FullDebug
;
854 assert
!(tcx
.sess
.opts
.debuginfo
!= DebugInfo
::None
);
857 let compile_unit_file
= llvm
::LLVMRustDIBuilderCreateFile(
858 debug_context
.builder
,
859 name_in_debuginfo
.as_ptr().cast(),
860 name_in_debuginfo
.len(),
861 work_dir
.as_ptr().cast(),
863 llvm
::ChecksumKind
::None
,
868 let unit_metadata
= llvm
::LLVMRustDIBuilderCreateCompileUnit(
869 debug_context
.builder
,
872 producer
.as_ptr().cast(),
874 tcx
.sess
.opts
.optimize
!= config
::OptLevel
::No
,
875 flags
.as_ptr().cast(),
877 // NB: this doesn't actually have any perceptible effect, it seems. LLVM will instead
878 // put the path supplied to `MCSplitDwarfFile` into the debug info of the final
880 split_name
.as_ptr().cast(),
884 tcx
.sess
.opts
.debugging_opts
.split_dwarf_inlining
,
887 if tcx
.sess
.opts
.debugging_opts
.profile
{
888 let cu_desc_metadata
=
889 llvm
::LLVMRustMetadataAsValue(debug_context
.llcontext
, unit_metadata
);
890 let default_gcda_path
= &output_filenames
.with_extension("gcda");
892 tcx
.sess
.opts
.debugging_opts
.profile_emit
.as_ref().unwrap_or(default_gcda_path
);
895 path_to_mdstring(debug_context
.llcontext
, &output_filenames
.with_extension("gcno")),
896 path_to_mdstring(debug_context
.llcontext
, gcda_path
),
899 let gcov_metadata
= llvm
::LLVMMDNodeInContext(
900 debug_context
.llcontext
,
901 gcov_cu_info
.as_ptr(),
902 gcov_cu_info
.len() as c_uint
,
905 let llvm_gcov_ident
= cstr
!("llvm.gcov");
906 llvm
::LLVMAddNamedMetadataOperand(
908 llvm_gcov_ident
.as_ptr(),
913 // Insert `llvm.ident` metadata on the wasm targets since that will
914 // get hooked up to the "producer" sections `processed-by` information.
915 if tcx
.sess
.target
.is_like_wasm
{
916 let name_metadata
= llvm
::LLVMMDStringInContext(
917 debug_context
.llcontext
,
918 rustc_producer
.as_ptr().cast(),
919 rustc_producer
.as_bytes().len() as c_uint
,
921 llvm
::LLVMAddNamedMetadataOperand(
923 cstr
!("llvm.ident").as_ptr(),
924 llvm
::LLVMMDNodeInContext(debug_context
.llcontext
, &name_metadata
, 1),
928 return unit_metadata
;
931 fn path_to_mdstring
<'ll
>(llcx
: &'ll llvm
::Context
, path
: &Path
) -> &'ll Value
{
932 let path_str
= path_to_c_string(path
);
934 llvm
::LLVMMDStringInContext(
937 path_str
.as_bytes().len() as c_uint
,
943 /// Creates a `DW_TAG_member` entry inside the DIE represented by the given `type_di_node`.
944 fn build_field_di_node
<'ll
, 'tcx
>(
945 cx
: &CodegenCx
<'ll
, 'tcx
>,
948 size_and_align
: (Size
, Align
),
951 type_di_node
: &'ll DIType
,
954 llvm
::LLVMRustDIBuilderCreateMemberType(
957 name
.as_ptr().cast(),
959 unknown_file_metadata(cx
),
961 size_and_align
.0.bits(),
962 size_and_align
.1.bits() as u32,
970 /// Creates the debuginfo node for a Rust struct type. Maybe be a regular struct or a tuple-struct.
971 fn build_struct_type_di_node
<'ll
, 'tcx
>(
972 cx
: &CodegenCx
<'ll
, 'tcx
>,
973 unique_type_id
: UniqueTypeId
<'tcx
>,
974 ) -> DINodeCreationResult
<'ll
> {
975 let struct_type
= unique_type_id
.expect_ty();
976 let ty
::Adt(adt_def
, _
) = struct_type
.kind() else {
977 bug
!("build_struct_type_di_node() called with non-struct-type: {:?}", struct_type
);
979 debug_assert
!(adt_def
.is_struct());
980 let containing_scope
= get_namespace_for_item(cx
, adt_def
.did());
981 let struct_type_and_layout
= cx
.layout_of(struct_type
);
982 let variant_def
= adt_def
.non_enum_variant();
984 type_map
::build_type_with_children(
990 &compute_debuginfo_type_name(cx
.tcx
, struct_type
, false),
991 size_and_align_of(struct_type_and_layout
),
992 Some(containing_scope
),
1002 let field_name
= if variant_def
.ctor_kind
== CtorKind
::Fn
{
1003 // This is a tuple struct
1006 // This is struct with named fields
1007 Cow
::Borrowed(f
.name
.as_str())
1009 let field_layout
= struct_type_and_layout
.field(cx
, i
);
1010 build_field_di_node(
1014 (field_layout
.size
, field_layout
.align
.abi
),
1015 struct_type_and_layout
.fields
.offset(i
),
1017 type_di_node(cx
, field_layout
.ty
),
1022 |cx
| build_generic_type_param_di_nodes(cx
, struct_type
),
1026 //=-----------------------------------------------------------------------------
1028 //=-----------------------------------------------------------------------------
1030 /// Returns names of captured upvars for closures and generators.
1032 /// Here are some examples:
1033 /// - `name__field1__field2` when the upvar is captured by value.
1034 /// - `_ref__name__field` when the upvar is captured by reference.
1036 /// For generators this only contains upvars that are shared by all states.
1037 fn closure_saved_names_of_captured_variables(tcx
: TyCtxt
<'_
>, def_id
: DefId
) -> SmallVec
<String
> {
1038 let body
= tcx
.optimized_mir(def_id
);
1043 let is_ref
= match var
.value
{
1044 mir
::VarDebugInfoContents
::Place(place
) if place
.local
== mir
::Local
::new(1) => {
1045 // The projection is either `[.., Field, Deref]` or `[.., Field]`. It
1046 // implies whether the variable is captured by value or by reference.
1047 matches
!(place
.projection
.last().unwrap(), mir
::ProjectionElem
::Deref
)
1051 let prefix
= if is_ref { "_ref__" }
else { "" }
;
1052 Some(prefix
.to_owned() + var
.name
.as_str())
1057 /// Builds the DW_TAG_member debuginfo nodes for the upvars of a closure or generator.
1058 /// For a generator, this will handle upvars shared by all states.
1059 fn build_upvar_field_di_nodes
<'ll
, 'tcx
>(
1060 cx
: &CodegenCx
<'ll
, 'tcx
>,
1061 closure_or_generator_ty
: Ty
<'tcx
>,
1062 closure_or_generator_di_node
: &'ll DIType
,
1063 ) -> SmallVec
<&'ll DIType
> {
1064 let (&def_id
, up_var_tys
) = match closure_or_generator_ty
.kind() {
1065 ty
::Generator(def_id
, substs
, _
) => {
1066 let upvar_tys
: SmallVec
<_
> = substs
.as_generator().prefix_tys().collect();
1069 ty
::Closure(def_id
, substs
) => {
1070 let upvar_tys
: SmallVec
<_
> = substs
.as_closure().upvar_tys().collect();
1075 "build_upvar_field_di_nodes() called with non-closure-or-generator-type: {:?}",
1076 closure_or_generator_ty
1084 .all(|&t
| t
== cx
.tcx
.normalize_erasing_regions(ParamEnv
::reveal_all(), t
))
1087 let capture_names
= closure_saved_names_of_captured_variables(cx
.tcx
, def_id
);
1088 let layout
= cx
.layout_of(closure_or_generator_ty
);
1092 .zip(capture_names
.iter())
1094 .map(|(index
, (up_var_ty
, capture_name
))| {
1095 build_field_di_node(
1097 closure_or_generator_di_node
,
1099 cx
.size_and_align_of(up_var_ty
),
1100 layout
.fields
.offset(index
),
1102 type_di_node(cx
, up_var_ty
),
1108 /// Builds the DW_TAG_structure_type debuginfo node for a Rust tuple type.
1109 fn build_tuple_type_di_node
<'ll
, 'tcx
>(
1110 cx
: &CodegenCx
<'ll
, 'tcx
>,
1111 unique_type_id
: UniqueTypeId
<'tcx
>,
1112 ) -> DINodeCreationResult
<'ll
> {
1113 let tuple_type
= unique_type_id
.expect_ty();
1114 let &ty
::Tuple(component_types
) = tuple_type
.kind() else {
1115 bug
!("build_tuple_type_di_node() called with non-tuple-type: {:?}", tuple_type
)
1118 let tuple_type_and_layout
= cx
.layout_of(tuple_type
);
1119 let type_name
= compute_debuginfo_type_name(cx
.tcx
, tuple_type
, false);
1121 type_map
::build_type_with_children(
1128 size_and_align_of(tuple_type_and_layout
),
1133 |cx
, tuple_di_node
| {
1137 .map(|(index
, component_type
)| {
1138 build_field_di_node(
1141 &tuple_field_name(index
),
1142 cx
.size_and_align_of(component_type
),
1143 tuple_type_and_layout
.fields
.offset(index
),
1145 type_di_node(cx
, component_type
),
1154 /// Builds the debuginfo node for a closure environment.
1155 fn build_closure_env_di_node
<'ll
, 'tcx
>(
1156 cx
: &CodegenCx
<'ll
, 'tcx
>,
1157 unique_type_id
: UniqueTypeId
<'tcx
>,
1158 ) -> DINodeCreationResult
<'ll
> {
1159 let closure_env_type
= unique_type_id
.expect_ty();
1160 let &ty
::Closure(def_id
, _substs
) = closure_env_type
.kind() else {
1161 bug
!("build_closure_env_di_node() called with non-closure-type: {:?}", closure_env_type
)
1163 let containing_scope
= get_namespace_for_item(cx
, def_id
);
1164 let type_name
= compute_debuginfo_type_name(cx
.tcx
, closure_env_type
, false);
1166 type_map
::build_type_with_children(
1173 cx
.size_and_align_of(closure_env_type
),
1174 Some(containing_scope
),
1178 |cx
, owner
| build_upvar_field_di_nodes(cx
, closure_env_type
, owner
),
1183 /// Build the debuginfo node for a Rust `union` type.
1184 fn build_union_type_di_node
<'ll
, 'tcx
>(
1185 cx
: &CodegenCx
<'ll
, 'tcx
>,
1186 unique_type_id
: UniqueTypeId
<'tcx
>,
1187 ) -> DINodeCreationResult
<'ll
> {
1188 let union_type
= unique_type_id
.expect_ty();
1189 let (union_def_id
, variant_def
) = match union_type
.kind() {
1190 ty
::Adt(def
, _
) => (def
.did(), def
.non_enum_variant()),
1191 _
=> bug
!("build_union_type_di_node on a non-ADT"),
1193 let containing_scope
= get_namespace_for_item(cx
, union_def_id
);
1194 let union_ty_and_layout
= cx
.layout_of(union_type
);
1195 let type_name
= compute_debuginfo_type_name(cx
.tcx
, union_type
, false);
1197 type_map
::build_type_with_children(
1204 size_and_align_of(union_ty_and_layout
),
1205 Some(containing_scope
),
1215 let field_layout
= union_ty_and_layout
.field(cx
, i
);
1216 build_field_di_node(
1220 size_and_align_of(field_layout
),
1223 type_di_node(cx
, field_layout
.ty
),
1229 |cx
| build_generic_type_param_di_nodes(cx
, union_type
),
1233 // FIXME(eddyb) maybe precompute this? Right now it's computed once
1234 // per generator monomorphization, but it doesn't depend on substs.
1235 fn generator_layout_and_saved_local_names
<'tcx
>(
1238 ) -> (&'tcx GeneratorLayout
<'tcx
>, IndexVec
<mir
::GeneratorSavedLocal
, Option
<Symbol
>>) {
1239 let body
= tcx
.optimized_mir(def_id
);
1240 let generator_layout
= body
.generator_layout().unwrap();
1241 let mut generator_saved_local_names
= IndexVec
::from_elem(None
, &generator_layout
.field_tys
);
1243 let state_arg
= mir
::Local
::new(1);
1244 for var
in &body
.var_debug_info
{
1245 let mir
::VarDebugInfoContents
::Place(place
) = &var
.value
else { continue }
;
1246 if place
.local
!= state_arg
{
1249 match place
.projection
[..] {
1251 // Deref of the `Pin<&mut Self>` state argument.
1252 mir
::ProjectionElem
::Field(..),
1253 mir
::ProjectionElem
::Deref
,
1254 // Field of a variant of the state.
1255 mir
::ProjectionElem
::Downcast(_
, variant
),
1256 mir
::ProjectionElem
::Field(field
, _
),
1258 let name
= &mut generator_saved_local_names
1259 [generator_layout
.variant_fields
[variant
][field
]];
1261 name
.replace(var
.name
);
1267 (generator_layout
, generator_saved_local_names
)
1270 /// Computes the type parameters for a type, if any, for the given metadata.
1271 fn build_generic_type_param_di_nodes
<'ll
, 'tcx
>(
1272 cx
: &CodegenCx
<'ll
, 'tcx
>,
1274 ) -> SmallVec
<&'ll DIType
> {
1275 if let ty
::Adt(def
, substs
) = *ty
.kind() {
1276 if substs
.types().next().is_some() {
1277 let generics
= cx
.tcx
.generics_of(def
.did());
1278 let names
= get_parameter_names(cx
, generics
);
1279 let template_params
: SmallVec
<_
> = iter
::zip(substs
, names
)
1280 .filter_map(|(kind
, name
)| {
1281 if let GenericArgKind
::Type(ty
) = kind
.unpack() {
1283 cx
.tcx
.normalize_erasing_regions(ParamEnv
::reveal_all(), ty
);
1284 let actual_type_di_node
= type_di_node(cx
, actual_type
);
1285 let name
= name
.as_str();
1287 llvm
::LLVMRustDIBuilderCreateTemplateTypeParameter(
1290 name
.as_ptr().cast(),
1292 actual_type_di_node
,
1301 return template_params
;
1307 fn get_parameter_names(cx
: &CodegenCx
<'_
, '_
>, generics
: &ty
::Generics
) -> Vec
<Symbol
> {
1308 let mut names
= generics
1310 .map_or_else(Vec
::new
, |def_id
| get_parameter_names(cx
, cx
.tcx
.generics_of(def_id
)));
1311 names
.extend(generics
.params
.iter().map(|param
| param
.name
));
1316 /// Creates debug information for the given global variable.
1318 /// Adds the created debuginfo nodes directly to the crate's IR.
1319 pub fn build_global_var_di_node
<'ll
>(cx
: &CodegenCx
<'ll
, '_
>, def_id
: DefId
, global
: &'ll Value
) {
1320 if cx
.dbg_cx
.is_none() {
1324 // Only create type information if full debuginfo is enabled
1325 if cx
.sess().opts
.debuginfo
!= DebugInfo
::Full
{
1331 // We may want to remove the namespace scope if we're in an extern block (see
1332 // https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952).
1333 let var_scope
= get_namespace_for_item(cx
, def_id
);
1334 let span
= tcx
.def_span(def_id
);
1336 let (file_metadata
, line_number
) = if !span
.is_dummy() {
1337 let loc
= cx
.lookup_debug_loc(span
.lo());
1338 (file_metadata(cx
, &loc
.file
), loc
.line
)
1340 (unknown_file_metadata(cx
), UNKNOWN_LINE_NUMBER
)
1343 let is_local_to_unit
= is_node_local_to_unit(cx
, def_id
);
1344 let variable_type
= Instance
::mono(cx
.tcx
, def_id
).ty(cx
.tcx
, ty
::ParamEnv
::reveal_all());
1345 let type_di_node
= type_di_node(cx
, variable_type
);
1346 let var_name
= tcx
.item_name(def_id
);
1347 let var_name
= var_name
.as_str();
1348 let linkage_name
= mangled_name_of_instance(cx
, Instance
::mono(tcx
, def_id
)).name
;
1349 // When empty, linkage_name field is omitted,
1350 // which is what we want for no_mangle statics
1351 let linkage_name
= if var_name
== linkage_name { "" }
else { linkage_name }
;
1353 let global_align
= cx
.align_of(variable_type
);
1356 llvm
::LLVMRustDIBuilderCreateStaticVariable(
1359 var_name
.as_ptr().cast(),
1361 linkage_name
.as_ptr().cast(),
1369 global_align
.bits() as u32,
1374 /// Generates LLVM debuginfo for a vtable.
1376 /// The vtable type looks like a struct with a field for each function pointer and super-trait
1377 /// pointer it contains (plus the `size` and `align` fields).
1379 /// Except for `size`, `align`, and `drop_in_place`, the field names don't try to mirror
1380 /// the name of the method they implement. This can be implemented in the future once there
1381 /// is a proper disambiguation scheme for dealing with methods from different traits that have
1383 fn build_vtable_type_di_node
<'ll
, 'tcx
>(
1384 cx
: &CodegenCx
<'ll
, 'tcx
>,
1386 poly_trait_ref
: Option
<ty
::PolyExistentialTraitRef
<'tcx
>>,
1390 let vtable_entries
= if let Some(poly_trait_ref
) = poly_trait_ref
{
1391 let trait_ref
= poly_trait_ref
.with_self_ty(tcx
, ty
);
1392 let trait_ref
= tcx
.erase_regions(trait_ref
);
1394 tcx
.vtable_entries(trait_ref
)
1396 TyCtxt
::COMMON_VTABLE_ENTRIES
1399 // All function pointers are described as opaque pointers. This could be improved in the future
1400 // by describing them as actual function pointers.
1401 let void_pointer_ty
= tcx
.mk_imm_ptr(tcx
.types
.unit
);
1402 let void_pointer_type_di_node
= type_di_node(cx
, void_pointer_ty
);
1403 let usize_di_node
= type_di_node(cx
, tcx
.types
.usize);
1404 let (pointer_size
, pointer_align
) = cx
.size_and_align_of(void_pointer_ty
);
1405 // If `usize` is not pointer-sized and -aligned then the size and alignment computations
1406 // for the vtable as a whole would be wrong. Let's make sure this holds even on weird
1408 assert_eq
!(cx
.size_and_align_of(tcx
.types
.usize), (pointer_size
, pointer_align
));
1410 let vtable_type_name
=
1411 compute_debuginfo_vtable_name(cx
.tcx
, ty
, poly_trait_ref
, VTableNameKind
::Type
);
1412 let unique_type_id
= UniqueTypeId
::for_vtable_ty(tcx
, ty
, poly_trait_ref
);
1413 let size
= pointer_size
* vtable_entries
.len() as u64;
1415 // This gets mapped to a DW_AT_containing_type attribute which allows GDB to correlate
1416 // the vtable to the type it is for.
1417 let vtable_holder
= type_di_node(cx
, ty
);
1419 build_type_with_children(
1423 Stub
::VtableTy { vtable_holder }
,
1426 (size
, pointer_align
),
1428 DIFlags
::FlagArtificial
,
1430 |cx
, vtable_type_di_node
| {
1434 .filter_map(|(index
, vtable_entry
)| {
1435 let (field_name
, field_type_di_node
) = match vtable_entry
{
1436 ty
::VtblEntry
::MetadataDropInPlace
=> {
1437 ("drop_in_place".to_string(), void_pointer_type_di_node
)
1439 ty
::VtblEntry
::Method(_
) => {
1440 // Note: This code does not try to give a proper name to each method
1441 // because their might be multiple methods with the same name
1442 // (coming from different traits).
1443 (format
!("__method{}", index
), void_pointer_type_di_node
)
1445 ty
::VtblEntry
::TraitVPtr(_
) => {
1446 (format
!("__super_trait_ptr{}", index
), void_pointer_type_di_node
)
1448 ty
::VtblEntry
::MetadataAlign
=> ("align".to_string(), usize_di_node
),
1449 ty
::VtblEntry
::MetadataSize
=> ("size".to_string(), usize_di_node
),
1450 ty
::VtblEntry
::Vacant
=> return None
,
1453 let field_offset
= pointer_size
* index
as u64;
1455 Some(build_field_di_node(
1457 vtable_type_di_node
,
1459 (pointer_size
, pointer_align
),
1472 fn vcall_visibility_metadata
<'ll
, 'tcx
>(
1473 cx
: &CodegenCx
<'ll
, 'tcx
>,
1475 trait_ref
: Option
<PolyExistentialTraitRef
<'tcx
>>,
1478 enum VCallVisibility
{
1481 TranslationUnit
= 2,
1484 let Some(trait_ref
) = trait_ref
else { return }
;
1486 let trait_ref_self
= trait_ref
.with_self_ty(cx
.tcx
, ty
);
1487 let trait_ref_self
= cx
.tcx
.erase_regions(trait_ref_self
);
1488 let trait_def_id
= trait_ref_self
.def_id();
1489 let trait_vis
= cx
.tcx
.visibility(trait_def_id
);
1491 let cgus
= cx
.sess().codegen_units();
1492 let single_cgu
= cgus
== 1;
1494 let lto
= cx
.sess().lto();
1496 // Since LLVM requires full LTO for the virtual function elimination optimization to apply,
1497 // only the `Lto::Fat` cases are relevant currently.
1498 let vcall_visibility
= match (lto
, trait_vis
, single_cgu
) {
1499 // If there is not LTO and the visibility in public, we have to assume that the vtable can
1500 // be seen from anywhere. With multiple CGUs, the vtable is quasi-public.
1501 (Lto
::No
| Lto
::ThinLocal
, Visibility
::Public
, _
)
1502 | (Lto
::No
, Visibility
::Restricted(_
) | Visibility
::Invisible
, false) => {
1503 VCallVisibility
::Public
1505 // With LTO and a quasi-public visibility, the usages of the functions of the vtable are
1506 // all known by the `LinkageUnit`.
1507 // FIXME: LLVM only supports this optimization for `Lto::Fat` currently. Once it also
1508 // supports `Lto::Thin` the `VCallVisibility` may have to be adjusted for those.
1509 (Lto
::Fat
| Lto
::Thin
, Visibility
::Public
, _
)
1511 Lto
::ThinLocal
| Lto
::Thin
| Lto
::Fat
,
1512 Visibility
::Restricted(_
) | Visibility
::Invisible
,
1514 ) => VCallVisibility
::LinkageUnit
,
1515 // If there is only one CGU, private vtables can only be seen by that CGU/translation unit
1516 // and therefore we know of all usages of functions in the vtable.
1517 (_
, Visibility
::Restricted(_
) | Visibility
::Invisible
, true) => {
1518 VCallVisibility
::TranslationUnit
1522 let trait_ref_typeid
= typeid_for_trait_ref(cx
.tcx
, trait_ref
);
1525 let typeid
= llvm
::LLVMMDStringInContext(
1527 trait_ref_typeid
.as_ptr() as *const c_char
,
1528 trait_ref_typeid
.as_bytes().len() as c_uint
,
1530 let v
= [cx
.const_usize(0), typeid
];
1531 llvm
::LLVMRustGlobalAddMetadata(
1533 llvm
::MD_type
as c_uint
,
1534 llvm
::LLVMValueAsMetadata(llvm
::LLVMMDNodeInContext(
1540 let vcall_visibility
= llvm
::LLVMValueAsMetadata(cx
.const_u64(vcall_visibility
as u64));
1541 let vcall_visibility_metadata
= llvm
::LLVMMDNodeInContext2(cx
.llcx
, &vcall_visibility
, 1);
1542 llvm
::LLVMGlobalSetMetadata(
1544 llvm
::MetadataType
::MD_vcall_visibility
as c_uint
,
1545 vcall_visibility_metadata
,
1550 /// Creates debug information for the given vtable, which is for the
1553 /// Adds the created metadata nodes directly to the crate's IR.
1554 pub fn create_vtable_di_node
<'ll
, 'tcx
>(
1555 cx
: &CodegenCx
<'ll
, 'tcx
>,
1557 poly_trait_ref
: Option
<ty
::PolyExistentialTraitRef
<'tcx
>>,
1560 // FIXME(flip1995): The virtual function elimination optimization only works with full LTO in
1561 // LLVM at the moment.
1562 if cx
.sess().opts
.debugging_opts
.virtual_function_elimination
&& cx
.sess().lto() == Lto
::Fat
{
1563 vcall_visibility_metadata(cx
, ty
, poly_trait_ref
, vtable
);
1566 if cx
.dbg_cx
.is_none() {
1570 // Only create type information if full debuginfo is enabled
1571 if cx
.sess().opts
.debuginfo
!= DebugInfo
::Full
{
1576 compute_debuginfo_vtable_name(cx
.tcx
, ty
, poly_trait_ref
, VTableNameKind
::GlobalVariable
);
1577 let vtable_type_di_node
= build_vtable_type_di_node(cx
, ty
, poly_trait_ref
);
1578 let linkage_name
= "";
1581 llvm
::LLVMRustDIBuilderCreateStaticVariable(
1584 vtable_name
.as_ptr().cast(),
1586 linkage_name
.as_ptr().cast(),
1588 unknown_file_metadata(cx
),
1589 UNKNOWN_LINE_NUMBER
,
1590 vtable_type_di_node
,
1599 /// Creates an "extension" of an existing `DIScope` into another file.
1600 pub fn extend_scope_to_file
<'ll
>(
1601 cx
: &CodegenCx
<'ll
, '_
>,
1602 scope_metadata
: &'ll DIScope
,
1604 ) -> &'ll DILexicalBlock
{
1605 let file_metadata
= file_metadata(cx
, file
);
1606 unsafe { llvm::LLVMRustDIBuilderCreateLexicalBlockFile(DIB(cx), scope_metadata, file_metadata) }
1609 pub fn tuple_field_name(field_index
: usize) -> Cow
<'
static, str> {
1610 const TUPLE_FIELD_NAMES
: [&'
static str; 16] = [
1611 "__0", "__1", "__2", "__3", "__4", "__5", "__6", "__7", "__8", "__9", "__10", "__11",
1612 "__12", "__13", "__14", "__15",
1616 .map(|s
| Cow
::from(*s
))
1617 .unwrap_or_else(|| Cow
::from(format
!("__{}", field_index
)))