2019-12-24 22:38:22 +00:00
|
|
|
use self::MemberDescriptionFactory::*;
|
|
|
|
use self::RecursiveTypeDescription::*;
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2018-02-19 11:41:10 +00:00
|
|
|
use super::namespace::mangled_name_of_instance;
|
2021-10-06 12:26:50 +00:00
|
|
|
use super::type_names::{compute_debuginfo_type_name, compute_debuginfo_vtable_name};
|
2019-12-24 22:38:22 +00:00
|
|
|
use super::utils::{
|
2020-02-25 00:00:00 +00:00
|
|
|
create_DIArray, debug_context, get_namespace_for_item, is_node_local_to_unit, DIB,
|
2019-12-24 22:38:22 +00:00
|
|
|
};
|
2019-09-26 17:30:44 +00:00
|
|
|
use super::CrateDebugContext;
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2019-05-17 01:20:14 +00:00
|
|
|
use crate::abi;
|
|
|
|
use crate::common::CodegenCx;
|
2022-01-13 17:13:54 +00:00
|
|
|
use crate::debuginfo::utils::fat_pointer_kind;
|
|
|
|
use crate::debuginfo::utils::FatPtrKind;
|
2019-02-17 18:58:58 +00:00
|
|
|
use crate::llvm;
|
2019-12-24 22:38:22 +00:00
|
|
|
use crate::llvm::debuginfo::{
|
|
|
|
DIArray, DICompositeType, DIDescriptor, DIFile, DIFlags, DILexicalBlock, DIScope, DIType,
|
|
|
|
DebugEmissionKind,
|
|
|
|
};
|
2019-05-17 01:20:14 +00:00
|
|
|
use crate::value::Value;
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2021-02-13 11:17:15 +00:00
|
|
|
use cstr::cstr;
|
2021-12-28 21:57:18 +00:00
|
|
|
use rustc_codegen_ssa::debuginfo::type_names::cpp_like_debuginfo;
|
2022-01-25 13:34:34 +00:00
|
|
|
use rustc_codegen_ssa::debuginfo::type_names::VTableNameKind;
|
2019-12-24 22:38:22 +00:00
|
|
|
use rustc_codegen_ssa::traits::*;
|
2019-12-24 04:02:53 +00:00
|
|
|
use rustc_data_structures::fx::FxHashMap;
|
2019-12-24 22:38:22 +00:00
|
|
|
use rustc_fs_util::path_to_c_string;
|
2020-01-05 01:37:57 +00:00
|
|
|
use rustc_hir::def::CtorKind;
|
2020-02-10 01:03:24 +00:00
|
|
|
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
2019-12-24 22:38:22 +00:00
|
|
|
use rustc_index::vec::{Idx, IndexVec};
|
2022-01-10 14:59:52 +00:00
|
|
|
use rustc_middle::bug;
|
2021-06-24 20:37:03 +00:00
|
|
|
use rustc_middle::mir::{self, GeneratorLayout};
|
2021-08-30 14:38:27 +00:00
|
|
|
use rustc_middle::ty::layout::{self, IntegerExt, LayoutOf, PrimitiveExt, TyAndLayout};
|
2020-06-20 01:37:52 +00:00
|
|
|
use rustc_middle::ty::subst::GenericArgKind;
|
2021-10-06 12:26:50 +00:00
|
|
|
use rustc_middle::ty::{
|
|
|
|
self, AdtKind, GeneratorSubsts, Instance, ParamEnv, Ty, TyCtxt, COMMON_VTABLE_ENTRIES,
|
|
|
|
};
|
2020-03-11 11:49:08 +00:00
|
|
|
use rustc_session::config::{self, DebugInfo};
|
2021-08-08 15:24:30 +00:00
|
|
|
use rustc_span::symbol::Symbol;
|
2021-08-26 10:46:01 +00:00
|
|
|
use rustc_span::FileNameDisplayPreference;
|
2022-01-10 14:59:52 +00:00
|
|
|
use rustc_span::{self, SourceFile, SourceFileHash};
|
2021-08-30 14:38:27 +00:00
|
|
|
use rustc_target::abi::{Abi, Align, HasDataLayout, Integer, TagEncoding};
|
2020-03-31 16:16:47 +00:00
|
|
|
use rustc_target::abi::{Int, Pointer, F32, F64};
|
|
|
|
use rustc_target::abi::{Primitive, Size, VariantIdx, Variants};
|
2022-02-04 12:19:55 +00:00
|
|
|
use smallvec::SmallVec;
|
2020-08-05 11:35:53 +00:00
|
|
|
use tracing::debug;
|
2015-04-24 04:48:10 +00:00
|
|
|
|
2019-12-24 22:38:22 +00:00
|
|
|
use libc::{c_longlong, c_uint};
|
2022-02-04 12:19:55 +00:00
|
|
|
use std::cell::RefCell;
|
2019-05-06 01:47:03 +00:00
|
|
|
use std::collections::hash_map::Entry;
|
2018-07-04 13:36:49 +00:00
|
|
|
use std::fmt::{self, Write};
|
|
|
|
use std::hash::{Hash, Hasher};
|
2018-07-26 15:11:10 +00:00
|
|
|
use std::iter;
|
2017-12-14 07:09:19 +00:00
|
|
|
use std::path::{Path, PathBuf};
|
2019-12-24 22:38:22 +00:00
|
|
|
use std::ptr;
|
2015-04-24 04:48:10 +00:00
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
impl PartialEq for llvm::Metadata {
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
2019-01-12 15:13:33 +00:00
|
|
|
ptr::eq(self, other)
|
2018-07-04 13:36:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Eq for llvm::Metadata {}
|
|
|
|
|
|
|
|
impl Hash for llvm::Metadata {
|
|
|
|
fn hash<H: Hasher>(&self, hasher: &mut H) {
|
|
|
|
(self as *const Self).hash(hasher);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Debug for llvm::Metadata {
|
2019-02-25 07:40:18 +00:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2018-07-04 13:36:49 +00:00
|
|
|
(self as *const Self).fmt(f)
|
|
|
|
}
|
|
|
|
}
|
2016-10-21 21:56:36 +00:00
|
|
|
|
2016-03-18 21:30:15 +00:00
|
|
|
// From DWARF 5.
|
2019-05-17 01:20:14 +00:00
|
|
|
// See http://www.dwarfstd.org/ShowIssue.php?issue=140129.1.
|
2016-03-18 21:30:15 +00:00
|
|
|
const DW_LANG_RUST: c_uint = 0x1c;
|
2015-04-24 04:48:10 +00:00
|
|
|
#[allow(non_upper_case_globals)]
|
|
|
|
const DW_ATE_boolean: c_uint = 0x02;
|
|
|
|
#[allow(non_upper_case_globals)]
|
|
|
|
const DW_ATE_float: c_uint = 0x04;
|
|
|
|
#[allow(non_upper_case_globals)]
|
|
|
|
const DW_ATE_signed: c_uint = 0x05;
|
|
|
|
#[allow(non_upper_case_globals)]
|
|
|
|
const DW_ATE_unsigned: c_uint = 0x07;
|
|
|
|
#[allow(non_upper_case_globals)]
|
2021-10-14 17:26:42 +00:00
|
|
|
const DW_ATE_UTF: c_uint = 0x10;
|
2015-04-24 04:48:10 +00:00
|
|
|
|
2015-04-29 06:14:37 +00:00
|
|
|
pub const UNKNOWN_LINE_NUMBER: c_uint = 0;
|
|
|
|
pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0;
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
pub const NO_SCOPE_METADATA: Option<&DIScope> = None;
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2021-08-08 15:24:30 +00:00
|
|
|
mod unique_type_id {
|
2022-02-04 12:19:55 +00:00
|
|
|
use rustc_data_structures::{
|
|
|
|
fingerprint::Fingerprint,
|
|
|
|
stable_hasher::{HashStable, NodeIdHashingMode, StableHasher},
|
|
|
|
};
|
|
|
|
use rustc_middle::ty::{ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt};
|
|
|
|
use rustc_target::abi::VariantIdx;
|
|
|
|
|
|
|
|
// 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: (),
|
|
|
|
}
|
2021-08-08 15:24:30 +00:00
|
|
|
|
2022-02-04 12:19:55 +00:00
|
|
|
/// 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).
|
2022-02-24 16:19:18 +00:00
|
|
|
///
|
|
|
|
/// 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.
|
2022-02-04 12:19:55 +00:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, HashStable)]
|
|
|
|
pub(super) enum UniqueTypeId<'tcx> {
|
2022-02-24 16:19:18 +00:00
|
|
|
/// The ID of a regular type as it shows up at the language level.
|
2022-02-04 12:19:55 +00:00
|
|
|
Ty(Ty<'tcx>, HiddenZst),
|
2022-02-24 16:19:18 +00:00
|
|
|
/// The ID for the artificial struct type describing a single enum variant.
|
2022-02-04 12:19:55 +00:00
|
|
|
Variant(Ty<'tcx>, VariantIdx, HiddenZst),
|
2022-02-24 16:19:18 +00:00
|
|
|
/// The ID for the single DW_TAG_variant_part nested inside the top-level
|
|
|
|
/// DW_TAG_structure_type that describes enums and generators.
|
2022-02-04 12:19:55 +00:00
|
|
|
VariantPart(Ty<'tcx>, HiddenZst),
|
2022-02-24 16:19:18 +00:00
|
|
|
/// The ID of the artificial type we create for VTables.
|
2022-02-04 12:19:55 +00:00
|
|
|
VTableTy(Ty<'tcx>, Option<PolyExistentialTraitRef<'tcx>>, HiddenZst),
|
2021-08-08 15:24:30 +00:00
|
|
|
}
|
|
|
|
|
2022-02-04 12:19:55 +00:00
|
|
|
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: () })
|
|
|
|
}
|
2021-08-08 15:24:30 +00:00
|
|
|
|
2022-02-04 12:19:55 +00:00
|
|
|
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: () })
|
2021-08-08 15:24:30 +00:00
|
|
|
}
|
|
|
|
|
2022-02-04 12:19:55 +00:00
|
|
|
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: () })
|
2021-08-08 15:24:30 +00:00
|
|
|
}
|
|
|
|
|
2022-02-04 12:19:55 +00:00
|
|
|
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: () })
|
|
|
|
}
|
|
|
|
|
2022-02-24 16:19:18 +00:00
|
|
|
/// 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 {
|
2022-02-04 12:19:55 +00:00
|
|
|
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()
|
2021-08-08 15:24:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
use unique_type_id::*;
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2022-02-04 12:19:55 +00:00
|
|
|
/// The `TypeMap` is where the debug context holds the type metadata nodes
|
|
|
|
/// created so far. The metadata nodes are indexed by `UniqueTypeId`.
|
2018-10-16 14:57:53 +00:00
|
|
|
#[derive(Default)]
|
2018-07-04 13:36:49 +00:00
|
|
|
pub struct TypeMap<'ll, 'tcx> {
|
2022-02-04 12:19:55 +00:00
|
|
|
unique_id_to_metadata: RefCell<FxHashMap<UniqueTypeId<'tcx>, &'ll DIType>>,
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
|
2021-12-14 18:49:49 +00:00
|
|
|
impl<'ll, 'tcx> TypeMap<'ll, 'tcx> {
|
2019-05-17 01:20:14 +00:00
|
|
|
/// Adds a `UniqueTypeId` to metadata mapping to the `TypeMap`. The method will
|
|
|
|
/// fail if the mapping already exists.
|
2018-07-04 13:36:49 +00:00
|
|
|
fn register_unique_id_with_metadata(
|
2022-02-04 12:19:55 +00:00
|
|
|
&self,
|
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
2018-07-04 13:36:49 +00:00
|
|
|
metadata: &'ll DIType,
|
|
|
|
) {
|
2022-02-04 12:19:55 +00:00
|
|
|
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);
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-04 12:19:55 +00:00
|
|
|
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()
|
2022-01-25 13:34:34 +00:00
|
|
|
}
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
|
2019-05-17 01:20:14 +00:00
|
|
|
/// A description of some recursive type. It can either be already finished (as
|
|
|
|
/// with `FinalMetadata`) or it is not yet finished, but contains all information
|
|
|
|
/// needed to generate the missing parts of the description. See the
|
|
|
|
/// documentation section on Recursive Types at the top of this file for more
|
|
|
|
/// information.
|
2018-07-04 13:36:49 +00:00
|
|
|
enum RecursiveTypeDescription<'ll, 'tcx> {
|
2015-04-29 06:14:37 +00:00
|
|
|
UnfinishedMetadata {
|
|
|
|
unfinished_type: Ty<'tcx>,
|
2022-02-04 12:19:55 +00:00
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
2018-07-04 13:36:49 +00:00
|
|
|
metadata_stub: &'ll DICompositeType,
|
2017-11-29 21:42:25 +00:00
|
|
|
member_holding_stub: &'ll DICompositeType,
|
2018-07-04 13:36:49 +00:00
|
|
|
member_description_factory: MemberDescriptionFactory<'ll, 'tcx>,
|
2015-04-29 06:14:37 +00:00
|
|
|
},
|
2019-12-24 22:38:22 +00:00
|
|
|
FinalMetadata(&'ll DICompositeType),
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
|
2021-12-14 18:49:49 +00:00
|
|
|
fn create_and_register_recursive_type_forward_declaration<'ll, 'tcx>(
|
2018-07-04 13:36:49 +00:00
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
2015-04-29 06:14:37 +00:00
|
|
|
unfinished_type: Ty<'tcx>,
|
2022-02-04 12:19:55 +00:00
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
2018-07-04 13:36:49 +00:00
|
|
|
metadata_stub: &'ll DICompositeType,
|
2017-11-29 21:42:25 +00:00
|
|
|
member_holding_stub: &'ll DICompositeType,
|
2018-07-04 13:36:49 +00:00
|
|
|
member_description_factory: MemberDescriptionFactory<'ll, 'tcx>,
|
|
|
|
) -> RecursiveTypeDescription<'ll, 'tcx> {
|
2019-05-17 01:20:14 +00:00
|
|
|
// Insert the stub into the `TypeMap` in order to allow for recursive references.
|
2022-02-04 12:19:55 +00:00
|
|
|
debug_context(cx).type_map.register_unique_id_with_metadata(unique_type_id, metadata_stub);
|
2015-04-29 06:14:37 +00:00
|
|
|
|
|
|
|
UnfinishedMetadata {
|
2017-08-07 05:54:09 +00:00
|
|
|
unfinished_type,
|
|
|
|
unique_type_id,
|
|
|
|
metadata_stub,
|
2017-11-29 21:42:25 +00:00
|
|
|
member_holding_stub,
|
2017-08-07 05:54:09 +00:00
|
|
|
member_description_factory,
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-14 18:49:49 +00:00
|
|
|
impl<'ll, 'tcx> RecursiveTypeDescription<'ll, 'tcx> {
|
2019-05-17 01:20:14 +00:00
|
|
|
/// Finishes up the description of the type in question (mostly by providing
|
|
|
|
/// descriptions of the fields of the given type) and returns the final type
|
|
|
|
/// metadata.
|
2018-07-04 13:36:49 +00:00
|
|
|
fn finalize(&self, cx: &CodegenCx<'ll, 'tcx>) -> MetadataCreationResult<'ll> {
|
2015-04-29 06:14:37 +00:00
|
|
|
match *self {
|
|
|
|
FinalMetadata(metadata) => MetadataCreationResult::new(metadata, false),
|
|
|
|
UnfinishedMetadata {
|
|
|
|
unfinished_type,
|
|
|
|
unique_type_id,
|
|
|
|
metadata_stub,
|
2017-11-29 21:42:25 +00:00
|
|
|
member_holding_stub,
|
2015-04-29 06:14:37 +00:00
|
|
|
ref member_description_factory,
|
|
|
|
} => {
|
|
|
|
// Make sure that we have a forward declaration of the type in
|
|
|
|
// the TypeMap so that recursive references are possible. This
|
|
|
|
// will always be the case if the RecursiveTypeDescription has
|
|
|
|
// been properly created through the
|
2019-05-17 01:20:14 +00:00
|
|
|
// `create_and_register_recursive_type_forward_declaration()`
|
2015-04-29 06:14:37 +00:00
|
|
|
// function.
|
|
|
|
{
|
2022-02-04 12:19:55 +00:00
|
|
|
if debug_context(cx)
|
|
|
|
.type_map
|
|
|
|
.find_metadata_for_unique_id(unique_type_id)
|
|
|
|
.is_none()
|
2019-12-24 22:38:22 +00:00
|
|
|
{
|
|
|
|
bug!(
|
|
|
|
"Forward declaration of potentially recursive type \
|
2016-03-28 23:46:02 +00:00
|
|
|
'{:?}' was not found in TypeMap!",
|
2019-12-24 22:38:22 +00:00
|
|
|
unfinished_type
|
|
|
|
);
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ... then create the member descriptions ...
|
2019-12-24 22:38:22 +00:00
|
|
|
let member_descriptions = member_description_factory.create_member_descriptions(cx);
|
2022-01-25 13:26:50 +00:00
|
|
|
let type_params = compute_type_parameters(cx, unfinished_type);
|
2015-04-29 06:14:37 +00:00
|
|
|
|
|
|
|
// ... and attach them to the stub to complete it.
|
2019-12-24 22:38:22 +00:00
|
|
|
set_members_of_composite_type(
|
|
|
|
cx,
|
|
|
|
member_holding_stub,
|
|
|
|
member_descriptions,
|
2021-04-30 08:14:42 +00:00
|
|
|
None,
|
2022-01-25 13:26:50 +00:00
|
|
|
type_params,
|
2019-12-24 22:38:22 +00:00
|
|
|
);
|
2020-03-20 14:03:11 +00:00
|
|
|
MetadataCreationResult::new(metadata_stub, true)
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-04-24 04:48:10 +00:00
|
|
|
|
2019-05-17 01:20:14 +00:00
|
|
|
/// Returns from the enclosing function if the type metadata with the given
|
|
|
|
/// unique ID can be found in the type map.
|
2015-04-24 04:48:10 +00:00
|
|
|
macro_rules! return_if_metadata_created_in_meantime {
|
2019-12-24 22:38:22 +00:00
|
|
|
($cx: expr, $unique_type_id: expr) => {
|
|
|
|
if let Some(metadata) =
|
2022-02-04 12:19:55 +00:00
|
|
|
debug_context($cx).type_map.find_metadata_for_unique_id($unique_type_id)
|
2018-10-09 13:15:41 +00:00
|
|
|
{
|
2018-10-16 09:14:10 +00:00
|
|
|
return MetadataCreationResult::new(metadata, true);
|
2015-10-21 16:20:46 +00:00
|
|
|
}
|
2019-12-24 22:38:22 +00:00
|
|
|
};
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
|
2022-01-13 17:13:54 +00:00
|
|
|
/// Creates debuginfo for a fixed size array (e.g. `[u64; 123]`).
|
|
|
|
/// For slices (that is, "arrays" of unknown size) use [slice_type_metadata].
|
|
|
|
fn fixed_size_array_metadata<'ll, 'tcx>(
|
2018-07-04 13:36:49 +00:00
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
2022-02-04 12:19:55 +00:00
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
2022-01-13 17:13:54 +00:00
|
|
|
array_type: Ty<'tcx>,
|
2018-07-04 13:36:49 +00:00
|
|
|
) -> MetadataCreationResult<'ll> {
|
2022-01-13 17:13:54 +00:00
|
|
|
let ty::Array(element_type, len) = array_type.kind() else {
|
|
|
|
bug!("fixed_size_array_metadata() called with non-ty::Array type `{:?}`", array_type)
|
|
|
|
};
|
|
|
|
|
Overhaul `TyS` and `Ty`.
Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
means we can move a lot of methods away from `TyS`, leaving `TyS` as a
barely-used type, which is appropriate given that it's not meant to
be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
than via `TyS`, which wasn't obvious at all.
Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs
Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
`Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
(pointer-based, for the `Equal` case) and partly on `TyS`
(contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
or `&`. They seem to be unavoidable.
2022-01-25 03:13:38 +00:00
|
|
|
let element_type_metadata = type_metadata(cx, *element_type);
|
2015-04-24 04:48:10 +00:00
|
|
|
|
|
|
|
return_if_metadata_created_in_meantime!(cx, unique_type_id);
|
|
|
|
|
2022-01-13 17:13:54 +00:00
|
|
|
let (size, align) = cx.size_and_align_of(array_type);
|
2015-04-24 04:48:10 +00:00
|
|
|
|
2022-01-13 17:13:54 +00:00
|
|
|
let upper_bound = len.eval_usize(cx.tcx, ty::ParamEnv::reveal_all()) as c_longlong;
|
2015-04-24 04:48:10 +00:00
|
|
|
|
2019-12-24 22:38:22 +00:00
|
|
|
let subrange =
|
|
|
|
unsafe { Some(llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)) };
|
2015-04-24 04:48:10 +00:00
|
|
|
|
|
|
|
let subscripts = create_DIArray(DIB(cx), &[subrange]);
|
|
|
|
let metadata = unsafe {
|
2016-08-01 23:35:09 +00:00
|
|
|
llvm::LLVMRustDIBuilderCreateArrayType(
|
2015-04-24 04:48:10 +00:00
|
|
|
DIB(cx),
|
2017-06-01 18:50:53 +00:00
|
|
|
size.bits(),
|
2018-09-08 22:16:45 +00:00
|
|
|
align.bits() as u32,
|
2015-04-24 04:48:10 +00:00
|
|
|
element_type_metadata,
|
2019-12-24 22:38:22 +00:00
|
|
|
subscripts,
|
|
|
|
)
|
2015-04-24 04:48:10 +00:00
|
|
|
};
|
|
|
|
|
2020-03-20 14:03:11 +00:00
|
|
|
MetadataCreationResult::new(metadata, false)
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
|
2022-01-13 17:13:54 +00:00
|
|
|
/// Creates debuginfo for built-in pointer-like things:
|
|
|
|
///
|
|
|
|
/// - ty::Ref
|
|
|
|
/// - ty::RawPtr
|
|
|
|
/// - ty::Adt in the case it's Box
|
|
|
|
///
|
|
|
|
/// At some point we might want to remove the special handling of Box
|
|
|
|
/// and treat it the same as other smart pointers (like Rc, Arc, ...).
|
|
|
|
fn pointer_or_reference_metadata<'ll, 'tcx>(
|
2018-07-04 13:36:49 +00:00
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
2022-01-13 17:13:54 +00:00
|
|
|
ptr_type: Ty<'tcx>,
|
|
|
|
pointee_type: Ty<'tcx>,
|
2022-02-04 12:19:55 +00:00
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
2018-07-04 13:36:49 +00:00
|
|
|
) -> MetadataCreationResult<'ll> {
|
2022-01-13 17:13:54 +00:00
|
|
|
let pointee_type_metadata = type_metadata(cx, pointee_type);
|
2015-04-24 04:48:10 +00:00
|
|
|
|
|
|
|
return_if_metadata_created_in_meantime!(cx, unique_type_id);
|
|
|
|
|
2022-01-13 17:13:54 +00:00
|
|
|
let (thin_pointer_size, thin_pointer_align) =
|
|
|
|
cx.size_and_align_of(cx.tcx.mk_imm_ptr(cx.tcx.types.unit));
|
|
|
|
let ptr_type_debuginfo_name = compute_debuginfo_type_name(cx.tcx, ptr_type, true);
|
2015-04-24 04:48:10 +00:00
|
|
|
|
2022-01-13 17:13:54 +00:00
|
|
|
let pointer_type_metadata = match fat_pointer_kind(cx, pointee_type) {
|
|
|
|
None => {
|
|
|
|
// This is a thin pointer. Create a regular pointer type and give it the correct name.
|
|
|
|
debug_assert_eq!(
|
|
|
|
(thin_pointer_size, thin_pointer_align),
|
2022-02-23 16:11:50 +00:00
|
|
|
cx.size_and_align_of(ptr_type),
|
|
|
|
"ptr_type={}, pointee_type={}",
|
|
|
|
ptr_type,
|
|
|
|
pointee_type,
|
2022-01-13 17:13:54 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
llvm::LLVMRustDIBuilderCreatePointerType(
|
|
|
|
DIB(cx),
|
|
|
|
pointee_type_metadata,
|
|
|
|
thin_pointer_size.bits(),
|
|
|
|
thin_pointer_align.bits() as u32,
|
|
|
|
0, // Ignore DWARF address space.
|
|
|
|
ptr_type_debuginfo_name.as_ptr().cast(),
|
|
|
|
ptr_type_debuginfo_name.len(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Some(fat_pointer_kind) => {
|
|
|
|
let layout = cx.layout_of(ptr_type);
|
|
|
|
|
|
|
|
let addr_field = layout.field(cx, abi::FAT_PTR_ADDR);
|
|
|
|
let extra_field = layout.field(cx, abi::FAT_PTR_EXTRA);
|
|
|
|
|
|
|
|
let (addr_field_name, extra_field_name) = match fat_pointer_kind {
|
|
|
|
FatPtrKind::Dyn => ("pointer", "vtable"),
|
|
|
|
FatPtrKind::Slice => ("data_ptr", "length"),
|
|
|
|
};
|
|
|
|
|
|
|
|
debug_assert_eq!(abi::FAT_PTR_ADDR, 0);
|
|
|
|
debug_assert_eq!(abi::FAT_PTR_EXTRA, 1);
|
|
|
|
|
|
|
|
// The data pointer type is a regular, thin pointer, regardless of whether this is a slice
|
|
|
|
// or a trait object.
|
|
|
|
let data_ptr_type_metadata = unsafe {
|
|
|
|
llvm::LLVMRustDIBuilderCreatePointerType(
|
|
|
|
DIB(cx),
|
|
|
|
pointee_type_metadata,
|
|
|
|
addr_field.size.bits(),
|
|
|
|
addr_field.align.abi.bits() as u32,
|
|
|
|
0, // Ignore DWARF address space.
|
|
|
|
std::ptr::null(),
|
|
|
|
0,
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
|
|
|
let member_descriptions = vec![
|
|
|
|
MemberDescription {
|
|
|
|
name: addr_field_name.into(),
|
|
|
|
type_metadata: data_ptr_type_metadata,
|
|
|
|
offset: layout.fields.offset(abi::FAT_PTR_ADDR),
|
|
|
|
size: addr_field.size,
|
|
|
|
align: addr_field.align.abi,
|
2022-01-28 09:41:36 +00:00
|
|
|
flags: DIFlags::FlagZero,
|
2022-01-13 17:13:54 +00:00
|
|
|
discriminant: None,
|
|
|
|
source_info: None,
|
|
|
|
},
|
|
|
|
MemberDescription {
|
|
|
|
name: extra_field_name.into(),
|
|
|
|
type_metadata: type_metadata(cx, extra_field.ty),
|
|
|
|
offset: layout.fields.offset(abi::FAT_PTR_EXTRA),
|
|
|
|
size: extra_field.size,
|
|
|
|
align: extra_field.align.abi,
|
2022-01-28 09:41:36 +00:00
|
|
|
flags: DIFlags::FlagZero,
|
2022-01-13 17:13:54 +00:00
|
|
|
discriminant: None,
|
|
|
|
source_info: None,
|
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
composite_type_metadata(
|
|
|
|
cx,
|
|
|
|
ptr_type,
|
|
|
|
&ptr_type_debuginfo_name,
|
|
|
|
unique_type_id,
|
|
|
|
member_descriptions,
|
|
|
|
NO_SCOPE_METADATA,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
MetadataCreationResult { metadata: pointer_type_metadata, already_stored_in_typemap: false }
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
|
2021-12-14 18:49:49 +00:00
|
|
|
fn subroutine_type_metadata<'ll, 'tcx>(
|
2018-07-04 13:36:49 +00:00
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
2022-02-04 12:19:55 +00:00
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
2018-07-04 13:36:49 +00:00
|
|
|
) -> MetadataCreationResult<'ll> {
|
2022-02-04 12:19:55 +00:00
|
|
|
// 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 UniqueTypeId::Ty(fn_ty, _) = unique_type_id else {
|
|
|
|
bug!("subroutine_type_metadata() called with unexpected input type: {:?}", unique_type_id)
|
|
|
|
};
|
2015-04-24 04:48:10 +00:00
|
|
|
|
2022-02-04 12:19:55 +00:00
|
|
|
let signature = cx
|
|
|
|
.tcx
|
|
|
|
.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), fn_ty.fn_sig(cx.tcx));
|
2015-04-24 04:48:10 +00:00
|
|
|
|
2022-02-04 12:19:55 +00:00
|
|
|
let signature_metadata: SmallVec<[_; 32]> = iter::once(
|
2018-07-26 15:11:10 +00:00
|
|
|
// return type
|
2020-08-02 22:49:11 +00:00
|
|
|
match signature.output().kind() {
|
2022-02-04 12:19:55 +00:00
|
|
|
ty::Tuple(tys) if tys.is_empty() => {
|
|
|
|
// this is a "void" function
|
|
|
|
None
|
|
|
|
}
|
2022-01-10 14:59:52 +00:00
|
|
|
_ => Some(type_metadata(cx, signature.output())),
|
2019-12-24 22:38:22 +00:00
|
|
|
},
|
|
|
|
)
|
|
|
|
.chain(
|
2018-07-26 15:11:10 +00:00
|
|
|
// regular arguments
|
Overhaul `TyS` and `Ty`.
Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
means we can move a lot of methods away from `TyS`, leaving `TyS` as a
barely-used type, which is appropriate given that it's not meant to
be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
than via `TyS`, which wasn't obvious at all.
Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs
Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
`Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
(pointer-based, for the `Equal` case) and partly on `TyS`
(contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
or `&`. They seem to be unavoidable.
2022-01-25 03:13:38 +00:00
|
|
|
signature.inputs().iter().map(|&argument_type| Some(type_metadata(cx, argument_type))),
|
2019-12-24 22:38:22 +00:00
|
|
|
)
|
|
|
|
.collect();
|
2015-04-24 04:48:10 +00:00
|
|
|
|
2022-02-04 12:19:55 +00:00
|
|
|
debug_context(cx).type_map.unique_id_to_metadata.borrow_mut().remove(&unique_type_id);
|
2015-04-24 04:48:10 +00:00
|
|
|
|
2022-02-04 12:19:55 +00:00
|
|
|
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)
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
|
2022-01-21 09:35:18 +00:00
|
|
|
/// Create debuginfo for `dyn SomeTrait` types. Currently these are empty structs
|
|
|
|
/// we with the correct type name (e.g. "dyn SomeTrait<Foo, Item=u32> + Sync").
|
2022-01-13 17:13:54 +00:00
|
|
|
fn dyn_type_metadata<'ll, 'tcx>(
|
2018-07-04 13:36:49 +00:00
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
2022-01-13 17:13:54 +00:00
|
|
|
dyn_type: Ty<'tcx>,
|
2022-02-04 12:19:55 +00:00
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
2018-07-04 13:36:49 +00:00
|
|
|
) -> &'ll DIType {
|
2022-01-13 17:13:54 +00:00
|
|
|
if let ty::Dynamic(..) = dyn_type.kind() {
|
|
|
|
let type_name = compute_debuginfo_type_name(cx.tcx, dyn_type, true);
|
|
|
|
composite_type_metadata(cx, dyn_type, &type_name, unique_type_id, vec![], NO_SCOPE_METADATA)
|
|
|
|
} else {
|
|
|
|
bug!("Only ty::Dynamic is valid for dyn_type_metadata(). Found {:?} instead.", dyn_type)
|
|
|
|
}
|
|
|
|
}
|
2015-04-24 04:48:10 +00:00
|
|
|
|
2022-01-21 09:35:18 +00:00
|
|
|
/// Create debuginfo for `[T]` and `str`. These are unsized.
|
|
|
|
///
|
2022-01-27 15:55:48 +00:00
|
|
|
/// NOTE: We currently emit just emit the debuginfo for the element type here
|
|
|
|
/// (i.e. `T` for slices and `u8` for `str`), so that we end up with
|
|
|
|
/// `*const T` for the `data_ptr` field of the corresponding fat-pointer
|
|
|
|
/// debuginfo of `&[T]`.
|
2022-01-21 09:35:18 +00:00
|
|
|
///
|
2022-01-27 15:55:48 +00:00
|
|
|
/// It would be preferable and more accurate if we emitted a DIArray of T
|
|
|
|
/// without an upper bound instead. That is, LLVM already supports emitting
|
|
|
|
/// debuginfo of arrays of unknown size. But GDB currently seems to end up
|
|
|
|
/// in an infinite loop when confronted with such a type.
|
2022-01-21 09:35:18 +00:00
|
|
|
///
|
2022-01-27 15:55:48 +00:00
|
|
|
/// As a side effect of the current encoding every instance of a type like
|
|
|
|
/// `struct Foo { unsized_field: [u8] }` will look like
|
|
|
|
/// `struct Foo { unsized_field: u8 }` in debuginfo. If the length of the
|
|
|
|
/// slice is zero, then accessing `unsized_field` in the debugger would
|
|
|
|
/// result in an out-of-bounds access.
|
2022-01-13 17:13:54 +00:00
|
|
|
fn slice_type_metadata<'ll, 'tcx>(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
slice_type: Ty<'tcx>,
|
2022-02-04 12:19:55 +00:00
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
2022-01-13 17:13:54 +00:00
|
|
|
) -> MetadataCreationResult<'ll> {
|
|
|
|
let element_type = match slice_type.kind() {
|
Overhaul `TyS` and `Ty`.
Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
means we can move a lot of methods away from `TyS`, leaving `TyS` as a
barely-used type, which is appropriate given that it's not meant to
be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
than via `TyS`, which wasn't obvious at all.
Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs
Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
`Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
(pointer-based, for the `Equal` case) and partly on `TyS`
(contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
or `&`. They seem to be unavoidable.
2022-01-25 03:13:38 +00:00
|
|
|
ty::Slice(element_type) => *element_type,
|
2022-01-13 17:13:54 +00:00
|
|
|
ty::Str => cx.tcx.types.u8,
|
|
|
|
_ => {
|
|
|
|
bug!(
|
|
|
|
"Only ty::Slice is valid for slice_type_metadata(). Found {:?} instead.",
|
|
|
|
slice_type
|
|
|
|
)
|
|
|
|
}
|
Improve debug symbol names to avoid ambiguity and work better with MSVC's debugger
There are several cases where names of types and functions in the debug info are either ambiguous, or not helpful, such as including ambiguous placeholders (e.g., `{{impl}}`, `{{closure}}` or `dyn _'`) or dropping qualifications (e.g., for dynamic types).
Instead, each debug symbol name should be unique and useful:
* Include disambiguators for anonymous `DefPathDataName` (closures and generators), and unify their formatting when used as a path-qualifier vs item being qualified.
* Qualify the principal trait for dynamic types.
* If there is no principal trait for a dynamic type, emit all other traits instead.
* Respect the `qualified` argument when emitting ref and pointer types.
* For implementations, emit the disambiguator.
* Print const generics when emitting generic parameters or arguments.
Additionally, when targeting MSVC, its debugger treats many command arguments as C++ expressions, even when the argument is defined to be a symbol name. As such names in the debug info need to be more C++-like to be parsed correctly:
* Avoid characters with special meaning (`#`, `[`, `"`, `+`).
* Never start a name with `<` or `{` as this is treated as an operator.
* `>>` is always treated as a right-shift, even when parsing generic arguments (so add a space to avoid this).
* Emit function declarations using C/C++ style syntax (e.g., leading return type).
* Emit arrays as a synthetic `array$<type, size>` type.
* Include a `$` in all synthetic types as this is a legal character for C++, but not Rust (thus we avoid collisions with user types).
2021-06-24 17:36:28 +00:00
|
|
|
};
|
2015-04-24 04:48:10 +00:00
|
|
|
|
2022-01-13 17:13:54 +00:00
|
|
|
let element_type_metadata = type_metadata(cx, element_type);
|
|
|
|
return_if_metadata_created_in_meantime!(cx, unique_type_id);
|
|
|
|
MetadataCreationResult { metadata: element_type_metadata, already_stored_in_typemap: false }
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
|
2022-01-10 14:59:52 +00:00
|
|
|
pub fn type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
|
2022-02-04 12:19:55 +00:00
|
|
|
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;
|
|
|
|
}
|
2015-04-24 04:48:10 +00:00
|
|
|
|
|
|
|
debug!("type_metadata: {:?}", t);
|
|
|
|
|
2020-08-02 22:49:11 +00:00
|
|
|
let MetadataCreationResult { metadata, already_stored_in_typemap } = match *t.kind() {
|
2019-12-24 22:38:22 +00:00
|
|
|
ty::Never | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) => {
|
2015-04-24 04:48:10 +00:00
|
|
|
MetadataCreationResult::new(basic_type_metadata(cx, t), false)
|
|
|
|
}
|
2021-09-30 17:38:50 +00:00
|
|
|
ty::Tuple(elements) if elements.is_empty() => {
|
2015-04-24 04:48:10 +00:00
|
|
|
MetadataCreationResult::new(basic_type_metadata(cx, t), false)
|
|
|
|
}
|
2022-01-13 17:13:54 +00:00
|
|
|
ty::Array(..) => fixed_size_array_metadata(cx, unique_type_id, t),
|
|
|
|
ty::Slice(_) | ty::Str => slice_type_metadata(cx, t, unique_type_id),
|
2018-08-22 00:35:02 +00:00
|
|
|
ty::Dynamic(..) => {
|
2022-01-13 17:13:54 +00:00
|
|
|
MetadataCreationResult::new(dyn_type_metadata(cx, t, unique_type_id), false)
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
2018-08-22 00:35:29 +00:00
|
|
|
ty::Foreign(..) => {
|
2019-12-24 22:38:22 +00:00
|
|
|
MetadataCreationResult::new(foreign_type_metadata(cx, t, unique_type_id), false)
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
2022-01-13 17:13:54 +00:00
|
|
|
ty::RawPtr(ty::TypeAndMut { ty: pointee_type, .. }) | ty::Ref(_, pointee_type, _) => {
|
|
|
|
pointer_or_reference_metadata(cx, t, pointee_type, unique_type_id)
|
|
|
|
}
|
|
|
|
ty::Adt(def, _) if def.is_box() => {
|
|
|
|
pointer_or_reference_metadata(cx, t, t.boxed_ty(), unique_type_id)
|
|
|
|
}
|
2022-02-04 12:19:55 +00:00
|
|
|
ty::FnDef(..) | ty::FnPtr(_) => subroutine_type_metadata(cx, unique_type_id),
|
2018-08-22 00:35:02 +00:00
|
|
|
ty::Closure(def_id, substs) => {
|
2020-03-13 01:23:38 +00:00
|
|
|
let upvar_tys: Vec<_> = substs.as_closure().upvar_tys().collect();
|
2019-08-25 03:01:46 +00:00
|
|
|
let containing_scope = get_namespace_for_item(cx, def_id);
|
2022-01-10 14:59:52 +00:00
|
|
|
prepare_tuple_metadata(cx, t, &upvar_tys, unique_type_id, Some(containing_scope))
|
|
|
|
.finalize(cx)
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
2019-12-24 22:38:22 +00:00
|
|
|
ty::Generator(def_id, substs, _) => {
|
|
|
|
let upvar_tys: Vec<_> = substs
|
|
|
|
.as_generator()
|
2020-03-13 01:23:38 +00:00
|
|
|
.prefix_tys()
|
2019-12-24 22:38:22 +00:00
|
|
|
.map(|t| cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t))
|
|
|
|
.collect();
|
2022-01-10 14:59:52 +00:00
|
|
|
prepare_enum_metadata(cx, t, def_id, unique_type_id, upvar_tys).finalize(cx)
|
2016-12-26 13:34:03 +00:00
|
|
|
}
|
2018-08-22 00:35:02 +00:00
|
|
|
ty::Adt(def, ..) => match def.adt_kind() {
|
2022-01-10 14:59:52 +00:00
|
|
|
AdtKind::Struct => prepare_struct_metadata(cx, t, unique_type_id).finalize(cx),
|
|
|
|
AdtKind::Union => prepare_union_metadata(cx, t, unique_type_id).finalize(cx),
|
2016-09-05 22:26:02 +00:00
|
|
|
AdtKind::Enum => {
|
2022-01-10 14:59:52 +00:00
|
|
|
prepare_enum_metadata(cx, t, def.did, unique_type_id, vec![]).finalize(cx)
|
2016-09-05 22:26:02 +00:00
|
|
|
}
|
|
|
|
},
|
2022-02-07 15:06:31 +00:00
|
|
|
ty::Tuple(tys) => {
|
|
|
|
prepare_tuple_metadata(cx, t, tys, unique_type_id, NO_SCOPE_METADATA).finalize(cx)
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
2020-06-22 12:36:53 +00:00
|
|
|
// Type parameters from polymorphized functions.
|
|
|
|
ty::Param(_) => MetadataCreationResult::new(param_type_metadata(cx, t), false),
|
2019-12-24 22:38:22 +00:00
|
|
|
_ => bug!("debuginfo: unexpected type in type_metadata: {:?}", t),
|
2015-04-24 04:48:10 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
{
|
|
|
|
if already_stored_in_typemap {
|
2022-02-04 12:19:55 +00:00
|
|
|
// 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 => {
|
2022-01-10 14:59:52 +00:00
|
|
|
bug!(
|
2022-02-04 12:19:55 +00:00
|
|
|
"expected type metadata for unique \
|
|
|
|
type ID '{:?}' to already be in \
|
|
|
|
the `debuginfo::TypeMap` but it \
|
2022-02-24 16:19:18 +00:00
|
|
|
was not.",
|
2022-02-04 12:19:55 +00:00
|
|
|
unique_type_id,
|
2019-12-24 22:38:22 +00:00
|
|
|
);
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
2022-02-04 12:19:55 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
debug_assert_eq!(metadata_for_uid as *const _, metadata as *const _);
|
2015-04-24 04:48:10 +00:00
|
|
|
} else {
|
2022-02-04 12:19:55 +00:00
|
|
|
debug_context(cx).type_map.register_unique_id_with_metadata(unique_type_id, metadata);
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
metadata
|
|
|
|
}
|
|
|
|
|
2022-02-04 12:19:55 +00:00
|
|
|
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.
|
2022-02-24 16:19:18 +00:00
|
|
|
//
|
|
|
|
// FIXME: it might make sense to use an actual pointer type here
|
|
|
|
// so that debuggers can show the address.
|
2022-02-04 12:19:55 +00:00
|
|
|
let name = "<recur_type>";
|
|
|
|
llvm::LLVMRustDIBuilderCreateBasicType(
|
|
|
|
DIB(cx),
|
|
|
|
name.as_ptr().cast(),
|
|
|
|
name.len(),
|
|
|
|
cx.tcx.data_layout.pointer_size.bits(),
|
|
|
|
DW_ATE_unsigned,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-03-31 05:17:15 +00:00
|
|
|
fn hex_encode(data: &[u8]) -> String {
|
|
|
|
let mut hex_string = String::with_capacity(data.len() * 2);
|
|
|
|
for byte in data.iter() {
|
|
|
|
write!(&mut hex_string, "{:02x}", byte).unwrap();
|
|
|
|
}
|
|
|
|
hex_string
|
|
|
|
}
|
|
|
|
|
2021-12-14 18:49:49 +00:00
|
|
|
pub fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) -> &'ll DIFile {
|
2021-04-19 22:27:02 +00:00
|
|
|
debug!("file_metadata: file_name: {:?}", source_file.name);
|
2015-04-24 04:48:10 +00:00
|
|
|
|
2020-04-05 08:43:44 +00:00
|
|
|
let hash = Some(&source_file.src_hash);
|
2021-04-19 22:27:02 +00:00
|
|
|
let file_name = Some(source_file.name.prefer_remapped().to_string());
|
2020-02-10 01:03:24 +00:00
|
|
|
let directory = if source_file.is_real_file() && !source_file.is_imported() {
|
2021-08-26 10:46:01 +00:00
|
|
|
Some(
|
|
|
|
cx.sess()
|
|
|
|
.opts
|
|
|
|
.working_dir
|
|
|
|
.to_string_lossy(FileNameDisplayPreference::Remapped)
|
|
|
|
.to_string(),
|
|
|
|
)
|
2017-04-24 17:01:19 +00:00
|
|
|
} else {
|
|
|
|
// If the path comes from an upstream crate we assume it has been made
|
|
|
|
// independent of the compiler's working directory one way or another.
|
2019-05-06 01:47:03 +00:00
|
|
|
None
|
|
|
|
};
|
2020-03-31 05:17:15 +00:00
|
|
|
file_metadata_raw(cx, file_name, directory, hash)
|
Workaround ODR violations in enum debuginfo
When using a generic enum type that was defined in an external crate,
our debuginfo currently claims that the concrete type (e.g. Option<i32>)
was defined in the current crate, where it was first used.
This means that if there are multiple crates that all use, for example,
Option<i32> values, they'll have conflicting debuginfo, each crate
claiming to have defined that type. This doesn't cause problems in
regular builds, but with LTO enabled, LLVM complains because it tries to
merge the debuginfo for those types and sees the ODR violations.
Since I couldn't find a way to get the file info for the external crate
that actually defined the enum, I'm working around the issue by using
"<unknown>" as the file for enum types. We'll want to re-visit and fix
this later, but this at least this fixes the ICE. And with the file
being unknown instead of wrong, the debuginfo isn't really worse than
before either.
Fixes #26447
2015-07-29 11:53:59 +00:00
|
|
|
}
|
|
|
|
|
2021-12-14 18:49:49 +00:00
|
|
|
pub fn unknown_file_metadata<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile {
|
2020-03-31 05:17:15 +00:00
|
|
|
file_metadata_raw(cx, None, None, None)
|
Workaround ODR violations in enum debuginfo
When using a generic enum type that was defined in an external crate,
our debuginfo currently claims that the concrete type (e.g. Option<i32>)
was defined in the current crate, where it was first used.
This means that if there are multiple crates that all use, for example,
Option<i32> values, they'll have conflicting debuginfo, each crate
claiming to have defined that type. This doesn't cause problems in
regular builds, but with LTO enabled, LLVM complains because it tries to
merge the debuginfo for those types and sees the ODR violations.
Since I couldn't find a way to get the file info for the external crate
that actually defined the enum, I'm working around the issue by using
"<unknown>" as the file for enum types. We'll want to re-visit and fix
this later, but this at least this fixes the ICE. And with the file
being unknown instead of wrong, the debuginfo isn't really worse than
before either.
Fixes #26447
2015-07-29 11:53:59 +00:00
|
|
|
}
|
|
|
|
|
2021-12-14 18:49:49 +00:00
|
|
|
fn file_metadata_raw<'ll>(
|
2019-12-24 22:38:22 +00:00
|
|
|
cx: &CodegenCx<'ll, '_>,
|
|
|
|
file_name: Option<String>,
|
|
|
|
directory: Option<String>,
|
2020-03-31 05:17:15 +00:00
|
|
|
hash: Option<&SourceFileHash>,
|
2019-12-24 22:38:22 +00:00
|
|
|
) -> &'ll DIFile {
|
2019-05-06 01:47:03 +00:00
|
|
|
let key = (file_name, directory);
|
|
|
|
|
|
|
|
match debug_context(cx).created_files.borrow_mut().entry(key) {
|
2020-03-20 14:03:11 +00:00
|
|
|
Entry::Occupied(o) => o.get(),
|
2019-05-06 01:47:03 +00:00
|
|
|
Entry::Vacant(v) => {
|
|
|
|
let (file_name, directory) = v.key();
|
|
|
|
debug!("file_metadata: file_name: {:?}, directory: {:?}", file_name, directory);
|
|
|
|
|
2020-03-06 00:00:00 +00:00
|
|
|
let file_name = file_name.as_deref().unwrap_or("<unknown>");
|
|
|
|
let directory = directory.as_deref().unwrap_or("");
|
2019-05-06 01:47:03 +00:00
|
|
|
|
2020-03-31 05:17:15 +00:00
|
|
|
let (hash_kind, hash_value) = match hash {
|
|
|
|
Some(hash) => {
|
|
|
|
let kind = match hash.kind {
|
|
|
|
rustc_span::SourceFileHashAlgorithm::Md5 => llvm::ChecksumKind::MD5,
|
|
|
|
rustc_span::SourceFileHashAlgorithm::Sha1 => llvm::ChecksumKind::SHA1,
|
2020-10-13 15:41:06 +00:00
|
|
|
rustc_span::SourceFileHashAlgorithm::Sha256 => llvm::ChecksumKind::SHA256,
|
2020-03-31 05:17:15 +00:00
|
|
|
};
|
|
|
|
(kind, hex_encode(hash.hash_bytes()))
|
|
|
|
}
|
|
|
|
None => (llvm::ChecksumKind::None, String::new()),
|
|
|
|
};
|
|
|
|
|
2019-05-06 01:47:03 +00:00
|
|
|
let file_metadata = unsafe {
|
2020-03-06 00:00:00 +00:00
|
|
|
llvm::LLVMRustDIBuilderCreateFile(
|
|
|
|
DIB(cx),
|
|
|
|
file_name.as_ptr().cast(),
|
|
|
|
file_name.len(),
|
|
|
|
directory.as_ptr().cast(),
|
|
|
|
directory.len(),
|
2020-03-31 05:17:15 +00:00
|
|
|
hash_kind,
|
|
|
|
hash_value.as_ptr().cast(),
|
|
|
|
hash_value.len(),
|
2020-03-06 00:00:00 +00:00
|
|
|
)
|
2019-05-06 01:47:03 +00:00
|
|
|
};
|
2017-04-24 17:01:19 +00:00
|
|
|
|
2019-05-06 01:47:03 +00:00
|
|
|
v.insert(file_metadata);
|
|
|
|
file_metadata
|
|
|
|
}
|
Workaround ODR violations in enum debuginfo
When using a generic enum type that was defined in an external crate,
our debuginfo currently claims that the concrete type (e.g. Option<i32>)
was defined in the current crate, where it was first used.
This means that if there are multiple crates that all use, for example,
Option<i32> values, they'll have conflicting debuginfo, each crate
claiming to have defined that type. This doesn't cause problems in
regular builds, but with LTO enabled, LLVM complains because it tries to
merge the debuginfo for those types and sees the ODR violations.
Since I couldn't find a way to get the file info for the external crate
that actually defined the enum, I'm working around the issue by using
"<unknown>" as the file for enum types. We'll want to re-visit and fix
this later, but this at least this fixes the ICE. And with the file
being unknown instead of wrong, the debuginfo isn't really worse than
before either.
Fixes #26447
2015-07-29 11:53:59 +00:00
|
|
|
}
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
|
2020-06-25 06:28:00 +00:00
|
|
|
trait MsvcBasicName {
|
|
|
|
fn msvc_basic_name(self) -> &'static str;
|
|
|
|
}
|
|
|
|
|
2020-12-12 14:32:30 +00:00
|
|
|
impl MsvcBasicName for ty::IntTy {
|
2020-06-25 06:28:00 +00:00
|
|
|
fn msvc_basic_name(self) -> &'static str {
|
|
|
|
match self {
|
2020-12-12 14:32:30 +00:00
|
|
|
ty::IntTy::Isize => "ptrdiff_t",
|
|
|
|
ty::IntTy::I8 => "__int8",
|
|
|
|
ty::IntTy::I16 => "__int16",
|
|
|
|
ty::IntTy::I32 => "__int32",
|
|
|
|
ty::IntTy::I64 => "__int64",
|
|
|
|
ty::IntTy::I128 => "__int128",
|
2020-06-25 06:28:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-12 14:32:30 +00:00
|
|
|
impl MsvcBasicName for ty::UintTy {
|
2020-06-25 06:28:00 +00:00
|
|
|
fn msvc_basic_name(self) -> &'static str {
|
|
|
|
match self {
|
2020-12-12 14:32:30 +00:00
|
|
|
ty::UintTy::Usize => "size_t",
|
|
|
|
ty::UintTy::U8 => "unsigned __int8",
|
|
|
|
ty::UintTy::U16 => "unsigned __int16",
|
|
|
|
ty::UintTy::U32 => "unsigned __int32",
|
|
|
|
ty::UintTy::U64 => "unsigned __int64",
|
|
|
|
ty::UintTy::U128 => "unsigned __int128",
|
2020-06-25 06:28:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-12 14:32:30 +00:00
|
|
|
impl MsvcBasicName for ty::FloatTy {
|
2020-06-25 06:28:00 +00:00
|
|
|
fn msvc_basic_name(self) -> &'static str {
|
|
|
|
match self {
|
2020-12-12 14:32:30 +00:00
|
|
|
ty::FloatTy::F32 => "float",
|
|
|
|
ty::FloatTy::F64 => "double",
|
2020-06-25 06:28:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-14 18:49:49 +00:00
|
|
|
fn basic_type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
|
2015-04-24 04:48:10 +00:00
|
|
|
debug!("basic_type_metadata: {:?}", t);
|
|
|
|
|
2020-06-25 06:28:00 +00:00
|
|
|
// When targeting MSVC, emit MSVC style type names for compatibility with
|
|
|
|
// .natvis visualizers (and perhaps other existing native debuggers?)
|
2021-12-28 21:57:18 +00:00
|
|
|
let cpp_like_debuginfo = cpp_like_debuginfo(cx.tcx);
|
2020-06-25 06:28:00 +00:00
|
|
|
|
2020-08-02 22:49:11 +00:00
|
|
|
let (name, encoding) = match t.kind() {
|
2018-08-22 00:35:02 +00:00
|
|
|
ty::Never => ("!", DW_ATE_unsigned),
|
2021-09-30 17:38:50 +00:00
|
|
|
ty::Tuple(elements) if elements.is_empty() => ("()", DW_ATE_unsigned),
|
2018-08-22 00:35:55 +00:00
|
|
|
ty::Bool => ("bool", DW_ATE_boolean),
|
2021-10-14 17:26:42 +00:00
|
|
|
ty::Char => ("char", DW_ATE_UTF),
|
2021-12-28 21:57:18 +00:00
|
|
|
ty::Int(int_ty) if cpp_like_debuginfo => (int_ty.msvc_basic_name(), DW_ATE_signed),
|
|
|
|
ty::Uint(uint_ty) if cpp_like_debuginfo => (uint_ty.msvc_basic_name(), DW_ATE_unsigned),
|
|
|
|
ty::Float(float_ty) if cpp_like_debuginfo => (float_ty.msvc_basic_name(), DW_ATE_float),
|
2019-12-24 22:38:22 +00:00
|
|
|
ty::Int(int_ty) => (int_ty.name_str(), DW_ATE_signed),
|
|
|
|
ty::Uint(uint_ty) => (uint_ty.name_str(), DW_ATE_unsigned),
|
|
|
|
ty::Float(float_ty) => (float_ty.name_str(), DW_ATE_float),
|
|
|
|
_ => bug!("debuginfo::basic_type_metadata - `t` is invalid type"),
|
2015-04-24 04:48:10 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
let ty_metadata = unsafe {
|
2016-08-01 23:35:09 +00:00
|
|
|
llvm::LLVMRustDIBuilderCreateBasicType(
|
2015-04-24 04:48:10 +00:00
|
|
|
DIB(cx),
|
2020-03-06 00:00:00 +00:00
|
|
|
name.as_ptr().cast(),
|
|
|
|
name.len(),
|
2020-05-21 17:53:41 +00:00
|
|
|
cx.size_of(t).bits(),
|
2019-12-24 22:38:22 +00:00
|
|
|
encoding,
|
|
|
|
)
|
2015-04-24 04:48:10 +00:00
|
|
|
};
|
|
|
|
|
2021-12-28 21:57:18 +00:00
|
|
|
if !cpp_like_debuginfo {
|
2020-06-25 06:28:00 +00:00
|
|
|
return ty_metadata;
|
|
|
|
}
|
|
|
|
|
2020-08-02 22:49:11 +00:00
|
|
|
let typedef_name = match t.kind() {
|
2020-06-25 06:28:00 +00:00
|
|
|
ty::Int(int_ty) => int_ty.name_str(),
|
|
|
|
ty::Uint(uint_ty) => uint_ty.name_str(),
|
|
|
|
ty::Float(float_ty) => float_ty.name_str(),
|
|
|
|
_ => return ty_metadata,
|
|
|
|
};
|
|
|
|
|
|
|
|
let typedef_metadata = unsafe {
|
|
|
|
llvm::LLVMRustDIBuilderCreateTypedef(
|
|
|
|
DIB(cx),
|
|
|
|
ty_metadata,
|
|
|
|
typedef_name.as_ptr().cast(),
|
|
|
|
typedef_name.len(),
|
|
|
|
unknown_file_metadata(cx),
|
|
|
|
0,
|
|
|
|
None,
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef_metadata
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
|
2021-12-14 18:49:49 +00:00
|
|
|
fn foreign_type_metadata<'ll, 'tcx>(
|
2018-07-04 13:36:49 +00:00
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
t: Ty<'tcx>,
|
2022-02-04 12:19:55 +00:00
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
2018-07-04 13:36:49 +00:00
|
|
|
) -> &'ll DIType {
|
2017-09-03 18:53:58 +00:00
|
|
|
debug!("foreign_type_metadata: {:?}", t);
|
|
|
|
|
2019-03-30 14:45:09 +00:00
|
|
|
let name = compute_debuginfo_type_name(cx.tcx, t, false);
|
2022-01-25 13:26:50 +00:00
|
|
|
let (size, align) = cx.size_and_align_of(t);
|
|
|
|
create_struct_stub(
|
|
|
|
cx,
|
|
|
|
size,
|
|
|
|
align,
|
|
|
|
&name,
|
|
|
|
unique_type_id,
|
|
|
|
NO_SCOPE_METADATA,
|
|
|
|
DIFlags::FlagZero,
|
|
|
|
None,
|
|
|
|
)
|
2017-09-03 18:53:58 +00:00
|
|
|
}
|
|
|
|
|
2021-12-14 18:49:49 +00:00
|
|
|
fn param_type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
|
2020-06-22 12:36:53 +00:00
|
|
|
debug!("param_type_metadata: {:?}", t);
|
|
|
|
let name = format!("{:?}", t);
|
2020-08-07 22:39:38 +00:00
|
|
|
unsafe {
|
2020-06-22 12:36:53 +00:00
|
|
|
llvm::LLVMRustDIBuilderCreateBasicType(
|
|
|
|
DIB(cx),
|
|
|
|
name.as_ptr().cast(),
|
|
|
|
name.len(),
|
|
|
|
Size::ZERO.bits(),
|
|
|
|
DW_ATE_unsigned,
|
|
|
|
)
|
2020-08-07 22:39:38 +00:00
|
|
|
}
|
2020-06-22 12:36:53 +00:00
|
|
|
}
|
|
|
|
|
2021-12-14 18:49:49 +00:00
|
|
|
pub fn compile_unit_metadata<'ll, 'tcx>(
|
|
|
|
tcx: TyCtxt<'tcx>,
|
2019-06-11 21:11:55 +00:00
|
|
|
codegen_unit_name: &str,
|
2021-12-14 18:49:49 +00:00
|
|
|
debug_context: &CrateDebugContext<'ll, 'tcx>,
|
2019-06-11 21:11:55 +00:00
|
|
|
) -> &'ll DIDescriptor {
|
2018-01-05 04:14:44 +00:00
|
|
|
let mut name_in_debuginfo = match tcx.sess.local_crate_source_file {
|
2017-05-19 08:55:25 +00:00
|
|
|
Some(ref path) => path.clone(),
|
2021-12-15 03:39:23 +00:00
|
|
|
None => PathBuf::from(tcx.crate_name(LOCAL_CRATE).as_str()),
|
2015-04-24 04:48:10 +00:00
|
|
|
};
|
|
|
|
|
2021-12-17 04:39:41 +00:00
|
|
|
// To avoid breaking split DWARF, we need to ensure that each codegen unit
|
|
|
|
// has a unique `DW_AT_name`. This is because there's a remote chance that
|
|
|
|
// different codegen units for the same module will have entirely
|
|
|
|
// identical DWARF entries for the purpose of the DWO ID, which would
|
|
|
|
// violate Appendix F ("Split Dwarf Object Files") of the DWARF 5
|
|
|
|
// specification. LLVM uses the algorithm specified in section 7.32 "Type
|
|
|
|
// Signature Computation" to compute the DWO ID, which does not include
|
|
|
|
// any fields that would distinguish compilation units. So we must embed
|
|
|
|
// the codegen unit name into the `DW_AT_name`. (Issue #88521.)
|
|
|
|
//
|
|
|
|
// Additionally, the OSX linker has an idiosyncrasy where it will ignore
|
|
|
|
// some debuginfo if multiple object files with the same `DW_AT_name` are
|
|
|
|
// linked together.
|
|
|
|
//
|
|
|
|
// As a workaround for these two issues, we generate unique names for each
|
|
|
|
// object file. Those do not correspond to an actual source file but that
|
|
|
|
// is harmless.
|
|
|
|
name_in_debuginfo.push("@");
|
|
|
|
name_in_debuginfo.push(codegen_unit_name);
|
2017-05-19 08:55:25 +00:00
|
|
|
|
|
|
|
debug!("compile_unit_metadata: {:?}", name_in_debuginfo);
|
2019-12-24 22:38:22 +00:00
|
|
|
let rustc_producer =
|
|
|
|
format!("rustc version {}", option_env!("CFG_VERSION").expect("CFG_VERSION"),);
|
2017-03-08 18:08:09 +00:00
|
|
|
// FIXME(#41252) Remove "clang LLVM" if we can get GDB and LLVM to play nice.
|
2019-07-19 14:08:37 +00:00
|
|
|
let producer = format!("clang LLVM ({})", rustc_producer);
|
2015-04-24 04:48:10 +00:00
|
|
|
|
2018-08-07 14:04:34 +00:00
|
|
|
let name_in_debuginfo = name_in_debuginfo.to_string_lossy();
|
2021-08-26 10:46:01 +00:00
|
|
|
let work_dir = tcx.sess.opts.working_dir.to_string_lossy(FileNameDisplayPreference::Remapped);
|
2015-04-24 04:48:10 +00:00
|
|
|
let flags = "\0";
|
2021-05-11 12:39:04 +00:00
|
|
|
let output_filenames = tcx.output_filenames(());
|
2020-11-30 16:39:08 +00:00
|
|
|
let split_name = if tcx.sess.target_can_use_split_dwarf() {
|
2021-05-11 12:39:04 +00:00
|
|
|
output_filenames
|
sess/cg: re-introduce split dwarf kind
In #79570, `-Z split-dwarf-kind={none,single,split}` was replaced by `-C
split-debuginfo={off,packed,unpacked}`. `-C split-debuginfo`'s packed
and unpacked aren't exact parallels to single and split, respectively.
On Unix, `-C split-debuginfo=packed` will put debuginfo into object
files and package debuginfo into a DWARF package file (`.dwp`) and
`-C split-debuginfo=unpacked` will put debuginfo into dwarf object files
and won't package it.
In the initial implementation of Split DWARF, split mode wrote sections
which did not require relocation into a DWARF object (`.dwo`) file which
was ignored by the linker and then packaged those DWARF objects into
DWARF packages (`.dwp`). In single mode, sections which did not require
relocation were written into object files but ignored by the linker and
were not packaged. However, both split and single modes could be
packaged or not, the primary difference in behaviour was where the
debuginfo sections that did not require link-time relocation were
written (in a DWARF object or the object file).
This commit re-introduces a `-Z split-dwarf-kind` flag, which can be
used to pick between split and single modes when `-C split-debuginfo` is
used to enable Split DWARF (either packed or unpacked).
Signed-off-by: David Wood <david.wood@huawei.com>
2021-10-08 16:10:17 +00:00
|
|
|
.split_dwarf_path(
|
|
|
|
tcx.sess.split_debuginfo(),
|
|
|
|
tcx.sess.opts.debugging_opts.split_dwarf_kind,
|
|
|
|
Some(codegen_unit_name),
|
|
|
|
)
|
2021-12-06 23:59:59 +00:00
|
|
|
// We get a path relative to the working directory from split_dwarf_path
|
|
|
|
.map(|f| tcx.sess.source_map().path_mapping().map_prefix(f).0)
|
2020-11-30 16:39:08 +00:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
.unwrap_or_default();
|
2020-09-23 16:33:54 +00:00
|
|
|
let split_name = split_name.to_str().unwrap();
|
2019-05-21 11:41:44 +00:00
|
|
|
|
|
|
|
// FIXME(#60020):
|
|
|
|
//
|
|
|
|
// This should actually be
|
|
|
|
//
|
2019-05-17 01:20:14 +00:00
|
|
|
// let kind = DebugEmissionKind::from_generic(tcx.sess.opts.debuginfo);
|
2019-05-21 11:41:44 +00:00
|
|
|
//
|
2019-05-17 01:20:14 +00:00
|
|
|
// That is, we should set LLVM's emission kind to `LineTablesOnly` if
|
2019-05-21 11:41:44 +00:00
|
|
|
// we are compiling with "limited" debuginfo. However, some of the
|
|
|
|
// existing tools relied on slightly more debuginfo being generated than
|
|
|
|
// would be the case with `LineTablesOnly`, and we did not want to break
|
|
|
|
// these tools in a "drive-by fix", without a good idea or plan about
|
|
|
|
// what limited debuginfo should exactly look like. So for now we keep
|
|
|
|
// the emission kind as `FullDebug`.
|
|
|
|
//
|
|
|
|
// See https://github.com/rust-lang/rust/issues/60020 for details.
|
|
|
|
let kind = DebugEmissionKind::FullDebug;
|
|
|
|
assert!(tcx.sess.opts.debuginfo != DebugInfo::None);
|
2017-02-11 21:01:25 +00:00
|
|
|
|
|
|
|
unsafe {
|
2021-02-14 15:12:14 +00:00
|
|
|
let compile_unit_file = llvm::LLVMRustDIBuilderCreateFile(
|
2019-12-24 22:38:22 +00:00
|
|
|
debug_context.builder,
|
2020-03-06 00:00:00 +00:00
|
|
|
name_in_debuginfo.as_ptr().cast(),
|
|
|
|
name_in_debuginfo.len(),
|
2021-02-14 15:12:14 +00:00
|
|
|
work_dir.as_ptr().cast(),
|
|
|
|
work_dir.len(),
|
2020-03-31 05:17:15 +00:00
|
|
|
llvm::ChecksumKind::None,
|
|
|
|
ptr::null(),
|
|
|
|
0,
|
2019-12-24 22:38:22 +00:00
|
|
|
);
|
2017-02-11 21:01:25 +00:00
|
|
|
|
2017-02-13 09:57:50 +00:00
|
|
|
let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit(
|
2016-07-12 22:40:38 +00:00
|
|
|
debug_context.builder,
|
2015-04-24 04:48:10 +00:00
|
|
|
DW_LANG_RUST,
|
2021-02-14 15:12:14 +00:00
|
|
|
compile_unit_file,
|
2020-03-06 00:00:00 +00:00
|
|
|
producer.as_ptr().cast(),
|
|
|
|
producer.len(),
|
2018-01-05 04:14:44 +00:00
|
|
|
tcx.sess.opts.optimize != config::OptLevel::No,
|
2019-10-05 07:48:14 +00:00
|
|
|
flags.as_ptr().cast(),
|
2015-04-24 04:48:10 +00:00
|
|
|
0,
|
2021-02-14 15:12:14 +00:00
|
|
|
// NB: this doesn't actually have any perceptible effect, it seems. LLVM will instead
|
|
|
|
// put the path supplied to `MCSplitDwarfFile` into the debug info of the final
|
|
|
|
// output(s).
|
2019-10-05 07:48:14 +00:00
|
|
|
split_name.as_ptr().cast(),
|
2020-03-06 00:00:00 +00:00
|
|
|
split_name.len(),
|
2019-12-24 22:38:22 +00:00
|
|
|
kind,
|
2020-09-23 15:25:20 +00:00
|
|
|
0,
|
2020-09-23 16:33:54 +00:00
|
|
|
tcx.sess.opts.debugging_opts.split_dwarf_inlining,
|
2019-12-24 22:38:22 +00:00
|
|
|
);
|
2017-02-13 09:57:50 +00:00
|
|
|
|
2018-01-05 04:14:44 +00:00
|
|
|
if tcx.sess.opts.debugging_opts.profile {
|
2019-12-24 22:38:22 +00:00
|
|
|
let cu_desc_metadata =
|
|
|
|
llvm::LLVMRustMetadataAsValue(debug_context.llcontext, unit_metadata);
|
2021-05-11 12:39:04 +00:00
|
|
|
let default_gcda_path = &output_filenames.with_extension("gcda");
|
2020-05-26 17:41:40 +00:00
|
|
|
let gcda_path =
|
|
|
|
tcx.sess.opts.debugging_opts.profile_emit.as_ref().unwrap_or(default_gcda_path);
|
2017-06-04 16:50:25 +00:00
|
|
|
|
|
|
|
let gcov_cu_info = [
|
2021-05-11 12:39:04 +00:00
|
|
|
path_to_mdstring(debug_context.llcontext, &output_filenames.with_extension("gcno")),
|
2021-09-30 17:38:50 +00:00
|
|
|
path_to_mdstring(debug_context.llcontext, gcda_path),
|
2017-06-04 16:50:25 +00:00
|
|
|
cu_desc_metadata,
|
|
|
|
];
|
2019-12-24 22:38:22 +00:00
|
|
|
let gcov_metadata = llvm::LLVMMDNodeInContext(
|
|
|
|
debug_context.llcontext,
|
|
|
|
gcov_cu_info.as_ptr(),
|
|
|
|
gcov_cu_info.len() as c_uint,
|
|
|
|
);
|
2017-06-04 16:50:25 +00:00
|
|
|
|
2021-02-13 11:17:15 +00:00
|
|
|
let llvm_gcov_ident = cstr!("llvm.gcov");
|
2019-12-24 22:38:22 +00:00
|
|
|
llvm::LLVMAddNamedMetadataOperand(
|
|
|
|
debug_context.llmod,
|
|
|
|
llvm_gcov_ident.as_ptr(),
|
|
|
|
gcov_metadata,
|
|
|
|
);
|
2017-06-04 16:50:25 +00:00
|
|
|
}
|
2017-02-13 09:57:50 +00:00
|
|
|
|
2020-12-30 18:52:21 +00:00
|
|
|
// Insert `llvm.ident` metadata on the wasm targets since that will
|
2019-07-19 14:08:37 +00:00
|
|
|
// get hooked up to the "producer" sections `processed-by` information.
|
2020-12-30 18:52:21 +00:00
|
|
|
if tcx.sess.target.is_like_wasm {
|
2019-07-19 14:08:37 +00:00
|
|
|
let name_metadata = llvm::LLVMMDStringInContext(
|
|
|
|
debug_context.llcontext,
|
2019-10-05 07:48:14 +00:00
|
|
|
rustc_producer.as_ptr().cast(),
|
2019-07-19 14:08:37 +00:00
|
|
|
rustc_producer.as_bytes().len() as c_uint,
|
|
|
|
);
|
|
|
|
llvm::LLVMAddNamedMetadataOperand(
|
|
|
|
debug_context.llmod,
|
2021-02-13 11:17:15 +00:00
|
|
|
cstr!("llvm.ident").as_ptr(),
|
2019-07-19 14:08:37 +00:00
|
|
|
llvm::LLVMMDNodeInContext(debug_context.llcontext, &name_metadata, 1),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-02-13 09:57:50 +00:00
|
|
|
return unit_metadata;
|
2015-04-24 04:48:10 +00:00
|
|
|
};
|
|
|
|
|
2021-12-14 18:49:49 +00:00
|
|
|
fn path_to_mdstring<'ll>(llcx: &'ll llvm::Context, path: &Path) -> &'ll Value {
|
2018-11-29 13:09:28 +00:00
|
|
|
let path_str = path_to_c_string(path);
|
2017-02-13 09:57:50 +00:00
|
|
|
unsafe {
|
2019-12-24 22:38:22 +00:00
|
|
|
llvm::LLVMMDStringInContext(
|
|
|
|
llcx,
|
|
|
|
path_str.as_ptr(),
|
|
|
|
path_str.as_bytes().len() as c_uint,
|
|
|
|
)
|
2017-02-13 09:57:50 +00:00
|
|
|
}
|
|
|
|
}
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
struct MetadataCreationResult<'ll> {
|
|
|
|
metadata: &'ll DIType,
|
2019-12-24 22:38:22 +00:00
|
|
|
already_stored_in_typemap: bool,
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
|
2021-12-14 18:49:49 +00:00
|
|
|
impl<'ll> MetadataCreationResult<'ll> {
|
2018-07-04 13:36:49 +00:00
|
|
|
fn new(metadata: &'ll DIType, already_stored_in_typemap: bool) -> Self {
|
2019-12-24 22:38:22 +00:00
|
|
|
MetadataCreationResult { metadata, already_stored_in_typemap }
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
}
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2020-06-17 23:04:25 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
struct SourceInfo<'ll> {
|
|
|
|
file: &'ll DIFile,
|
|
|
|
line: u32,
|
|
|
|
}
|
|
|
|
|
2019-11-21 18:40:27 +00:00
|
|
|
/// Description of a type member, which can either be a regular field (as in
|
2019-05-17 01:20:14 +00:00
|
|
|
/// structs or tuples) or an enum variant.
|
2015-05-12 02:41:08 +00:00
|
|
|
#[derive(Debug)]
|
2018-07-04 13:36:49 +00:00
|
|
|
struct MemberDescription<'ll> {
|
2015-04-29 06:14:37 +00:00
|
|
|
name: String,
|
2018-07-04 13:36:49 +00:00
|
|
|
type_metadata: &'ll DIType,
|
2017-06-01 18:50:53 +00:00
|
|
|
offset: Size,
|
|
|
|
size: Size,
|
2018-09-08 22:16:45 +00:00
|
|
|
align: Align,
|
2016-11-18 22:15:14 +00:00
|
|
|
flags: DIFlags,
|
2017-11-29 21:42:25 +00:00
|
|
|
discriminant: Option<u64>,
|
2020-06-17 23:04:25 +00:00
|
|
|
source_info: Option<SourceInfo<'ll>>,
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
|
2019-04-13 00:03:03 +00:00
|
|
|
impl<'ll> MemberDescription<'ll> {
|
2019-12-24 22:38:22 +00:00
|
|
|
fn into_metadata(
|
|
|
|
self,
|
|
|
|
cx: &CodegenCx<'ll, '_>,
|
|
|
|
composite_type_metadata: &'ll DIScope,
|
|
|
|
) -> &'ll DIType {
|
2020-06-17 23:04:25 +00:00
|
|
|
let (file, line) = self
|
|
|
|
.source_info
|
|
|
|
.map(|info| (info.file, info.line))
|
|
|
|
.unwrap_or_else(|| (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER));
|
2019-04-13 00:03:03 +00:00
|
|
|
unsafe {
|
|
|
|
llvm::LLVMRustDIBuilderCreateVariantMemberType(
|
|
|
|
DIB(cx),
|
|
|
|
composite_type_metadata,
|
2020-03-06 00:00:00 +00:00
|
|
|
self.name.as_ptr().cast(),
|
|
|
|
self.name.len(),
|
2020-06-17 23:04:25 +00:00
|
|
|
file,
|
|
|
|
line,
|
2019-04-13 00:03:03 +00:00
|
|
|
self.size.bits(),
|
|
|
|
self.align.bits() as u32,
|
|
|
|
self.offset.bits(),
|
2020-11-23 03:58:21 +00:00
|
|
|
self.discriminant.map(|v| cx.const_u64(v)),
|
2019-04-13 00:03:03 +00:00
|
|
|
self.flags,
|
2019-12-24 22:38:22 +00:00
|
|
|
self.type_metadata,
|
|
|
|
)
|
2019-04-13 00:03:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-17 01:20:14 +00:00
|
|
|
/// A factory for `MemberDescription`s. It produces a list of member descriptions
|
|
|
|
/// for some record-like type. `MemberDescriptionFactory`s are used to defer the
|
|
|
|
/// creation of type member descriptions in order to break cycles arising from
|
|
|
|
/// recursive type definitions.
|
2018-07-04 13:36:49 +00:00
|
|
|
enum MemberDescriptionFactory<'ll, 'tcx> {
|
2015-04-29 06:14:37 +00:00
|
|
|
StructMDF(StructMemberDescriptionFactory<'tcx>),
|
|
|
|
TupleMDF(TupleMemberDescriptionFactory<'tcx>),
|
2018-07-04 13:36:49 +00:00
|
|
|
EnumMDF(EnumMemberDescriptionFactory<'ll, 'tcx>),
|
2016-08-22 18:11:22 +00:00
|
|
|
UnionMDF(UnionMemberDescriptionFactory<'tcx>),
|
2021-06-24 20:37:03 +00:00
|
|
|
VariantMDF(VariantMemberDescriptionFactory<'tcx>),
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
|
2021-12-14 18:49:49 +00:00
|
|
|
impl<'ll, 'tcx> MemberDescriptionFactory<'ll, 'tcx> {
|
2019-12-24 22:38:22 +00:00
|
|
|
fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDescription<'ll>> {
|
2015-04-29 06:14:37 +00:00
|
|
|
match *self {
|
2019-12-24 22:38:22 +00:00
|
|
|
StructMDF(ref this) => this.create_member_descriptions(cx),
|
|
|
|
TupleMDF(ref this) => this.create_member_descriptions(cx),
|
|
|
|
EnumMDF(ref this) => this.create_member_descriptions(cx),
|
|
|
|
UnionMDF(ref this) => this.create_member_descriptions(cx),
|
|
|
|
VariantMDF(ref this) => this.create_member_descriptions(cx),
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
// Structs
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
|
2019-05-17 01:20:14 +00:00
|
|
|
/// Creates `MemberDescription`s for the fields of a struct.
|
2015-04-29 06:14:37 +00:00
|
|
|
struct StructMemberDescriptionFactory<'tcx> {
|
2016-11-21 00:56:51 +00:00
|
|
|
ty: Ty<'tcx>,
|
2016-11-24 23:33:29 +00:00
|
|
|
variant: &'tcx ty::VariantDef,
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> StructMemberDescriptionFactory<'tcx> {
|
2021-12-14 18:49:49 +00:00
|
|
|
fn create_member_descriptions<'ll>(
|
|
|
|
&self,
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
) -> Vec<MemberDescription<'ll>> {
|
2016-11-21 00:56:51 +00:00
|
|
|
let layout = cx.layout_of(self.ty);
|
2019-12-24 22:38:22 +00:00
|
|
|
self.variant
|
|
|
|
.fields
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.map(|(i, f)| {
|
|
|
|
let name = if self.variant.ctor_kind == CtorKind::Fn {
|
|
|
|
format!("__{}", i)
|
|
|
|
} else {
|
2022-01-03 03:37:05 +00:00
|
|
|
f.name.to_string()
|
2019-12-24 22:38:22 +00:00
|
|
|
};
|
|
|
|
let field = layout.field(cx, i);
|
|
|
|
MemberDescription {
|
|
|
|
name,
|
2022-01-10 14:59:52 +00:00
|
|
|
type_metadata: type_metadata(cx, field.ty),
|
2019-12-24 22:38:22 +00:00
|
|
|
offset: layout.fields.offset(i),
|
|
|
|
size: field.size,
|
|
|
|
align: field.align.abi,
|
|
|
|
flags: DIFlags::FlagZero,
|
|
|
|
discriminant: None,
|
2020-06-17 23:04:25 +00:00
|
|
|
source_info: None,
|
2019-12-24 22:38:22 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect()
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-14 18:49:49 +00:00
|
|
|
fn prepare_struct_metadata<'ll, 'tcx>(
|
2018-07-04 13:36:49 +00:00
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
struct_type: Ty<'tcx>,
|
2022-02-04 12:19:55 +00:00
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
2018-07-04 13:36:49 +00:00
|
|
|
) -> RecursiveTypeDescription<'ll, 'tcx> {
|
2019-03-30 14:45:09 +00:00
|
|
|
let struct_name = compute_debuginfo_type_name(cx.tcx, struct_type, false);
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2020-08-02 22:49:11 +00:00
|
|
|
let (struct_def_id, variant) = match struct_type.kind() {
|
2018-08-22 00:35:02 +00:00
|
|
|
ty::Adt(def, _) => (def.did, def.non_enum_variant()),
|
2019-12-24 22:38:22 +00:00
|
|
|
_ => bug!("prepare_struct_metadata on a non-ADT"),
|
2015-08-02 19:52:50 +00:00
|
|
|
};
|
|
|
|
|
2017-07-07 12:23:38 +00:00
|
|
|
let containing_scope = get_namespace_for_item(cx, struct_def_id);
|
2022-01-25 13:26:50 +00:00
|
|
|
let (size, align) = cx.size_and_align_of(struct_type);
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2020-06-18 02:39:23 +00:00
|
|
|
let struct_metadata_stub = create_struct_stub(
|
|
|
|
cx,
|
2022-01-25 13:26:50 +00:00
|
|
|
size,
|
|
|
|
align,
|
2020-06-18 02:39:23 +00:00
|
|
|
&struct_name,
|
|
|
|
unique_type_id,
|
|
|
|
Some(containing_scope),
|
|
|
|
DIFlags::FlagZero,
|
2022-01-25 13:26:50 +00:00
|
|
|
None,
|
2020-06-18 02:39:23 +00:00
|
|
|
);
|
2015-04-29 06:14:37 +00:00
|
|
|
|
|
|
|
create_and_register_recursive_type_forward_declaration(
|
|
|
|
cx,
|
|
|
|
struct_type,
|
|
|
|
unique_type_id,
|
|
|
|
struct_metadata_stub,
|
2017-11-29 21:42:25 +00:00
|
|
|
struct_metadata_stub,
|
2022-01-10 14:59:52 +00:00
|
|
|
StructMDF(StructMemberDescriptionFactory { ty: struct_type, variant }),
|
2015-04-29 06:14:37 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
// Tuples
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
|
2021-05-15 11:01:13 +00:00
|
|
|
/// Returns names of captured upvars for closures and generators.
|
|
|
|
///
|
|
|
|
/// Here are some examples:
|
|
|
|
/// - `name__field1__field2` when the upvar is captured by value.
|
|
|
|
/// - `_ref__name__field` when the upvar is captured by reference.
|
2021-12-14 18:49:49 +00:00
|
|
|
fn closure_saved_names_of_captured_variables(tcx: TyCtxt<'_>, def_id: DefId) -> Vec<String> {
|
2021-05-15 11:01:13 +00:00
|
|
|
let body = tcx.optimized_mir(def_id);
|
|
|
|
|
|
|
|
body.var_debug_info
|
|
|
|
.iter()
|
|
|
|
.filter_map(|var| {
|
|
|
|
let is_ref = match var.value {
|
|
|
|
mir::VarDebugInfoContents::Place(place) if place.local == mir::Local::new(1) => {
|
|
|
|
// The projection is either `[.., Field, Deref]` or `[.., Field]`. It
|
|
|
|
// implies whether the variable is captured by value or by reference.
|
|
|
|
matches!(place.projection.last().unwrap(), mir::ProjectionElem::Deref)
|
|
|
|
}
|
|
|
|
_ => return None,
|
|
|
|
};
|
|
|
|
let prefix = if is_ref { "_ref__" } else { "" };
|
2021-12-15 03:39:23 +00:00
|
|
|
Some(prefix.to_owned() + var.name.as_str())
|
2021-05-15 11:01:13 +00:00
|
|
|
})
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
}
|
|
|
|
|
2019-05-17 01:20:14 +00:00
|
|
|
/// Creates `MemberDescription`s for the fields of a tuple.
|
2015-04-29 06:14:37 +00:00
|
|
|
struct TupleMemberDescriptionFactory<'tcx> {
|
2016-11-21 00:56:51 +00:00
|
|
|
ty: Ty<'tcx>,
|
2015-04-29 06:14:37 +00:00
|
|
|
component_types: Vec<Ty<'tcx>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> TupleMemberDescriptionFactory<'tcx> {
|
2021-12-14 18:49:49 +00:00
|
|
|
fn create_member_descriptions<'ll>(
|
|
|
|
&self,
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
) -> Vec<MemberDescription<'ll>> {
|
2021-07-09 13:00:51 +00:00
|
|
|
let mut capture_names = match *self.ty.kind() {
|
2021-05-15 11:01:13 +00:00
|
|
|
ty::Generator(def_id, ..) | ty::Closure(def_id, ..) => {
|
2021-07-09 13:00:51 +00:00
|
|
|
Some(closure_saved_names_of_captured_variables(cx.tcx, def_id).into_iter())
|
2021-05-05 15:50:44 +00:00
|
|
|
}
|
|
|
|
_ => None,
|
|
|
|
};
|
2016-11-21 00:56:51 +00:00
|
|
|
let layout = cx.layout_of(self.ty);
|
2019-12-24 22:38:22 +00:00
|
|
|
self.component_types
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.map(|(i, &component_type)| {
|
|
|
|
let (size, align) = cx.size_and_align_of(component_type);
|
2021-07-09 13:00:51 +00:00
|
|
|
let name = if let Some(names) = capture_names.as_mut() {
|
|
|
|
names.next().unwrap()
|
2021-05-15 11:01:13 +00:00
|
|
|
} else {
|
|
|
|
format!("__{}", i)
|
|
|
|
};
|
2019-12-24 22:38:22 +00:00
|
|
|
MemberDescription {
|
2021-05-05 15:50:44 +00:00
|
|
|
name,
|
2022-01-10 14:59:52 +00:00
|
|
|
type_metadata: type_metadata(cx, component_type),
|
2019-12-24 22:38:22 +00:00
|
|
|
offset: layout.fields.offset(i),
|
|
|
|
size,
|
|
|
|
align,
|
|
|
|
flags: DIFlags::FlagZero,
|
|
|
|
discriminant: None,
|
2020-06-17 23:04:25 +00:00
|
|
|
source_info: None,
|
2019-12-24 22:38:22 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect()
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-14 18:49:49 +00:00
|
|
|
fn prepare_tuple_metadata<'ll, 'tcx>(
|
2018-07-04 13:36:49 +00:00
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
tuple_type: Ty<'tcx>,
|
|
|
|
component_types: &[Ty<'tcx>],
|
2022-02-04 12:19:55 +00:00
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
2019-08-25 03:01:46 +00:00
|
|
|
containing_scope: Option<&'ll DIScope>,
|
2018-07-04 13:36:49 +00:00
|
|
|
) -> RecursiveTypeDescription<'ll, 'tcx> {
|
2022-01-25 13:26:50 +00:00
|
|
|
let (size, align) = cx.size_and_align_of(tuple_type);
|
2019-03-30 14:45:09 +00:00
|
|
|
let tuple_name = compute_debuginfo_type_name(cx.tcx, tuple_type, false);
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2020-06-18 02:39:23 +00:00
|
|
|
let struct_stub = create_struct_stub(
|
|
|
|
cx,
|
2022-01-25 13:26:50 +00:00
|
|
|
size,
|
|
|
|
align,
|
2020-06-18 02:39:23 +00:00
|
|
|
&tuple_name[..],
|
|
|
|
unique_type_id,
|
|
|
|
containing_scope,
|
|
|
|
DIFlags::FlagZero,
|
2022-01-25 13:26:50 +00:00
|
|
|
None,
|
2020-06-18 02:39:23 +00:00
|
|
|
);
|
2017-11-29 21:42:25 +00:00
|
|
|
|
2015-04-29 06:14:37 +00:00
|
|
|
create_and_register_recursive_type_forward_declaration(
|
|
|
|
cx,
|
|
|
|
tuple_type,
|
|
|
|
unique_type_id,
|
2017-11-29 21:42:25 +00:00
|
|
|
struct_stub,
|
|
|
|
struct_stub,
|
2015-04-29 06:14:37 +00:00
|
|
|
TupleMDF(TupleMemberDescriptionFactory {
|
2016-11-21 00:56:51 +00:00
|
|
|
ty: tuple_type,
|
2015-04-29 06:14:37 +00:00
|
|
|
component_types: component_types.to_vec(),
|
2019-12-24 22:38:22 +00:00
|
|
|
}),
|
2015-04-29 06:14:37 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2016-08-22 18:11:22 +00:00
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
// Unions
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
struct UnionMemberDescriptionFactory<'tcx> {
|
2020-03-04 14:50:21 +00:00
|
|
|
layout: TyAndLayout<'tcx>,
|
2016-11-24 23:33:29 +00:00
|
|
|
variant: &'tcx ty::VariantDef,
|
2016-08-22 18:11:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> UnionMemberDescriptionFactory<'tcx> {
|
2021-12-14 18:49:49 +00:00
|
|
|
fn create_member_descriptions<'ll>(
|
|
|
|
&self,
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
) -> Vec<MemberDescription<'ll>> {
|
2019-12-24 22:38:22 +00:00
|
|
|
self.variant
|
|
|
|
.fields
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.map(|(i, f)| {
|
|
|
|
let field = self.layout.field(cx, i);
|
|
|
|
MemberDescription {
|
2022-01-03 03:37:05 +00:00
|
|
|
name: f.name.to_string(),
|
2022-01-10 14:59:52 +00:00
|
|
|
type_metadata: type_metadata(cx, field.ty),
|
2019-12-24 22:38:22 +00:00
|
|
|
offset: Size::ZERO,
|
|
|
|
size: field.size,
|
|
|
|
align: field.align.abi,
|
|
|
|
flags: DIFlags::FlagZero,
|
|
|
|
discriminant: None,
|
2020-06-17 23:04:25 +00:00
|
|
|
source_info: None,
|
2019-12-24 22:38:22 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect()
|
2016-08-22 18:11:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-14 18:49:49 +00:00
|
|
|
fn prepare_union_metadata<'ll, 'tcx>(
|
2018-07-04 13:36:49 +00:00
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
union_type: Ty<'tcx>,
|
2022-02-04 12:19:55 +00:00
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
2018-07-04 13:36:49 +00:00
|
|
|
) -> RecursiveTypeDescription<'ll, 'tcx> {
|
2019-03-30 14:45:09 +00:00
|
|
|
let union_name = compute_debuginfo_type_name(cx.tcx, union_type, false);
|
2016-08-22 18:11:22 +00:00
|
|
|
|
2020-08-02 22:49:11 +00:00
|
|
|
let (union_def_id, variant) = match union_type.kind() {
|
2018-08-22 00:35:02 +00:00
|
|
|
ty::Adt(def, _) => (def.did, def.non_enum_variant()),
|
2019-12-24 22:38:22 +00:00
|
|
|
_ => bug!("prepare_union_metadata on a non-ADT"),
|
2016-08-22 18:11:22 +00:00
|
|
|
};
|
|
|
|
|
2017-07-07 12:23:38 +00:00
|
|
|
let containing_scope = get_namespace_for_item(cx, union_def_id);
|
2016-08-22 18:11:22 +00:00
|
|
|
|
2019-12-24 22:38:22 +00:00
|
|
|
let union_metadata_stub =
|
|
|
|
create_union_stub(cx, union_type, &union_name, unique_type_id, containing_scope);
|
2016-08-22 18:11:22 +00:00
|
|
|
|
|
|
|
create_and_register_recursive_type_forward_declaration(
|
|
|
|
cx,
|
|
|
|
union_type,
|
|
|
|
unique_type_id,
|
|
|
|
union_metadata_stub,
|
2017-11-29 21:42:25 +00:00
|
|
|
union_metadata_stub,
|
2022-01-10 14:59:52 +00:00
|
|
|
UnionMDF(UnionMemberDescriptionFactory { layout: cx.layout_of(union_type), variant }),
|
2016-08-22 18:11:22 +00:00
|
|
|
)
|
|
|
|
}
|
2015-04-29 06:14:37 +00:00
|
|
|
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
// Enums
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
|
2018-05-16 15:58:54 +00:00
|
|
|
// FIXME(eddyb) maybe precompute this? Right now it's computed once
|
|
|
|
// per generator monomorphization, but it doesn't depend on substs.
|
2021-12-14 18:49:49 +00:00
|
|
|
fn generator_layout_and_saved_local_names<'tcx>(
|
2018-05-16 15:58:54 +00:00
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
def_id: DefId,
|
2020-04-19 11:00:18 +00:00
|
|
|
) -> (&'tcx GeneratorLayout<'tcx>, IndexVec<mir::GeneratorSavedLocal, Option<Symbol>>) {
|
2018-05-16 15:58:54 +00:00
|
|
|
let body = tcx.optimized_mir(def_id);
|
2021-01-17 12:27:05 +00:00
|
|
|
let generator_layout = body.generator_layout().unwrap();
|
2019-12-24 22:38:22 +00:00
|
|
|
let mut generator_saved_local_names = IndexVec::from_elem(None, &generator_layout.field_tys);
|
2018-05-16 15:58:54 +00:00
|
|
|
|
2019-12-11 19:50:03 +00:00
|
|
|
let state_arg = mir::Local::new(1);
|
2018-05-16 15:58:54 +00:00
|
|
|
for var in &body.var_debug_info {
|
2022-01-18 19:26:13 +00:00
|
|
|
let mir::VarDebugInfoContents::Place(place) = &var.value else { continue };
|
2020-05-30 19:02:32 +00:00
|
|
|
if place.local != state_arg {
|
2018-05-16 15:58:54 +00:00
|
|
|
continue;
|
|
|
|
}
|
2020-05-30 19:02:32 +00:00
|
|
|
match place.projection[..] {
|
2018-05-16 15:58:54 +00:00
|
|
|
[
|
|
|
|
// Deref of the `Pin<&mut Self>` state argument.
|
|
|
|
mir::ProjectionElem::Field(..),
|
|
|
|
mir::ProjectionElem::Deref,
|
|
|
|
// Field of a variant of the state.
|
|
|
|
mir::ProjectionElem::Downcast(_, variant),
|
|
|
|
mir::ProjectionElem::Field(field, _),
|
|
|
|
] => {
|
2021-11-30 18:08:41 +00:00
|
|
|
let name = &mut generator_saved_local_names
|
|
|
|
[generator_layout.variant_fields[variant][field]];
|
2018-05-16 15:58:54 +00:00
|
|
|
if name.is_none() {
|
|
|
|
name.replace(var.name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(generator_layout, generator_saved_local_names)
|
|
|
|
}
|
|
|
|
|
2019-05-17 01:20:14 +00:00
|
|
|
/// Describes the members of an enum value; an enum is described as a union of
|
|
|
|
/// structs in DWARF. This `MemberDescriptionFactory` provides the description for
|
|
|
|
/// the members of this union; so for every variant of the given enum, this
|
|
|
|
/// factory will produce one `MemberDescription` (all with no name and a fixed
|
|
|
|
/// offset of zero bytes).
|
2018-07-04 13:36:49 +00:00
|
|
|
struct EnumMemberDescriptionFactory<'ll, 'tcx> {
|
2015-04-29 06:14:37 +00:00
|
|
|
enum_type: Ty<'tcx>,
|
2020-03-04 14:50:21 +00:00
|
|
|
layout: TyAndLayout<'tcx>,
|
2020-05-23 11:22:45 +00:00
|
|
|
tag_type_metadata: Option<&'ll DIType>,
|
2021-04-30 08:14:42 +00:00
|
|
|
common_members: Vec<Option<&'ll DIType>>,
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
|
2021-12-14 18:49:49 +00:00
|
|
|
impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> {
|
2019-12-24 22:38:22 +00:00
|
|
|
fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDescription<'ll>> {
|
2020-08-02 22:49:11 +00:00
|
|
|
let generator_variant_info_data = match *self.enum_type.kind() {
|
2018-05-16 15:58:54 +00:00
|
|
|
ty::Generator(def_id, ..) => {
|
|
|
|
Some(generator_layout_and_saved_local_names(cx.tcx, def_id))
|
|
|
|
}
|
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
|
2020-08-02 22:49:11 +00:00
|
|
|
let variant_info_for = |index: VariantIdx| match *self.enum_type.kind() {
|
2022-02-04 12:19:55 +00:00
|
|
|
ty::Adt(adt, _) => VariantInfo::Adt(&adt.variants[index], index),
|
2020-06-20 01:37:52 +00:00
|
|
|
ty::Generator(def_id, _, _) => {
|
2019-12-24 22:38:22 +00:00
|
|
|
let (generator_layout, generator_saved_local_names) =
|
|
|
|
generator_variant_info_data.as_ref().unwrap();
|
|
|
|
VariantInfo::Generator {
|
2020-06-17 23:04:25 +00:00
|
|
|
def_id,
|
2019-12-24 22:38:22 +00:00
|
|
|
generator_layout: *generator_layout,
|
|
|
|
generator_saved_local_names,
|
|
|
|
variant_index: index,
|
2019-04-18 22:36:16 +00:00
|
|
|
}
|
2019-04-13 00:03:03 +00:00
|
|
|
}
|
2019-12-24 22:38:22 +00:00
|
|
|
_ => bug!(),
|
2019-04-13 00:03:03 +00:00
|
|
|
};
|
2017-11-29 21:42:25 +00:00
|
|
|
|
2021-12-28 21:57:18 +00:00
|
|
|
// While LLVM supports generating debuginfo for variant types (enums), it doesn't support
|
|
|
|
// lowering that debuginfo to CodeView records for msvc targets. So if we are targeting
|
|
|
|
// msvc, then we need to use a different, fallback encoding of the debuginfo.
|
|
|
|
let fallback = cpp_like_debuginfo(cx.tcx);
|
2021-05-26 16:02:07 +00:00
|
|
|
// This will always find the metadata in the type map.
|
2022-01-10 14:59:52 +00:00
|
|
|
let self_metadata = type_metadata(cx, self.enum_type);
|
2017-11-29 21:42:25 +00:00
|
|
|
|
2017-09-22 22:54:45 +00:00
|
|
|
match self.layout.variants {
|
2020-03-31 16:16:47 +00:00
|
|
|
Variants::Single { index } => {
|
2020-08-02 22:49:11 +00:00
|
|
|
if let ty::Adt(adt, _) = self.enum_type.kind() {
|
2019-04-13 00:03:03 +00:00
|
|
|
if adt.variants.is_empty() {
|
|
|
|
return vec![];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let variant_info = variant_info_for(index);
|
2021-06-24 20:37:03 +00:00
|
|
|
let (variant_type_metadata, member_description_factory) =
|
2022-01-10 14:59:52 +00:00
|
|
|
describe_enum_variant(cx, self.layout, variant_info, self_metadata);
|
2019-12-24 22:38:22 +00:00
|
|
|
|
|
|
|
let member_descriptions = member_description_factory.create_member_descriptions(cx);
|
2022-01-25 13:26:50 +00:00
|
|
|
let type_params = compute_type_parameters(cx, self.enum_type);
|
2019-12-24 22:38:22 +00:00
|
|
|
|
|
|
|
set_members_of_composite_type(
|
|
|
|
cx,
|
|
|
|
variant_type_metadata,
|
|
|
|
member_descriptions,
|
2021-04-30 08:14:42 +00:00
|
|
|
Some(&self.common_members),
|
2022-01-25 13:26:50 +00:00
|
|
|
type_params,
|
2019-12-24 22:38:22 +00:00
|
|
|
);
|
|
|
|
vec![MemberDescription {
|
2021-06-25 17:33:00 +00:00
|
|
|
name: variant_info.variant_name(),
|
2019-12-24 22:38:22 +00:00
|
|
|
type_metadata: variant_type_metadata,
|
|
|
|
offset: Size::ZERO,
|
|
|
|
size: self.layout.size,
|
|
|
|
align: self.layout.align.abi,
|
2021-04-30 12:02:53 +00:00
|
|
|
flags: DIFlags::FlagZero,
|
2019-12-24 22:38:22 +00:00
|
|
|
discriminant: None,
|
2020-06-17 23:04:25 +00:00
|
|
|
source_info: variant_info.source_info(cx),
|
2019-12-24 22:38:22 +00:00
|
|
|
}]
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
2020-03-31 16:16:47 +00:00
|
|
|
Variants::Multiple {
|
2020-05-23 11:22:45 +00:00
|
|
|
tag_encoding: TagEncoding::Direct,
|
|
|
|
tag_field,
|
2019-03-29 05:44:54 +00:00
|
|
|
ref variants,
|
|
|
|
..
|
|
|
|
} => {
|
2021-06-24 20:37:03 +00:00
|
|
|
let fallback_discr_variant = if fallback {
|
|
|
|
// For MSVC, we generate a union of structs for each variant and an
|
|
|
|
// explicit discriminant field roughly equivalent to the following C:
|
2021-05-17 15:09:13 +00:00
|
|
|
// ```c
|
2021-05-20 17:58:13 +00:00
|
|
|
// union enum$<{name}> {
|
2021-05-17 15:09:13 +00:00
|
|
|
// struct {variant 0 name} {
|
|
|
|
// <variant 0 fields>
|
2021-05-26 16:02:07 +00:00
|
|
|
// } variant0;
|
2021-05-17 15:09:13 +00:00
|
|
|
// <other variant structs>
|
2021-06-24 20:37:03 +00:00
|
|
|
// {name} discriminant;
|
2021-05-17 15:09:13 +00:00
|
|
|
// }
|
|
|
|
// ```
|
2021-07-01 01:53:48 +00:00
|
|
|
// The natvis in `intrinsic.natvis` then matches on `this.discriminant` to
|
2021-05-17 15:09:13 +00:00
|
|
|
// determine which variant is active and then displays it.
|
2021-06-24 20:37:03 +00:00
|
|
|
let enum_layout = self.layout;
|
|
|
|
let offset = enum_layout.fields.offset(tag_field);
|
|
|
|
let discr_ty = enum_layout.field(cx, tag_field).ty;
|
|
|
|
let (size, align) = cx.size_and_align_of(discr_ty);
|
|
|
|
Some(MemberDescription {
|
|
|
|
name: "discriminant".into(),
|
|
|
|
type_metadata: self.tag_type_metadata.unwrap(),
|
|
|
|
offset,
|
|
|
|
size,
|
|
|
|
align,
|
|
|
|
flags: DIFlags::FlagZero,
|
|
|
|
discriminant: None,
|
|
|
|
source_info: None,
|
2021-04-27 14:42:06 +00:00
|
|
|
})
|
2017-11-29 21:42:25 +00:00
|
|
|
} else {
|
2021-04-27 14:42:06 +00:00
|
|
|
None
|
2017-11-29 21:42:25 +00:00
|
|
|
};
|
2021-06-24 20:37:03 +00:00
|
|
|
|
2019-12-24 22:38:22 +00:00
|
|
|
variants
|
|
|
|
.iter_enumerated()
|
|
|
|
.map(|(i, _)| {
|
|
|
|
let variant = self.layout.for_variant(cx, i);
|
|
|
|
let variant_info = variant_info_for(i);
|
2022-01-10 14:59:52 +00:00
|
|
|
let (variant_type_metadata, member_desc_factory) =
|
|
|
|
describe_enum_variant(cx, variant, variant_info, self_metadata);
|
2019-12-24 22:38:22 +00:00
|
|
|
|
|
|
|
let member_descriptions =
|
|
|
|
member_desc_factory.create_member_descriptions(cx);
|
2022-01-25 13:26:50 +00:00
|
|
|
let type_params = compute_type_parameters(cx, self.enum_type);
|
2019-12-24 22:38:22 +00:00
|
|
|
|
|
|
|
set_members_of_composite_type(
|
|
|
|
cx,
|
|
|
|
variant_type_metadata,
|
|
|
|
member_descriptions,
|
2021-04-30 08:14:42 +00:00
|
|
|
Some(&self.common_members),
|
2022-01-25 13:26:50 +00:00
|
|
|
type_params,
|
2019-12-24 22:38:22 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
MemberDescription {
|
|
|
|
name: if fallback {
|
2021-05-26 16:02:07 +00:00
|
|
|
format!("variant{}", i.as_u32())
|
2019-12-24 22:38:22 +00:00
|
|
|
} else {
|
|
|
|
variant_info.variant_name()
|
|
|
|
},
|
|
|
|
type_metadata: variant_type_metadata,
|
|
|
|
offset: Size::ZERO,
|
|
|
|
size: self.layout.size,
|
|
|
|
align: self.layout.align.abi,
|
2021-04-30 12:02:53 +00:00
|
|
|
flags: DIFlags::FlagZero,
|
2019-12-24 22:38:22 +00:00
|
|
|
discriminant: Some(
|
|
|
|
self.layout.ty.discriminant_for_variant(cx.tcx, i).unwrap().val
|
|
|
|
as u64,
|
|
|
|
),
|
2020-06-17 23:04:25 +00:00
|
|
|
source_info: variant_info.source_info(cx),
|
2019-12-24 22:38:22 +00:00
|
|
|
}
|
|
|
|
})
|
2021-06-24 20:37:03 +00:00
|
|
|
.chain(fallback_discr_variant.into_iter())
|
2019-12-24 22:38:22 +00:00
|
|
|
.collect()
|
2017-09-22 22:54:45 +00:00
|
|
|
}
|
2020-03-31 16:16:47 +00:00
|
|
|
Variants::Multiple {
|
2020-05-23 11:22:45 +00:00
|
|
|
tag_encoding:
|
|
|
|
TagEncoding::Niche { ref niche_variants, niche_start, dataful_variant },
|
2021-08-29 09:06:55 +00:00
|
|
|
tag,
|
2017-11-29 21:42:25 +00:00
|
|
|
ref variants,
|
2020-05-23 11:22:45 +00:00
|
|
|
tag_field,
|
2017-11-29 21:42:25 +00:00
|
|
|
} => {
|
2021-05-13 20:39:19 +00:00
|
|
|
let calculate_niche_value = |i: VariantIdx| {
|
|
|
|
if i == dataful_variant {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
let value = (i.as_u32() as u128)
|
|
|
|
.wrapping_sub(niche_variants.start().as_u32() as u128)
|
|
|
|
.wrapping_add(niche_start);
|
|
|
|
let value = tag.value.size(cx).truncate(value);
|
|
|
|
// NOTE(eddyb) do *NOT* remove this assert, until
|
|
|
|
// we pass the full 128-bit value to LLVM, otherwise
|
|
|
|
// truncation will be silent and remain undetected.
|
|
|
|
assert_eq!(value as u64 as u128, value);
|
|
|
|
Some(value as u64)
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-05-26 16:02:07 +00:00
|
|
|
// For MSVC, we will generate a union of two fields, one for the dataful variant
|
|
|
|
// and one that just points to the discriminant. We also create an enum that
|
|
|
|
// contains tag values for the non-dataful variants and make the discriminant field
|
|
|
|
// that type. We then use natvis to render the enum type correctly in Windbg/VS.
|
2021-05-17 15:09:13 +00:00
|
|
|
// This will generate debuginfo roughly equivalent to the following C:
|
|
|
|
// ```c
|
2021-05-26 16:02:07 +00:00
|
|
|
// union enum$<{name}, {min niche}, {max niche}, {dataful variant name}> {
|
|
|
|
// struct <dataful variant name> {
|
2021-05-17 15:09:13 +00:00
|
|
|
// <fields in dataful variant>
|
2021-05-26 16:02:07 +00:00
|
|
|
// } dataful_variant;
|
|
|
|
// enum Discriminant$ {
|
|
|
|
// <non-dataful variants>
|
|
|
|
// } discriminant;
|
2021-05-17 15:09:13 +00:00
|
|
|
// }
|
|
|
|
// ```
|
2021-05-20 17:58:13 +00:00
|
|
|
// The natvis in `intrinsic.natvis` matches on the type name `enum$<*, *, *, *>`
|
2021-05-26 16:02:07 +00:00
|
|
|
// and evaluates `this.discriminant`. If the value is between the min niche and max
|
|
|
|
// niche, then the enum is in the dataful variant and `this.dataful_variant` is
|
|
|
|
// rendered. Otherwise, the enum is in one of the non-dataful variants. In that
|
|
|
|
// case, we just need to render the name of the `this.discriminant` enum.
|
2017-11-29 21:42:25 +00:00
|
|
|
if fallback {
|
2021-05-13 20:39:19 +00:00
|
|
|
let dataful_variant_layout = self.layout.for_variant(cx, dataful_variant);
|
|
|
|
|
|
|
|
let mut discr_enum_ty = tag.value.to_ty(cx.tcx);
|
|
|
|
// If the niche is the NULL value of a reference, then `discr_enum_ty` will be a RawPtr.
|
|
|
|
// CodeView doesn't know what to do with enums whose base type is a pointer so we fix this up
|
|
|
|
// to just be `usize`.
|
|
|
|
if let ty::RawPtr(_) = discr_enum_ty.kind() {
|
|
|
|
discr_enum_ty = cx.tcx.types.usize;
|
|
|
|
}
|
|
|
|
|
|
|
|
let tags: Vec<_> = variants
|
|
|
|
.iter_enumerated()
|
|
|
|
.filter_map(|(variant_idx, _)| {
|
|
|
|
calculate_niche_value(variant_idx).map(|tag| {
|
|
|
|
let variant = variant_info_for(variant_idx);
|
|
|
|
let name = variant.variant_name();
|
|
|
|
|
|
|
|
Some(unsafe {
|
|
|
|
llvm::LLVMRustDIBuilderCreateEnumerator(
|
|
|
|
DIB(cx),
|
|
|
|
name.as_ptr().cast(),
|
|
|
|
name.len(),
|
|
|
|
tag as i64,
|
|
|
|
!discr_enum_ty.is_signed(),
|
|
|
|
)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
let discr_enum = unsafe {
|
|
|
|
llvm::LLVMRustDIBuilderCreateEnumerationType(
|
|
|
|
DIB(cx),
|
|
|
|
self_metadata,
|
2021-05-26 16:02:07 +00:00
|
|
|
"Discriminant$".as_ptr().cast(),
|
|
|
|
"Discriminant$".len(),
|
2021-05-13 20:39:19 +00:00
|
|
|
unknown_file_metadata(cx),
|
|
|
|
UNKNOWN_LINE_NUMBER,
|
|
|
|
tag.value.size(cx).bits(),
|
|
|
|
tag.value.align(cx).abi.bits() as u32,
|
|
|
|
create_DIArray(DIB(cx), &tags),
|
2022-01-10 14:59:52 +00:00
|
|
|
type_metadata(cx, discr_enum_ty),
|
2021-05-13 20:39:19 +00:00
|
|
|
true,
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
|
|
|
let variant_info = variant_info_for(dataful_variant);
|
|
|
|
let (variant_type_metadata, member_desc_factory) = describe_enum_variant(
|
2019-12-24 22:38:22 +00:00
|
|
|
cx,
|
2021-05-13 20:39:19 +00:00
|
|
|
dataful_variant_layout,
|
|
|
|
variant_info,
|
2021-04-28 20:32:54 +00:00
|
|
|
self_metadata,
|
2019-12-24 22:38:22 +00:00
|
|
|
);
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2021-05-13 20:39:19 +00:00
|
|
|
let member_descriptions = member_desc_factory.create_member_descriptions(cx);
|
2022-01-25 13:26:50 +00:00
|
|
|
let type_params = compute_type_parameters(cx, self.enum_type);
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2019-12-24 22:38:22 +00:00
|
|
|
set_members_of_composite_type(
|
|
|
|
cx,
|
|
|
|
variant_type_metadata,
|
2021-05-13 20:39:19 +00:00
|
|
|
member_descriptions,
|
2021-04-30 08:14:42 +00:00
|
|
|
Some(&self.common_members),
|
2022-01-25 13:26:50 +00:00
|
|
|
type_params,
|
2019-12-24 22:38:22 +00:00
|
|
|
);
|
2017-11-29 21:42:25 +00:00
|
|
|
|
2021-05-26 16:02:07 +00:00
|
|
|
let (size, align) =
|
|
|
|
cx.size_and_align_of(dataful_variant_layout.field(cx, tag_field).ty);
|
|
|
|
|
2021-05-13 20:39:19 +00:00
|
|
|
vec![
|
|
|
|
MemberDescription {
|
|
|
|
// Name the dataful variant so that we can identify it for natvis
|
|
|
|
name: "dataful_variant".to_string(),
|
|
|
|
type_metadata: variant_type_metadata,
|
|
|
|
offset: Size::ZERO,
|
|
|
|
size: self.layout.size,
|
|
|
|
align: self.layout.align.abi,
|
|
|
|
flags: DIFlags::FlagZero,
|
|
|
|
discriminant: None,
|
|
|
|
source_info: variant_info.source_info(cx),
|
|
|
|
},
|
|
|
|
MemberDescription {
|
2021-05-26 16:02:07 +00:00
|
|
|
name: "discriminant".into(),
|
|
|
|
type_metadata: discr_enum,
|
|
|
|
offset: dataful_variant_layout.fields.offset(tag_field),
|
|
|
|
size,
|
|
|
|
align,
|
2021-05-13 20:39:19 +00:00
|
|
|
flags: DIFlags::FlagZero,
|
|
|
|
discriminant: None,
|
|
|
|
source_info: None,
|
|
|
|
},
|
|
|
|
]
|
2017-11-29 21:42:25 +00:00
|
|
|
} else {
|
2019-12-24 22:38:22 +00:00
|
|
|
variants
|
|
|
|
.iter_enumerated()
|
|
|
|
.map(|(i, _)| {
|
|
|
|
let variant = self.layout.for_variant(cx, i);
|
|
|
|
let variant_info = variant_info_for(i);
|
|
|
|
let (variant_type_metadata, member_desc_factory) =
|
2022-01-10 14:59:52 +00:00
|
|
|
describe_enum_variant(cx, variant, variant_info, self_metadata);
|
2019-12-24 22:38:22 +00:00
|
|
|
|
|
|
|
let member_descriptions =
|
|
|
|
member_desc_factory.create_member_descriptions(cx);
|
2022-01-25 13:26:50 +00:00
|
|
|
let type_params = compute_type_parameters(cx, self.enum_type);
|
2019-12-24 22:38:22 +00:00
|
|
|
|
|
|
|
set_members_of_composite_type(
|
|
|
|
cx,
|
|
|
|
variant_type_metadata,
|
|
|
|
member_descriptions,
|
2021-04-30 08:14:42 +00:00
|
|
|
Some(&self.common_members),
|
2022-01-25 13:26:50 +00:00
|
|
|
type_params,
|
2019-12-24 22:38:22 +00:00
|
|
|
);
|
|
|
|
|
2021-05-13 20:39:19 +00:00
|
|
|
let niche_value = calculate_niche_value(i);
|
2019-12-24 22:38:22 +00:00
|
|
|
|
|
|
|
MemberDescription {
|
|
|
|
name: variant_info.variant_name(),
|
|
|
|
type_metadata: variant_type_metadata,
|
|
|
|
offset: Size::ZERO,
|
|
|
|
size: self.layout.size,
|
|
|
|
align: self.layout.align.abi,
|
2021-04-30 12:02:53 +00:00
|
|
|
flags: DIFlags::FlagZero,
|
2019-12-24 22:38:22 +00:00
|
|
|
discriminant: niche_value,
|
2020-06-17 23:04:25 +00:00
|
|
|
source_info: variant_info.source_info(cx),
|
2019-12-24 22:38:22 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect()
|
2017-09-11 19:31:16 +00:00
|
|
|
}
|
2017-09-22 22:54:45 +00:00
|
|
|
}
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-17 01:20:14 +00:00
|
|
|
// Creates `MemberDescription`s for the fields of a single enum variant.
|
2021-06-24 20:37:03 +00:00
|
|
|
struct VariantMemberDescriptionFactory<'tcx> {
|
2019-05-17 01:20:14 +00:00
|
|
|
/// Cloned from the `layout::Struct` describing the variant.
|
2020-03-31 16:16:47 +00:00
|
|
|
offsets: Vec<Size>,
|
2015-04-29 06:14:37 +00:00
|
|
|
args: Vec<(String, Ty<'tcx>)>,
|
|
|
|
}
|
|
|
|
|
2021-12-14 18:49:49 +00:00
|
|
|
impl<'tcx> VariantMemberDescriptionFactory<'tcx> {
|
|
|
|
fn create_member_descriptions<'ll>(
|
|
|
|
&self,
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
) -> Vec<MemberDescription<'ll>> {
|
2019-12-24 22:38:22 +00:00
|
|
|
self.args
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.map(|(i, &(ref name, ty))| {
|
|
|
|
let (size, align) = cx.size_and_align_of(ty);
|
|
|
|
MemberDescription {
|
|
|
|
name: name.to_string(),
|
2022-01-10 14:59:52 +00:00
|
|
|
type_metadata: type_metadata(cx, ty),
|
2019-12-24 22:38:22 +00:00
|
|
|
offset: self.offsets[i],
|
|
|
|
size,
|
|
|
|
align,
|
2021-06-24 20:37:03 +00:00
|
|
|
flags: DIFlags::FlagZero,
|
2019-12-24 22:38:22 +00:00
|
|
|
discriminant: None,
|
2020-06-17 23:04:25 +00:00
|
|
|
source_info: None,
|
2019-12-24 22:38:22 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect()
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-13 00:03:03 +00:00
|
|
|
#[derive(Copy, Clone)]
|
2018-05-16 15:58:54 +00:00
|
|
|
enum VariantInfo<'a, 'tcx> {
|
2022-02-04 12:19:55 +00:00
|
|
|
Adt(&'tcx ty::VariantDef, VariantIdx),
|
2018-05-16 15:58:54 +00:00
|
|
|
Generator {
|
2020-06-17 23:04:25 +00:00
|
|
|
def_id: DefId,
|
2018-05-16 15:58:54 +00:00
|
|
|
generator_layout: &'tcx GeneratorLayout<'tcx>,
|
2020-04-19 11:00:18 +00:00
|
|
|
generator_saved_local_names: &'a IndexVec<mir::GeneratorSavedLocal, Option<Symbol>>,
|
2018-05-16 15:58:54 +00:00
|
|
|
variant_index: VariantIdx,
|
|
|
|
},
|
2019-04-13 00:03:03 +00:00
|
|
|
}
|
|
|
|
|
2018-05-16 15:58:54 +00:00
|
|
|
impl<'tcx> VariantInfo<'_, 'tcx> {
|
2022-02-04 12:19:55 +00:00
|
|
|
fn variant_idx(&self) -> VariantIdx {
|
|
|
|
match self {
|
|
|
|
VariantInfo::Adt(_, variant_index) | VariantInfo::Generator { variant_index, .. } => {
|
|
|
|
*variant_index
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-18 00:46:40 +00:00
|
|
|
fn map_struct_name<R>(&self, f: impl FnOnce(&str) -> R) -> R {
|
2019-04-13 00:03:03 +00:00
|
|
|
match self {
|
2022-02-04 12:19:55 +00:00
|
|
|
VariantInfo::Adt(variant, _) => f(variant.name.as_str()),
|
2020-06-20 01:37:52 +00:00
|
|
|
VariantInfo::Generator { variant_index, .. } => {
|
|
|
|
f(&GeneratorSubsts::variant_name(*variant_index))
|
2019-12-24 22:38:22 +00:00
|
|
|
}
|
2019-04-13 00:03:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-18 00:46:40 +00:00
|
|
|
fn variant_name(&self) -> String {
|
|
|
|
match self {
|
2022-02-04 12:19:55 +00:00
|
|
|
VariantInfo::Adt(variant, _) => variant.name.to_string(),
|
2018-05-16 15:58:54 +00:00
|
|
|
VariantInfo::Generator { variant_index, .. } => {
|
2019-04-18 00:46:40 +00:00
|
|
|
// Since GDB currently prints out the raw discriminant along
|
|
|
|
// with every variant, make each variant name be just the value
|
|
|
|
// of the discriminant. The struct name for the variant includes
|
|
|
|
// the actual variant description.
|
2019-06-08 10:06:58 +00:00
|
|
|
format!("{}", variant_index.as_usize())
|
2019-04-18 00:46:40 +00:00
|
|
|
}
|
|
|
|
}
|
2019-04-13 00:03:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn field_name(&self, i: usize) -> String {
|
2018-05-16 15:58:54 +00:00
|
|
|
let field_name = match *self {
|
2022-02-04 12:19:55 +00:00
|
|
|
VariantInfo::Adt(variant, _) if variant.ctor_kind != CtorKind::Fn => {
|
2022-01-03 03:37:05 +00:00
|
|
|
Some(variant.fields[i].name)
|
2019-12-24 22:38:22 +00:00
|
|
|
}
|
2018-05-16 15:58:54 +00:00
|
|
|
VariantInfo::Generator {
|
|
|
|
generator_layout,
|
|
|
|
generator_saved_local_names,
|
|
|
|
variant_index,
|
|
|
|
..
|
2019-12-24 22:38:22 +00:00
|
|
|
} => {
|
|
|
|
generator_saved_local_names
|
|
|
|
[generator_layout.variant_fields[variant_index][i.into()]]
|
|
|
|
}
|
2019-04-18 22:36:16 +00:00
|
|
|
_ => None,
|
|
|
|
};
|
2018-05-16 15:58:54 +00:00
|
|
|
field_name.map(|name| name.to_string()).unwrap_or_else(|| format!("__{}", i))
|
2019-04-13 00:03:03 +00:00
|
|
|
}
|
2020-06-17 23:04:25 +00:00
|
|
|
|
2021-12-14 18:49:49 +00:00
|
|
|
fn source_info<'ll>(&self, cx: &CodegenCx<'ll, 'tcx>) -> Option<SourceInfo<'ll>> {
|
2021-09-30 17:38:50 +00:00
|
|
|
if let VariantInfo::Generator { def_id, variant_index, .. } = self {
|
|
|
|
let span =
|
|
|
|
cx.tcx.generator_layout(*def_id).unwrap().variant_source_info[*variant_index].span;
|
|
|
|
if !span.is_dummy() {
|
|
|
|
let loc = cx.lookup_debug_loc(span.lo());
|
|
|
|
return Some(SourceInfo { file: file_metadata(cx, &loc.file), line: loc.line });
|
2020-06-17 23:04:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
2019-04-13 00:03:03 +00:00
|
|
|
}
|
|
|
|
|
2019-05-17 01:20:14 +00:00
|
|
|
/// Returns a tuple of (1) `type_metadata_stub` of the variant, (2) a
|
|
|
|
/// `MemberDescriptionFactory` for producing the descriptions of the
|
|
|
|
/// fields of the variant. This is a rudimentary version of a full
|
|
|
|
/// `RecursiveTypeDescription`.
|
2021-12-14 18:49:49 +00:00
|
|
|
fn describe_enum_variant<'ll, 'tcx>(
|
2018-07-04 13:36:49 +00:00
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
2020-03-04 14:50:21 +00:00
|
|
|
layout: layout::TyAndLayout<'tcx>,
|
2018-05-16 15:58:54 +00:00
|
|
|
variant: VariantInfo<'_, 'tcx>,
|
2018-07-04 13:36:49 +00:00
|
|
|
containing_scope: &'ll DIScope,
|
|
|
|
) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) {
|
2019-04-18 00:46:40 +00:00
|
|
|
let metadata_stub = variant.map_struct_name(|variant_name| {
|
2022-02-04 12:19:55 +00:00
|
|
|
let unique_type_id =
|
|
|
|
UniqueTypeId::for_enum_variant(cx.tcx, layout.ty, variant.variant_idx());
|
2022-01-25 13:26:50 +00:00
|
|
|
|
|
|
|
let (size, align) = cx.size_and_align_of(layout.ty);
|
|
|
|
|
2020-06-18 02:39:23 +00:00
|
|
|
create_struct_stub(
|
|
|
|
cx,
|
2022-01-25 13:26:50 +00:00
|
|
|
size,
|
|
|
|
align,
|
2021-09-30 17:38:50 +00:00
|
|
|
variant_name,
|
2020-06-18 02:39:23 +00:00
|
|
|
unique_type_id,
|
|
|
|
Some(containing_scope),
|
2021-04-30 12:02:53 +00:00
|
|
|
DIFlags::FlagZero,
|
2022-01-25 13:26:50 +00:00
|
|
|
None,
|
2020-06-18 02:39:23 +00:00
|
|
|
)
|
2019-04-13 00:03:03 +00:00
|
|
|
});
|
2019-04-02 20:51:13 +00:00
|
|
|
|
2021-06-24 20:37:03 +00:00
|
|
|
let offsets = (0..layout.fields.count()).map(|i| layout.fields.offset(i)).collect();
|
|
|
|
let args = (0..layout.fields.count())
|
|
|
|
.map(|i| (variant.field_name(i), layout.field(cx, i).ty))
|
|
|
|
.collect();
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2022-01-10 14:59:52 +00:00
|
|
|
let member_description_factory = VariantMDF(VariantMemberDescriptionFactory { offsets, args });
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2017-06-01 18:50:53 +00:00
|
|
|
(metadata_stub, member_description_factory)
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
|
2021-12-14 18:49:49 +00:00
|
|
|
fn prepare_enum_metadata<'ll, 'tcx>(
|
2018-07-04 13:36:49 +00:00
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
enum_type: Ty<'tcx>,
|
|
|
|
enum_def_id: DefId,
|
2022-02-04 12:19:55 +00:00
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
2019-04-13 00:03:03 +00:00
|
|
|
outer_field_tys: Vec<Ty<'tcx>>,
|
2018-07-04 13:36:49 +00:00
|
|
|
) -> RecursiveTypeDescription<'ll, 'tcx> {
|
2020-06-17 23:04:25 +00:00
|
|
|
let tcx = cx.tcx;
|
|
|
|
let enum_name = compute_debuginfo_type_name(tcx, enum_type, false);
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2017-07-07 12:23:38 +00:00
|
|
|
let containing_scope = get_namespace_for_item(cx, enum_def_id);
|
Workaround ODR violations in enum debuginfo
When using a generic enum type that was defined in an external crate,
our debuginfo currently claims that the concrete type (e.g. Option<i32>)
was defined in the current crate, where it was first used.
This means that if there are multiple crates that all use, for example,
Option<i32> values, they'll have conflicting debuginfo, each crate
claiming to have defined that type. This doesn't cause problems in
regular builds, but with LTO enabled, LLVM complains because it tries to
merge the debuginfo for those types and sees the ODR violations.
Since I couldn't find a way to get the file info for the external crate
that actually defined the enum, I'm working around the issue by using
"<unknown>" as the file for enum types. We'll want to re-visit and fix
this later, but this at least this fixes the ICE. And with the file
being unknown instead of wrong, the debuginfo isn't really worse than
before either.
Fixes #26447
2015-07-29 11:53:59 +00:00
|
|
|
// FIXME: This should emit actual file metadata for the enum, but we
|
|
|
|
// currently can't get the necessary information when it comes to types
|
|
|
|
// imported from other crates. Formerly we violated the ODR when performing
|
|
|
|
// LTO because we emitted debuginfo for the same type with varying file
|
|
|
|
// metadata, so as a workaround we pretend that the type comes from
|
|
|
|
// <unknown>
|
|
|
|
let file_metadata = unknown_file_metadata(cx);
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2020-03-31 16:16:47 +00:00
|
|
|
let discriminant_type_metadata = |discr: Primitive| {
|
2020-08-02 22:49:11 +00:00
|
|
|
let enumerators_metadata: Vec<_> = match enum_type.kind() {
|
2021-03-08 23:32:41 +00:00
|
|
|
ty::Adt(def, _) => iter::zip(def.discriminants(tcx), &def.variants)
|
2019-04-13 00:03:03 +00:00
|
|
|
.map(|((_, discr), v)| {
|
2022-01-03 03:37:05 +00:00
|
|
|
let name = v.name.as_str();
|
2020-08-02 22:49:11 +00:00
|
|
|
let is_unsigned = match discr.ty.kind() {
|
2020-03-05 00:00:00 +00:00
|
|
|
ty::Int(_) => false,
|
|
|
|
ty::Uint(_) => true,
|
|
|
|
_ => bug!("non integer discriminant"),
|
|
|
|
};
|
2019-04-13 00:03:03 +00:00
|
|
|
unsafe {
|
|
|
|
Some(llvm::LLVMRustDIBuilderCreateEnumerator(
|
|
|
|
DIB(cx),
|
2020-03-05 00:00:00 +00:00
|
|
|
name.as_ptr().cast(),
|
|
|
|
name.len(),
|
2019-04-13 00:03:03 +00:00
|
|
|
// FIXME: what if enumeration has i128 discriminant?
|
2020-03-05 00:00:00 +00:00
|
|
|
discr.val as i64,
|
2020-03-05 00:00:00 +00:00
|
|
|
is_unsigned,
|
2019-12-24 22:38:22 +00:00
|
|
|
))
|
2019-04-13 00:03:03 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect(),
|
|
|
|
ty::Generator(_, substs, _) => substs
|
2019-10-03 13:51:30 +00:00
|
|
|
.as_generator()
|
2020-06-17 23:04:25 +00:00
|
|
|
.variant_range(enum_def_id, tcx)
|
2019-05-03 23:11:39 +00:00
|
|
|
.map(|variant_index| {
|
2020-06-17 23:04:25 +00:00
|
|
|
debug_assert_eq!(tcx.types.u32, substs.as_generator().discr_ty(tcx));
|
2020-06-20 01:37:52 +00:00
|
|
|
let name = GeneratorSubsts::variant_name(variant_index);
|
2019-04-13 00:03:03 +00:00
|
|
|
unsafe {
|
|
|
|
Some(llvm::LLVMRustDIBuilderCreateEnumerator(
|
|
|
|
DIB(cx),
|
2020-03-05 00:00:00 +00:00
|
|
|
name.as_ptr().cast(),
|
|
|
|
name.len(),
|
2020-06-17 23:04:25 +00:00
|
|
|
// Generators use u32 as discriminant type, verified above.
|
2020-03-05 00:00:00 +00:00
|
|
|
variant_index.as_u32().into(),
|
|
|
|
true, // IsUnsigned
|
2019-12-24 22:38:22 +00:00
|
|
|
))
|
2019-04-13 00:03:03 +00:00
|
|
|
}
|
2019-05-03 23:11:39 +00:00
|
|
|
})
|
2019-04-13 00:03:03 +00:00
|
|
|
.collect(),
|
|
|
|
_ => bug!(),
|
|
|
|
};
|
2017-11-29 21:42:25 +00:00
|
|
|
|
2017-09-16 09:23:22 +00:00
|
|
|
let disr_type_key = (enum_def_id, discr);
|
2019-12-24 22:38:22 +00:00
|
|
|
let cached_discriminant_type_metadata =
|
|
|
|
debug_context(cx).created_enum_disr_types.borrow().get(&disr_type_key).cloned();
|
2015-04-29 06:14:37 +00:00
|
|
|
match cached_discriminant_type_metadata {
|
|
|
|
Some(discriminant_type_metadata) => discriminant_type_metadata,
|
|
|
|
None => {
|
2019-12-24 22:38:22 +00:00
|
|
|
let (discriminant_size, discriminant_align) = (discr.size(cx), discr.align(cx));
|
2022-01-10 14:59:52 +00:00
|
|
|
let discriminant_base_type_metadata = type_metadata(cx, discr.to_ty(tcx));
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2020-03-06 00:00:00 +00:00
|
|
|
let item_name;
|
2020-08-02 22:49:11 +00:00
|
|
|
let discriminant_name = match enum_type.kind() {
|
2020-03-06 00:00:00 +00:00
|
|
|
ty::Adt(..) => {
|
2021-12-14 21:32:21 +00:00
|
|
|
item_name = tcx.item_name(enum_def_id);
|
|
|
|
item_name.as_str()
|
2020-03-06 00:00:00 +00:00
|
|
|
}
|
|
|
|
ty::Generator(..) => enum_name.as_str(),
|
2019-04-13 00:03:03 +00:00
|
|
|
_ => bug!(),
|
|
|
|
};
|
|
|
|
|
2015-04-29 06:14:37 +00:00
|
|
|
let discriminant_type_metadata = unsafe {
|
2016-08-01 23:35:09 +00:00
|
|
|
llvm::LLVMRustDIBuilderCreateEnumerationType(
|
2015-04-29 06:14:37 +00:00
|
|
|
DIB(cx),
|
|
|
|
containing_scope,
|
2020-03-06 00:00:00 +00:00
|
|
|
discriminant_name.as_ptr().cast(),
|
|
|
|
discriminant_name.len(),
|
2016-07-07 12:15:10 +00:00
|
|
|
file_metadata,
|
2015-04-29 06:14:37 +00:00
|
|
|
UNKNOWN_LINE_NUMBER,
|
2017-06-01 18:50:53 +00:00
|
|
|
discriminant_size.bits(),
|
2018-09-08 21:22:22 +00:00
|
|
|
discriminant_align.abi.bits() as u32,
|
2015-04-29 06:14:37 +00:00
|
|
|
create_DIArray(DIB(cx), &enumerators_metadata),
|
2019-12-24 22:38:22 +00:00
|
|
|
discriminant_base_type_metadata,
|
|
|
|
true,
|
|
|
|
)
|
2015-04-29 06:14:37 +00:00
|
|
|
};
|
|
|
|
|
2019-12-24 22:38:22 +00:00
|
|
|
debug_context(cx)
|
|
|
|
.created_enum_disr_types
|
|
|
|
.borrow_mut()
|
|
|
|
.insert(disr_type_key, discriminant_type_metadata);
|
2015-04-29 06:14:37 +00:00
|
|
|
|
|
|
|
discriminant_type_metadata
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-09-22 22:54:45 +00:00
|
|
|
let layout = cx.layout_of(enum_type);
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2021-08-29 09:06:55 +00:00
|
|
|
if let (Abi::Scalar(_), Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, .. }) =
|
|
|
|
(layout.abi, &layout.variants)
|
2020-03-22 12:36:56 +00:00
|
|
|
{
|
2020-05-23 11:22:45 +00:00
|
|
|
return FinalMetadata(discriminant_type_metadata(tag.value));
|
2017-09-16 20:12:39 +00:00
|
|
|
}
|
|
|
|
|
2021-12-28 21:57:18 +00:00
|
|
|
// While LLVM supports generating debuginfo for variant types (enums), it doesn't support
|
|
|
|
// lowering that debuginfo to CodeView records for msvc targets. So if we are targeting
|
|
|
|
// msvc, then we need to use a different encoding of the debuginfo.
|
|
|
|
if cpp_like_debuginfo(tcx) {
|
2017-11-29 21:42:25 +00:00
|
|
|
let discriminant_type_metadata = match layout.variants {
|
2021-05-13 20:39:19 +00:00
|
|
|
Variants::Single { .. } => None,
|
2021-08-29 09:06:55 +00:00
|
|
|
Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, tag, .. }
|
|
|
|
| Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, .. } => {
|
2020-05-23 11:22:45 +00:00
|
|
|
Some(discriminant_type_metadata(tag.value))
|
2020-03-31 16:16:47 +00:00
|
|
|
}
|
2017-11-29 21:42:25 +00:00
|
|
|
};
|
|
|
|
|
2020-03-06 00:00:00 +00:00
|
|
|
let enum_metadata = {
|
2022-02-24 16:19:18 +00:00
|
|
|
let unique_type_id_str = unique_type_id.generate_unique_id_string(tcx);
|
2020-03-06 00:00:00 +00:00
|
|
|
|
|
|
|
unsafe {
|
|
|
|
llvm::LLVMRustDIBuilderCreateUnionType(
|
|
|
|
DIB(cx),
|
2021-04-26 18:39:57 +00:00
|
|
|
None,
|
2020-03-06 00:00:00 +00:00
|
|
|
enum_name.as_ptr().cast(),
|
|
|
|
enum_name.len(),
|
|
|
|
file_metadata,
|
|
|
|
UNKNOWN_LINE_NUMBER,
|
|
|
|
layout.size.bits(),
|
|
|
|
layout.align.abi.bits() as u32,
|
2021-04-30 12:02:53 +00:00
|
|
|
DIFlags::FlagZero,
|
2020-03-06 00:00:00 +00:00
|
|
|
None,
|
|
|
|
0, // RuntimeLang
|
|
|
|
unique_type_id_str.as_ptr().cast(),
|
|
|
|
unique_type_id_str.len(),
|
|
|
|
)
|
|
|
|
}
|
2017-11-29 21:42:25 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
return create_and_register_recursive_type_forward_declaration(
|
|
|
|
cx,
|
|
|
|
enum_type,
|
|
|
|
unique_type_id,
|
|
|
|
enum_metadata,
|
|
|
|
enum_metadata,
|
|
|
|
EnumMDF(EnumMemberDescriptionFactory {
|
|
|
|
enum_type,
|
|
|
|
layout,
|
2020-05-23 11:22:45 +00:00
|
|
|
tag_type_metadata: discriminant_type_metadata,
|
2021-04-30 08:14:42 +00:00
|
|
|
common_members: vec![],
|
2017-11-29 21:42:25 +00:00
|
|
|
}),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-08-02 22:49:11 +00:00
|
|
|
let discriminator_name = match enum_type.kind() {
|
2020-03-06 00:00:00 +00:00
|
|
|
ty::Generator(..) => "__state",
|
|
|
|
_ => "",
|
2019-04-13 00:03:03 +00:00
|
|
|
};
|
2019-03-29 05:44:54 +00:00
|
|
|
let discriminator_metadata = match layout.variants {
|
2017-11-29 21:42:25 +00:00
|
|
|
// A single-variant enum has no discriminant.
|
2020-03-31 16:16:47 +00:00
|
|
|
Variants::Single { .. } => None,
|
2017-11-29 21:42:25 +00:00
|
|
|
|
2021-08-29 09:06:55 +00:00
|
|
|
Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, tag, tag_field, .. } => {
|
2017-11-29 21:42:25 +00:00
|
|
|
// Find the integer type of the correct size.
|
2020-05-23 11:22:45 +00:00
|
|
|
let size = tag.value.size(cx);
|
|
|
|
let align = tag.value.align(cx);
|
2018-09-07 15:29:40 +00:00
|
|
|
|
2020-05-23 11:22:45 +00:00
|
|
|
let tag_type = match tag.value {
|
2020-03-31 16:16:47 +00:00
|
|
|
Int(t, _) => t,
|
|
|
|
F32 => Integer::I32,
|
|
|
|
F64 => Integer::I64,
|
|
|
|
Pointer => cx.data_layout().ptr_sized_integer(),
|
2019-12-24 22:38:22 +00:00
|
|
|
}
|
|
|
|
.to_ty(cx.tcx, false);
|
2017-11-29 21:42:25 +00:00
|
|
|
|
2020-05-23 11:22:45 +00:00
|
|
|
let tag_metadata = basic_type_metadata(cx, tag_type);
|
2017-11-29 21:42:25 +00:00
|
|
|
unsafe {
|
|
|
|
Some(llvm::LLVMRustDIBuilderCreateMemberType(
|
|
|
|
DIB(cx),
|
|
|
|
containing_scope,
|
2020-03-06 00:00:00 +00:00
|
|
|
discriminator_name.as_ptr().cast(),
|
|
|
|
discriminator_name.len(),
|
2017-11-29 21:42:25 +00:00
|
|
|
file_metadata,
|
|
|
|
UNKNOWN_LINE_NUMBER,
|
|
|
|
size.bits(),
|
2018-09-08 21:22:22 +00:00
|
|
|
align.abi.bits() as u32,
|
2020-05-23 11:22:45 +00:00
|
|
|
layout.fields.offset(tag_field).bits(),
|
2017-11-29 21:42:25 +00:00
|
|
|
DIFlags::FlagArtificial,
|
2020-05-23 11:22:45 +00:00
|
|
|
tag_metadata,
|
2019-12-24 22:38:22 +00:00
|
|
|
))
|
2017-11-29 21:42:25 +00:00
|
|
|
}
|
2019-12-24 22:38:22 +00:00
|
|
|
}
|
2017-11-29 21:42:25 +00:00
|
|
|
|
2021-08-29 09:06:55 +00:00
|
|
|
Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, tag_field, .. } => {
|
2020-05-23 11:22:45 +00:00
|
|
|
let discr_type = tag.value.to_ty(cx.tcx);
|
2017-11-29 21:42:25 +00:00
|
|
|
let (size, align) = cx.size_and_align_of(discr_type);
|
|
|
|
|
|
|
|
let discr_metadata = basic_type_metadata(cx, discr_type);
|
|
|
|
unsafe {
|
|
|
|
Some(llvm::LLVMRustDIBuilderCreateMemberType(
|
|
|
|
DIB(cx),
|
|
|
|
containing_scope,
|
2020-03-06 00:00:00 +00:00
|
|
|
discriminator_name.as_ptr().cast(),
|
|
|
|
discriminator_name.len(),
|
2017-11-29 21:42:25 +00:00
|
|
|
file_metadata,
|
|
|
|
UNKNOWN_LINE_NUMBER,
|
|
|
|
size.bits(),
|
2018-09-08 22:16:45 +00:00
|
|
|
align.bits() as u32,
|
2020-05-23 11:22:45 +00:00
|
|
|
layout.fields.offset(tag_field).bits(),
|
2017-11-29 21:42:25 +00:00
|
|
|
DIFlags::FlagArtificial,
|
2019-12-24 22:38:22 +00:00
|
|
|
discr_metadata,
|
|
|
|
))
|
2017-11-29 21:42:25 +00:00
|
|
|
}
|
2019-12-24 22:38:22 +00:00
|
|
|
}
|
2017-11-29 21:42:25 +00:00
|
|
|
};
|
|
|
|
|
2021-04-30 08:14:42 +00:00
|
|
|
let outer_fields = match layout.variants {
|
2020-03-31 16:16:47 +00:00
|
|
|
Variants::Single { .. } => vec![],
|
|
|
|
Variants::Multiple { .. } => {
|
2022-01-10 14:59:52 +00:00
|
|
|
let tuple_mdf =
|
|
|
|
TupleMemberDescriptionFactory { ty: enum_type, component_types: outer_field_tys };
|
2019-04-13 00:03:03 +00:00
|
|
|
tuple_mdf
|
|
|
|
.create_member_descriptions(cx)
|
|
|
|
.into_iter()
|
|
|
|
.map(|desc| Some(desc.into_metadata(cx, containing_scope)))
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-02-04 12:19:55 +00:00
|
|
|
let variant_part_unique_type_id_str =
|
2022-02-24 16:19:18 +00:00
|
|
|
UniqueTypeId::for_enum_variant_part(tcx, enum_type).generate_unique_id_string(tcx);
|
2022-02-04 12:19:55 +00:00
|
|
|
|
2017-11-29 21:42:25 +00:00
|
|
|
let empty_array = create_DIArray(DIB(cx), &[]);
|
2020-03-06 00:00:00 +00:00
|
|
|
let name = "";
|
2017-11-29 21:42:25 +00:00
|
|
|
let variant_part = unsafe {
|
|
|
|
llvm::LLVMRustDIBuilderCreateVariantPart(
|
|
|
|
DIB(cx),
|
|
|
|
containing_scope,
|
2020-03-06 00:00:00 +00:00
|
|
|
name.as_ptr().cast(),
|
|
|
|
name.len(),
|
2017-11-29 21:42:25 +00:00
|
|
|
file_metadata,
|
|
|
|
UNKNOWN_LINE_NUMBER,
|
2018-09-08 19:14:55 +00:00
|
|
|
layout.size.bits(),
|
2018-09-08 21:22:22 +00:00
|
|
|
layout.align.abi.bits() as u32,
|
2021-04-30 12:02:53 +00:00
|
|
|
DIFlags::FlagZero,
|
2017-11-29 21:42:25 +00:00
|
|
|
discriminator_metadata,
|
|
|
|
empty_array,
|
2020-03-06 00:00:00 +00:00
|
|
|
variant_part_unique_type_id_str.as_ptr().cast(),
|
|
|
|
variant_part_unique_type_id_str.len(),
|
2019-12-24 22:38:22 +00:00
|
|
|
)
|
2017-11-29 21:42:25 +00:00
|
|
|
};
|
|
|
|
|
2020-03-06 00:00:00 +00:00
|
|
|
let struct_wrapper = {
|
|
|
|
// The variant part must be wrapped in a struct according to DWARF.
|
2021-04-30 08:14:42 +00:00
|
|
|
// All fields except the discriminant (including `outer_fields`)
|
|
|
|
// should be put into structures inside the variant part, which gives
|
|
|
|
// an equivalent layout but offers us much better integration with
|
|
|
|
// debuggers.
|
|
|
|
let type_array = create_DIArray(DIB(cx), &[Some(variant_part)]);
|
2022-02-24 16:19:18 +00:00
|
|
|
let unique_type_id_str = unique_type_id.generate_unique_id_string(tcx);
|
2020-03-06 00:00:00 +00:00
|
|
|
|
|
|
|
unsafe {
|
|
|
|
llvm::LLVMRustDIBuilderCreateStructType(
|
|
|
|
DIB(cx),
|
|
|
|
Some(containing_scope),
|
|
|
|
enum_name.as_ptr().cast(),
|
|
|
|
enum_name.len(),
|
|
|
|
file_metadata,
|
|
|
|
UNKNOWN_LINE_NUMBER,
|
|
|
|
layout.size.bits(),
|
|
|
|
layout.align.abi.bits() as u32,
|
2021-04-30 12:02:53 +00:00
|
|
|
DIFlags::FlagZero,
|
2020-03-06 00:00:00 +00:00
|
|
|
None,
|
|
|
|
type_array,
|
|
|
|
0,
|
|
|
|
None,
|
|
|
|
unique_type_id_str.as_ptr().cast(),
|
|
|
|
unique_type_id_str.len(),
|
|
|
|
)
|
|
|
|
}
|
2015-04-29 06:14:37 +00:00
|
|
|
};
|
|
|
|
|
2020-03-20 14:03:11 +00:00
|
|
|
create_and_register_recursive_type_forward_declaration(
|
2015-04-29 06:14:37 +00:00
|
|
|
cx,
|
|
|
|
enum_type,
|
|
|
|
unique_type_id,
|
2017-11-29 21:42:25 +00:00
|
|
|
struct_wrapper,
|
|
|
|
variant_part,
|
2015-04-29 06:14:37 +00:00
|
|
|
EnumMDF(EnumMemberDescriptionFactory {
|
2017-08-07 05:54:09 +00:00
|
|
|
enum_type,
|
2017-09-22 22:54:45 +00:00
|
|
|
layout,
|
2020-05-23 11:22:45 +00:00
|
|
|
tag_type_metadata: None,
|
2021-04-30 08:14:42 +00:00
|
|
|
common_members: outer_fields,
|
2015-04-29 06:14:37 +00:00
|
|
|
}),
|
2020-03-20 14:03:11 +00:00
|
|
|
)
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Creates debug information for a composite type, that is, anything that
|
|
|
|
/// results in a LLVM struct.
|
|
|
|
///
|
|
|
|
/// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums.
|
2021-12-14 18:49:49 +00:00
|
|
|
fn composite_type_metadata<'ll, 'tcx>(
|
2018-07-04 13:36:49 +00:00
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
composite_type: Ty<'tcx>,
|
|
|
|
composite_type_name: &str,
|
2022-02-04 12:19:55 +00:00
|
|
|
composite_type_unique_id: UniqueTypeId<'tcx>,
|
2018-08-07 14:04:34 +00:00
|
|
|
member_descriptions: Vec<MemberDescription<'ll>>,
|
2018-07-04 13:36:49 +00:00
|
|
|
containing_scope: Option<&'ll DIScope>,
|
|
|
|
) -> &'ll DICompositeType {
|
2022-01-25 13:26:50 +00:00
|
|
|
let (size, align) = cx.size_and_align_of(composite_type);
|
|
|
|
|
2015-04-29 06:14:37 +00:00
|
|
|
// Create the (empty) struct metadata node ...
|
2019-12-24 22:38:22 +00:00
|
|
|
let composite_type_metadata = create_struct_stub(
|
|
|
|
cx,
|
2022-01-25 13:26:50 +00:00
|
|
|
size,
|
|
|
|
align,
|
2019-12-24 22:38:22 +00:00
|
|
|
composite_type_name,
|
|
|
|
composite_type_unique_id,
|
|
|
|
containing_scope,
|
2020-06-18 02:39:23 +00:00
|
|
|
DIFlags::FlagZero,
|
2022-01-25 13:26:50 +00:00
|
|
|
None,
|
2019-12-24 22:38:22 +00:00
|
|
|
);
|
2022-01-25 13:26:50 +00:00
|
|
|
|
2015-04-29 06:14:37 +00:00
|
|
|
// ... and immediately create and add the member descriptions.
|
2021-04-30 08:14:42 +00:00
|
|
|
set_members_of_composite_type(
|
|
|
|
cx,
|
|
|
|
composite_type_metadata,
|
|
|
|
member_descriptions,
|
|
|
|
None,
|
2022-01-25 13:26:50 +00:00
|
|
|
compute_type_parameters(cx, composite_type),
|
2021-04-30 08:14:42 +00:00
|
|
|
);
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2018-10-09 13:14:38 +00:00
|
|
|
composite_type_metadata
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
|
2021-12-14 18:49:49 +00:00
|
|
|
fn set_members_of_composite_type<'ll, 'tcx>(
|
2019-12-24 22:38:22 +00:00
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
composite_type_metadata: &'ll DICompositeType,
|
|
|
|
member_descriptions: Vec<MemberDescription<'ll>>,
|
2021-04-30 08:14:42 +00:00
|
|
|
common_members: Option<&Vec<Option<&'ll DIType>>>,
|
2022-01-25 13:26:50 +00:00
|
|
|
type_params: &'ll DIArray,
|
2019-12-24 22:38:22 +00:00
|
|
|
) {
|
2015-04-29 06:14:37 +00:00
|
|
|
// In some rare cases LLVM metadata uniquing would lead to an existing type
|
|
|
|
// description being used instead of a new one created in
|
|
|
|
// create_struct_stub. This would cause a hard to trace assertion in
|
|
|
|
// DICompositeType::SetTypeArray(). The following check makes sure that we
|
|
|
|
// get a better error message if this should happen again due to some
|
|
|
|
// regression.
|
|
|
|
{
|
|
|
|
let mut composite_types_completed =
|
|
|
|
debug_context(cx).composite_types_completed.borrow_mut();
|
2021-09-30 17:38:50 +00:00
|
|
|
if !composite_types_completed.insert(composite_type_metadata) {
|
2019-12-24 22:38:22 +00:00
|
|
|
bug!(
|
|
|
|
"debuginfo::set_members_of_composite_type() - \
|
|
|
|
Already completed forward declaration re-encountered."
|
|
|
|
);
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-30 08:14:42 +00:00
|
|
|
let mut member_metadata: Vec<_> = member_descriptions
|
2018-08-07 14:04:34 +00:00
|
|
|
.into_iter()
|
2019-04-13 00:03:03 +00:00
|
|
|
.map(|desc| Some(desc.into_metadata(cx, composite_type_metadata)))
|
2015-04-29 06:14:37 +00:00
|
|
|
.collect();
|
2021-04-30 08:14:42 +00:00
|
|
|
if let Some(other_members) = common_members {
|
|
|
|
member_metadata.extend(other_members.iter());
|
|
|
|
}
|
2015-04-29 06:14:37 +00:00
|
|
|
|
|
|
|
unsafe {
|
2022-01-25 13:26:50 +00:00
|
|
|
let field_array = create_DIArray(DIB(cx), &member_metadata);
|
2018-10-12 13:34:14 +00:00
|
|
|
llvm::LLVMRustDICompositeTypeReplaceArrays(
|
2019-12-24 22:38:22 +00:00
|
|
|
DIB(cx),
|
|
|
|
composite_type_metadata,
|
2022-01-25 13:26:50 +00:00
|
|
|
Some(field_array),
|
2020-12-29 21:24:15 +00:00
|
|
|
Some(type_params),
|
2019-12-24 22:38:22 +00:00
|
|
|
);
|
2018-10-12 13:34:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-17 01:20:14 +00:00
|
|
|
/// Computes the type parameters for a type, if any, for the given metadata.
|
2021-12-14 18:49:49 +00:00
|
|
|
fn compute_type_parameters<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> &'ll DIArray {
|
2020-08-02 22:49:11 +00:00
|
|
|
if let ty::Adt(def, substs) = *ty.kind() {
|
2020-02-29 00:56:37 +00:00
|
|
|
if substs.types().next().is_some() {
|
2018-10-12 13:34:14 +00:00
|
|
|
let generics = cx.tcx.generics_of(def.did);
|
|
|
|
let names = get_parameter_names(cx, generics);
|
2021-03-08 23:32:41 +00:00
|
|
|
let template_params: Vec<_> = iter::zip(substs, names)
|
2019-12-24 22:38:22 +00:00
|
|
|
.filter_map(|(kind, name)| {
|
|
|
|
if let GenericArgKind::Type(ty) = kind.unpack() {
|
|
|
|
let actual_type =
|
|
|
|
cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
|
2022-01-10 14:59:52 +00:00
|
|
|
let actual_type_metadata = type_metadata(cx, actual_type);
|
2021-12-15 03:39:23 +00:00
|
|
|
let name = name.as_str();
|
2019-12-24 22:38:22 +00:00
|
|
|
Some(unsafe {
|
|
|
|
Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
|
|
|
|
DIB(cx),
|
|
|
|
None,
|
2020-03-06 00:00:00 +00:00
|
|
|
name.as_ptr().cast(),
|
|
|
|
name.len(),
|
2019-12-24 22:38:22 +00:00
|
|
|
actual_type_metadata,
|
|
|
|
))
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect();
|
2018-10-12 13:34:14 +00:00
|
|
|
|
2021-12-03 02:06:36 +00:00
|
|
|
return create_DIArray(DIB(cx), &template_params);
|
2018-10-12 13:34:14 +00:00
|
|
|
}
|
|
|
|
}
|
2020-12-29 21:24:15 +00:00
|
|
|
return create_DIArray(DIB(cx), &[]);
|
2018-10-12 13:34:14 +00:00
|
|
|
|
2019-12-24 22:38:22 +00:00
|
|
|
fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec<Symbol> {
|
|
|
|
let mut names = generics
|
|
|
|
.parent
|
2021-02-25 01:13:42 +00:00
|
|
|
.map_or_else(Vec::new, |def_id| get_parameter_names(cx, cx.tcx.generics_of(def_id)));
|
2018-10-12 13:34:14 +00:00
|
|
|
names.extend(generics.params.iter().map(|param| param.name));
|
|
|
|
names
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-17 01:20:14 +00:00
|
|
|
/// A convenience wrapper around `LLVMRustDIBuilderCreateStructType()`. Does not do
|
|
|
|
/// any caching, does not add any fields to the struct. This can be done later
|
|
|
|
/// with `set_members_of_composite_type()`.
|
2021-12-14 18:49:49 +00:00
|
|
|
fn create_struct_stub<'ll, 'tcx>(
|
2018-07-04 13:36:49 +00:00
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
2022-01-25 13:26:50 +00:00
|
|
|
size: Size,
|
|
|
|
align: Align,
|
|
|
|
type_name: &str,
|
2022-02-04 12:19:55 +00:00
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
2018-07-04 13:36:49 +00:00
|
|
|
containing_scope: Option<&'ll DIScope>,
|
2020-06-18 02:39:23 +00:00
|
|
|
flags: DIFlags,
|
2022-01-25 13:26:50 +00:00
|
|
|
vtable_holder: Option<&'ll DIType>,
|
2018-07-04 13:36:49 +00:00
|
|
|
) -> &'ll DICompositeType {
|
2022-02-24 16:19:18 +00:00
|
|
|
let unique_type_id = unique_type_id.generate_unique_id_string(cx.tcx);
|
2020-03-06 00:00:00 +00:00
|
|
|
|
2015-04-29 06:14:37 +00:00
|
|
|
let metadata_stub = unsafe {
|
2019-05-17 01:20:14 +00:00
|
|
|
// `LLVMRustDIBuilderCreateStructType()` wants an empty array. A null
|
2015-04-29 06:14:37 +00:00
|
|
|
// pointer will lead to hard to trace and debug LLVM assertions
|
2019-05-17 01:20:14 +00:00
|
|
|
// later on in `llvm/lib/IR/Value.cpp`.
|
2015-04-29 06:14:37 +00:00
|
|
|
let empty_array = create_DIArray(DIB(cx), &[]);
|
|
|
|
|
2016-08-01 23:35:09 +00:00
|
|
|
llvm::LLVMRustDIBuilderCreateStructType(
|
2015-04-29 06:14:37 +00:00
|
|
|
DIB(cx),
|
|
|
|
containing_scope,
|
2022-01-25 13:26:50 +00:00
|
|
|
type_name.as_ptr().cast(),
|
|
|
|
type_name.len(),
|
2016-07-07 12:15:10 +00:00
|
|
|
unknown_file_metadata(cx),
|
2015-04-29 06:14:37 +00:00
|
|
|
UNKNOWN_LINE_NUMBER,
|
2022-01-25 13:26:50 +00:00
|
|
|
size.bits(),
|
|
|
|
align.bits() as u32,
|
2020-06-18 02:39:23 +00:00
|
|
|
flags,
|
2018-06-27 10:12:47 +00:00
|
|
|
None,
|
2015-04-29 06:14:37 +00:00
|
|
|
empty_array,
|
|
|
|
0,
|
2022-01-25 13:26:50 +00:00
|
|
|
vtable_holder,
|
2020-03-06 00:00:00 +00:00
|
|
|
unique_type_id.as_ptr().cast(),
|
|
|
|
unique_type_id.len(),
|
2019-12-24 22:38:22 +00:00
|
|
|
)
|
2015-04-29 06:14:37 +00:00
|
|
|
};
|
|
|
|
|
2018-10-09 13:14:38 +00:00
|
|
|
metadata_stub
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
|
2021-12-14 18:49:49 +00:00
|
|
|
fn create_union_stub<'ll, 'tcx>(
|
2018-07-04 13:36:49 +00:00
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
union_type: Ty<'tcx>,
|
|
|
|
union_type_name: &str,
|
2022-02-04 12:19:55 +00:00
|
|
|
unique_type_id: UniqueTypeId<'tcx>,
|
2018-07-04 13:36:49 +00:00
|
|
|
containing_scope: &'ll DIScope,
|
|
|
|
) -> &'ll DICompositeType {
|
2017-06-01 18:50:53 +00:00
|
|
|
let (union_size, union_align) = cx.size_and_align_of(union_type);
|
2022-02-24 16:19:18 +00:00
|
|
|
let unique_type_id = unique_type_id.generate_unique_id_string(cx.tcx);
|
2020-03-06 00:00:00 +00:00
|
|
|
|
2016-08-22 18:11:22 +00:00
|
|
|
let metadata_stub = unsafe {
|
2019-05-17 01:20:14 +00:00
|
|
|
// `LLVMRustDIBuilderCreateUnionType()` wants an empty array. A null
|
2016-08-22 18:11:22 +00:00
|
|
|
// pointer will lead to hard to trace and debug LLVM assertions
|
2019-05-17 01:20:14 +00:00
|
|
|
// later on in `llvm/lib/IR/Value.cpp`.
|
2016-08-22 18:11:22 +00:00
|
|
|
let empty_array = create_DIArray(DIB(cx), &[]);
|
|
|
|
|
|
|
|
llvm::LLVMRustDIBuilderCreateUnionType(
|
|
|
|
DIB(cx),
|
2021-04-26 18:39:57 +00:00
|
|
|
Some(containing_scope),
|
2020-03-06 00:00:00 +00:00
|
|
|
union_type_name.as_ptr().cast(),
|
|
|
|
union_type_name.len(),
|
2016-08-22 18:11:22 +00:00
|
|
|
unknown_file_metadata(cx),
|
|
|
|
UNKNOWN_LINE_NUMBER,
|
2017-06-01 18:50:53 +00:00
|
|
|
union_size.bits(),
|
2018-09-08 22:16:45 +00:00
|
|
|
union_align.bits() as u32,
|
2016-11-18 22:15:14 +00:00
|
|
|
DIFlags::FlagZero,
|
2018-07-04 13:36:49 +00:00
|
|
|
Some(empty_array),
|
2016-08-22 18:11:22 +00:00
|
|
|
0, // RuntimeLang
|
2020-03-06 00:00:00 +00:00
|
|
|
unique_type_id.as_ptr().cast(),
|
|
|
|
unique_type_id.len(),
|
2019-12-24 22:38:22 +00:00
|
|
|
)
|
2016-08-22 18:11:22 +00:00
|
|
|
};
|
|
|
|
|
2018-10-09 13:14:38 +00:00
|
|
|
metadata_stub
|
2016-08-22 18:11:22 +00:00
|
|
|
}
|
|
|
|
|
2015-04-29 06:14:37 +00:00
|
|
|
/// Creates debug information for the given global variable.
|
|
|
|
///
|
|
|
|
/// Adds the created metadata nodes directly to the crate's IR.
|
2021-12-14 18:49:49 +00:00
|
|
|
pub fn create_global_var_metadata<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId, global: &'ll Value) {
|
2018-01-05 04:58:34 +00:00
|
|
|
if cx.dbg_cx.is_none() {
|
2015-04-29 06:14:37 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-02-11 22:20:02 +00:00
|
|
|
// Only create type information if full debuginfo is enabled
|
|
|
|
if cx.sess().opts.debuginfo != DebugInfo::Full {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-01-05 04:58:34 +00:00
|
|
|
let tcx = cx.tcx;
|
2018-04-12 12:52:09 +00:00
|
|
|
|
2019-05-17 01:20:14 +00:00
|
|
|
// We may want to remove the namespace scope if we're in an extern block (see
|
|
|
|
// https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952).
|
2018-02-19 11:41:10 +00:00
|
|
|
let var_scope = get_namespace_for_item(cx, def_id);
|
2018-04-12 12:52:09 +00:00
|
|
|
let span = tcx.def_span(def_id);
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2018-06-24 22:00:21 +00:00
|
|
|
let (file_metadata, line_number) = if !span.is_dummy() {
|
2020-02-25 00:00:00 +00:00
|
|
|
let loc = cx.lookup_debug_loc(span.lo());
|
2020-02-10 01:03:24 +00:00
|
|
|
(file_metadata(cx, &loc.file), loc.line)
|
2015-04-29 06:14:37 +00:00
|
|
|
} else {
|
2021-02-19 20:50:15 +00:00
|
|
|
(unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
|
2015-04-29 06:14:37 +00:00
|
|
|
};
|
|
|
|
|
2018-02-19 11:41:10 +00:00
|
|
|
let is_local_to_unit = is_node_local_to_unit(cx, def_id);
|
2020-06-22 12:57:03 +00:00
|
|
|
let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx, ty::ParamEnv::reveal_all());
|
2022-01-10 14:59:52 +00:00
|
|
|
let type_metadata = type_metadata(cx, variable_type);
|
2021-12-14 21:32:21 +00:00
|
|
|
let var_name = tcx.item_name(def_id);
|
|
|
|
let var_name = var_name.as_str();
|
2020-07-10 05:45:05 +00:00
|
|
|
let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id)).name;
|
2020-03-06 00:00:00 +00:00
|
|
|
// When empty, linkage_name field is omitted,
|
|
|
|
// which is what we want for no_mangle statics
|
2020-05-26 00:00:00 +00:00
|
|
|
let linkage_name = if var_name == linkage_name { "" } else { linkage_name };
|
2016-11-18 16:11:18 +00:00
|
|
|
|
2017-03-02 03:35:25 +00:00
|
|
|
let global_align = cx.align_of(variable_type);
|
2016-11-18 16:11:18 +00:00
|
|
|
|
2015-04-29 06:14:37 +00:00
|
|
|
unsafe {
|
2019-12-24 22:38:22 +00:00
|
|
|
llvm::LLVMRustDIBuilderCreateStaticVariable(
|
|
|
|
DIB(cx),
|
|
|
|
Some(var_scope),
|
2020-03-06 00:00:00 +00:00
|
|
|
var_name.as_ptr().cast(),
|
|
|
|
var_name.len(),
|
|
|
|
linkage_name.as_ptr().cast(),
|
|
|
|
linkage_name.len(),
|
2019-12-24 22:38:22 +00:00
|
|
|
file_metadata,
|
2021-02-19 20:50:15 +00:00
|
|
|
line_number,
|
2019-12-24 22:38:22 +00:00
|
|
|
type_metadata,
|
|
|
|
is_local_to_unit,
|
|
|
|
global,
|
|
|
|
None,
|
|
|
|
global_align.bytes() as u32,
|
2016-11-18 16:11:18 +00:00
|
|
|
);
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
}
|
2016-08-25 02:34:31 +00:00
|
|
|
|
2021-10-06 12:26:50 +00:00
|
|
|
/// Generates LLVM debuginfo for a vtable.
|
2022-01-25 13:34:34 +00:00
|
|
|
///
|
|
|
|
/// The vtable type looks like a struct with a field for each function pointer and super-trait
|
|
|
|
/// pointer it contains (plus the `size` and `align` fields).
|
|
|
|
///
|
|
|
|
/// Except for `size`, `align`, and `drop_in_place`, the field names don't try to mirror
|
|
|
|
/// the name of the method they implement. This can be implemented in the future once there
|
|
|
|
/// is a proper disambiguation scheme for dealing with methods from different traits that have
|
|
|
|
/// the same name.
|
2021-12-14 18:49:49 +00:00
|
|
|
fn vtable_type_metadata<'ll, 'tcx>(
|
2021-10-06 12:26:50 +00:00
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
ty: Ty<'tcx>,
|
|
|
|
poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
|
|
|
|
) -> &'ll DIType {
|
|
|
|
let tcx = cx.tcx;
|
|
|
|
|
|
|
|
let vtable_entries = if let Some(poly_trait_ref) = poly_trait_ref {
|
|
|
|
let trait_ref = poly_trait_ref.with_self_ty(tcx, ty);
|
|
|
|
let trait_ref = tcx.erase_regions(trait_ref);
|
|
|
|
|
|
|
|
tcx.vtable_entries(trait_ref)
|
|
|
|
} else {
|
|
|
|
COMMON_VTABLE_ENTRIES
|
|
|
|
};
|
|
|
|
|
2022-01-25 13:34:34 +00:00
|
|
|
// All function pointers are described as opaque pointers. This could be improved in the future
|
|
|
|
// by describing them as actual function pointers.
|
|
|
|
let void_pointer_ty = tcx.mk_imm_ptr(tcx.types.unit);
|
|
|
|
let void_pointer_type_debuginfo = type_metadata(cx, void_pointer_ty);
|
|
|
|
let usize_debuginfo = type_metadata(cx, tcx.types.usize);
|
|
|
|
let (pointer_size, pointer_align) = cx.size_and_align_of(void_pointer_ty);
|
|
|
|
// If `usize` is not pointer-sized and -aligned then the size and alignment computations
|
|
|
|
// for the vtable as a whole would be wrong. Let's make sure this holds even on weird
|
|
|
|
// platforms.
|
|
|
|
assert_eq!(cx.size_and_align_of(tcx.types.usize), (pointer_size, pointer_align));
|
|
|
|
|
|
|
|
let vtable_type_name =
|
|
|
|
compute_debuginfo_vtable_name(cx.tcx, ty, poly_trait_ref, VTableNameKind::Type);
|
2022-02-04 12:19:55 +00:00
|
|
|
let unique_type_id = UniqueTypeId::for_vtable_ty(tcx, ty, poly_trait_ref);
|
2022-01-25 13:34:34 +00:00
|
|
|
let size = pointer_size * vtable_entries.len() as u64;
|
|
|
|
|
|
|
|
// This gets mapped to a DW_AT_containing_type attribute which allows GDB to correlate
|
|
|
|
// the vtable to the type it is for.
|
|
|
|
let vtable_holder = type_metadata(cx, ty);
|
|
|
|
|
|
|
|
let vtable_type_metadata = create_struct_stub(
|
|
|
|
cx,
|
|
|
|
size,
|
|
|
|
pointer_align,
|
|
|
|
&vtable_type_name,
|
|
|
|
unique_type_id,
|
|
|
|
NO_SCOPE_METADATA,
|
|
|
|
DIFlags::FlagArtificial,
|
|
|
|
Some(vtable_holder),
|
|
|
|
);
|
|
|
|
|
|
|
|
// Create a field for each entry in the vtable.
|
|
|
|
let fields: Vec<_> = vtable_entries
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.filter_map(|(index, vtable_entry)| {
|
|
|
|
let (field_name, field_type) = match vtable_entry {
|
|
|
|
ty::VtblEntry::MetadataDropInPlace => {
|
|
|
|
("drop_in_place".to_string(), void_pointer_type_debuginfo)
|
|
|
|
}
|
|
|
|
ty::VtblEntry::Method(_) => {
|
|
|
|
// Note: This code does not try to give a proper name to each method
|
2022-02-08 14:31:09 +00:00
|
|
|
// because there might be multiple methods with the same name
|
2022-01-25 13:34:34 +00:00
|
|
|
// (coming from different traits).
|
|
|
|
(format!("__method{}", index), void_pointer_type_debuginfo)
|
|
|
|
}
|
|
|
|
ty::VtblEntry::TraitVPtr(_) => {
|
2022-02-08 14:31:09 +00:00
|
|
|
// Note: In the future we could try to set the type of this pointer
|
|
|
|
// to the type that we generate for the corresponding vtable.
|
2022-01-25 13:34:34 +00:00
|
|
|
(format!("__super_trait_ptr{}", index), void_pointer_type_debuginfo)
|
|
|
|
}
|
|
|
|
ty::VtblEntry::MetadataAlign => ("align".to_string(), usize_debuginfo),
|
|
|
|
ty::VtblEntry::MetadataSize => ("size".to_string(), usize_debuginfo),
|
|
|
|
ty::VtblEntry::Vacant => return None,
|
|
|
|
};
|
|
|
|
|
|
|
|
Some(MemberDescription {
|
|
|
|
name: field_name,
|
|
|
|
type_metadata: field_type,
|
|
|
|
offset: pointer_size * index as u64,
|
|
|
|
size: pointer_size,
|
|
|
|
align: pointer_align,
|
|
|
|
flags: DIFlags::FlagZero,
|
|
|
|
discriminant: None,
|
|
|
|
source_info: None,
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.collect();
|
2021-10-06 12:26:50 +00:00
|
|
|
|
2022-01-25 13:34:34 +00:00
|
|
|
let type_params = create_DIArray(DIB(cx), &[]);
|
|
|
|
set_members_of_composite_type(cx, vtable_type_metadata, fields, None, type_params);
|
|
|
|
vtable_type_metadata
|
2021-10-06 12:26:50 +00:00
|
|
|
}
|
|
|
|
|
2018-09-20 13:47:22 +00:00
|
|
|
/// Creates debug information for the given vtable, which is for the
|
|
|
|
/// given type.
|
|
|
|
///
|
|
|
|
/// Adds the created metadata nodes directly to the crate's IR.
|
2021-12-14 18:49:49 +00:00
|
|
|
pub fn create_vtable_metadata<'ll, 'tcx>(
|
2021-10-06 12:26:50 +00:00
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
ty: Ty<'tcx>,
|
|
|
|
poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
|
|
|
|
vtable: &'ll Value,
|
|
|
|
) {
|
2018-09-20 13:47:22 +00:00
|
|
|
if cx.dbg_cx.is_none() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-02-11 22:20:02 +00:00
|
|
|
// Only create type information if full debuginfo is enabled
|
|
|
|
if cx.sess().opts.debuginfo != DebugInfo::Full {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-01-25 13:34:34 +00:00
|
|
|
let vtable_name =
|
|
|
|
compute_debuginfo_vtable_name(cx.tcx, ty, poly_trait_ref, VTableNameKind::GlobalVariable);
|
2021-10-06 12:26:50 +00:00
|
|
|
let vtable_type = vtable_type_metadata(cx, ty, poly_trait_ref);
|
2022-01-25 13:34:34 +00:00
|
|
|
let linkage_name = "";
|
2018-09-20 13:47:22 +00:00
|
|
|
|
|
|
|
unsafe {
|
2019-12-24 22:38:22 +00:00
|
|
|
llvm::LLVMRustDIBuilderCreateStaticVariable(
|
|
|
|
DIB(cx),
|
|
|
|
NO_SCOPE_METADATA,
|
2021-10-06 12:26:50 +00:00
|
|
|
vtable_name.as_ptr().cast(),
|
|
|
|
vtable_name.len(),
|
2020-03-06 00:00:00 +00:00
|
|
|
linkage_name.as_ptr().cast(),
|
|
|
|
linkage_name.len(),
|
2019-12-24 22:38:22 +00:00
|
|
|
unknown_file_metadata(cx),
|
|
|
|
UNKNOWN_LINE_NUMBER,
|
|
|
|
vtable_type,
|
|
|
|
true,
|
|
|
|
vtable,
|
|
|
|
None,
|
|
|
|
0,
|
|
|
|
);
|
2018-09-20 13:47:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-17 01:20:14 +00:00
|
|
|
/// Creates an "extension" of an existing `DIScope` into another file.
|
2021-12-14 18:49:49 +00:00
|
|
|
pub fn extend_scope_to_file<'ll>(
|
2018-07-04 13:36:49 +00:00
|
|
|
cx: &CodegenCx<'ll, '_>,
|
|
|
|
scope_metadata: &'ll DIScope,
|
2020-02-10 01:03:24 +00:00
|
|
|
file: &SourceFile,
|
2018-07-04 13:36:49 +00:00
|
|
|
) -> &'ll DILexicalBlock {
|
2020-02-10 01:03:24 +00:00
|
|
|
let file_metadata = file_metadata(cx, file);
|
2019-12-24 22:38:22 +00:00
|
|
|
unsafe { llvm::LLVMRustDIBuilderCreateLexicalBlockFile(DIB(cx), scope_metadata, file_metadata) }
|
2016-08-26 16:23:42 +00:00
|
|
|
}
|