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;
|
2016-10-21 21:56:36 +00:00
|
|
|
use super::type_names::compute_debuginfo_type_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;
|
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;
|
2019-12-24 22:38:22 +00:00
|
|
|
use rustc_codegen_ssa::traits::*;
|
|
|
|
use rustc_data_structures::fingerprint::Fingerprint;
|
2019-12-24 04:02:53 +00:00
|
|
|
use rustc_data_structures::fx::FxHashMap;
|
2019-12-24 22:38:22 +00:00
|
|
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
|
|
|
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};
|
2020-03-29 14:41:09 +00:00
|
|
|
use rustc_middle::ich::NodeIdHashingMode;
|
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;
|
2020-03-29 14:41:09 +00:00
|
|
|
use rustc_middle::ty::Instance;
|
2020-06-20 01:37:52 +00:00
|
|
|
use rustc_middle::ty::{self, AdtKind, GeneratorSubsts, ParamEnv, Ty, TyCtxt};
|
2020-03-29 14:41:09 +00:00
|
|
|
use rustc_middle::{bug, span_bug};
|
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;
|
2020-04-05 08:43:44 +00:00
|
|
|
use rustc_span::{self, SourceFile, SourceFileHash, Span};
|
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};
|
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};
|
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)]
|
|
|
|
const DW_ATE_unsigned_char: c_uint = 0x08;
|
|
|
|
|
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 {
|
|
|
|
use super::*;
|
|
|
|
use rustc_arena::DroplessArena;
|
|
|
|
|
|
|
|
#[derive(Copy, Hash, Eq, PartialEq, Clone)]
|
|
|
|
pub(super) struct UniqueTypeId(u32);
|
|
|
|
|
|
|
|
// The `&'static str`s in this type actually point into the arena.
|
|
|
|
//
|
|
|
|
// The `FxHashMap`+`Vec` pair could be replaced by `FxIndexSet`, but #75278
|
|
|
|
// found that to regress performance up to 2% in some cases. This might be
|
|
|
|
// revisited after further improvements to `indexmap`.
|
|
|
|
#[derive(Default)]
|
|
|
|
pub(super) struct TypeIdInterner {
|
|
|
|
arena: DroplessArena,
|
|
|
|
names: FxHashMap<&'static str, UniqueTypeId>,
|
|
|
|
strings: Vec<&'static str>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TypeIdInterner {
|
|
|
|
#[inline]
|
|
|
|
pub(super) fn intern(&mut self, string: &str) -> UniqueTypeId {
|
|
|
|
if let Some(&name) = self.names.get(string) {
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
let name = UniqueTypeId(self.strings.len() as u32);
|
|
|
|
|
|
|
|
// `from_utf8_unchecked` is safe since we just allocated a `&str` which is known to be
|
|
|
|
// UTF-8.
|
|
|
|
let string: &str =
|
|
|
|
unsafe { std::str::from_utf8_unchecked(self.arena.alloc_slice(string.as_bytes())) };
|
|
|
|
// It is safe to extend the arena allocation to `'static` because we only access
|
|
|
|
// these while the arena is still alive.
|
|
|
|
let string: &'static str = unsafe { &*(string as *const str) };
|
|
|
|
self.strings.push(string);
|
|
|
|
self.names.insert(string, name);
|
|
|
|
name
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the symbol as a string. `Symbol::as_str()` should be used in
|
|
|
|
// preference to this function.
|
|
|
|
pub(super) fn get(&self, symbol: UniqueTypeId) -> &str {
|
|
|
|
self.strings[symbol.0 as usize]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
use unique_type_id::*;
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2019-11-21 18:40:27 +00:00
|
|
|
/// The `TypeMap` is where the `CrateDebugContext` holds the type metadata nodes
|
|
|
|
/// created so far. The metadata nodes are indexed by `UniqueTypeId`, and, for
|
|
|
|
/// faster lookup, also by `Ty`. The `TypeMap` is responsible for creating
|
|
|
|
/// `UniqueTypeId`s.
|
2018-10-16 14:57:53 +00:00
|
|
|
#[derive(Default)]
|
2018-07-04 13:36:49 +00:00
|
|
|
pub struct TypeMap<'ll, 'tcx> {
|
2019-11-21 18:40:27 +00:00
|
|
|
/// The `UniqueTypeId`s created so far.
|
2021-08-08 15:24:30 +00:00
|
|
|
unique_id_interner: TypeIdInterner,
|
2019-11-21 18:40:27 +00:00
|
|
|
/// A map from `UniqueTypeId` to debuginfo metadata for that type. This is a 1:1 mapping.
|
2018-07-04 13:36:49 +00:00
|
|
|
unique_id_to_metadata: FxHashMap<UniqueTypeId, &'ll DIType>,
|
2019-11-21 18:40:27 +00:00
|
|
|
/// A map from types to debuginfo metadata. This is an N:1 mapping.
|
2018-07-04 13:36:49 +00:00
|
|
|
type_to_metadata: FxHashMap<Ty<'tcx>, &'ll DIType>,
|
2019-11-21 18:40:27 +00:00
|
|
|
/// A map from types to `UniqueTypeId`. This is an N:1 mapping.
|
2019-12-24 22:38:22 +00:00
|
|
|
type_to_unique_id: FxHashMap<Ty<'tcx>, UniqueTypeId>,
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
impl TypeMap<'ll, 'tcx> {
|
2019-05-17 01:20:14 +00:00
|
|
|
/// Adds a Ty to metadata mapping to the TypeMap. The method will fail if
|
|
|
|
/// the mapping already exists.
|
2019-12-24 22:38:22 +00:00
|
|
|
fn register_type_with_metadata(&mut self, type_: Ty<'tcx>, metadata: &'ll DIType) {
|
2015-04-29 06:14:37 +00:00
|
|
|
if self.type_to_metadata.insert(type_, metadata).is_some() {
|
2019-05-17 01:20:14 +00:00
|
|
|
bug!("type metadata for `Ty` '{}' is already in the `TypeMap`!", type_);
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-17 01:20:14 +00:00
|
|
|
/// Removes a `Ty`-to-metadata mapping.
|
|
|
|
/// This is useful when computing the metadata for a potentially
|
|
|
|
/// recursive type (e.g., a function pointer of the form:
|
|
|
|
///
|
|
|
|
/// fn foo() -> impl Copy { foo }
|
|
|
|
///
|
|
|
|
/// This kind of type cannot be properly represented
|
|
|
|
/// via LLVM debuginfo. As a workaround,
|
|
|
|
/// we register a temporary Ty to metadata mapping
|
|
|
|
/// for the function before we compute its actual metadata.
|
|
|
|
/// If the metadata computation ends up recursing back to the
|
|
|
|
/// original function, it will use the temporary mapping
|
|
|
|
/// for the inner self-reference, preventing us from
|
|
|
|
/// recursing forever.
|
|
|
|
///
|
|
|
|
/// This function is used to remove the temporary metadata
|
|
|
|
/// mapping after we've computed the actual metadata.
|
2019-12-24 22:38:22 +00:00
|
|
|
fn remove_type(&mut self, type_: Ty<'tcx>) {
|
Fix stack overflow when generating debuginfo for 'recursive' type
By using 'impl trait', it's possible to create a self-referential
type as follows:
fn foo() -> impl Copy { foo }
This is a function which returns itself.
Normally, the signature of this function would be impossible
to write - it would look like 'fn foo() -> fn() -> fn() ...'
e.g. a function which returns a function, which returns a function...
Using 'impl trait' allows us to avoid writing this infinitely long
type. While it's useless for practical purposes, it does compile and run
However, issues arise when we try to generate llvm debuginfo for such a
type. All 'impl trait' types (e.g. ty::Opaque) are resolved when we
generate debuginfo, which can lead to us recursing back to the original
'fn' type when we try to process its return type.
To resolve this, I've modified debuginfo generation to account for these
kinds of weird types. Unfortunately, there's no 'correct' debuginfo that
we can generate - 'impl trait' does not exist in debuginfo, and this
kind of recursive type is impossible to directly represent.
To ensure that we emit *something*, this commit emits dummy
debuginfo/type names whenever it encounters a self-reference. In
practice, this should never happen - it's just to ensure that we can
emit some kind of debuginfo, even if it's not particularly meaningful
Fixes #58463
2019-03-26 19:30:41 +00:00
|
|
|
if self.type_to_metadata.remove(type_).is_none() {
|
2019-05-17 01:20:14 +00:00
|
|
|
bug!("type metadata `Ty` '{}' is not in the `TypeMap`!", type_);
|
Fix stack overflow when generating debuginfo for 'recursive' type
By using 'impl trait', it's possible to create a self-referential
type as follows:
fn foo() -> impl Copy { foo }
This is a function which returns itself.
Normally, the signature of this function would be impossible
to write - it would look like 'fn foo() -> fn() -> fn() ...'
e.g. a function which returns a function, which returns a function...
Using 'impl trait' allows us to avoid writing this infinitely long
type. While it's useless for practical purposes, it does compile and run
However, issues arise when we try to generate llvm debuginfo for such a
type. All 'impl trait' types (e.g. ty::Opaque) are resolved when we
generate debuginfo, which can lead to us recursing back to the original
'fn' type when we try to process its return type.
To resolve this, I've modified debuginfo generation to account for these
kinds of weird types. Unfortunately, there's no 'correct' debuginfo that
we can generate - 'impl trait' does not exist in debuginfo, and this
kind of recursive type is impossible to directly represent.
To ensure that we emit *something*, this commit emits dummy
debuginfo/type names whenever it encounters a self-reference. In
practice, this should never happen - it's just to ensure that we can
emit some kind of debuginfo, even if it's not particularly meaningful
Fixes #58463
2019-03-26 19:30:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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(
|
|
|
|
&mut self,
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
metadata: &'ll DIType,
|
|
|
|
) {
|
2015-04-29 06:14:37 +00:00
|
|
|
if self.unique_id_to_metadata.insert(unique_type_id, metadata).is_some() {
|
2019-12-24 22:38:22 +00:00
|
|
|
bug!(
|
|
|
|
"type metadata for unique ID '{}' is already in the `TypeMap`!",
|
|
|
|
self.get_unique_type_id_as_string(unique_type_id)
|
|
|
|
);
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
fn find_metadata_for_type(&self, type_: Ty<'tcx>) -> Option<&'ll DIType> {
|
2015-04-29 06:14:37 +00:00
|
|
|
self.type_to_metadata.get(&type_).cloned()
|
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
fn find_metadata_for_unique_id(&self, unique_type_id: UniqueTypeId) -> Option<&'ll DIType> {
|
2015-04-29 06:14:37 +00:00
|
|
|
self.unique_id_to_metadata.get(&unique_type_id).cloned()
|
|
|
|
}
|
|
|
|
|
2019-05-17 01:20:14 +00:00
|
|
|
/// Gets the string representation of a `UniqueTypeId`. This method will fail if
|
|
|
|
/// the ID is unknown.
|
2016-11-19 05:55:28 +00:00
|
|
|
fn get_unique_type_id_as_string(&self, unique_type_id: UniqueTypeId) -> &str {
|
2021-08-08 15:24:30 +00:00
|
|
|
self.unique_id_interner.get(unique_type_id)
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
|
2019-05-17 01:20:14 +00:00
|
|
|
/// Gets the `UniqueTypeId` for the given type. If the `UniqueTypeId` for the given
|
|
|
|
/// type has been requested before, this is just a table lookup. Otherwise, an
|
|
|
|
/// ID will be generated and stored for later lookup.
|
2019-12-24 22:38:22 +00:00
|
|
|
fn get_unique_type_id_of_type<'a>(
|
|
|
|
&mut self,
|
|
|
|
cx: &CodegenCx<'a, 'tcx>,
|
|
|
|
type_: Ty<'tcx>,
|
|
|
|
) -> UniqueTypeId {
|
2019-05-17 01:20:14 +00:00
|
|
|
// Let's see if we already have something in the cache.
|
2018-10-09 13:15:41 +00:00
|
|
|
if let Some(unique_type_id) = self.type_to_unique_id.get(&type_).cloned() {
|
2018-10-16 09:14:10 +00:00
|
|
|
return unique_type_id;
|
2018-10-09 13:15:41 +00:00
|
|
|
}
|
2019-05-17 01:20:14 +00:00
|
|
|
// If not, generate one.
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2016-10-27 02:42:48 +00:00
|
|
|
// The hasher we are using to generate the UniqueTypeId. We want
|
|
|
|
// something that provides more than the 64 bits of the DefaultHasher.
|
2019-09-26 22:54:39 +00:00
|
|
|
let mut hasher = StableHasher::new();
|
2018-05-08 11:52:01 +00:00
|
|
|
let mut hcx = cx.tcx.create_stable_hashing_context();
|
2020-10-24 00:21:18 +00:00
|
|
|
let type_ = cx.tcx.erase_regions(type_);
|
2018-05-08 11:52:01 +00:00
|
|
|
hcx.while_hashing_spans(false, |hcx| {
|
|
|
|
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
|
|
|
|
type_.hash_stable(hcx, &mut hasher);
|
|
|
|
});
|
|
|
|
});
|
2019-09-26 22:54:39 +00:00
|
|
|
let unique_type_id = hasher.finish::<Fingerprint>().to_hex();
|
2017-10-16 12:43:36 +00:00
|
|
|
|
2016-10-12 17:54:41 +00:00
|
|
|
let key = self.unique_id_interner.intern(&unique_type_id);
|
2021-08-08 15:24:30 +00:00
|
|
|
self.type_to_unique_id.insert(type_, key);
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2021-08-08 15:24:30 +00:00
|
|
|
key
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
|
2019-11-21 18:40:27 +00:00
|
|
|
/// Gets the `UniqueTypeId` for an enum variant. Enum variants are not really
|
|
|
|
/// types of their own, so they need special handling. We still need a
|
|
|
|
/// `UniqueTypeId` for them, since to debuginfo they *are* real types.
|
2019-12-24 22:38:22 +00:00
|
|
|
fn get_unique_type_id_of_enum_variant<'a>(
|
|
|
|
&mut self,
|
|
|
|
cx: &CodegenCx<'a, 'tcx>,
|
|
|
|
enum_type: Ty<'tcx>,
|
|
|
|
variant_name: &str,
|
|
|
|
) -> UniqueTypeId {
|
2015-04-29 06:14:37 +00:00
|
|
|
let enum_type_id = self.get_unique_type_id_of_type(cx, enum_type);
|
2019-12-24 22:38:22 +00:00
|
|
|
let enum_variant_type_id =
|
|
|
|
format!("{}::{}", self.get_unique_type_id_as_string(enum_type_id), variant_name);
|
2016-10-12 17:54:41 +00:00
|
|
|
let interner_key = self.unique_id_interner.intern(&enum_variant_type_id);
|
2021-08-08 15:24:30 +00:00
|
|
|
interner_key
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
2019-03-27 05:22:37 +00:00
|
|
|
|
2019-11-21 18:40:27 +00:00
|
|
|
/// Gets the unique type ID string for an enum variant part.
|
|
|
|
/// Variant parts are not types and shouldn't really have their own ID,
|
|
|
|
/// but it makes `set_members_of_composite_type()` simpler.
|
2020-03-06 00:00:00 +00:00
|
|
|
fn get_unique_type_id_str_of_enum_variant_part(
|
|
|
|
&mut self,
|
|
|
|
enum_type_id: UniqueTypeId,
|
|
|
|
) -> String {
|
2020-03-06 00:00:00 +00:00
|
|
|
format!("{}_variant_part", self.get_unique_type_id_as_string(enum_type_id))
|
2019-03-27 05:22:37 +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>,
|
|
|
|
unique_type_id: UniqueTypeId,
|
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
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
fn create_and_register_recursive_type_forward_declaration(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
2015-04-29 06:14:37 +00:00
|
|
|
unfinished_type: Ty<'tcx>,
|
|
|
|
unique_type_id: UniqueTypeId,
|
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.
|
2015-04-29 06:14:37 +00:00
|
|
|
let mut type_map = debug_context(cx).type_map.borrow_mut();
|
2016-03-28 23:46:02 +00:00
|
|
|
type_map.register_unique_id_with_metadata(unique_type_id, metadata_stub);
|
|
|
|
type_map.register_type_with_metadata(unfinished_type, 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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
impl 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.
|
|
|
|
{
|
|
|
|
let type_map = debug_context(cx).type_map.borrow();
|
2019-12-24 22:38:22 +00:00
|
|
|
if type_map.find_metadata_for_unique_id(unique_type_id).is_none()
|
|
|
|
|| type_map.find_metadata_for_type(unfinished_type).is_none()
|
|
|
|
{
|
|
|
|
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);
|
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,
|
|
|
|
unfinished_type,
|
|
|
|
member_holding_stub,
|
|
|
|
member_descriptions,
|
2021-04-30 08:14:42 +00:00
|
|
|
None,
|
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) =
|
|
|
|
debug_context($cx).type_map.borrow().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
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
fn fixed_vec_metadata(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
array_or_slice_type: Ty<'tcx>,
|
|
|
|
element_type: Ty<'tcx>,
|
|
|
|
span: Span,
|
|
|
|
) -> MetadataCreationResult<'ll> {
|
2015-04-24 04:48:10 +00:00
|
|
|
let element_type_metadata = type_metadata(cx, element_type, span);
|
|
|
|
|
|
|
|
return_if_metadata_created_in_meantime!(cx, unique_type_id);
|
|
|
|
|
2017-06-01 18:50:53 +00:00
|
|
|
let (size, align) = cx.size_and_align_of(array_or_slice_type);
|
2015-04-24 04:48:10 +00:00
|
|
|
|
2020-08-02 22:49:11 +00:00
|
|
|
let upper_bound = match array_or_slice_type.kind() {
|
2019-03-25 23:13:09 +00:00
|
|
|
ty::Array(_, len) => len.eval_usize(cx.tcx, ty::ParamEnv::reveal_all()) as c_longlong,
|
2019-12-24 22:38:22 +00:00
|
|
|
_ => -1,
|
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
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
fn vec_slice_metadata(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
slice_ptr_type: Ty<'tcx>,
|
|
|
|
element_type: Ty<'tcx>,
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
span: Span,
|
|
|
|
) -> MetadataCreationResult<'ll> {
|
2018-01-05 04:58:34 +00:00
|
|
|
let data_ptr_type = cx.tcx.mk_imm_ptr(element_type);
|
2015-04-24 04:48:10 +00:00
|
|
|
|
2017-06-01 18:50:53 +00:00
|
|
|
let data_ptr_metadata = type_metadata(cx, data_ptr_type, span);
|
2015-04-24 04:48:10 +00:00
|
|
|
|
|
|
|
return_if_metadata_created_in_meantime!(cx, unique_type_id);
|
|
|
|
|
2019-03-30 14:45:09 +00:00
|
|
|
let slice_type_name = compute_debuginfo_type_name(cx.tcx, slice_ptr_type, true);
|
2017-06-01 18:50:53 +00:00
|
|
|
|
|
|
|
let (pointer_size, pointer_align) = cx.size_and_align_of(data_ptr_type);
|
2018-01-05 04:58:34 +00:00
|
|
|
let (usize_size, usize_align) = cx.size_and_align_of(cx.tcx.types.usize);
|
2015-04-24 04:48:10 +00:00
|
|
|
|
2018-08-07 14:04:34 +00:00
|
|
|
let member_descriptions = vec![
|
2015-04-24 04:48:10 +00:00
|
|
|
MemberDescription {
|
2018-10-09 13:16:20 +00:00
|
|
|
name: "data_ptr".to_owned(),
|
2017-06-01 18:50:53 +00:00
|
|
|
type_metadata: data_ptr_metadata,
|
2018-05-20 12:14:39 +00:00
|
|
|
offset: Size::ZERO,
|
2017-06-01 18:50:53 +00:00
|
|
|
size: pointer_size,
|
|
|
|
align: pointer_align,
|
2016-11-18 22:15:14 +00:00
|
|
|
flags: DIFlags::FlagZero,
|
2017-11-29 21:42:25 +00:00
|
|
|
discriminant: None,
|
2020-06-17 23:04:25 +00:00
|
|
|
source_info: None,
|
2015-04-24 04:48:10 +00:00
|
|
|
},
|
|
|
|
MemberDescription {
|
2018-10-09 13:16:20 +00:00
|
|
|
name: "length".to_owned(),
|
2018-01-05 04:58:34 +00:00
|
|
|
type_metadata: type_metadata(cx, cx.tcx.types.usize, span),
|
2017-06-01 18:50:53 +00:00
|
|
|
offset: pointer_size,
|
|
|
|
size: usize_size,
|
|
|
|
align: usize_align,
|
2016-11-18 22:15:14 +00:00
|
|
|
flags: DIFlags::FlagZero,
|
2017-11-29 21:42:25 +00:00
|
|
|
discriminant: None,
|
2020-06-17 23:04:25 +00:00
|
|
|
source_info: None,
|
2015-04-24 04:48:10 +00:00
|
|
|
},
|
|
|
|
];
|
|
|
|
|
2017-04-24 17:01:19 +00:00
|
|
|
let file_metadata = unknown_file_metadata(cx);
|
2015-04-24 04:48:10 +00:00
|
|
|
|
2019-12-24 22:38:22 +00:00
|
|
|
let metadata = composite_type_metadata(
|
|
|
|
cx,
|
|
|
|
slice_ptr_type,
|
|
|
|
&slice_type_name[..],
|
|
|
|
unique_type_id,
|
|
|
|
member_descriptions,
|
|
|
|
NO_SCOPE_METADATA,
|
|
|
|
file_metadata,
|
|
|
|
span,
|
|
|
|
);
|
2017-06-01 18:50:53 +00:00
|
|
|
MetadataCreationResult::new(metadata, false)
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
fn subroutine_type_metadata(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
signature: ty::PolyFnSig<'tcx>,
|
|
|
|
span: Span,
|
|
|
|
) -> MetadataCreationResult<'ll> {
|
2019-12-24 22:38:22 +00:00
|
|
|
let signature =
|
2020-10-24 00:21:18 +00:00
|
|
|
cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), signature);
|
2015-04-24 04:48:10 +00:00
|
|
|
|
2018-06-27 10:12:47 +00:00
|
|
|
let signature_metadata: Vec<_> = iter::once(
|
2018-07-26 15:11:10 +00:00
|
|
|
// return type
|
2020-08-02 22:49:11 +00:00
|
|
|
match signature.output().kind() {
|
2021-09-30 17:38:50 +00:00
|
|
|
ty::Tuple(tys) if tys.is_empty() => None,
|
2019-12-24 22:38:22 +00:00
|
|
|
_ => Some(type_metadata(cx, signature.output(), span)),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.chain(
|
2018-07-26 15:11:10 +00:00
|
|
|
// regular arguments
|
2019-12-24 22:38:22 +00:00
|
|
|
signature.inputs().iter().map(|argument_type| Some(type_metadata(cx, argument_type, span))),
|
|
|
|
)
|
|
|
|
.collect();
|
2015-04-24 04:48:10 +00:00
|
|
|
|
|
|
|
return_if_metadata_created_in_meantime!(cx, unique_type_id);
|
|
|
|
|
2020-03-20 14:03:11 +00:00
|
|
|
MetadataCreationResult::new(
|
2015-04-24 04:48:10 +00:00
|
|
|
unsafe {
|
2016-08-01 23:35:09 +00:00
|
|
|
llvm::LLVMRustDIBuilderCreateSubroutineType(
|
2015-04-24 04:48:10 +00:00
|
|
|
DIB(cx),
|
2019-12-24 22:38:22 +00:00
|
|
|
create_DIArray(DIB(cx), &signature_metadata[..]),
|
|
|
|
)
|
2015-04-24 04:48:10 +00:00
|
|
|
},
|
2019-12-24 22:38:22 +00:00
|
|
|
false,
|
2020-03-20 14:03:11 +00:00
|
|
|
)
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
|
2019-06-17 22:40:24 +00:00
|
|
|
// FIXME(1563): This is all a bit of a hack because 'trait pointer' is an ill-
|
|
|
|
// defined concept. For the case of an actual trait pointer (i.e., `Box<Trait>`,
|
|
|
|
// `&Trait`), `trait_object_type` should be the whole thing (e.g, `Box<Trait>`) and
|
|
|
|
// `trait_type` should be the actual trait (e.g., `Trait`). Where the trait is part
|
|
|
|
// of a DST struct, there is no `trait_object_type` and the results of this
|
2015-04-24 04:48:10 +00:00
|
|
|
// function will be a little bit weird.
|
2018-07-04 13:36:49 +00:00
|
|
|
fn trait_pointer_metadata(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
trait_type: Ty<'tcx>,
|
|
|
|
trait_object_type: Option<Ty<'tcx>>,
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
) -> &'ll DIType {
|
2015-04-24 04:48:10 +00:00
|
|
|
// The implementation provided here is a stub. It makes sure that the trait
|
|
|
|
// type is assigned the correct name, size, namespace, and source location.
|
2019-06-17 22:40:24 +00:00
|
|
|
// However, it does not describe the trait's methods.
|
2015-04-24 04:48:10 +00:00
|
|
|
|
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
|
|
|
let (containing_scope, trait_type_name) = match trait_object_type {
|
|
|
|
Some(trait_object_type) => match trait_object_type.kind() {
|
|
|
|
ty::Adt(def, _) => (
|
|
|
|
Some(get_namespace_for_item(cx, def.did)),
|
|
|
|
compute_debuginfo_type_name(cx.tcx, trait_object_type, false),
|
|
|
|
),
|
|
|
|
ty::RawPtr(_) | ty::Ref(..) => {
|
|
|
|
(NO_SCOPE_METADATA, compute_debuginfo_type_name(cx.tcx, trait_object_type, true))
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
bug!(
|
|
|
|
"debuginfo: unexpected trait-object type in \
|
|
|
|
trait_pointer_metadata(): {:?}",
|
|
|
|
trait_object_type
|
|
|
|
);
|
|
|
|
}
|
|
|
|
},
|
2015-04-24 04:48:10 +00:00
|
|
|
|
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
|
|
|
// No object type, use the trait type directly (no scope here since the type
|
|
|
|
// will be wrapped in the dyn$ synthetic type).
|
|
|
|
None => (NO_SCOPE_METADATA, compute_debuginfo_type_name(cx.tcx, trait_type, true)),
|
|
|
|
};
|
2015-04-24 04:48:10 +00:00
|
|
|
|
2016-07-07 12:15:10 +00:00
|
|
|
let file_metadata = unknown_file_metadata(cx);
|
2015-04-24 04:48:10 +00:00
|
|
|
|
2018-01-05 04:58:34 +00:00
|
|
|
let layout = cx.layout_of(cx.tcx.mk_mut_ptr(trait_type));
|
2017-05-27 19:46:42 +00:00
|
|
|
|
|
|
|
assert_eq!(abi::FAT_PTR_ADDR, 0);
|
|
|
|
assert_eq!(abi::FAT_PTR_EXTRA, 1);
|
2017-06-01 18:50:53 +00:00
|
|
|
|
|
|
|
let data_ptr_field = layout.field(cx, 0);
|
|
|
|
let vtable_field = layout.field(cx, 1);
|
2018-08-07 14:04:34 +00:00
|
|
|
let member_descriptions = vec![
|
2017-05-27 19:46:42 +00:00
|
|
|
MemberDescription {
|
2018-10-09 13:16:20 +00:00
|
|
|
name: "pointer".to_owned(),
|
2019-12-24 22:38:22 +00:00
|
|
|
type_metadata: type_metadata(
|
|
|
|
cx,
|
2018-01-05 04:58:34 +00:00
|
|
|
cx.tcx.mk_mut_ptr(cx.tcx.types.u8),
|
2019-12-31 17:15:40 +00:00
|
|
|
rustc_span::DUMMY_SP,
|
2019-12-24 22:38:22 +00:00
|
|
|
),
|
2017-09-13 11:35:04 +00:00
|
|
|
offset: layout.fields.offset(0),
|
2017-09-22 19:44:40 +00:00
|
|
|
size: data_ptr_field.size,
|
2018-09-08 22:16:45 +00:00
|
|
|
align: data_ptr_field.align.abi,
|
2017-05-27 19:46:42 +00:00
|
|
|
flags: DIFlags::FlagArtificial,
|
2017-11-29 21:42:25 +00:00
|
|
|
discriminant: None,
|
2020-06-17 23:04:25 +00:00
|
|
|
source_info: None,
|
2017-05-27 19:46:42 +00:00
|
|
|
},
|
|
|
|
MemberDescription {
|
2018-10-09 13:16:20 +00:00
|
|
|
name: "vtable".to_owned(),
|
2019-12-31 17:15:40 +00:00
|
|
|
type_metadata: type_metadata(cx, vtable_field.ty, rustc_span::DUMMY_SP),
|
2017-09-13 11:35:04 +00:00
|
|
|
offset: layout.fields.offset(1),
|
2017-09-22 19:44:40 +00:00
|
|
|
size: vtable_field.size,
|
2018-09-08 22:16:45 +00:00
|
|
|
align: vtable_field.align.abi,
|
2017-05-27 19:46:42 +00:00
|
|
|
flags: DIFlags::FlagArtificial,
|
2017-11-29 21:42:25 +00:00
|
|
|
discriminant: None,
|
2020-06-17 23:04:25 +00:00
|
|
|
source_info: None,
|
2017-05-27 19:46:42 +00:00
|
|
|
},
|
|
|
|
];
|
|
|
|
|
2019-12-24 22:38:22 +00:00
|
|
|
composite_type_metadata(
|
|
|
|
cx,
|
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
|
|
|
trait_object_type.unwrap_or(trait_type),
|
2019-12-24 22:38:22 +00:00
|
|
|
&trait_type_name[..],
|
|
|
|
unique_type_id,
|
|
|
|
member_descriptions,
|
|
|
|
containing_scope,
|
|
|
|
file_metadata,
|
2019-12-31 17:15:40 +00:00
|
|
|
rustc_span::DUMMY_SP,
|
2019-12-24 22:38:22 +00:00
|
|
|
)
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
|
2019-12-24 22:38:22 +00:00
|
|
|
pub fn type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>, usage_site_span: Span) -> &'ll DIType {
|
2019-05-17 01:20:14 +00:00
|
|
|
// Get the unique type ID of this type.
|
2015-04-24 04:48:10 +00:00
|
|
|
let unique_type_id = {
|
|
|
|
let mut type_map = debug_context(cx).type_map.borrow_mut();
|
2019-05-17 01:20:14 +00:00
|
|
|
// First, try to find the type in `TypeMap`. If we have seen it before, we
|
2015-04-24 04:48:10 +00:00
|
|
|
// can exit early here.
|
|
|
|
match type_map.find_metadata_for_type(t) {
|
|
|
|
Some(metadata) => {
|
|
|
|
return metadata;
|
2019-12-24 22:38:22 +00:00
|
|
|
}
|
2015-04-24 04:48:10 +00:00
|
|
|
None => {
|
2019-05-17 01:20:14 +00:00
|
|
|
// The Ty is not in the `TypeMap` but maybe we have already seen
|
2018-11-27 02:59:49 +00:00
|
|
|
// an equivalent type (e.g., only differing in region arguments).
|
2019-05-17 01:20:14 +00:00
|
|
|
// In order to find out, generate the unique type ID and look
|
2015-04-24 04:48:10 +00:00
|
|
|
// that up.
|
|
|
|
let unique_type_id = type_map.get_unique_type_id_of_type(cx, t);
|
|
|
|
match type_map.find_metadata_for_unique_id(unique_type_id) {
|
|
|
|
Some(metadata) => {
|
|
|
|
// There is already an equivalent type in the TypeMap.
|
|
|
|
// Register this Ty as an alias in the cache and
|
|
|
|
// return the cached metadata.
|
2016-03-28 23:46:02 +00:00
|
|
|
type_map.register_type_with_metadata(t, metadata);
|
2015-04-24 04:48:10 +00:00
|
|
|
return metadata;
|
2019-12-24 22:38:22 +00:00
|
|
|
}
|
2015-04-24 04:48:10 +00:00
|
|
|
None => {
|
|
|
|
// There really is no type metadata for this type, so
|
|
|
|
// proceed by creating it.
|
|
|
|
unique_type_id
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
debug!("type_metadata: {:?}", t);
|
|
|
|
|
2020-08-02 22:49:11 +00:00
|
|
|
let ptr_metadata = |ty: Ty<'tcx>| match *ty.kind() {
|
2019-12-24 22:38:22 +00:00
|
|
|
ty::Slice(typ) => Ok(vec_slice_metadata(cx, t, typ, unique_type_id, usage_site_span)),
|
|
|
|
ty::Str => Ok(vec_slice_metadata(cx, t, cx.tcx.types.u8, unique_type_id, usage_site_span)),
|
|
|
|
ty::Dynamic(..) => Ok(MetadataCreationResult::new(
|
|
|
|
trait_pointer_metadata(cx, ty, Some(t), unique_type_id),
|
|
|
|
false,
|
|
|
|
)),
|
|
|
|
_ => {
|
|
|
|
let pointee_metadata = type_metadata(cx, ty, usage_site_span);
|
2017-01-21 14:40:31 +00:00
|
|
|
|
2019-12-24 22:38:22 +00:00
|
|
|
if let Some(metadata) =
|
|
|
|
debug_context(cx).type_map.borrow().find_metadata_for_unique_id(unique_type_id)
|
|
|
|
{
|
|
|
|
return Err(metadata);
|
2017-01-21 14:40:31 +00:00
|
|
|
}
|
2019-12-24 22:38:22 +00:00
|
|
|
|
|
|
|
Ok(MetadataCreationResult::new(pointer_type_metadata(cx, t, pointee_metadata), false))
|
2017-01-21 14:40:31 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
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)
|
|
|
|
}
|
2019-12-24 22:38:22 +00:00
|
|
|
ty::Array(typ, _) | ty::Slice(typ) => {
|
2017-06-01 18:50:53 +00:00
|
|
|
fixed_vec_metadata(cx, unique_type_id, t, typ, usage_site_span)
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
2019-12-24 22:38:22 +00:00
|
|
|
ty::Str => fixed_vec_metadata(cx, unique_type_id, t, cx.tcx.types.i8, usage_site_span),
|
2018-08-22 00:35:02 +00:00
|
|
|
ty::Dynamic(..) => {
|
2019-12-24 22:38:22 +00:00
|
|
|
MetadataCreationResult::new(trait_pointer_metadata(cx, t, None, 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
|
|
|
}
|
2019-12-24 22:38:22 +00:00
|
|
|
ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _) => match ptr_metadata(ty) {
|
|
|
|
Ok(res) => res,
|
|
|
|
Err(metadata) => return metadata,
|
|
|
|
},
|
|
|
|
ty::Adt(def, _) if def.is_box() => match ptr_metadata(t.boxed_ty()) {
|
|
|
|
Ok(res) => res,
|
|
|
|
Err(metadata) => return metadata,
|
|
|
|
},
|
2018-08-22 00:35:02 +00:00
|
|
|
ty::FnDef(..) | ty::FnPtr(_) => {
|
2019-12-24 22:38:22 +00:00
|
|
|
if let Some(metadata) =
|
|
|
|
debug_context(cx).type_map.borrow().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 metadata;
|
2018-10-09 13:15:41 +00:00
|
|
|
}
|
2015-07-13 19:50:21 +00:00
|
|
|
|
Fix stack overflow when generating debuginfo for 'recursive' type
By using 'impl trait', it's possible to create a self-referential
type as follows:
fn foo() -> impl Copy { foo }
This is a function which returns itself.
Normally, the signature of this function would be impossible
to write - it would look like 'fn foo() -> fn() -> fn() ...'
e.g. a function which returns a function, which returns a function...
Using 'impl trait' allows us to avoid writing this infinitely long
type. While it's useless for practical purposes, it does compile and run
However, issues arise when we try to generate llvm debuginfo for such a
type. All 'impl trait' types (e.g. ty::Opaque) are resolved when we
generate debuginfo, which can lead to us recursing back to the original
'fn' type when we try to process its return type.
To resolve this, I've modified debuginfo generation to account for these
kinds of weird types. Unfortunately, there's no 'correct' debuginfo that
we can generate - 'impl trait' does not exist in debuginfo, and this
kind of recursive type is impossible to directly represent.
To ensure that we emit *something*, this commit emits dummy
debuginfo/type names whenever it encounters a self-reference. In
practice, this should never happen - it's just to ensure that we can
emit some kind of debuginfo, even if it's not particularly meaningful
Fixes #58463
2019-03-26 19:30:41 +00:00
|
|
|
// It's possible to create a self-referential
|
|
|
|
// type in Rust by using 'impl trait':
|
|
|
|
//
|
|
|
|
// fn foo() -> impl Copy { foo }
|
|
|
|
//
|
2019-05-17 01:20:14 +00:00
|
|
|
// See `TypeMap::remove_type` for more detals
|
|
|
|
// about the workaround.
|
Fix stack overflow when generating debuginfo for 'recursive' type
By using 'impl trait', it's possible to create a self-referential
type as follows:
fn foo() -> impl Copy { foo }
This is a function which returns itself.
Normally, the signature of this function would be impossible
to write - it would look like 'fn foo() -> fn() -> fn() ...'
e.g. a function which returns a function, which returns a function...
Using 'impl trait' allows us to avoid writing this infinitely long
type. While it's useless for practical purposes, it does compile and run
However, issues arise when we try to generate llvm debuginfo for such a
type. All 'impl trait' types (e.g. ty::Opaque) are resolved when we
generate debuginfo, which can lead to us recursing back to the original
'fn' type when we try to process its return type.
To resolve this, I've modified debuginfo generation to account for these
kinds of weird types. Unfortunately, there's no 'correct' debuginfo that
we can generate - 'impl trait' does not exist in debuginfo, and this
kind of recursive type is impossible to directly represent.
To ensure that we emit *something*, this commit emits dummy
debuginfo/type names whenever it encounters a self-reference. In
practice, this should never happen - it's just to ensure that we can
emit some kind of debuginfo, even if it's not particularly meaningful
Fixes #58463
2019-03-26 19:30:41 +00:00
|
|
|
|
|
|
|
let temp_type = {
|
|
|
|
unsafe {
|
|
|
|
// The choice of type here is pretty arbitrary -
|
|
|
|
// anything reading the debuginfo for a recursive
|
2020-03-06 11:13:55 +00:00
|
|
|
// type is going to see *something* weird - the only
|
2019-05-17 01:20:14 +00:00
|
|
|
// question is what exactly it will see.
|
2020-03-06 00:00:00 +00:00
|
|
|
let name = "<recur_type>";
|
Fix stack overflow when generating debuginfo for 'recursive' type
By using 'impl trait', it's possible to create a self-referential
type as follows:
fn foo() -> impl Copy { foo }
This is a function which returns itself.
Normally, the signature of this function would be impossible
to write - it would look like 'fn foo() -> fn() -> fn() ...'
e.g. a function which returns a function, which returns a function...
Using 'impl trait' allows us to avoid writing this infinitely long
type. While it's useless for practical purposes, it does compile and run
However, issues arise when we try to generate llvm debuginfo for such a
type. All 'impl trait' types (e.g. ty::Opaque) are resolved when we
generate debuginfo, which can lead to us recursing back to the original
'fn' type when we try to process its return type.
To resolve this, I've modified debuginfo generation to account for these
kinds of weird types. Unfortunately, there's no 'correct' debuginfo that
we can generate - 'impl trait' does not exist in debuginfo, and this
kind of recursive type is impossible to directly represent.
To ensure that we emit *something*, this commit emits dummy
debuginfo/type names whenever it encounters a self-reference. In
practice, this should never happen - it's just to ensure that we can
emit some kind of debuginfo, even if it's not particularly meaningful
Fixes #58463
2019-03-26 19:30:41 +00:00
|
|
|
llvm::LLVMRustDIBuilderCreateBasicType(
|
|
|
|
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
|
|
|
DW_ATE_unsigned,
|
|
|
|
)
|
Fix stack overflow when generating debuginfo for 'recursive' type
By using 'impl trait', it's possible to create a self-referential
type as follows:
fn foo() -> impl Copy { foo }
This is a function which returns itself.
Normally, the signature of this function would be impossible
to write - it would look like 'fn foo() -> fn() -> fn() ...'
e.g. a function which returns a function, which returns a function...
Using 'impl trait' allows us to avoid writing this infinitely long
type. While it's useless for practical purposes, it does compile and run
However, issues arise when we try to generate llvm debuginfo for such a
type. All 'impl trait' types (e.g. ty::Opaque) are resolved when we
generate debuginfo, which can lead to us recursing back to the original
'fn' type when we try to process its return type.
To resolve this, I've modified debuginfo generation to account for these
kinds of weird types. Unfortunately, there's no 'correct' debuginfo that
we can generate - 'impl trait' does not exist in debuginfo, and this
kind of recursive type is impossible to directly represent.
To ensure that we emit *something*, this commit emits dummy
debuginfo/type names whenever it encounters a self-reference. In
practice, this should never happen - it's just to ensure that we can
emit some kind of debuginfo, even if it's not particularly meaningful
Fixes #58463
2019-03-26 19:30:41 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let type_map = &debug_context(cx).type_map;
|
|
|
|
type_map.borrow_mut().register_type_with_metadata(t, temp_type);
|
|
|
|
|
2019-12-24 22:38:22 +00:00
|
|
|
let fn_metadata =
|
|
|
|
subroutine_type_metadata(cx, unique_type_id, t.fn_sig(cx.tcx), usage_site_span)
|
|
|
|
.metadata;
|
Fix stack overflow when generating debuginfo for 'recursive' type
By using 'impl trait', it's possible to create a self-referential
type as follows:
fn foo() -> impl Copy { foo }
This is a function which returns itself.
Normally, the signature of this function would be impossible
to write - it would look like 'fn foo() -> fn() -> fn() ...'
e.g. a function which returns a function, which returns a function...
Using 'impl trait' allows us to avoid writing this infinitely long
type. While it's useless for practical purposes, it does compile and run
However, issues arise when we try to generate llvm debuginfo for such a
type. All 'impl trait' types (e.g. ty::Opaque) are resolved when we
generate debuginfo, which can lead to us recursing back to the original
'fn' type when we try to process its return type.
To resolve this, I've modified debuginfo generation to account for these
kinds of weird types. Unfortunately, there's no 'correct' debuginfo that
we can generate - 'impl trait' does not exist in debuginfo, and this
kind of recursive type is impossible to directly represent.
To ensure that we emit *something*, this commit emits dummy
debuginfo/type names whenever it encounters a self-reference. In
practice, this should never happen - it's just to ensure that we can
emit some kind of debuginfo, even if it's not particularly meaningful
Fixes #58463
2019-03-26 19:30:41 +00:00
|
|
|
|
|
|
|
type_map.borrow_mut().remove_type(t);
|
|
|
|
|
2019-05-17 01:20:14 +00:00
|
|
|
// This is actually a function pointer, so wrap it in pointer DI.
|
2015-07-13 19:50:21 +00:00
|
|
|
MetadataCreationResult::new(pointer_type_metadata(cx, t, fn_metadata), false)
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
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);
|
2019-12-24 22:38:22 +00:00
|
|
|
prepare_tuple_metadata(
|
|
|
|
cx,
|
|
|
|
t,
|
|
|
|
&upvar_tys,
|
|
|
|
unique_type_id,
|
|
|
|
usage_site_span,
|
|
|
|
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();
|
|
|
|
prepare_enum_metadata(cx, t, def_id, unique_type_id, usage_site_span, 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() {
|
2016-09-05 22:26:02 +00:00
|
|
|
AdtKind::Struct => {
|
2019-12-24 22:38:22 +00:00
|
|
|
prepare_struct_metadata(cx, t, unique_type_id, usage_site_span).finalize(cx)
|
2016-09-05 22:26:02 +00:00
|
|
|
}
|
|
|
|
AdtKind::Union => {
|
2019-12-24 22:38:22 +00:00
|
|
|
prepare_union_metadata(cx, t, unique_type_id, usage_site_span).finalize(cx)
|
2016-09-05 22:26:02 +00:00
|
|
|
}
|
|
|
|
AdtKind::Enum => {
|
2019-12-24 22:38:22 +00:00
|
|
|
prepare_enum_metadata(cx, t, def.did, unique_type_id, usage_site_span, vec![])
|
|
|
|
.finalize(cx)
|
2016-09-05 22:26:02 +00:00
|
|
|
}
|
|
|
|
},
|
2021-09-30 17:38:50 +00:00
|
|
|
ty::Tuple(elements) => {
|
2019-04-25 23:27:33 +00:00
|
|
|
let tys: Vec<_> = elements.iter().map(|k| k.expect_ty()).collect();
|
2019-12-24 22:38:22 +00:00
|
|
|
prepare_tuple_metadata(cx, t, &tys, unique_type_id, usage_site_span, 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
|
|
|
};
|
|
|
|
|
|
|
|
{
|
|
|
|
let mut type_map = debug_context(cx).type_map.borrow_mut();
|
|
|
|
|
|
|
|
if already_stored_in_typemap {
|
2019-05-17 01:20:14 +00:00
|
|
|
// Also make sure that we already have a `TypeMap` entry for the unique type ID.
|
2015-04-24 04:48:10 +00:00
|
|
|
let metadata_for_uid = match type_map.find_metadata_for_unique_id(unique_type_id) {
|
|
|
|
Some(metadata) => metadata,
|
|
|
|
None => {
|
2019-12-24 22:38:22 +00:00
|
|
|
span_bug!(
|
|
|
|
usage_site_span,
|
|
|
|
"expected type metadata for unique \
|
2019-05-17 01:20:14 +00:00
|
|
|
type ID '{}' to already be in \
|
|
|
|
the `debuginfo::TypeMap` but it \
|
2016-03-28 23:46:02 +00:00
|
|
|
was not. (Ty = {})",
|
2019-12-24 22:38:22 +00:00
|
|
|
type_map.get_unique_type_id_as_string(unique_type_id),
|
|
|
|
t
|
|
|
|
);
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
match type_map.find_metadata_for_type(t) {
|
|
|
|
Some(metadata) => {
|
|
|
|
if metadata != metadata_for_uid {
|
2019-12-24 22:38:22 +00:00
|
|
|
span_bug!(
|
|
|
|
usage_site_span,
|
|
|
|
"mismatch between `Ty` and \
|
2019-05-17 01:20:14 +00:00
|
|
|
`UniqueTypeId` maps in \
|
|
|
|
`debuginfo::TypeMap`. \
|
2016-03-28 23:46:02 +00:00
|
|
|
UniqueTypeId={}, Ty={}",
|
2019-12-24 22:38:22 +00:00
|
|
|
type_map.get_unique_type_id_as_string(unique_type_id),
|
|
|
|
t
|
|
|
|
);
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
None => {
|
2016-03-28 23:46:02 +00:00
|
|
|
type_map.register_type_with_metadata(t, metadata);
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2016-03-28 23:46:02 +00:00
|
|
|
type_map.register_type_with_metadata(t, metadata);
|
|
|
|
type_map.register_unique_id_with_metadata(unique_type_id, metadata);
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
metadata
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2020-02-10 01:03:24 +00:00
|
|
|
pub fn file_metadata(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
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
pub fn unknown_file_metadata(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
|
|
|
}
|
|
|
|
|
2019-12-24 22:38:22 +00:00
|
|
|
fn file_metadata_raw(
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
fn basic_type_metadata(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?)
|
2020-11-08 11:27:51 +00:00
|
|
|
let msvc_like_names = cx.tcx.sess.target.is_like_msvc;
|
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),
|
|
|
|
ty::Char => ("char", DW_ATE_unsigned_char),
|
2020-06-25 06:28:00 +00:00
|
|
|
ty::Int(int_ty) if msvc_like_names => (int_ty.msvc_basic_name(), DW_ATE_signed),
|
|
|
|
ty::Uint(uint_ty) if msvc_like_names => (uint_ty.msvc_basic_name(), DW_ATE_unsigned),
|
|
|
|
ty::Float(float_ty) if msvc_like_names => (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
|
|
|
};
|
|
|
|
|
2020-06-25 06:28:00 +00:00
|
|
|
if !msvc_like_names {
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
fn foreign_type_metadata(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
t: Ty<'tcx>,
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
) -> &'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);
|
2020-06-18 02:39:23 +00:00
|
|
|
create_struct_stub(cx, t, &name, unique_type_id, NO_SCOPE_METADATA, DIFlags::FlagZero)
|
2017-09-03 18:53:58 +00:00
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
fn pointer_type_metadata(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
pointer_type: Ty<'tcx>,
|
|
|
|
pointee_type_metadata: &'ll DIType,
|
|
|
|
) -> &'ll DIType {
|
2017-06-01 18:50:53 +00:00
|
|
|
let (pointer_size, pointer_align) = cx.size_and_align_of(pointer_type);
|
2019-03-30 14:45:09 +00:00
|
|
|
let name = compute_debuginfo_type_name(cx.tcx, pointer_type, false);
|
2017-06-01 18:50:53 +00:00
|
|
|
unsafe {
|
2016-08-01 23:35:09 +00:00
|
|
|
llvm::LLVMRustDIBuilderCreatePointerType(
|
2015-04-24 04:48:10 +00:00
|
|
|
DIB(cx),
|
|
|
|
pointee_type_metadata,
|
2017-06-01 18:50:53 +00:00
|
|
|
pointer_size.bits(),
|
2018-09-08 22:16:45 +00:00
|
|
|
pointer_align.bits() as u32,
|
2020-03-06 00:00:00 +00:00
|
|
|
0, // Ignore DWARF address space.
|
|
|
|
name.as_ptr().cast(),
|
|
|
|
name.len(),
|
2019-12-24 22:38:22 +00:00
|
|
|
)
|
2017-06-01 18:50:53 +00:00
|
|
|
}
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
|
2020-06-22 12:36:53 +00:00
|
|
|
fn param_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2019-06-11 21:11:55 +00:00
|
|
|
pub fn compile_unit_metadata(
|
2019-06-13 21:48:52 +00:00
|
|
|
tcx: TyCtxt<'_>,
|
2019-06-11 21:11:55 +00:00
|
|
|
codegen_unit_name: &str,
|
|
|
|
debug_context: &CrateDebugContext<'ll, '_>,
|
|
|
|
) -> &'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(),
|
2018-01-05 04:14:44 +00:00
|
|
|
None => PathBuf::from(&*tcx.crate_name(LOCAL_CRATE).as_str()),
|
2015-04-24 04:48:10 +00:00
|
|
|
};
|
|
|
|
|
2017-05-19 08:55:25 +00:00
|
|
|
// The OSX linker has an idiosyncrasy where it will ignore some debuginfo
|
2019-05-17 01:20:14 +00:00
|
|
|
// if multiple object files with the same `DW_AT_name` are linked together.
|
2017-05-19 08:55:25 +00:00
|
|
|
// As a workaround we generate unique names for each object file. Those do
|
2021-02-14 15:12:14 +00:00
|
|
|
// not correspond to an actual source file but that is harmless.
|
2020-11-08 11:27:51 +00:00
|
|
|
if tcx.sess.target.is_like_osx {
|
2017-12-14 07:09:19 +00:00
|
|
|
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(());
|
|
|
|
let out_dir = &output_filenames.out_directory;
|
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
|
2021-02-14 15:12:14 +00:00
|
|
|
.split_dwarf_path(tcx.sess.split_debuginfo(), Some(codegen_unit_name))
|
|
|
|
.map(|f| out_dir.join(f))
|
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
|
|
|
};
|
|
|
|
|
2018-07-10 10:28:39 +00:00
|
|
|
fn path_to_mdstring(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
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
impl MetadataCreationResult<'ll> {
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
impl 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
|
|
|
span: Span,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> StructMemberDescriptionFactory<'tcx> {
|
2019-12-24 22:38:22 +00:00
|
|
|
fn create_member_descriptions(&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 {
|
|
|
|
f.ident.to_string()
|
|
|
|
};
|
|
|
|
let field = layout.field(cx, i);
|
|
|
|
MemberDescription {
|
|
|
|
name,
|
|
|
|
type_metadata: type_metadata(cx, field.ty, self.span),
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
fn prepare_struct_metadata(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
struct_type: Ty<'tcx>,
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
span: Span,
|
|
|
|
) -> 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);
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2020-06-18 02:39:23 +00:00
|
|
|
let struct_metadata_stub = create_struct_stub(
|
|
|
|
cx,
|
|
|
|
struct_type,
|
|
|
|
&struct_name,
|
|
|
|
unique_type_id,
|
|
|
|
Some(containing_scope),
|
|
|
|
DIFlags::FlagZero,
|
|
|
|
);
|
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,
|
2019-12-24 22:38:22 +00:00
|
|
|
StructMDF(StructMemberDescriptionFactory { ty: struct_type, variant, span }),
|
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.
|
|
|
|
fn closure_saved_names_of_captured_variables(tcx: TyCtxt<'tcx>, def_id: DefId) -> Vec<String> {
|
|
|
|
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 { "" };
|
|
|
|
Some(prefix.to_owned() + &var.name.as_str())
|
|
|
|
})
|
|
|
|
.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>>,
|
|
|
|
span: Span,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> TupleMemberDescriptionFactory<'tcx> {
|
2019-12-24 22:38:22 +00:00
|
|
|
fn create_member_descriptions(&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,
|
2019-12-24 22:38:22 +00:00
|
|
|
type_metadata: type_metadata(cx, component_type, self.span),
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
fn prepare_tuple_metadata(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
tuple_type: Ty<'tcx>,
|
|
|
|
component_types: &[Ty<'tcx>],
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
span: Span,
|
2019-08-25 03:01:46 +00:00
|
|
|
containing_scope: Option<&'ll DIScope>,
|
2018-07-04 13:36:49 +00:00
|
|
|
) -> RecursiveTypeDescription<'ll, 'tcx> {
|
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,
|
|
|
|
tuple_type,
|
|
|
|
&tuple_name[..],
|
|
|
|
unique_type_id,
|
|
|
|
containing_scope,
|
|
|
|
DIFlags::FlagZero,
|
|
|
|
);
|
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(),
|
2017-08-07 05:54:09 +00:00
|
|
|
span,
|
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
|
|
|
span: Span,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> UnionMemberDescriptionFactory<'tcx> {
|
2019-12-24 22:38:22 +00:00
|
|
|
fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDescription<'ll>> {
|
|
|
|
self.variant
|
|
|
|
.fields
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.map(|(i, f)| {
|
|
|
|
let field = self.layout.field(cx, i);
|
|
|
|
MemberDescription {
|
|
|
|
name: f.ident.to_string(),
|
|
|
|
type_metadata: type_metadata(cx, field.ty, self.span),
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
fn prepare_union_metadata(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
union_type: Ty<'tcx>,
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
span: Span,
|
|
|
|
) -> 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,
|
2019-12-24 22:38:22 +00:00
|
|
|
UnionMDF(UnionMemberDescriptionFactory { layout: cx.layout_of(union_type), variant, span }),
|
2016-08-22 18:11:22 +00:00
|
|
|
)
|
|
|
|
}
|
2015-04-29 06:14:37 +00:00
|
|
|
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
// Enums
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
|
2020-04-14 19:10:58 +00:00
|
|
|
/// DWARF variant support is only available starting in LLVM 8, but
|
|
|
|
/// on MSVC we have to use the fallback mode, because LLVM doesn't
|
|
|
|
/// lower variant parts to PDB.
|
2019-02-25 07:40:18 +00:00
|
|
|
fn use_enum_fallback(cx: &CodegenCx<'_, '_>) -> bool {
|
2020-11-08 11:27:51 +00:00
|
|
|
cx.sess().target.is_like_msvc
|
2017-11-29 21:42:25 +00:00
|
|
|
}
|
|
|
|
|
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.
|
|
|
|
fn generator_layout_and_saved_local_names(
|
|
|
|
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 {
|
2020-05-30 19:02:32 +00:00
|
|
|
let place = if let mir::VarDebugInfoContents::Place(p) = var.value { p } else { continue };
|
|
|
|
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, _),
|
|
|
|
] => {
|
|
|
|
let name = &mut generator_saved_local_names[
|
|
|
|
generator_layout.variant_fields[variant][field]
|
|
|
|
];
|
|
|
|
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
|
|
|
span: Span,
|
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
impl 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() {
|
2019-12-24 22:38:22 +00:00
|
|
|
ty::Adt(adt, _) => VariantInfo::Adt(&adt.variants[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
|
|
|
|
|
|
|
let fallback = use_enum_fallback(cx);
|
2021-05-26 16:02:07 +00:00
|
|
|
// This will always find the metadata in the type map.
|
2021-04-28 20:32:54 +00:00
|
|
|
let self_metadata = type_metadata(cx, self.enum_type, self.span);
|
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) =
|
|
|
|
describe_enum_variant(cx, self.layout, variant_info, self_metadata, self.span);
|
2019-12-24 22:38:22 +00:00
|
|
|
|
|
|
|
let member_descriptions = member_description_factory.create_member_descriptions(cx);
|
|
|
|
|
|
|
|
set_members_of_composite_type(
|
|
|
|
cx,
|
|
|
|
self.enum_type,
|
|
|
|
variant_type_metadata,
|
|
|
|
member_descriptions,
|
2021-04-30 08:14:42 +00:00
|
|
|
Some(&self.common_members),
|
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);
|
|
|
|
let (variant_type_metadata, member_desc_factory) = describe_enum_variant(
|
|
|
|
cx,
|
|
|
|
variant,
|
|
|
|
variant_info,
|
|
|
|
self_metadata,
|
|
|
|
self.span,
|
|
|
|
);
|
|
|
|
|
|
|
|
let member_descriptions =
|
|
|
|
member_desc_factory.create_member_descriptions(cx);
|
|
|
|
|
|
|
|
set_members_of_composite_type(
|
|
|
|
cx,
|
|
|
|
self.enum_type,
|
|
|
|
variant_type_metadata,
|
|
|
|
member_descriptions,
|
2021-04-30 08:14:42 +00:00
|
|
|
Some(&self.common_members),
|
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),
|
|
|
|
type_metadata(cx, discr_enum_ty, self.span),
|
|
|
|
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
|
|
|
self.span,
|
|
|
|
);
|
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);
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2019-12-24 22:38:22 +00:00
|
|
|
set_members_of_composite_type(
|
|
|
|
cx,
|
|
|
|
self.enum_type,
|
|
|
|
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),
|
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) =
|
|
|
|
describe_enum_variant(
|
|
|
|
cx,
|
|
|
|
variant,
|
|
|
|
variant_info,
|
|
|
|
self_metadata,
|
|
|
|
self.span,
|
|
|
|
);
|
|
|
|
|
|
|
|
let member_descriptions =
|
|
|
|
member_desc_factory.create_member_descriptions(cx);
|
|
|
|
|
|
|
|
set_members_of_composite_type(
|
|
|
|
cx,
|
|
|
|
self.enum_type,
|
|
|
|
variant_type_metadata,
|
|
|
|
member_descriptions,
|
2021-04-30 08:14:42 +00:00
|
|
|
Some(&self.common_members),
|
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>)>,
|
|
|
|
span: Span,
|
|
|
|
}
|
|
|
|
|
2021-06-24 20:37:03 +00:00
|
|
|
impl VariantMemberDescriptionFactory<'tcx> {
|
2019-12-24 22:38:22 +00:00
|
|
|
fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDescription<'ll>> {
|
|
|
|
self.args
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.map(|(i, &(ref name, ty))| {
|
|
|
|
let (size, align) = cx.size_and_align_of(ty);
|
|
|
|
MemberDescription {
|
|
|
|
name: name.to_string(),
|
2021-06-24 20:37:03 +00:00
|
|
|
type_metadata: type_metadata(cx, ty, self.span),
|
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> {
|
2019-04-13 00:03:03 +00:00
|
|
|
Adt(&'tcx ty::VariantDef),
|
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> {
|
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 {
|
|
|
|
VariantInfo::Adt(variant) => f(&variant.ident.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 {
|
|
|
|
VariantInfo::Adt(variant) => variant.ident.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 {
|
2019-12-24 22:38:22 +00:00
|
|
|
VariantInfo::Adt(variant) if variant.ctor_kind != CtorKind::Fn => {
|
|
|
|
Some(variant.fields[i].ident.name)
|
|
|
|
}
|
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
|
|
|
|
|
|
|
fn source_info(&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`.
|
2018-07-04 13:36:49 +00:00
|
|
|
fn describe_enum_variant(
|
|
|
|
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,
|
|
|
|
span: Span,
|
|
|
|
) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) {
|
2019-04-18 00:46:40 +00:00
|
|
|
let metadata_stub = variant.map_struct_name(|variant_name| {
|
2019-12-24 22:38:22 +00:00
|
|
|
let unique_type_id = debug_context(cx)
|
|
|
|
.type_map
|
|
|
|
.borrow_mut()
|
2021-09-30 17:38:50 +00:00
|
|
|
.get_unique_type_id_of_enum_variant(cx, layout.ty, variant_name);
|
2020-06-18 02:39:23 +00:00
|
|
|
create_struct_stub(
|
|
|
|
cx,
|
|
|
|
layout.ty,
|
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,
|
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
|
|
|
|
2021-06-24 20:37:03 +00:00
|
|
|
let member_description_factory =
|
|
|
|
VariantMDF(VariantMemberDescriptionFactory { offsets, args, span });
|
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
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
fn prepare_enum_metadata(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
enum_type: Ty<'tcx>,
|
|
|
|
enum_def_id: DefId,
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
span: Span,
|
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)| {
|
2020-03-05 00:00:00 +00:00
|
|
|
let name = v.ident.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));
|
2015-04-29 06:14:37 +00:00
|
|
|
let discriminant_base_type_metadata =
|
2020-06-17 23:04:25 +00:00
|
|
|
type_metadata(cx, discr.to_ty(tcx), rustc_span::DUMMY_SP);
|
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(..) => {
|
2020-06-17 23:04:25 +00:00
|
|
|
item_name = tcx.item_name(enum_def_id).as_str();
|
2020-03-06 00:00:00 +00:00
|
|
|
&*item_name
|
|
|
|
}
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2017-11-29 21:42:25 +00:00
|
|
|
if use_enum_fallback(cx) {
|
|
|
|
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 = {
|
|
|
|
let type_map = debug_context(cx).type_map.borrow();
|
|
|
|
let unique_type_id_str = type_map.get_unique_type_id_as_string(unique_type_id);
|
|
|
|
|
|
|
|
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
|
|
|
span,
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
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 { .. } => {
|
2019-04-13 00:03:03 +00:00
|
|
|
let tuple_mdf = TupleMemberDescriptionFactory {
|
|
|
|
ty: enum_type,
|
|
|
|
component_types: outer_field_tys,
|
2019-12-24 22:38:22 +00:00
|
|
|
span,
|
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()
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-03-06 00:00:00 +00:00
|
|
|
let variant_part_unique_type_id_str = debug_context(cx)
|
|
|
|
.type_map
|
|
|
|
.borrow_mut()
|
|
|
|
.get_unique_type_id_str_of_enum_variant_part(unique_type_id);
|
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)]);
|
2020-03-06 00:00:00 +00:00
|
|
|
|
|
|
|
let type_map = debug_context(cx).type_map.borrow();
|
|
|
|
let unique_type_id_str = type_map.get_unique_type_id_as_string(unique_type_id);
|
|
|
|
|
|
|
|
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,
|
2017-08-07 05:54:09 +00:00
|
|
|
span,
|
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.
|
2018-07-04 13:36:49 +00:00
|
|
|
fn composite_type_metadata(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
composite_type: Ty<'tcx>,
|
|
|
|
composite_type_name: &str,
|
|
|
|
composite_type_unique_id: UniqueTypeId,
|
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>,
|
|
|
|
|
|
|
|
// Ignore source location information as long as it
|
|
|
|
// can't be reconstructed for non-local crates.
|
|
|
|
_file_metadata: &'ll DIFile,
|
|
|
|
_definition_span: Span,
|
|
|
|
) -> &'ll DICompositeType {
|
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,
|
|
|
|
composite_type,
|
|
|
|
composite_type_name,
|
|
|
|
composite_type_unique_id,
|
|
|
|
containing_scope,
|
2020-06-18 02:39:23 +00:00
|
|
|
DIFlags::FlagZero,
|
2019-12-24 22:38:22 +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,
|
|
|
|
composite_type_metadata,
|
|
|
|
member_descriptions,
|
|
|
|
None,
|
|
|
|
);
|
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
|
|
|
}
|
|
|
|
|
2019-12-24 22:38:22 +00:00
|
|
|
fn set_members_of_composite_type(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
composite_type: Ty<'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>>>,
|
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
|
|
|
|
2018-10-12 13:34:14 +00:00
|
|
|
let type_params = compute_type_parameters(cx, composite_type);
|
2015-04-29 06:14:37 +00:00
|
|
|
unsafe {
|
|
|
|
let type_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,
|
|
|
|
Some(type_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.
|
2020-12-29 21:24:15 +00:00
|
|
|
fn compute_type_parameters(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);
|
|
|
|
let actual_type_metadata =
|
2019-12-31 17:15:40 +00:00
|
|
|
type_metadata(cx, actual_type, rustc_span::DUMMY_SP);
|
2020-03-06 00:00:00 +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
|
|
|
|
2020-12-29 21:24:15 +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()`.
|
2018-07-04 13:36:49 +00:00
|
|
|
fn create_struct_stub(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
struct_type: Ty<'tcx>,
|
|
|
|
struct_type_name: &str,
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
containing_scope: Option<&'ll DIScope>,
|
2020-06-18 02:39:23 +00:00
|
|
|
flags: DIFlags,
|
2018-07-04 13:36:49 +00:00
|
|
|
) -> &'ll DICompositeType {
|
2017-06-01 18:50:53 +00:00
|
|
|
let (struct_size, struct_align) = cx.size_and_align_of(struct_type);
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2020-03-06 00:00:00 +00:00
|
|
|
let type_map = debug_context(cx).type_map.borrow();
|
|
|
|
let unique_type_id = type_map.get_unique_type_id_as_string(unique_type_id);
|
|
|
|
|
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,
|
2020-03-06 00:00:00 +00:00
|
|
|
struct_type_name.as_ptr().cast(),
|
|
|
|
struct_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,
|
2017-06-01 18:50:53 +00:00
|
|
|
struct_size.bits(),
|
2018-09-08 22:16:45 +00:00
|
|
|
struct_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,
|
2018-06-27 10:12:47 +00:00
|
|
|
None,
|
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
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
fn create_union_stub(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
union_type: Ty<'tcx>,
|
|
|
|
union_type_name: &str,
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
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);
|
2016-08-22 18:11:22 +00:00
|
|
|
|
2020-03-06 00:00:00 +00:00
|
|
|
let type_map = debug_context(cx).type_map.borrow();
|
|
|
|
let unique_type_id = type_map.get_unique_type_id_as_string(unique_type_id);
|
|
|
|
|
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.
|
2019-12-24 22:38:22 +00:00
|
|
|
pub fn create_global_var_metadata(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());
|
2015-04-29 06:14:37 +00:00
|
|
|
let type_metadata = type_metadata(cx, variable_type, span);
|
2020-03-06 00:00:00 +00:00
|
|
|
let var_name = tcx.item_name(def_id).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
|
|
|
|
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.
|
2019-06-12 13:06:35 +00:00
|
|
|
pub fn create_vtable_metadata(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'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;
|
|
|
|
}
|
|
|
|
|
2019-12-31 17:15:40 +00:00
|
|
|
let type_metadata = type_metadata(cx, ty, rustc_span::DUMMY_SP);
|
2018-09-20 13:47:22 +00:00
|
|
|
|
|
|
|
unsafe {
|
2019-05-17 01:20:14 +00:00
|
|
|
// `LLVMRustDIBuilderCreateStructType()` wants an empty array. A null
|
2018-09-20 13:47: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`.
|
2018-09-20 13:47:22 +00:00
|
|
|
let empty_array = create_DIArray(DIB(cx), &[]);
|
2020-03-06 00:00:00 +00:00
|
|
|
let name = "vtable";
|
2018-09-20 13:47:22 +00:00
|
|
|
|
2019-05-17 01:20:14 +00:00
|
|
|
// Create a new one each time. We don't want metadata caching
|
2018-09-20 13:47:22 +00:00
|
|
|
// here, because each vtable will refer to a unique containing
|
|
|
|
// type.
|
|
|
|
let vtable_type = llvm::LLVMRustDIBuilderCreateStructType(
|
|
|
|
DIB(cx),
|
|
|
|
NO_SCOPE_METADATA,
|
2020-03-06 00:00:00 +00:00
|
|
|
name.as_ptr().cast(),
|
|
|
|
name.len(),
|
2018-09-20 13:47:22 +00:00
|
|
|
unknown_file_metadata(cx),
|
|
|
|
UNKNOWN_LINE_NUMBER,
|
|
|
|
Size::ZERO.bits(),
|
2018-09-08 21:22:22 +00:00
|
|
|
cx.tcx.data_layout.pointer_align.abi.bits() as u32,
|
2018-09-20 13:47:22 +00:00
|
|
|
DIFlags::FlagArtificial,
|
|
|
|
None,
|
|
|
|
empty_array,
|
|
|
|
0,
|
|
|
|
Some(type_metadata),
|
2020-03-06 00:00:00 +00:00
|
|
|
name.as_ptr().cast(),
|
|
|
|
name.len(),
|
2018-09-20 13:47:22 +00:00
|
|
|
);
|
|
|
|
|
2020-03-06 00:00:00 +00:00
|
|
|
let linkage_name = "";
|
2019-12-24 22:38:22 +00:00
|
|
|
llvm::LLVMRustDIBuilderCreateStaticVariable(
|
|
|
|
DIB(cx),
|
|
|
|
NO_SCOPE_METADATA,
|
2020-03-06 00:00:00 +00:00
|
|
|
name.as_ptr().cast(),
|
|
|
|
name.len(),
|
|
|
|
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.
|
2018-07-04 13:36:49 +00:00
|
|
|
pub fn extend_scope_to_file(
|
|
|
|
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
|
|
|
}
|