2020-05-23 11:22:45 +00:00
|
|
|
use self::EnumTagInfo::*;
|
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
|
|
|
|
2020-04-27 17:56:11 +00:00
|
|
|
use rustc_ast as ast;
|
2019-12-24 22:38:22 +00:00
|
|
|
use rustc_codegen_ssa::traits::*;
|
2019-10-22 15:51:35 +00:00
|
|
|
use rustc_data_structures::const_cstr;
|
2019-12-24 22:38:22 +00:00
|
|
|
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;
|
|
|
|
use rustc_middle::mir::{self, Field, GeneratorLayout};
|
2020-03-31 16:16:47 +00:00
|
|
|
use rustc_middle::ty::layout::{self, IntegerExt, 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};
|
2020-01-01 18:30:57 +00:00
|
|
|
use rustc_span::symbol::{Interner, Symbol};
|
2020-04-05 08:43:44 +00:00
|
|
|
use rustc_span::{self, SourceFile, SourceFileHash, Span};
|
2020-05-23 11:22:45 +00:00
|
|
|
use rustc_target::abi::{Abi, Align, HasDataLayout, Integer, LayoutOf, 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
|
|
|
|
|
|
|
#[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)]
|
2020-04-19 11:00:18 +00:00
|
|
|
pub struct UniqueTypeId(Symbol);
|
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.
|
2016-07-11 08:00:48 +00:00
|
|
|
unique_id_interner: Interner,
|
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 {
|
2015-04-29 06:14:37 +00:00
|
|
|
let UniqueTypeId(interner_key) = unique_type_id;
|
|
|
|
self.unique_id_interner.get(interner_key)
|
|
|
|
}
|
|
|
|
|
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();
|
|
|
|
let type_ = cx.tcx.erase_regions(&type_);
|
|
|
|
hcx.while_hashing_spans(false, |hcx| {
|
|
|
|
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
|
|
|
|
type_.hash_stable(hcx, &mut hasher);
|
|
|
|
});
|
|
|
|
});
|
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);
|
2015-04-29 06:14:37 +00:00
|
|
|
self.type_to_unique_id.insert(type_, UniqueTypeId(key));
|
|
|
|
|
2020-03-20 14:03:11 +00:00
|
|
|
UniqueTypeId(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);
|
2015-04-29 06:14:37 +00:00
|
|
|
UniqueTypeId(interner_key)
|
|
|
|
}
|
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,
|
|
|
|
);
|
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 =
|
|
|
|
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() {
|
2018-08-22 00:35:02 +00:00
|
|
|
ty::Tuple(ref 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
|
|
|
|
2020-08-02 22:49:11 +00:00
|
|
|
let containing_scope = match trait_type.kind() {
|
2019-12-24 22:38:22 +00:00
|
|
|
ty::Dynamic(ref data, ..) => {
|
|
|
|
data.principal_def_id().map(|did| get_namespace_for_item(cx, did))
|
|
|
|
}
|
2015-04-24 04:48:10 +00:00
|
|
|
_ => {
|
2019-12-24 22:38:22 +00:00
|
|
|
bug!(
|
|
|
|
"debuginfo: unexpected trait-object type in \
|
2016-03-28 23:46:02 +00:00
|
|
|
trait_pointer_metadata(): {:?}",
|
2019-12-24 22:38:22 +00:00
|
|
|
trait_type
|
|
|
|
);
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let trait_object_type = trait_object_type.unwrap_or(trait_type);
|
2019-12-24 22:38:22 +00:00
|
|
|
let trait_type_name = compute_debuginfo_type_name(cx.tcx, trait_object_type, false);
|
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,
|
|
|
|
trait_object_type,
|
|
|
|
&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)
|
|
|
|
}
|
2018-08-22 00:35:02 +00:00
|
|
|
ty::Tuple(ref 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
|
|
|
}
|
|
|
|
},
|
2018-08-22 00:35:02 +00:00
|
|
|
ty::Tuple(ref 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 {
|
|
|
|
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);
|
|
|
|
let file_name = Some(source_file.name.to_string());
|
2020-02-10 01:03:24 +00:00
|
|
|
let directory = if source_file.is_real_file() && !source_file.is_imported() {
|
2019-05-06 01:47:03 +00:00
|
|
|
Some(cx.sess().working_dir.0.to_string_lossy().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;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl MsvcBasicName for ast::IntTy {
|
|
|
|
fn msvc_basic_name(self) -> &'static str {
|
|
|
|
match self {
|
|
|
|
ast::IntTy::Isize => "ptrdiff_t",
|
|
|
|
ast::IntTy::I8 => "__int8",
|
|
|
|
ast::IntTy::I16 => "__int16",
|
|
|
|
ast::IntTy::I32 => "__int32",
|
|
|
|
ast::IntTy::I64 => "__int64",
|
|
|
|
ast::IntTy::I128 => "__int128",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl MsvcBasicName for ast::UintTy {
|
|
|
|
fn msvc_basic_name(self) -> &'static str {
|
|
|
|
match self {
|
|
|
|
ast::UintTy::Usize => "size_t",
|
|
|
|
ast::UintTy::U8 => "unsigned __int8",
|
|
|
|
ast::UintTy::U16 => "unsigned __int16",
|
|
|
|
ast::UintTy::U32 => "unsigned __int32",
|
|
|
|
ast::UintTy::U64 => "unsigned __int64",
|
|
|
|
ast::UintTy::U128 => "unsigned __int128",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl MsvcBasicName for ast::FloatTy {
|
|
|
|
fn msvc_basic_name(self) -> &'static str {
|
|
|
|
match self {
|
|
|
|
ast::FloatTy::F32 => "float",
|
|
|
|
ast::FloatTy::F64 => "double",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-10-15 09:44:00 +00:00
|
|
|
let msvc_like_names = cx.tcx.sess.target.options.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),
|
2019-12-24 22:38:22 +00:00
|
|
|
ty::Tuple(ref 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
|
|
|
|
// not correspond to an actual source file but that should be harmless.
|
2020-10-15 09:44:00 +00:00
|
|
|
if tcx.sess.target.options.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();
|
2020-03-06 00:00:00 +00:00
|
|
|
let work_dir = tcx.sess.working_dir.0.to_string_lossy();
|
2015-04-24 04:48:10 +00:00
|
|
|
let flags = "\0";
|
2020-03-06 00:00:00 +00:00
|
|
|
let split_name = "";
|
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 {
|
|
|
|
let file_metadata = 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(),
|
|
|
|
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,
|
2017-02-11 21:01:25 +00:00
|
|
|
file_metadata,
|
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,
|
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,
|
|
|
|
);
|
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);
|
2020-05-26 17:41:40 +00:00
|
|
|
let default_gcda_path = &tcx.output_filenames(LOCAL_CRATE).with_extension("gcda");
|
|
|
|
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 = [
|
2019-12-24 22:38:22 +00:00
|
|
|
path_to_mdstring(
|
|
|
|
debug_context.llcontext,
|
|
|
|
&tcx.output_filenames(LOCAL_CRATE).with_extension("gcno"),
|
|
|
|
),
|
2020-05-26 17:41:40 +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
|
|
|
|
2018-08-07 14:03:57 +00:00
|
|
|
let llvm_gcov_ident = const_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
|
|
|
|
2019-07-19 14:08:37 +00:00
|
|
|
// Insert `llvm.ident` metadata on the wasm32 targets since that will
|
|
|
|
// get hooked up to the "producer" sections `processed-by` information.
|
|
|
|
if tcx.sess.opts.target_triple.triple().starts_with("wasm32") {
|
|
|
|
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,
|
|
|
|
const_cstr!("llvm.ident").as_ptr(),
|
|
|
|
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(),
|
|
|
|
match self.discriminant {
|
|
|
|
None => None,
|
|
|
|
Some(value) => Some(cx.const_u64(value)),
|
|
|
|
},
|
|
|
|
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>),
|
2019-12-24 22:38:22 +00:00
|
|
|
VariantMDF(VariantMemberDescriptionFactory<'ll, '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
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
|
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>> {
|
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);
|
|
|
|
MemberDescription {
|
|
|
|
name: format!("__{}", i),
|
|
|
|
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-10-15 09:44:00 +00:00
|
|
|
cx.sess().target.options.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);
|
|
|
|
let generator_layout = body.generator_layout.as_ref().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 {
|
2019-12-11 19:50:03 +00:00
|
|
|
if var.place.local != state_arg {
|
2018-05-16 15:58:54 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
match var.place.projection[..] {
|
|
|
|
[
|
|
|
|
// 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>,
|
2018-07-04 13:36:49 +00:00
|
|
|
containing_scope: &'ll DIScope,
|
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
|
|
|
|
|
|
|
// This will always find the metadata in the type map.
|
|
|
|
let fallback = use_enum_fallback(cx);
|
|
|
|
let self_metadata = if fallback {
|
|
|
|
self.containing_scope
|
|
|
|
} else {
|
|
|
|
type_metadata(cx, self.enum_type, self.span)
|
|
|
|
};
|
2020-08-02 22:49:11 +00:00
|
|
|
let flags = match self.enum_type.kind() {
|
2020-06-18 02:39:23 +00:00
|
|
|
ty::Generator(..) => DIFlags::FlagArtificial,
|
|
|
|
_ => DIFlags::FlagZero,
|
|
|
|
};
|
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);
|
2019-12-24 22:38:22 +00:00
|
|
|
let (variant_type_metadata, member_description_factory) = describe_enum_variant(
|
|
|
|
cx,
|
|
|
|
self.layout,
|
|
|
|
variant_info,
|
2020-05-23 11:22:45 +00:00
|
|
|
NoTag,
|
2019-12-24 22:38:22 +00:00
|
|
|
self_metadata,
|
|
|
|
self.span,
|
|
|
|
);
|
|
|
|
|
|
|
|
let member_descriptions = member_description_factory.create_member_descriptions(cx);
|
|
|
|
|
|
|
|
set_members_of_composite_type(
|
|
|
|
cx,
|
|
|
|
self.enum_type,
|
|
|
|
variant_type_metadata,
|
|
|
|
member_descriptions,
|
|
|
|
);
|
|
|
|
vec![MemberDescription {
|
|
|
|
name: if fallback { String::new() } else { variant_info.variant_name() },
|
|
|
|
type_metadata: variant_type_metadata,
|
|
|
|
offset: Size::ZERO,
|
|
|
|
size: self.layout.size,
|
|
|
|
align: self.layout.align.abi,
|
2020-06-18 02:39:23 +00:00
|
|
|
flags,
|
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,
|
|
|
|
..
|
|
|
|
} => {
|
2020-05-23 11:22:45 +00:00
|
|
|
let tag_info = if fallback {
|
|
|
|
RegularTag {
|
|
|
|
tag_field: Field::from(tag_field),
|
|
|
|
tag_type_metadata: self.tag_type_metadata.unwrap(),
|
2019-04-02 22:57:50 +00:00
|
|
|
}
|
2017-11-29 21:42:25 +00:00
|
|
|
} else {
|
|
|
|
// This doesn't matter in this case.
|
2020-05-23 11:22:45 +00:00
|
|
|
NoTag
|
2017-11-29 21:42:25 +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,
|
2020-05-23 11:22:45 +00:00
|
|
|
tag_info,
|
2019-12-24 22:38:22 +00:00
|
|
|
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,
|
|
|
|
);
|
|
|
|
|
|
|
|
MemberDescription {
|
|
|
|
name: if fallback {
|
|
|
|
String::new()
|
|
|
|
} else {
|
|
|
|
variant_info.variant_name()
|
|
|
|
},
|
|
|
|
type_metadata: variant_type_metadata,
|
|
|
|
offset: Size::ZERO,
|
|
|
|
size: self.layout.size,
|
|
|
|
align: self.layout.align.abi,
|
2020-06-18 02:39:23 +00:00
|
|
|
flags,
|
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
|
|
|
}
|
|
|
|
})
|
|
|
|
.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 },
|
|
|
|
ref 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
|
|
|
} => {
|
|
|
|
if fallback {
|
|
|
|
let variant = self.layout.for_variant(cx, dataful_variant);
|
2019-05-17 01:20:14 +00:00
|
|
|
// Create a description of the non-null variant.
|
2019-12-24 22:38:22 +00:00
|
|
|
let (variant_type_metadata, member_description_factory) = describe_enum_variant(
|
|
|
|
cx,
|
|
|
|
variant,
|
|
|
|
variant_info_for(dataful_variant),
|
2020-05-23 11:22:45 +00:00
|
|
|
OptimizedTag,
|
2019-12-24 22:38:22 +00:00
|
|
|
self.containing_scope,
|
|
|
|
self.span,
|
|
|
|
);
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2017-11-29 21:42:25 +00:00
|
|
|
let variant_member_descriptions =
|
|
|
|
member_description_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,
|
|
|
|
variant_member_descriptions,
|
|
|
|
);
|
2017-11-29 21:42:25 +00:00
|
|
|
|
|
|
|
// Encode the information about the null variant in the union
|
|
|
|
// member's name.
|
|
|
|
let mut name = String::from("RUST$ENCODED$ENUM$");
|
|
|
|
// Right now it's not even going to work for `niche_start > 0`,
|
|
|
|
// and for multiple niche variants it only supports the first.
|
2019-12-24 22:38:22 +00:00
|
|
|
fn compute_field_path<'a, 'tcx>(
|
|
|
|
cx: &CodegenCx<'a, 'tcx>,
|
|
|
|
name: &mut String,
|
2020-03-04 14:50:21 +00:00
|
|
|
layout: TyAndLayout<'tcx>,
|
2019-12-24 22:38:22 +00:00
|
|
|
offset: Size,
|
|
|
|
size: Size,
|
|
|
|
) {
|
2017-11-29 21:42:25 +00:00
|
|
|
for i in 0..layout.fields.count() {
|
|
|
|
let field_offset = layout.fields.offset(i);
|
|
|
|
if field_offset > offset {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
let inner_offset = offset - field_offset;
|
|
|
|
let field = layout.field(cx, i);
|
|
|
|
if inner_offset + size <= field.size {
|
|
|
|
write!(name, "{}$", i).unwrap();
|
|
|
|
compute_field_path(cx, name, field, inner_offset, size);
|
|
|
|
}
|
2017-09-11 19:31:16 +00:00
|
|
|
}
|
|
|
|
}
|
2019-12-24 22:38:22 +00:00
|
|
|
compute_field_path(
|
|
|
|
cx,
|
|
|
|
&mut name,
|
|
|
|
self.layout,
|
2020-05-23 11:22:45 +00:00
|
|
|
self.layout.fields.offset(tag_field),
|
|
|
|
self.layout.field(cx, tag_field).size,
|
2019-12-24 22:38:22 +00:00
|
|
|
);
|
2020-06-17 23:04:25 +00:00
|
|
|
let variant_info = variant_info_for(*niche_variants.start());
|
|
|
|
variant_info.map_struct_name(|variant_name| {
|
2019-04-13 00:03:03 +00:00
|
|
|
name.push_str(variant_name);
|
|
|
|
});
|
2017-11-29 21:42:25 +00:00
|
|
|
|
|
|
|
// Create the (singleton) list of descriptions of union members.
|
2019-12-24 22:38:22 +00:00
|
|
|
vec![MemberDescription {
|
|
|
|
name,
|
|
|
|
type_metadata: variant_type_metadata,
|
|
|
|
offset: Size::ZERO,
|
|
|
|
size: variant.size,
|
|
|
|
align: variant.align.abi,
|
2020-06-18 02:39:23 +00:00
|
|
|
flags,
|
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
|
|
|
}]
|
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,
|
2020-05-23 11:22:45 +00:00
|
|
|
OptimizedTag,
|
2019-12-24 22:38:22 +00:00
|
|
|
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,
|
|
|
|
);
|
|
|
|
|
|
|
|
let niche_value = 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);
|
2020-11-04 13:41:58 +00:00
|
|
|
let value = tag.value.size(cx).truncate(value);
|
2019-12-24 22:38:22 +00:00
|
|
|
// 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)
|
|
|
|
};
|
|
|
|
|
|
|
|
MemberDescription {
|
|
|
|
name: variant_info.variant_name(),
|
|
|
|
type_metadata: variant_type_metadata,
|
|
|
|
offset: Size::ZERO,
|
|
|
|
size: self.layout.size,
|
|
|
|
align: self.layout.align.abi,
|
2020-06-18 02:39:23 +00:00
|
|
|
flags,
|
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.
|
2018-07-04 13:36:49 +00:00
|
|
|
struct VariantMemberDescriptionFactory<'ll, '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>)>,
|
2020-05-23 11:22:45 +00:00
|
|
|
tag_type_metadata: Option<&'ll DIType>,
|
2015-04-29 06:14:37 +00:00
|
|
|
span: Span,
|
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
impl VariantMemberDescriptionFactory<'ll, '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))| {
|
2020-06-23 23:23:01 +00:00
|
|
|
// Discriminant is always the first field of our variant
|
|
|
|
// when using the enum fallback.
|
|
|
|
let is_artificial_discr = use_enum_fallback(cx) && i == 0;
|
2019-12-24 22:38:22 +00:00
|
|
|
let (size, align) = cx.size_and_align_of(ty);
|
|
|
|
MemberDescription {
|
|
|
|
name: name.to_string(),
|
2020-06-23 23:23:01 +00:00
|
|
|
type_metadata: if is_artificial_discr {
|
|
|
|
self.tag_type_metadata.unwrap_or_else(|| type_metadata(cx, ty, self.span))
|
2019-12-24 22:38:22 +00:00
|
|
|
} else {
|
|
|
|
type_metadata(cx, ty, self.span)
|
|
|
|
},
|
|
|
|
offset: self.offsets[i],
|
|
|
|
size,
|
|
|
|
align,
|
2020-06-23 23:23:01 +00:00
|
|
|
flags: if is_artificial_discr {
|
|
|
|
DIFlags::FlagArtificial
|
|
|
|
} else {
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-15 17:12:14 +00:00
|
|
|
// FIXME: terminology here should be aligned with `abi::TagEncoding`.
|
|
|
|
// `OptimizedTag` is `TagEncoding::Niche`, `RegularTag` is `TagEncoding::Direct`.
|
|
|
|
// `NoTag` should be removed; users should use `Option<EnumTagInfo>` instead.
|
2015-04-29 06:14:37 +00:00
|
|
|
#[derive(Copy, Clone)]
|
2020-05-23 11:22:45 +00:00
|
|
|
enum EnumTagInfo<'ll> {
|
|
|
|
RegularTag { tag_field: Field, tag_type_metadata: &'ll DIType },
|
|
|
|
OptimizedTag,
|
|
|
|
NoTag,
|
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>> {
|
|
|
|
match self {
|
|
|
|
VariantInfo::Generator { def_id, variant_index, .. } => {
|
|
|
|
let span =
|
|
|
|
cx.tcx.generator_layout(*def_id).variant_source_info[*variant_index].span;
|
|
|
|
if !span.is_dummy() {
|
|
|
|
let loc = cx.lookup_debug_loc(span.lo());
|
|
|
|
return Some(SourceInfo {
|
2020-02-10 01:03:24 +00:00
|
|
|
file: file_metadata(cx, &loc.file),
|
2020-06-17 23:04:25 +00:00
|
|
|
line: loc.line.unwrap_or(UNKNOWN_LINE_NUMBER),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
2020-06-18 02:39:23 +00:00
|
|
|
|
|
|
|
fn is_artificial(&self) -> bool {
|
|
|
|
match self {
|
|
|
|
VariantInfo::Generator { .. } => true,
|
|
|
|
VariantInfo::Adt(..) => false,
|
|
|
|
}
|
|
|
|
}
|
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>,
|
2020-05-23 11:22:45 +00:00
|
|
|
discriminant_info: EnumTagInfo<'ll>,
|
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()
|
|
|
|
.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,
|
|
|
|
&variant_name,
|
|
|
|
unique_type_id,
|
|
|
|
Some(containing_scope),
|
|
|
|
// FIXME(tmandry): This doesn't seem to have any effect.
|
|
|
|
if variant.is_artificial() { DIFlags::FlagArtificial } else { DIFlags::FlagZero },
|
|
|
|
)
|
2019-04-13 00:03:03 +00:00
|
|
|
});
|
2019-04-02 20:51:13 +00:00
|
|
|
|
2015-04-29 06:14:37 +00:00
|
|
|
// Build an array of (field name, field type) pairs to be captured in the factory closure.
|
2017-11-29 21:42:25 +00:00
|
|
|
let (offsets, args) = if use_enum_fallback(cx) {
|
|
|
|
// If this is not a univariant enum, there is also the discriminant field.
|
|
|
|
let (discr_offset, discr_arg) = match discriminant_info {
|
2020-05-23 11:22:45 +00:00
|
|
|
RegularTag { tag_field, .. } => {
|
2017-11-29 21:42:25 +00:00
|
|
|
// We have the layout of an enum variant, we need the layout of the outer enum
|
|
|
|
let enum_layout = cx.layout_of(layout.ty);
|
2020-05-23 11:22:45 +00:00
|
|
|
let offset = enum_layout.fields.offset(tag_field.as_usize());
|
2019-12-24 22:38:22 +00:00
|
|
|
let args =
|
2020-05-23 11:22:45 +00:00
|
|
|
("RUST$ENUM$DISR".to_owned(), enum_layout.field(cx, tag_field.as_usize()).ty);
|
2019-04-02 22:57:50 +00:00
|
|
|
(Some(offset), Some(args))
|
2017-11-29 21:42:25 +00:00
|
|
|
}
|
|
|
|
_ => (None, None),
|
2017-09-17 16:34:28 +00:00
|
|
|
};
|
2017-11-29 21:42:25 +00:00
|
|
|
(
|
2019-12-24 22:38:22 +00:00
|
|
|
discr_offset
|
|
|
|
.into_iter()
|
|
|
|
.chain((0..layout.fields.count()).map(|i| layout.fields.offset(i)))
|
|
|
|
.collect(),
|
|
|
|
discr_arg
|
|
|
|
.into_iter()
|
|
|
|
.chain(
|
|
|
|
(0..layout.fields.count())
|
|
|
|
.map(|i| (variant.field_name(i), layout.field(cx, i).ty)),
|
|
|
|
)
|
|
|
|
.collect(),
|
2017-11-29 21:42:25 +00:00
|
|
|
)
|
|
|
|
} else {
|
|
|
|
(
|
2019-12-24 22:38:22 +00:00
|
|
|
(0..layout.fields.count()).map(|i| layout.fields.offset(i)).collect(),
|
|
|
|
(0..layout.fields.count())
|
|
|
|
.map(|i| (variant.field_name(i), layout.field(cx, i).ty))
|
|
|
|
.collect(),
|
2017-11-29 21:42:25 +00:00
|
|
|
)
|
|
|
|
};
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2019-12-24 22:38:22 +00:00
|
|
|
let member_description_factory = VariantMDF(VariantMemberDescriptionFactory {
|
|
|
|
offsets,
|
|
|
|
args,
|
2020-05-23 11:22:45 +00:00
|
|
|
tag_type_metadata: match discriminant_info {
|
|
|
|
RegularTag { tag_type_metadata, .. } => Some(tag_type_metadata),
|
2019-12-24 22:38:22 +00:00
|
|
|
_ => None,
|
|
|
|
},
|
|
|
|
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);
|
2020-06-18 02:39:23 +00:00
|
|
|
// FIXME(tmandry): This doesn't seem to have any effect.
|
2020-08-02 22:49:11 +00:00
|
|
|
let enum_flags = match enum_type.kind() {
|
2020-06-18 02:39:23 +00:00
|
|
|
ty::Generator(..) => DIFlags::FlagArtificial,
|
|
|
|
_ => DIFlags::FlagZero,
|
|
|
|
};
|
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() {
|
2019-04-13 00:03:03 +00:00
|
|
|
ty::Adt(def, _) => def
|
2020-06-17 23:04:25 +00:00
|
|
|
.discriminants(tcx)
|
2019-04-13 00:03:03 +00:00
|
|
|
.zip(&def.variants)
|
|
|
|
.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
|
|
|
|
2020-03-22 12:36:56 +00:00
|
|
|
if let (
|
2020-03-31 16:16:47 +00:00
|
|
|
&Abi::Scalar(_),
|
2020-05-23 11:22:45 +00:00
|
|
|
&Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, .. },
|
2020-03-22 12:36:56 +00:00
|
|
|
) = (&layout.abi, &layout.variants)
|
|
|
|
{
|
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 {
|
2020-03-31 16:16:47 +00:00
|
|
|
Variants::Single { .. }
|
2020-05-23 11:22:45 +00:00
|
|
|
| Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, .. } => None,
|
|
|
|
Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, .. } => {
|
|
|
|
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),
|
|
|
|
containing_scope,
|
|
|
|
enum_name.as_ptr().cast(),
|
|
|
|
enum_name.len(),
|
|
|
|
file_metadata,
|
|
|
|
UNKNOWN_LINE_NUMBER,
|
|
|
|
layout.size.bits(),
|
|
|
|
layout.align.abi.bits() as u32,
|
2020-06-18 02:39:23 +00:00
|
|
|
enum_flags,
|
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,
|
2017-11-29 21:42:25 +00:00
|
|
|
containing_scope,
|
|
|
|
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
|
|
|
|
2020-03-31 16:16:47 +00:00
|
|
|
Variants::Multiple {
|
2020-05-23 11:22:45 +00:00
|
|
|
tag_encoding: TagEncoding::Niche { .. }, ref tag, tag_field, ..
|
2019-03-29 05:44:54 +00:00
|
|
|
} => {
|
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
|
|
|
|
2020-05-23 11:22:45 +00:00
|
|
|
Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, tag_field, .. } => {
|
|
|
|
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
|
|
|
};
|
|
|
|
|
2019-04-13 00:03:03 +00:00
|
|
|
let mut 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,
|
2020-06-18 02:39:23 +00:00
|
|
|
enum_flags,
|
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
|
|
|
};
|
2019-04-13 00:03:03 +00:00
|
|
|
outer_fields.push(Some(variant_part));
|
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.
|
|
|
|
let type_array = create_DIArray(DIB(cx), &outer_fields);
|
|
|
|
|
|
|
|
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,
|
2020-06-18 02:39:23 +00:00
|
|
|
enum_flags,
|
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,
|
2017-08-07 05:54:09 +00:00
|
|
|
containing_scope,
|
|
|
|
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.
|
2019-12-24 22:38:22 +00:00
|
|
|
set_members_of_composite_type(cx, composite_type, composite_type_metadata, member_descriptions);
|
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>>,
|
|
|
|
) {
|
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();
|
2019-10-16 04:48:20 +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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-27 10:12:47 +00:00
|
|
|
let 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();
|
|
|
|
|
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),
|
|
|
|
type_params,
|
|
|
|
);
|
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.
|
2018-10-12 13:34:14 +00:00
|
|
|
fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> Option<&'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);
|
2019-12-24 22:38:22 +00:00
|
|
|
let template_params: Vec<_> = substs
|
|
|
|
.iter()
|
|
|
|
.zip(names)
|
|
|
|
.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
|
|
|
|
|
|
|
return Some(create_DIArray(DIB(cx), &template_params[..]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Some(create_DIArray(DIB(cx), &[]));
|
|
|
|
|
2019-12-24 22:38:22 +00:00
|
|
|
fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec<Symbol> {
|
|
|
|
let mut names = generics
|
|
|
|
.parent
|
|
|
|
.map_or(vec![], |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),
|
|
|
|
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 {
|
2020-02-25 00:00:00 +00:00
|
|
|
(unknown_file_metadata(cx), None)
|
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,
|
2020-02-25 00:00:00 +00:00
|
|
|
line_number.unwrap_or(UNKNOWN_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
|
|
|
}
|