|
|
|
@ -23,9 +23,7 @@
|
|
|
|
|
use rustc_codegen_ssa::debuginfo::type_names::cpp_like_debuginfo;
|
|
|
|
|
use rustc_codegen_ssa::debuginfo::type_names::VTableNameKind;
|
|
|
|
|
use rustc_codegen_ssa::traits::*;
|
|
|
|
|
use rustc_data_structures::fingerprint::Fingerprint;
|
|
|
|
|
use rustc_data_structures::fx::FxHashMap;
|
|
|
|
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
|
|
|
|
use rustc_fs_util::path_to_c_string;
|
|
|
|
|
use rustc_hir::def::CtorKind;
|
|
|
|
|
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
|
|
|
@ -37,7 +35,6 @@
|
|
|
|
|
use rustc_middle::ty::{
|
|
|
|
|
self, AdtKind, GeneratorSubsts, Instance, ParamEnv, Ty, TyCtxt, COMMON_VTABLE_ENTRIES,
|
|
|
|
|
};
|
|
|
|
|
use rustc_query_system::ich::NodeIdHashingMode;
|
|
|
|
|
use rustc_session::config::{self, DebugInfo};
|
|
|
|
|
use rustc_span::symbol::Symbol;
|
|
|
|
|
use rustc_span::FileNameDisplayPreference;
|
|
|
|
@ -45,9 +42,11 @@
|
|
|
|
|
use rustc_target::abi::{Abi, Align, HasDataLayout, Integer, TagEncoding};
|
|
|
|
|
use rustc_target::abi::{Int, Pointer, F32, F64};
|
|
|
|
|
use rustc_target::abi::{Primitive, Size, VariantIdx, Variants};
|
|
|
|
|
use smallvec::SmallVec;
|
|
|
|
|
use tracing::debug;
|
|
|
|
|
|
|
|
|
|
use libc::{c_longlong, c_uint};
|
|
|
|
|
use std::cell::RefCell;
|
|
|
|
|
use std::collections::hash_map::Entry;
|
|
|
|
|
use std::fmt::{self, Write};
|
|
|
|
|
use std::hash::{Hash, Hasher};
|
|
|
|
@ -95,193 +94,127 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
|
pub const NO_SCOPE_METADATA: Option<&DIScope> = None;
|
|
|
|
|
|
|
|
|
|
mod unique_type_id {
|
|
|
|
|
use super::*;
|
|
|
|
|
use rustc_arena::DroplessArena;
|
|
|
|
|
use rustc_data_structures::{
|
|
|
|
|
fingerprint::Fingerprint,
|
|
|
|
|
stable_hasher::{HashStable, NodeIdHashingMode, StableHasher},
|
|
|
|
|
};
|
|
|
|
|
use rustc_middle::ty::{ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt};
|
|
|
|
|
use rustc_target::abi::VariantIdx;
|
|
|
|
|
|
|
|
|
|
#[derive(Copy, Hash, Eq, PartialEq, Clone)]
|
|
|
|
|
pub(super) struct UniqueTypeId(u32);
|
|
|
|
|
|
|
|
|
|
// The `&'static str`s in this type actually point into the arena.
|
|
|
|
|
//
|
|
|
|
|
// The `FxHashMap`+`Vec` pair could be replaced by `FxIndexSet`, but #75278
|
|
|
|
|
// found that to regress performance up to 2% in some cases. This might be
|
|
|
|
|
// revisited after further improvements to `indexmap`.
|
|
|
|
|
#[derive(Default)]
|
|
|
|
|
pub(super) struct TypeIdInterner {
|
|
|
|
|
arena: DroplessArena,
|
|
|
|
|
names: FxHashMap<&'static str, UniqueTypeId>,
|
|
|
|
|
strings: Vec<&'static str>,
|
|
|
|
|
// This type cannot be constructed outside of this module because
|
|
|
|
|
// it has a private field. We make use of this in order to prevent
|
|
|
|
|
// `UniqueTypeId` from being constructed directly, without asserting
|
|
|
|
|
// the preconditions.
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, HashStable)]
|
|
|
|
|
pub struct HiddenZst {
|
|
|
|
|
_inaccessible: (),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl TypeIdInterner {
|
|
|
|
|
#[inline]
|
|
|
|
|
pub(super) fn intern(&mut self, string: &str) -> UniqueTypeId {
|
|
|
|
|
if let Some(&name) = self.names.get(string) {
|
|
|
|
|
return name;
|
|
|
|
|
}
|
|
|
|
|
/// A unique identifier for anything that we create a debuginfo node for.
|
|
|
|
|
/// The types it contains are expected to already be normalized (which
|
|
|
|
|
/// is debug_asserted in the constructors).
|
|
|
|
|
///
|
|
|
|
|
/// Note that there are some things that only show up in debuginfo, like
|
|
|
|
|
/// the separate type descriptions for each enum variant. These get an ID
|
|
|
|
|
/// too because they have their own debuginfo node in LLVM IR.
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, HashStable)]
|
|
|
|
|
pub(super) enum UniqueTypeId<'tcx> {
|
|
|
|
|
/// The ID of a regular type as it shows up at the language level.
|
|
|
|
|
Ty(Ty<'tcx>, HiddenZst),
|
|
|
|
|
/// The ID for the artificial struct type describing a single enum variant.
|
|
|
|
|
Variant(Ty<'tcx>, VariantIdx, HiddenZst),
|
|
|
|
|
/// The ID for the single DW_TAG_variant_part nested inside the top-level
|
|
|
|
|
/// DW_TAG_structure_type that describes enums and generators.
|
|
|
|
|
VariantPart(Ty<'tcx>, HiddenZst),
|
|
|
|
|
/// The ID of the artificial type we create for VTables.
|
|
|
|
|
VTableTy(Ty<'tcx>, Option<PolyExistentialTraitRef<'tcx>>, HiddenZst),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let name = UniqueTypeId(self.strings.len() as u32);
|
|
|
|
|
|
|
|
|
|
// `from_utf8_unchecked` is safe since we just allocated a `&str` which is known to be
|
|
|
|
|
// UTF-8.
|
|
|
|
|
let string: &str =
|
|
|
|
|
unsafe { std::str::from_utf8_unchecked(self.arena.alloc_slice(string.as_bytes())) };
|
|
|
|
|
// It is safe to extend the arena allocation to `'static` because we only access
|
|
|
|
|
// these while the arena is still alive.
|
|
|
|
|
let string: &'static str = unsafe { &*(string as *const str) };
|
|
|
|
|
self.strings.push(string);
|
|
|
|
|
self.names.insert(string, name);
|
|
|
|
|
name
|
|
|
|
|
impl<'tcx> UniqueTypeId<'tcx> {
|
|
|
|
|
pub fn for_ty(tcx: TyCtxt<'tcx>, t: Ty<'tcx>) -> Self {
|
|
|
|
|
debug_assert_eq!(t, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t));
|
|
|
|
|
UniqueTypeId::Ty(t, HiddenZst { _inaccessible: () })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get the symbol as a string. `Symbol::as_str()` should be used in
|
|
|
|
|
// preference to this function.
|
|
|
|
|
pub(super) fn get(&self, symbol: UniqueTypeId) -> &str {
|
|
|
|
|
self.strings[symbol.0 as usize]
|
|
|
|
|
pub fn for_enum_variant(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
enum_ty: Ty<'tcx>,
|
|
|
|
|
variant_idx: VariantIdx,
|
|
|
|
|
) -> Self {
|
|
|
|
|
debug_assert_eq!(
|
|
|
|
|
enum_ty,
|
|
|
|
|
tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty)
|
|
|
|
|
);
|
|
|
|
|
UniqueTypeId::Variant(enum_ty, variant_idx, HiddenZst { _inaccessible: () })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn for_enum_variant_part(tcx: TyCtxt<'tcx>, enum_ty: Ty<'tcx>) -> Self {
|
|
|
|
|
debug_assert_eq!(
|
|
|
|
|
enum_ty,
|
|
|
|
|
tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty)
|
|
|
|
|
);
|
|
|
|
|
UniqueTypeId::VariantPart(enum_ty, HiddenZst { _inaccessible: () })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn for_vtable_ty(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
self_type: Ty<'tcx>,
|
|
|
|
|
implemented_trait: Option<PolyExistentialTraitRef<'tcx>>,
|
|
|
|
|
) -> Self {
|
|
|
|
|
debug_assert_eq!(
|
|
|
|
|
self_type,
|
|
|
|
|
tcx.normalize_erasing_regions(ParamEnv::reveal_all(), self_type)
|
|
|
|
|
);
|
|
|
|
|
debug_assert_eq!(
|
|
|
|
|
implemented_trait,
|
|
|
|
|
tcx.normalize_erasing_regions(ParamEnv::reveal_all(), implemented_trait)
|
|
|
|
|
);
|
|
|
|
|
UniqueTypeId::VTableTy(self_type, implemented_trait, HiddenZst { _inaccessible: () })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Generates a string version of this [UniqueTypeId], which can be used as the `UniqueId`
|
|
|
|
|
/// argument of the various `LLVMRustDIBuilderCreate*Type()` methods.
|
|
|
|
|
///
|
|
|
|
|
/// Right now this takes the form of a hex-encoded opaque hash value.
|
|
|
|
|
pub fn generate_unique_id_string(&self, tcx: TyCtxt<'tcx>) -> String {
|
|
|
|
|
let mut hasher = StableHasher::new();
|
|
|
|
|
let mut hcx = tcx.create_stable_hashing_context();
|
|
|
|
|
hcx.while_hashing_spans(false, |hcx| {
|
|
|
|
|
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
|
|
|
|
|
self.hash_stable(hcx, &mut hasher);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
hasher.finish::<Fingerprint>().to_hex()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
use unique_type_id::*;
|
|
|
|
|
|
|
|
|
|
/// The `TypeMap` is where the `CrateDebugContext` holds the type metadata nodes
|
|
|
|
|
/// created so far. The metadata nodes are indexed by `UniqueTypeId`, and, for
|
|
|
|
|
/// faster lookup, also by `Ty`. The `TypeMap` is responsible for creating
|
|
|
|
|
/// `UniqueTypeId`s.
|
|
|
|
|
/// The `TypeMap` is where the debug context holds the type metadata nodes
|
|
|
|
|
/// created so far. The metadata nodes are indexed by `UniqueTypeId`.
|
|
|
|
|
#[derive(Default)]
|
|
|
|
|
pub struct TypeMap<'ll, 'tcx> {
|
|
|
|
|
/// The `UniqueTypeId`s created so far.
|
|
|
|
|
unique_id_interner: TypeIdInterner,
|
|
|
|
|
/// A map from `UniqueTypeId` to debuginfo metadata for that type. This is a 1:1 mapping.
|
|
|
|
|
unique_id_to_metadata: FxHashMap<UniqueTypeId, &'ll DIType>,
|
|
|
|
|
/// A map from types to debuginfo metadata. This is an N:1 mapping.
|
|
|
|
|
type_to_metadata: FxHashMap<Ty<'tcx>, &'ll DIType>,
|
|
|
|
|
/// A map from types to `UniqueTypeId`. This is an N:1 mapping.
|
|
|
|
|
type_to_unique_id: FxHashMap<Ty<'tcx>, UniqueTypeId>,
|
|
|
|
|
unique_id_to_metadata: RefCell<FxHashMap<UniqueTypeId<'tcx>, &'ll DIType>>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'ll, 'tcx> TypeMap<'ll, 'tcx> {
|
|
|
|
|
/// Adds a Ty to metadata mapping to the TypeMap. The method will fail if
|
|
|
|
|
/// the mapping already exists.
|
|
|
|
|
fn register_type_with_metadata(&mut self, type_: Ty<'tcx>, metadata: &'ll DIType) {
|
|
|
|
|
if self.type_to_metadata.insert(type_, metadata).is_some() {
|
|
|
|
|
bug!("type metadata for `Ty` '{}' is already in the `TypeMap`!", type_);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Removes a `Ty`-to-metadata mapping.
|
|
|
|
|
/// This is useful when computing the metadata for a potentially
|
|
|
|
|
/// recursive type (e.g., a function pointer of the form:
|
|
|
|
|
///
|
|
|
|
|
/// fn foo() -> impl Copy { foo }
|
|
|
|
|
///
|
|
|
|
|
/// This kind of type cannot be properly represented
|
|
|
|
|
/// via LLVM debuginfo. As a workaround,
|
|
|
|
|
/// we register a temporary Ty to metadata mapping
|
|
|
|
|
/// for the function before we compute its actual metadata.
|
|
|
|
|
/// If the metadata computation ends up recursing back to the
|
|
|
|
|
/// original function, it will use the temporary mapping
|
|
|
|
|
/// for the inner self-reference, preventing us from
|
|
|
|
|
/// recursing forever.
|
|
|
|
|
///
|
|
|
|
|
/// This function is used to remove the temporary metadata
|
|
|
|
|
/// mapping after we've computed the actual metadata.
|
|
|
|
|
fn remove_type(&mut self, ty: Ty<'tcx>) {
|
|
|
|
|
if self.type_to_metadata.remove(&ty).is_none() {
|
|
|
|
|
bug!("type metadata `Ty` '{}' is not in the `TypeMap`!", ty);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Adds a `UniqueTypeId` to metadata mapping to the `TypeMap`. The method will
|
|
|
|
|
/// fail if the mapping already exists.
|
|
|
|
|
fn register_unique_id_with_metadata(
|
|
|
|
|
&mut self,
|
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
|
&self,
|
|
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
|
|
|
|
metadata: &'ll DIType,
|
|
|
|
|
) {
|
|
|
|
|
if self.unique_id_to_metadata.insert(unique_type_id, metadata).is_some() {
|
|
|
|
|
bug!(
|
|
|
|
|
"type metadata for unique ID '{}' is already in the `TypeMap`!",
|
|
|
|
|
self.get_unique_type_id_as_string(unique_type_id)
|
|
|
|
|
);
|
|
|
|
|
if self.unique_id_to_metadata.borrow_mut().insert(unique_type_id, metadata).is_some() {
|
|
|
|
|
bug!("type metadata for unique ID '{:?}' is already in the `TypeMap`!", unique_type_id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn find_metadata_for_type(&self, type_: Ty<'tcx>) -> Option<&'ll DIType> {
|
|
|
|
|
self.type_to_metadata.get(&type_).cloned()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn find_metadata_for_unique_id(&self, unique_type_id: UniqueTypeId) -> Option<&'ll DIType> {
|
|
|
|
|
self.unique_id_to_metadata.get(&unique_type_id).cloned()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Gets the string representation of a `UniqueTypeId`. This method will fail if
|
|
|
|
|
/// the ID is unknown.
|
|
|
|
|
fn get_unique_type_id_as_string(&self, unique_type_id: UniqueTypeId) -> &str {
|
|
|
|
|
self.unique_id_interner.get(unique_type_id)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Gets the `UniqueTypeId` for the given type. If the `UniqueTypeId` for the given
|
|
|
|
|
/// type has been requested before, this is just a table lookup. Otherwise, an
|
|
|
|
|
/// ID will be generated and stored for later lookup.
|
|
|
|
|
fn get_unique_type_id_of_type<'a>(
|
|
|
|
|
&mut self,
|
|
|
|
|
cx: &CodegenCx<'a, 'tcx>,
|
|
|
|
|
type_: Ty<'tcx>,
|
|
|
|
|
) -> UniqueTypeId {
|
|
|
|
|
// Let's see if we already have something in the cache.
|
|
|
|
|
if let Some(unique_type_id) = self.type_to_unique_id.get(&type_).cloned() {
|
|
|
|
|
return unique_type_id;
|
|
|
|
|
}
|
|
|
|
|
// If not, generate one.
|
|
|
|
|
|
|
|
|
|
// The hasher we are using to generate the UniqueTypeId. We want
|
|
|
|
|
// something that provides more than the 64 bits of the DefaultHasher.
|
|
|
|
|
let mut hasher = StableHasher::new();
|
|
|
|
|
let mut hcx = cx.tcx.create_stable_hashing_context();
|
|
|
|
|
let type_ = cx.tcx.erase_regions(type_);
|
|
|
|
|
hcx.while_hashing_spans(false, |hcx| {
|
|
|
|
|
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
|
|
|
|
|
type_.hash_stable(hcx, &mut hasher);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
let unique_type_id = hasher.finish::<Fingerprint>().to_hex();
|
|
|
|
|
|
|
|
|
|
let key = self.unique_id_interner.intern(&unique_type_id);
|
|
|
|
|
self.type_to_unique_id.insert(type_, key);
|
|
|
|
|
|
|
|
|
|
key
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Gets the `UniqueTypeId` for an enum variant. Enum variants are not really
|
|
|
|
|
/// types of their own, so they need special handling. We still need a
|
|
|
|
|
/// `UniqueTypeId` for them, since to debuginfo they *are* real types.
|
|
|
|
|
fn get_unique_type_id_of_enum_variant<'a>(
|
|
|
|
|
&mut self,
|
|
|
|
|
cx: &CodegenCx<'a, 'tcx>,
|
|
|
|
|
enum_type: Ty<'tcx>,
|
|
|
|
|
variant_name: &str,
|
|
|
|
|
) -> UniqueTypeId {
|
|
|
|
|
let enum_type_id = self.get_unique_type_id_of_type(cx, enum_type);
|
|
|
|
|
let enum_variant_type_id =
|
|
|
|
|
format!("{}::{}", self.get_unique_type_id_as_string(enum_type_id), variant_name);
|
|
|
|
|
let interner_key = self.unique_id_interner.intern(&enum_variant_type_id);
|
|
|
|
|
interner_key
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Gets the unique type ID string for an enum variant part.
|
|
|
|
|
/// Variant parts are not types and shouldn't really have their own ID,
|
|
|
|
|
/// but it makes `set_members_of_composite_type()` simpler.
|
|
|
|
|
fn get_unique_type_id_str_of_enum_variant_part(
|
|
|
|
|
&mut self,
|
|
|
|
|
enum_type_id: UniqueTypeId,
|
|
|
|
|
) -> String {
|
|
|
|
|
format!("{}_variant_part", self.get_unique_type_id_as_string(enum_type_id))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Gets the `UniqueTypeId` for the type of a vtable.
|
|
|
|
|
fn get_unique_type_id_of_vtable_type(&mut self, vtable_type_name: &str) -> UniqueTypeId {
|
|
|
|
|
let interner_key = self.unique_id_interner.intern(vtable_type_name);
|
|
|
|
|
interner_key
|
|
|
|
|
fn find_metadata_for_unique_id(
|
|
|
|
|
&self,
|
|
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
|
|
|
|
) -> Option<&'ll DIType> {
|
|
|
|
|
self.unique_id_to_metadata.borrow().get(&unique_type_id).cloned()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -293,7 +226,7 @@ fn get_unique_type_id_of_vtable_type(&mut self, vtable_type_name: &str) -> Uniqu
|
|
|
|
|
enum RecursiveTypeDescription<'ll, 'tcx> {
|
|
|
|
|
UnfinishedMetadata {
|
|
|
|
|
unfinished_type: Ty<'tcx>,
|
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
|
|
|
|
metadata_stub: &'ll DICompositeType,
|
|
|
|
|
member_holding_stub: &'ll DICompositeType,
|
|
|
|
|
member_description_factory: MemberDescriptionFactory<'ll, 'tcx>,
|
|
|
|
@ -304,15 +237,13 @@ enum RecursiveTypeDescription<'ll, 'tcx> {
|
|
|
|
|
fn create_and_register_recursive_type_forward_declaration<'ll, 'tcx>(
|
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
|
unfinished_type: Ty<'tcx>,
|
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
|
|
|
|
metadata_stub: &'ll DICompositeType,
|
|
|
|
|
member_holding_stub: &'ll DICompositeType,
|
|
|
|
|
member_description_factory: MemberDescriptionFactory<'ll, 'tcx>,
|
|
|
|
|
) -> RecursiveTypeDescription<'ll, 'tcx> {
|
|
|
|
|
// Insert the stub into the `TypeMap` in order to allow for recursive references.
|
|
|
|
|
let mut type_map = debug_context(cx).type_map.borrow_mut();
|
|
|
|
|
type_map.register_unique_id_with_metadata(unique_type_id, metadata_stub);
|
|
|
|
|
type_map.register_type_with_metadata(unfinished_type, metadata_stub);
|
|
|
|
|
debug_context(cx).type_map.register_unique_id_with_metadata(unique_type_id, metadata_stub);
|
|
|
|
|
|
|
|
|
|
UnfinishedMetadata {
|
|
|
|
|
unfinished_type,
|
|
|
|
@ -344,9 +275,10 @@ fn finalize(&self, cx: &CodegenCx<'ll, 'tcx>) -> MetadataCreationResult<'ll> {
|
|
|
|
|
// `create_and_register_recursive_type_forward_declaration()`
|
|
|
|
|
// function.
|
|
|
|
|
{
|
|
|
|
|
let type_map = debug_context(cx).type_map.borrow();
|
|
|
|
|
if type_map.find_metadata_for_unique_id(unique_type_id).is_none()
|
|
|
|
|
|| type_map.find_metadata_for_type(unfinished_type).is_none()
|
|
|
|
|
if debug_context(cx)
|
|
|
|
|
.type_map
|
|
|
|
|
.find_metadata_for_unique_id(unique_type_id)
|
|
|
|
|
.is_none()
|
|
|
|
|
{
|
|
|
|
|
bug!(
|
|
|
|
|
"Forward declaration of potentially recursive type \
|
|
|
|
@ -379,7 +311,7 @@ fn finalize(&self, cx: &CodegenCx<'ll, 'tcx>) -> MetadataCreationResult<'ll> {
|
|
|
|
|
macro_rules! return_if_metadata_created_in_meantime {
|
|
|
|
|
($cx: expr, $unique_type_id: expr) => {
|
|
|
|
|
if let Some(metadata) =
|
|
|
|
|
debug_context($cx).type_map.borrow().find_metadata_for_unique_id($unique_type_id)
|
|
|
|
|
debug_context($cx).type_map.find_metadata_for_unique_id($unique_type_id)
|
|
|
|
|
{
|
|
|
|
|
return MetadataCreationResult::new(metadata, true);
|
|
|
|
|
}
|
|
|
|
@ -390,7 +322,7 @@ macro_rules! return_if_metadata_created_in_meantime {
|
|
|
|
|
/// For slices (that is, "arrays" of unknown size) use [slice_type_metadata].
|
|
|
|
|
fn fixed_size_array_metadata<'ll, 'tcx>(
|
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
|
|
|
|
array_type: Ty<'tcx>,
|
|
|
|
|
) -> MetadataCreationResult<'ll> {
|
|
|
|
|
let ty::Array(element_type, len) = array_type.kind() else {
|
|
|
|
@ -434,7 +366,7 @@ fn pointer_or_reference_metadata<'ll, 'tcx>(
|
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
|
ptr_type: Ty<'tcx>,
|
|
|
|
|
pointee_type: Ty<'tcx>,
|
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
|
|
|
|
) -> MetadataCreationResult<'ll> {
|
|
|
|
|
let pointee_type_metadata = type_metadata(cx, pointee_type);
|
|
|
|
|
|
|
|
|
@ -534,16 +466,42 @@ fn pointer_or_reference_metadata<'ll, 'tcx>(
|
|
|
|
|
|
|
|
|
|
fn subroutine_type_metadata<'ll, 'tcx>(
|
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
|
signature: ty::PolyFnSig<'tcx>,
|
|
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
|
|
|
|
) -> MetadataCreationResult<'ll> {
|
|
|
|
|
let signature =
|
|
|
|
|
cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), signature);
|
|
|
|
|
// It's possible to create a self-referential
|
|
|
|
|
// type in Rust by using 'impl trait':
|
|
|
|
|
//
|
|
|
|
|
// fn foo() -> impl Copy { foo }
|
|
|
|
|
//
|
|
|
|
|
// Unfortunately LLVM's API does not allow us to create recursive subroutine types.
|
|
|
|
|
// In order to work around that restriction we place a marker type in the type map,
|
|
|
|
|
// before creating the actual type. If the actual type is recursive, it will hit the
|
|
|
|
|
// marker type. So we end up with a type that looks like
|
|
|
|
|
//
|
|
|
|
|
// fn foo() -> <recursive_type>
|
|
|
|
|
//
|
|
|
|
|
// Once that is created, we replace the marker in the typemap with the actual type.
|
|
|
|
|
debug_context(cx)
|
|
|
|
|
.type_map
|
|
|
|
|
.unique_id_to_metadata
|
|
|
|
|
.borrow_mut()
|
|
|
|
|
.insert(unique_type_id, recursion_marker_type(cx));
|
|
|
|
|
|
|
|
|
|
let signature_metadata: Vec<_> = iter::once(
|
|
|
|
|
let UniqueTypeId::Ty(fn_ty, _) = unique_type_id else {
|
|
|
|
|
bug!("subroutine_type_metadata() called with unexpected input type: {:?}", unique_type_id)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let signature = cx
|
|
|
|
|
.tcx
|
|
|
|
|
.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), fn_ty.fn_sig(cx.tcx));
|
|
|
|
|
|
|
|
|
|
let signature_metadata: SmallVec<[_; 32]> = iter::once(
|
|
|
|
|
// return type
|
|
|
|
|
match signature.output().kind() {
|
|
|
|
|
ty::Tuple(tys) if tys.is_empty() => None,
|
|
|
|
|
ty::Tuple(tys) if tys.is_empty() => {
|
|
|
|
|
// this is a "void" function
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
_ => Some(type_metadata(cx, signature.output())),
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
@ -553,17 +511,30 @@ fn subroutine_type_metadata<'ll, 'tcx>(
|
|
|
|
|
)
|
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
|
|
return_if_metadata_created_in_meantime!(cx, unique_type_id);
|
|
|
|
|
debug_context(cx).type_map.unique_id_to_metadata.borrow_mut().remove(&unique_type_id);
|
|
|
|
|
|
|
|
|
|
MetadataCreationResult::new(
|
|
|
|
|
unsafe {
|
|
|
|
|
llvm::LLVMRustDIBuilderCreateSubroutineType(
|
|
|
|
|
DIB(cx),
|
|
|
|
|
create_DIArray(DIB(cx), &signature_metadata[..]),
|
|
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
false,
|
|
|
|
|
)
|
|
|
|
|
let fn_metadata = unsafe {
|
|
|
|
|
llvm::LLVMRustDIBuilderCreateSubroutineType(
|
|
|
|
|
DIB(cx),
|
|
|
|
|
create_DIArray(DIB(cx), &signature_metadata[..]),
|
|
|
|
|
)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// This is actually a function pointer, so wrap it in pointer DI.
|
|
|
|
|
let name = compute_debuginfo_type_name(cx.tcx, fn_ty, false);
|
|
|
|
|
let metadata = unsafe {
|
|
|
|
|
llvm::LLVMRustDIBuilderCreatePointerType(
|
|
|
|
|
DIB(cx),
|
|
|
|
|
fn_metadata,
|
|
|
|
|
cx.tcx.data_layout.pointer_size.bits(),
|
|
|
|
|
cx.tcx.data_layout.pointer_align.abi.bits() as u32,
|
|
|
|
|
0, // Ignore DWARF address space.
|
|
|
|
|
name.as_ptr().cast(),
|
|
|
|
|
name.len(),
|
|
|
|
|
)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
MetadataCreationResult::new(metadata, false)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Create debuginfo for `dyn SomeTrait` types. Currently these are empty structs
|
|
|
|
@ -571,7 +542,7 @@ fn subroutine_type_metadata<'ll, 'tcx>(
|
|
|
|
|
fn dyn_type_metadata<'ll, 'tcx>(
|
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
|
dyn_type: Ty<'tcx>,
|
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
|
|
|
|
) -> &'ll DIType {
|
|
|
|
|
if let ty::Dynamic(..) = dyn_type.kind() {
|
|
|
|
|
let type_name = compute_debuginfo_type_name(cx.tcx, dyn_type, true);
|
|
|
|
@ -601,7 +572,7 @@ fn dyn_type_metadata<'ll, 'tcx>(
|
|
|
|
|
fn slice_type_metadata<'ll, 'tcx>(
|
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
|
slice_type: Ty<'tcx>,
|
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
|
|
|
|
) -> MetadataCreationResult<'ll> {
|
|
|
|
|
let element_type = match slice_type.kind() {
|
|
|
|
|
ty::Slice(element_type) => *element_type,
|
|
|
|
@ -620,38 +591,11 @@ fn slice_type_metadata<'ll, 'tcx>(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
|
|
|
|
|
// Get the unique type ID of this type.
|
|
|
|
|
let unique_type_id = {
|
|
|
|
|
let mut type_map = debug_context(cx).type_map.borrow_mut();
|
|
|
|
|
// First, try to find the type in `TypeMap`. If we have seen it before, we
|
|
|
|
|
// can exit early here.
|
|
|
|
|
match type_map.find_metadata_for_type(t) {
|
|
|
|
|
Some(metadata) => {
|
|
|
|
|
return metadata;
|
|
|
|
|
}
|
|
|
|
|
None => {
|
|
|
|
|
// The Ty is not in the `TypeMap` but maybe we have already seen
|
|
|
|
|
// an equivalent type (e.g., only differing in region arguments).
|
|
|
|
|
// In order to find out, generate the unique type ID and look
|
|
|
|
|
// that up.
|
|
|
|
|
let unique_type_id = type_map.get_unique_type_id_of_type(cx, t);
|
|
|
|
|
match type_map.find_metadata_for_unique_id(unique_type_id) {
|
|
|
|
|
Some(metadata) => {
|
|
|
|
|
// There is already an equivalent type in the TypeMap.
|
|
|
|
|
// Register this Ty as an alias in the cache and
|
|
|
|
|
// return the cached metadata.
|
|
|
|
|
type_map.register_type_with_metadata(t, metadata);
|
|
|
|
|
return metadata;
|
|
|
|
|
}
|
|
|
|
|
None => {
|
|
|
|
|
// There really is no type metadata for this type, so
|
|
|
|
|
// proceed by creating it.
|
|
|
|
|
unique_type_id
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
let unique_type_id = UniqueTypeId::for_ty(cx.tcx, t);
|
|
|
|
|
|
|
|
|
|
if let Some(metadata) = debug_context(cx).type_map.find_metadata_for_unique_id(unique_type_id) {
|
|
|
|
|
return metadata;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
debug!("type_metadata: {:?}", t);
|
|
|
|
|
|
|
|
|
@ -676,64 +620,7 @@ pub fn type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll
|
|
|
|
|
ty::Adt(def, _) if def.is_box() => {
|
|
|
|
|
pointer_or_reference_metadata(cx, t, t.boxed_ty(), unique_type_id)
|
|
|
|
|
}
|
|
|
|
|
ty::FnDef(..) | ty::FnPtr(_) => {
|
|
|
|
|
if let Some(metadata) =
|
|
|
|
|
debug_context(cx).type_map.borrow().find_metadata_for_unique_id(unique_type_id)
|
|
|
|
|
{
|
|
|
|
|
return metadata;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// It's possible to create a self-referential
|
|
|
|
|
// type in Rust by using 'impl trait':
|
|
|
|
|
//
|
|
|
|
|
// fn foo() -> impl Copy { foo }
|
|
|
|
|
//
|
|
|
|
|
// See `TypeMap::remove_type` for more detals
|
|
|
|
|
// about the workaround.
|
|
|
|
|
|
|
|
|
|
let temp_type = {
|
|
|
|
|
unsafe {
|
|
|
|
|
// The choice of type here is pretty arbitrary -
|
|
|
|
|
// anything reading the debuginfo for a recursive
|
|
|
|
|
// type is going to see *something* weird - the only
|
|
|
|
|
// question is what exactly it will see.
|
|
|
|
|
let name = "<recur_type>";
|
|
|
|
|
llvm::LLVMRustDIBuilderCreateBasicType(
|
|
|
|
|
DIB(cx),
|
|
|
|
|
name.as_ptr().cast(),
|
|
|
|
|
name.len(),
|
|
|
|
|
cx.size_of(t).bits(),
|
|
|
|
|
DW_ATE_unsigned,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let type_map = &debug_context(cx).type_map;
|
|
|
|
|
type_map.borrow_mut().register_type_with_metadata(t, temp_type);
|
|
|
|
|
|
|
|
|
|
let fn_metadata =
|
|
|
|
|
subroutine_type_metadata(cx, unique_type_id, t.fn_sig(cx.tcx)).metadata;
|
|
|
|
|
|
|
|
|
|
type_map.borrow_mut().remove_type(t);
|
|
|
|
|
|
|
|
|
|
// This is actually a function pointer, so wrap it in pointer DI.
|
|
|
|
|
let (pointer_size, pointer_align) =
|
|
|
|
|
cx.size_and_align_of(cx.tcx.mk_imm_ptr(cx.tcx.mk_unit()));
|
|
|
|
|
let name = compute_debuginfo_type_name(cx.tcx, t, false);
|
|
|
|
|
let md = unsafe {
|
|
|
|
|
llvm::LLVMRustDIBuilderCreatePointerType(
|
|
|
|
|
DIB(cx),
|
|
|
|
|
fn_metadata,
|
|
|
|
|
pointer_size.bits(),
|
|
|
|
|
pointer_align.bits() as u32,
|
|
|
|
|
0, // Ignore DWARF address space.
|
|
|
|
|
name.as_ptr().cast(),
|
|
|
|
|
name.len(),
|
|
|
|
|
)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
MetadataCreationResult::new(md, false)
|
|
|
|
|
}
|
|
|
|
|
ty::FnDef(..) | ty::FnPtr(_) => subroutine_type_metadata(cx, unique_type_id),
|
|
|
|
|
ty::Closure(def_id, substs) => {
|
|
|
|
|
let upvar_tys: Vec<_> = substs.as_closure().upvar_tys().collect();
|
|
|
|
|
let containing_scope = get_namespace_for_item(cx, def_id);
|
|
|
|
@ -764,47 +651,56 @@ pub fn type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
let mut type_map = debug_context(cx).type_map.borrow_mut();
|
|
|
|
|
|
|
|
|
|
if already_stored_in_typemap {
|
|
|
|
|
// Also make sure that we already have a `TypeMap` entry for the unique type ID.
|
|
|
|
|
let Some(metadata_for_uid) = type_map.find_metadata_for_unique_id(unique_type_id) else {
|
|
|
|
|
bug!(
|
|
|
|
|
"expected type metadata for unique \
|
|
|
|
|
type ID '{}' to already be in \
|
|
|
|
|
the `debuginfo::TypeMap` but it \
|
|
|
|
|
was not. (Ty = {})",
|
|
|
|
|
type_map.get_unique_type_id_as_string(unique_type_id),
|
|
|
|
|
t
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
match type_map.find_metadata_for_type(t) {
|
|
|
|
|
Some(metadata) => {
|
|
|
|
|
if metadata != metadata_for_uid {
|
|
|
|
|
// Make sure that we really do have a `TypeMap` entry for the unique type ID.
|
|
|
|
|
let metadata_for_uid =
|
|
|
|
|
match debug_context(cx).type_map.find_metadata_for_unique_id(unique_type_id) {
|
|
|
|
|
Some(metadata) => metadata,
|
|
|
|
|
None => {
|
|
|
|
|
bug!(
|
|
|
|
|
"mismatch between `Ty` and \
|
|
|
|
|
`UniqueTypeId` maps in \
|
|
|
|
|
`debuginfo::TypeMap`. \
|
|
|
|
|
UniqueTypeId={}, Ty={}",
|
|
|
|
|
type_map.get_unique_type_id_as_string(unique_type_id),
|
|
|
|
|
t
|
|
|
|
|
"expected type metadata for unique \
|
|
|
|
|
type ID '{:?}' to already be in \
|
|
|
|
|
the `debuginfo::TypeMap` but it \
|
|
|
|
|
was not.",
|
|
|
|
|
unique_type_id,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
None => {
|
|
|
|
|
type_map.register_type_with_metadata(t, metadata);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
debug_assert_eq!(metadata_for_uid as *const _, metadata as *const _);
|
|
|
|
|
} else {
|
|
|
|
|
type_map.register_type_with_metadata(t, metadata);
|
|
|
|
|
type_map.register_unique_id_with_metadata(unique_type_id, metadata);
|
|
|
|
|
debug_context(cx).type_map.register_unique_id_with_metadata(unique_type_id, metadata);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
metadata
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn recursion_marker_type<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> &'ll DIType {
|
|
|
|
|
*debug_context(cx).recursion_marker_type.get_or_init(move || {
|
|
|
|
|
unsafe {
|
|
|
|
|
// The choice of type here is pretty arbitrary -
|
|
|
|
|
// anything reading the debuginfo for a recursive
|
|
|
|
|
// type is going to see *something* weird - the only
|
|
|
|
|
// question is what exactly it will see.
|
|
|
|
|
//
|
|
|
|
|
// FIXME: the name `<recur_type>` does not fit the naming scheme
|
|
|
|
|
// of other types.
|
|
|
|
|
//
|
|
|
|
|
// FIXME: it might make sense to use an actual pointer type here
|
|
|
|
|
// so that debuggers can show the address.
|
|
|
|
|
let name = "<recur_type>";
|
|
|
|
|
llvm::LLVMRustDIBuilderCreateBasicType(
|
|
|
|
|
DIB(cx),
|
|
|
|
|
name.as_ptr().cast(),
|
|
|
|
|
name.len(),
|
|
|
|
|
cx.tcx.data_layout.pointer_size.bits(),
|
|
|
|
|
DW_ATE_unsigned,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn hex_encode(data: &[u8]) -> String {
|
|
|
|
|
let mut hex_string = String::with_capacity(data.len() * 2);
|
|
|
|
|
for byte in data.iter() {
|
|
|
|
@ -985,7 +881,7 @@ fn basic_type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'l
|
|
|
|
|
fn foreign_type_metadata<'ll, 'tcx>(
|
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
|
t: Ty<'tcx>,
|
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
|
|
|
|
) -> &'ll DIType {
|
|
|
|
|
debug!("foreign_type_metadata: {:?}", t);
|
|
|
|
|
|
|
|
|
@ -1306,7 +1202,7 @@ fn create_member_descriptions<'ll>(
|
|
|
|
|
fn prepare_struct_metadata<'ll, 'tcx>(
|
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
|
struct_type: Ty<'tcx>,
|
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
|
|
|
|
) -> RecursiveTypeDescription<'ll, 'tcx> {
|
|
|
|
|
let struct_name = compute_debuginfo_type_name(cx.tcx, struct_type, false);
|
|
|
|
|
|
|
|
|
@ -1415,7 +1311,7 @@ fn prepare_tuple_metadata<'ll, 'tcx>(
|
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
|
tuple_type: Ty<'tcx>,
|
|
|
|
|
component_types: &[Ty<'tcx>],
|
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
|
|
|
|
containing_scope: Option<&'ll DIScope>,
|
|
|
|
|
) -> RecursiveTypeDescription<'ll, 'tcx> {
|
|
|
|
|
let (size, align) = cx.size_and_align_of(tuple_type);
|
|
|
|
@ -1483,7 +1379,7 @@ fn create_member_descriptions<'ll>(
|
|
|
|
|
fn prepare_union_metadata<'ll, 'tcx>(
|
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
|
union_type: Ty<'tcx>,
|
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
|
|
|
|
) -> RecursiveTypeDescription<'ll, 'tcx> {
|
|
|
|
|
let union_name = compute_debuginfo_type_name(cx.tcx, union_type, false);
|
|
|
|
|
|
|
|
|
@ -1570,7 +1466,7 @@ fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDes
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let variant_info_for = |index: VariantIdx| match *self.enum_type.kind() {
|
|
|
|
|
ty::Adt(adt, _) => VariantInfo::Adt(&adt.variants[index]),
|
|
|
|
|
ty::Adt(adt, _) => VariantInfo::Adt(&adt.variants[index], index),
|
|
|
|
|
ty::Generator(def_id, _, _) => {
|
|
|
|
|
let (generator_layout, generator_saved_local_names) =
|
|
|
|
|
generator_variant_info_data.as_ref().unwrap();
|
|
|
|
@ -1913,7 +1809,7 @@ fn create_member_descriptions<'ll>(
|
|
|
|
|
|
|
|
|
|
#[derive(Copy, Clone)]
|
|
|
|
|
enum VariantInfo<'a, 'tcx> {
|
|
|
|
|
Adt(&'tcx ty::VariantDef),
|
|
|
|
|
Adt(&'tcx ty::VariantDef, VariantIdx),
|
|
|
|
|
Generator {
|
|
|
|
|
def_id: DefId,
|
|
|
|
|
generator_layout: &'tcx GeneratorLayout<'tcx>,
|
|
|
|
@ -1923,9 +1819,17 @@ enum VariantInfo<'a, 'tcx> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'tcx> VariantInfo<'_, 'tcx> {
|
|
|
|
|
fn variant_idx(&self) -> VariantIdx {
|
|
|
|
|
match self {
|
|
|
|
|
VariantInfo::Adt(_, variant_index) | VariantInfo::Generator { variant_index, .. } => {
|
|
|
|
|
*variant_index
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn map_struct_name<R>(&self, f: impl FnOnce(&str) -> R) -> R {
|
|
|
|
|
match self {
|
|
|
|
|
VariantInfo::Adt(variant) => f(variant.name.as_str()),
|
|
|
|
|
VariantInfo::Adt(variant, _) => f(variant.name.as_str()),
|
|
|
|
|
VariantInfo::Generator { variant_index, .. } => {
|
|
|
|
|
f(&GeneratorSubsts::variant_name(*variant_index))
|
|
|
|
|
}
|
|
|
|
@ -1934,7 +1838,7 @@ fn map_struct_name<R>(&self, f: impl FnOnce(&str) -> R) -> R {
|
|
|
|
|
|
|
|
|
|
fn variant_name(&self) -> String {
|
|
|
|
|
match self {
|
|
|
|
|
VariantInfo::Adt(variant) => variant.name.to_string(),
|
|
|
|
|
VariantInfo::Adt(variant, _) => variant.name.to_string(),
|
|
|
|
|
VariantInfo::Generator { variant_index, .. } => {
|
|
|
|
|
// Since GDB currently prints out the raw discriminant along
|
|
|
|
|
// with every variant, make each variant name be just the value
|
|
|
|
@ -1947,7 +1851,7 @@ fn variant_name(&self) -> String {
|
|
|
|
|
|
|
|
|
|
fn field_name(&self, i: usize) -> String {
|
|
|
|
|
let field_name = match *self {
|
|
|
|
|
VariantInfo::Adt(variant) if variant.ctor_kind != CtorKind::Fn => {
|
|
|
|
|
VariantInfo::Adt(variant, _) if variant.ctor_kind != CtorKind::Fn => {
|
|
|
|
|
Some(variant.fields[i].name)
|
|
|
|
|
}
|
|
|
|
|
VariantInfo::Generator {
|
|
|
|
@ -1988,10 +1892,8 @@ fn describe_enum_variant<'ll, 'tcx>(
|
|
|
|
|
containing_scope: &'ll DIScope,
|
|
|
|
|
) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) {
|
|
|
|
|
let metadata_stub = variant.map_struct_name(|variant_name| {
|
|
|
|
|
let unique_type_id = debug_context(cx)
|
|
|
|
|
.type_map
|
|
|
|
|
.borrow_mut()
|
|
|
|
|
.get_unique_type_id_of_enum_variant(cx, layout.ty, variant_name);
|
|
|
|
|
let unique_type_id =
|
|
|
|
|
UniqueTypeId::for_enum_variant(cx.tcx, layout.ty, variant.variant_idx());
|
|
|
|
|
|
|
|
|
|
let (size, align) = cx.size_and_align_of(layout.ty);
|
|
|
|
|
|
|
|
|
@ -2021,7 +1923,7 @@ fn prepare_enum_metadata<'ll, 'tcx>(
|
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
|
enum_type: Ty<'tcx>,
|
|
|
|
|
enum_def_id: DefId,
|
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
|
|
|
|
outer_field_tys: Vec<Ty<'tcx>>,
|
|
|
|
|
) -> RecursiveTypeDescription<'ll, 'tcx> {
|
|
|
|
|
let tcx = cx.tcx;
|
|
|
|
@ -2145,8 +2047,7 @@ fn prepare_enum_metadata<'ll, 'tcx>(
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let enum_metadata = {
|
|
|
|
|
let type_map = debug_context(cx).type_map.borrow();
|
|
|
|
|
let unique_type_id_str = type_map.get_unique_type_id_as_string(unique_type_id);
|
|
|
|
|
let unique_type_id_str = unique_type_id.generate_unique_id_string(tcx);
|
|
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
|
llvm::LLVMRustDIBuilderCreateUnionType(
|
|
|
|
@ -2257,10 +2158,9 @@ fn prepare_enum_metadata<'ll, 'tcx>(
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let variant_part_unique_type_id_str = debug_context(cx)
|
|
|
|
|
.type_map
|
|
|
|
|
.borrow_mut()
|
|
|
|
|
.get_unique_type_id_str_of_enum_variant_part(unique_type_id);
|
|
|
|
|
let variant_part_unique_type_id_str =
|
|
|
|
|
UniqueTypeId::for_enum_variant_part(tcx, enum_type).generate_unique_id_string(tcx);
|
|
|
|
|
|
|
|
|
|
let empty_array = create_DIArray(DIB(cx), &[]);
|
|
|
|
|
let name = "";
|
|
|
|
|
let variant_part = unsafe {
|
|
|
|
@ -2288,9 +2188,7 @@ fn prepare_enum_metadata<'ll, 'tcx>(
|
|
|
|
|
// an equivalent layout but offers us much better integration with
|
|
|
|
|
// debuggers.
|
|
|
|
|
let type_array = create_DIArray(DIB(cx), &[Some(variant_part)]);
|
|
|
|
|
|
|
|
|
|
let type_map = debug_context(cx).type_map.borrow();
|
|
|
|
|
let unique_type_id_str = type_map.get_unique_type_id_as_string(unique_type_id);
|
|
|
|
|
let unique_type_id_str = unique_type_id.generate_unique_id_string(tcx);
|
|
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
|
llvm::LLVMRustDIBuilderCreateStructType(
|
|
|
|
@ -2336,7 +2234,7 @@ fn composite_type_metadata<'ll, 'tcx>(
|
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
|
composite_type: Ty<'tcx>,
|
|
|
|
|
composite_type_name: &str,
|
|
|
|
|
composite_type_unique_id: UniqueTypeId,
|
|
|
|
|
composite_type_unique_id: UniqueTypeId<'tcx>,
|
|
|
|
|
member_descriptions: Vec<MemberDescription<'ll>>,
|
|
|
|
|
containing_scope: Option<&'ll DIScope>,
|
|
|
|
|
) -> &'ll DICompositeType {
|
|
|
|
@ -2459,13 +2357,12 @@ fn create_struct_stub<'ll, 'tcx>(
|
|
|
|
|
size: Size,
|
|
|
|
|
align: Align,
|
|
|
|
|
type_name: &str,
|
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
|
|
|
|
containing_scope: Option<&'ll DIScope>,
|
|
|
|
|
flags: DIFlags,
|
|
|
|
|
vtable_holder: Option<&'ll DIType>,
|
|
|
|
|
) -> &'ll DICompositeType {
|
|
|
|
|
let type_map = debug_context(cx).type_map.borrow();
|
|
|
|
|
let unique_type_id = type_map.get_unique_type_id_as_string(unique_type_id);
|
|
|
|
|
let unique_type_id = unique_type_id.generate_unique_id_string(cx.tcx);
|
|
|
|
|
|
|
|
|
|
let metadata_stub = unsafe {
|
|
|
|
|
// `LLVMRustDIBuilderCreateStructType()` wants an empty array. A null
|
|
|
|
@ -2499,13 +2396,11 @@ fn create_union_stub<'ll, 'tcx>(
|
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
|
union_type: Ty<'tcx>,
|
|
|
|
|
union_type_name: &str,
|
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
|
|
|
|
containing_scope: &'ll DIScope,
|
|
|
|
|
) -> &'ll DICompositeType {
|
|
|
|
|
let (union_size, union_align) = cx.size_and_align_of(union_type);
|
|
|
|
|
|
|
|
|
|
let type_map = debug_context(cx).type_map.borrow();
|
|
|
|
|
let unique_type_id = type_map.get_unique_type_id_as_string(unique_type_id);
|
|
|
|
|
let unique_type_id = unique_type_id.generate_unique_id_string(cx.tcx);
|
|
|
|
|
|
|
|
|
|
let metadata_stub = unsafe {
|
|
|
|
|
// `LLVMRustDIBuilderCreateUnionType()` wants an empty array. A null
|
|
|
|
@ -2629,10 +2524,7 @@ fn vtable_type_metadata<'ll, 'tcx>(
|
|
|
|
|
|
|
|
|
|
let vtable_type_name =
|
|
|
|
|
compute_debuginfo_vtable_name(cx.tcx, ty, poly_trait_ref, VTableNameKind::Type);
|
|
|
|
|
let unique_type_id = debug_context(cx)
|
|
|
|
|
.type_map
|
|
|
|
|
.borrow_mut()
|
|
|
|
|
.get_unique_type_id_of_vtable_type(&vtable_type_name);
|
|
|
|
|
let unique_type_id = UniqueTypeId::for_vtable_ty(tcx, ty, poly_trait_ref);
|
|
|
|
|
let size = pointer_size * vtable_entries.len() as u64;
|
|
|
|
|
|
|
|
|
|
// This gets mapped to a DW_AT_containing_type attribute which allows GDB to correlate
|
|
|
|
|