2015-04-29 06:14:37 +00:00
|
|
|
use self::RecursiveTypeDescription::*;
|
|
|
|
use self::MemberDescriptionFactory::*;
|
|
|
|
use self::EnumDiscriminantInfo::*;
|
|
|
|
|
2017-06-01 18:50:53 +00:00
|
|
|
use super::utils::{debug_context, DIB, span_start,
|
2017-07-07 12:23:38 +00:00
|
|
|
get_namespace_for_item, create_DIArray, is_node_local_to_unit};
|
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;
|
2016-08-16 14:41:38 +00:00
|
|
|
use super::{CrateDebugContext};
|
2019-02-17 18:58:58 +00:00
|
|
|
use crate::abi;
|
|
|
|
use crate::value::Value;
|
2018-11-16 11:45:28 +00:00
|
|
|
use rustc_codegen_ssa::traits::*;
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2019-02-17 18:58:58 +00:00
|
|
|
use crate::llvm;
|
|
|
|
use crate::llvm::debuginfo::{DIArray, DIType, DIFile, DIScope, DIDescriptor,
|
2019-01-22 21:01:14 +00:00
|
|
|
DICompositeType, DILexicalBlock, DIFlags, DebugEmissionKind};
|
2019-02-17 18:58:58 +00:00
|
|
|
use crate::llvm_util;
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2019-02-17 18:58:58 +00:00
|
|
|
use crate::common::CodegenCx;
|
2018-05-17 23:43:36 +00:00
|
|
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
2018-05-08 13:10:16 +00:00
|
|
|
use rustc::hir::CodegenFnAttrFlags;
|
2016-09-14 21:51:46 +00:00
|
|
|
use rustc::hir::def::CtorKind;
|
2017-04-24 17:01:19 +00:00
|
|
|
use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
|
2018-08-04 00:34:23 +00:00
|
|
|
use rustc::ich::NodeIdHashingMode;
|
2019-04-02 22:57:50 +00:00
|
|
|
use rustc::mir::Field;
|
2019-03-28 08:31:18 +00:00
|
|
|
use rustc::mir::interpret::truncate;
|
2018-08-04 00:34:23 +00:00
|
|
|
use rustc_data_structures::fingerprint::Fingerprint;
|
2017-10-30 07:36:03 +00:00
|
|
|
use rustc::ty::Instance;
|
2018-03-03 13:23:28 +00:00
|
|
|
use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
|
2018-10-12 13:34:14 +00:00
|
|
|
use rustc::ty::layout::{self, Align, Integer, IntegerExt, LayoutOf,
|
2018-09-07 15:29:40 +00:00
|
|
|
PrimitiveExt, Size, TyLayout};
|
2018-10-12 13:34:14 +00:00
|
|
|
use rustc::ty::subst::UnpackedKind;
|
2018-01-05 04:14:44 +00:00
|
|
|
use rustc::session::config;
|
2017-05-27 18:48:09 +00:00
|
|
|
use rustc::util::nodemap::FxHashMap;
|
2018-11-29 13:09:28 +00:00
|
|
|
use rustc_fs_util::path_to_c_string;
|
2018-08-07 14:04:34 +00:00
|
|
|
use rustc_data_structures::small_c_str::SmallCStr;
|
2018-10-12 13:34:14 +00:00
|
|
|
use rustc_target::abi::HasDataLayout;
|
2015-04-24 04:48:10 +00:00
|
|
|
|
|
|
|
use libc::{c_uint, c_longlong};
|
|
|
|
use std::ffi::CString;
|
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;
|
2015-04-24 04:48:10 +00:00
|
|
|
use std::ptr;
|
2017-12-14 07:09:19 +00:00
|
|
|
use std::path::{Path, PathBuf};
|
2018-04-12 12:52:09 +00:00
|
|
|
use syntax::ast;
|
2017-04-24 17:01:19 +00:00
|
|
|
use syntax::symbol::{Interner, InternedString, Symbol};
|
2017-12-14 07:09:19 +00:00
|
|
|
use syntax_pos::{self, Span, FileName};
|
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.
|
|
|
|
// See http://www.dwarfstd.org/ShowIssue.php?issue=140129.1
|
|
|
|
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)]
|
|
|
|
pub struct UniqueTypeId(ast::Name);
|
|
|
|
|
|
|
|
// 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
|
|
|
|
// UniqueTypeIds.
|
2018-10-16 14:57:53 +00:00
|
|
|
#[derive(Default)]
|
2018-07-04 13:36:49 +00:00
|
|
|
pub struct TypeMap<'ll, 'tcx> {
|
2015-04-29 06:14:37 +00:00
|
|
|
// The UniqueTypeIds created so far
|
2016-07-11 08:00:48 +00:00
|
|
|
unique_id_interner: Interner,
|
2015-04-29 06:14:37 +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>,
|
2015-04-29 06:14:37 +00:00
|
|
|
// A map from types to debuginfo metadata. This is a N:1 mapping.
|
2018-07-04 13:36:49 +00:00
|
|
|
type_to_metadata: FxHashMap<Ty<'tcx>, &'ll DIType>,
|
2015-04-29 06:14:37 +00:00
|
|
|
// A map from types to UniqueTypeId. This is a N:1 mapping.
|
2016-11-08 03:02:55 +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> {
|
2015-04-29 06:14:37 +00:00
|
|
|
// Adds a Ty 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_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() {
|
2016-03-28 23:46:02 +00:00
|
|
|
bug!("Type metadata for Ty '{}' is already in the TypeMap!", type_);
|
2015-04-29 06:14:37 +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
|
|
|
// Removes a Ty to metadata mapping
|
|
|
|
// This is useful when computing the metadata for a potentially
|
|
|
|
// recursive type (e.g. a function ptr 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
|
2019-03-28 16:22:08 +00:00
|
|
|
// for the function before we compute its actual 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
|
|
|
// 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
|
2019-03-28 16:22:08 +00:00
|
|
|
// mapping after we've computed the actual 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
|
|
|
fn remove_type(
|
|
|
|
&mut self,
|
|
|
|
type_: Ty<'tcx>,
|
|
|
|
) {
|
|
|
|
if self.type_to_metadata.remove(type_).is_none() {
|
|
|
|
bug!("Type metadata Ty '{}' is not in the TypeMap!", type_);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-29 06:14:37 +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() {
|
2016-03-28 23:46:02 +00:00
|
|
|
bug!("Type metadata for unique id '{}' is already in the TypeMap!",
|
2016-11-19 05:55:28 +00:00
|
|
|
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()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get 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)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get 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.
|
2018-01-05 05:01:54 +00:00
|
|
|
fn get_unique_type_id_of_type<'a>(&mut self, cx: &CodegenCx<'a, 'tcx>,
|
2015-04-29 06:14:37 +00:00
|
|
|
type_: Ty<'tcx>) -> UniqueTypeId {
|
2016-10-21 21:56:36 +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
|
|
|
}
|
|
|
|
// 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.
|
2018-05-08 11:52:01 +00:00
|
|
|
let mut hasher = StableHasher::<Fingerprint>::new();
|
|
|
|
let mut hcx = cx.tcx.create_stable_hashing_context();
|
|
|
|
let type_ = cx.tcx.erase_regions(&type_);
|
|
|
|
hcx.while_hashing_spans(false, |hcx| {
|
|
|
|
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
|
|
|
|
type_.hash_stable(hcx, &mut hasher);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
let unique_type_id = hasher.finish().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));
|
|
|
|
|
|
|
|
return UniqueTypeId(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the UniqueTypeId for an enum variant. Enum variants are not really
|
|
|
|
// types of their own, so they need special handling. We still need a
|
|
|
|
// UniqueTypeId for them, since to debuginfo they *are* real types.
|
|
|
|
fn get_unique_type_id_of_enum_variant<'a>(&mut self,
|
2018-01-05 05:01:54 +00:00
|
|
|
cx: &CodegenCx<'a, 'tcx>,
|
2015-04-29 06:14:37 +00:00
|
|
|
enum_type: Ty<'tcx>,
|
|
|
|
variant_name: &str)
|
|
|
|
-> UniqueTypeId {
|
|
|
|
let enum_type_id = self.get_unique_type_id_of_type(cx, enum_type);
|
|
|
|
let enum_variant_type_id = format!("{}::{}",
|
2016-11-19 05:55:28 +00:00
|
|
|
self.get_unique_type_id_as_string(enum_type_id),
|
2015-04-29 06:14:37 +00:00
|
|
|
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
|
|
|
|
|
|
|
// Get the unique type id string for an enum variant part.
|
|
|
|
// Variant parts are not types and shouldn't really have their own id,
|
|
|
|
// but it makes set_members_of_composite_type() simpler.
|
|
|
|
fn get_unique_type_id_str_of_enum_variant_part<'a>(&mut self,
|
|
|
|
enum_type_id: UniqueTypeId) -> &str {
|
|
|
|
let variant_part_type_id = format!("{}_variant_part",
|
|
|
|
self.get_unique_type_id_as_string(enum_type_id));
|
|
|
|
let interner_key = self.unique_id_interner.intern(&variant_part_type_id);
|
|
|
|
self.unique_id_interner.get(interner_key)
|
|
|
|
}
|
2015-04-29 06:14:37 +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
|
|
|
},
|
2018-07-04 13:36:49 +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> {
|
2015-04-29 06:14:37 +00:00
|
|
|
|
|
|
|
// Insert the stub into the TypeMap in order to allow for recursive references
|
|
|
|
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> {
|
2015-04-29 06:14:37 +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
|
|
|
|
// create_and_register_recursive_type_forward_declaration()
|
|
|
|
// function.
|
|
|
|
{
|
|
|
|
let type_map = debug_context(cx).type_map.borrow();
|
|
|
|
if type_map.find_metadata_for_unique_id(unique_type_id).is_none() ||
|
|
|
|
type_map.find_metadata_for_type(unfinished_type).is_none() {
|
2016-03-28 23:46:02 +00:00
|
|
|
bug!("Forward declaration of potentially recursive type \
|
|
|
|
'{:?}' was not found in TypeMap!",
|
|
|
|
unfinished_type);
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ... then create the member descriptions ...
|
|
|
|
let member_descriptions =
|
|
|
|
member_description_factory.create_member_descriptions(cx);
|
|
|
|
|
|
|
|
// ... and attach them to the stub to complete it.
|
|
|
|
set_members_of_composite_type(cx,
|
2018-10-12 13:34:14 +00:00
|
|
|
unfinished_type,
|
2017-11-29 21:42:25 +00:00
|
|
|
member_holding_stub,
|
2018-08-07 14:04:34 +00:00
|
|
|
member_descriptions);
|
2015-04-29 06:14:37 +00:00
|
|
|
return MetadataCreationResult::new(metadata_stub, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-04-24 04:48:10 +00:00
|
|
|
|
|
|
|
// Returns from the enclosing function if the type metadata with the given
|
|
|
|
// unique id can be found in the type map
|
|
|
|
macro_rules! return_if_metadata_created_in_meantime {
|
|
|
|
($cx: expr, $unique_type_id: expr) => (
|
2018-10-09 13:15:41 +00:00
|
|
|
if let Some(metadata) = debug_context($cx).type_map
|
|
|
|
.borrow()
|
|
|
|
.find_metadata_for_unique_id($unique_type_id)
|
|
|
|
{
|
2018-10-16 09:14:10 +00:00
|
|
|
return MetadataCreationResult::new(metadata, true);
|
2015-10-21 16:20:46 +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
|
|
|
|
2017-06-01 18:50:53 +00:00
|
|
|
let upper_bound = match array_or_slice_type.sty {
|
2018-08-22 00:35:02 +00:00
|
|
|
ty::Array(_, len) => {
|
2018-04-26 07:18:19 +00:00
|
|
|
len.unwrap_usize(cx.tcx) as c_longlong
|
2017-06-01 18:50:53 +00:00
|
|
|
}
|
|
|
|
_ => -1
|
2015-04-24 04:48:10 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
let subrange = unsafe {
|
2018-07-04 13:36:49 +00:00
|
|
|
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,
|
|
|
|
subscripts)
|
|
|
|
};
|
|
|
|
|
|
|
|
return MetadataCreationResult::new(metadata, false);
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
|
2017-06-01 18:50:53 +00:00
|
|
|
let slice_type_name = compute_debuginfo_type_name(cx, slice_ptr_type, true);
|
|
|
|
|
|
|
|
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,
|
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,
|
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
|
|
|
|
|
|
|
let metadata = composite_type_metadata(cx,
|
2017-06-01 18:50:53 +00:00
|
|
|
slice_ptr_type,
|
2015-04-24 04:48:10 +00:00
|
|
|
&slice_type_name[..],
|
|
|
|
unique_type_id,
|
2018-08-07 14:04:34 +00:00
|
|
|
member_descriptions,
|
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
|
|
|
NO_SCOPE_METADATA,
|
2015-04-24 04:48:10 +00:00
|
|
|
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> {
|
2018-03-03 13:23:28 +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
|
|
|
|
match signature.output().sty {
|
2018-08-22 00:35:02 +00:00
|
|
|
ty::Tuple(ref tys) if tys.is_empty() => None,
|
2018-07-04 13:36:49 +00:00
|
|
|
_ => Some(type_metadata(cx, signature.output(), span))
|
2018-07-26 15:11:10 +00:00
|
|
|
}
|
|
|
|
).chain(
|
|
|
|
// regular arguments
|
2018-06-27 10:12:47 +00:00
|
|
|
signature.inputs().iter().map(|argument_type| {
|
2018-07-04 13:36:49 +00:00
|
|
|
Some(type_metadata(cx, argument_type, span))
|
2018-06-27 10:12:47 +00:00
|
|
|
})
|
2018-07-26 15:11:10 +00:00
|
|
|
).collect();
|
2015-04-24 04:48:10 +00:00
|
|
|
|
|
|
|
return_if_metadata_created_in_meantime!(cx, unique_type_id);
|
|
|
|
|
|
|
|
return MetadataCreationResult::new(
|
|
|
|
unsafe {
|
2016-08-01 23:35:09 +00:00
|
|
|
llvm::LLVMRustDIBuilderCreateSubroutineType(
|
2015-04-24 04:48:10 +00:00
|
|
|
DIB(cx),
|
2016-07-07 12:15:10 +00:00
|
|
|
unknown_file_metadata(cx),
|
2015-04-24 04:48:10 +00:00
|
|
|
create_DIArray(DIB(cx), &signature_metadata[..]))
|
|
|
|
},
|
|
|
|
false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
|
|
|
// 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.
|
|
|
|
// But it does not describe the trait's methods.
|
|
|
|
|
2016-11-12 22:46:16 +00:00
|
|
|
let containing_scope = match trait_type.sty {
|
2018-12-04 11:28:06 +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
|
|
|
_ => {
|
2016-03-28 23:46:02 +00:00
|
|
|
bug!("debuginfo: Unexpected trait-object type in \
|
|
|
|
trait_pointer_metadata(): {:?}",
|
|
|
|
trait_type);
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let trait_object_type = trait_object_type.unwrap_or(trait_type);
|
|
|
|
let trait_type_name =
|
|
|
|
compute_debuginfo_type_name(cx, trait_object_type, false);
|
|
|
|
|
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(),
|
2017-06-01 18:50:53 +00:00
|
|
|
type_metadata: type_metadata(cx,
|
2018-01-05 04:58:34 +00:00
|
|
|
cx.tcx.mk_mut_ptr(cx.tcx.types.u8),
|
2017-06-01 18:50:53 +00:00
|
|
|
syntax_pos::DUMMY_SP),
|
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,
|
2017-05-27 19:46:42 +00:00
|
|
|
},
|
|
|
|
MemberDescription {
|
2018-10-09 13:16:20 +00:00
|
|
|
name: "vtable".to_owned(),
|
2017-06-01 18:50:53 +00:00
|
|
|
type_metadata: type_metadata(cx, vtable_field.ty, syntax_pos::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,
|
2017-05-27 19:46:42 +00:00
|
|
|
},
|
|
|
|
];
|
|
|
|
|
2015-04-24 04:48:10 +00:00
|
|
|
composite_type_metadata(cx,
|
2017-06-01 18:50:53 +00:00
|
|
|
trait_object_type,
|
2015-04-24 04:48:10 +00:00
|
|
|
&trait_type_name[..],
|
|
|
|
unique_type_id,
|
2018-08-07 14:04:34 +00:00
|
|
|
member_descriptions,
|
2015-04-24 04:48:10 +00:00
|
|
|
containing_scope,
|
2016-07-07 12:15:10 +00:00
|
|
|
file_metadata,
|
2016-06-21 22:08:13 +00:00
|
|
|
syntax_pos::DUMMY_SP)
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
pub fn type_metadata(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
t: Ty<'tcx>,
|
|
|
|
usage_site_span: Span,
|
|
|
|
) -> &'ll DIType {
|
2015-04-24 04:48:10 +00:00
|
|
|
// Get the unique type id of this type.
|
|
|
|
let unique_type_id = {
|
|
|
|
let mut type_map = debug_context(cx).type_map.borrow_mut();
|
|
|
|
// First, try to find the type in TypeMap. If we have seen it before, we
|
|
|
|
// can exit early here.
|
|
|
|
match type_map.find_metadata_for_type(t) {
|
|
|
|
Some(metadata) => {
|
|
|
|
return metadata;
|
|
|
|
},
|
|
|
|
None => {
|
|
|
|
// The Ty is not in the TypeMap but maybe we have already seen
|
2018-11-27 02:59:49 +00:00
|
|
|
// an equivalent type (e.g., only differing in region arguments).
|
2015-04-24 04:48:10 +00:00
|
|
|
// In order to find out, generate the unique type id and look
|
|
|
|
// that up.
|
|
|
|
let unique_type_id = type_map.get_unique_type_id_of_type(cx, t);
|
|
|
|
match type_map.find_metadata_for_unique_id(unique_type_id) {
|
|
|
|
Some(metadata) => {
|
|
|
|
// There is already an equivalent type in the TypeMap.
|
|
|
|
// Register this Ty as an alias in the cache and
|
|
|
|
// return the cached metadata.
|
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;
|
|
|
|
},
|
|
|
|
None => {
|
|
|
|
// There really is no type metadata for this type, so
|
|
|
|
// proceed by creating it.
|
|
|
|
unique_type_id
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
debug!("type_metadata: {:?}", t);
|
|
|
|
|
2017-01-21 14:40:31 +00:00
|
|
|
let ptr_metadata = |ty: Ty<'tcx>| {
|
|
|
|
match ty.sty {
|
2018-08-22 00:35:02 +00:00
|
|
|
ty::Slice(typ) => {
|
2017-01-21 14:40:31 +00:00
|
|
|
Ok(vec_slice_metadata(cx, t, typ, unique_type_id, usage_site_span))
|
|
|
|
}
|
2018-08-22 00:35:55 +00:00
|
|
|
ty::Str => {
|
2018-01-05 04:58:34 +00:00
|
|
|
Ok(vec_slice_metadata(cx, t, cx.tcx.types.u8, unique_type_id, usage_site_span))
|
2017-01-21 14:40:31 +00:00
|
|
|
}
|
2018-08-22 00:35:02 +00:00
|
|
|
ty::Dynamic(..) => {
|
2017-01-21 14:40:31 +00:00
|
|
|
Ok(MetadataCreationResult::new(
|
|
|
|
trait_pointer_metadata(cx, ty, Some(t), unique_type_id),
|
|
|
|
false))
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
let pointee_metadata = type_metadata(cx, ty, usage_site_span);
|
|
|
|
|
2018-10-09 13:15:41 +00:00
|
|
|
if let Some(metadata) = debug_context(cx).type_map
|
|
|
|
.borrow()
|
|
|
|
.find_metadata_for_unique_id(unique_type_id)
|
|
|
|
{
|
2018-10-16 09:14:10 +00:00
|
|
|
return Err(metadata);
|
2018-10-09 13:15:41 +00:00
|
|
|
}
|
2017-01-21 14:40:31 +00:00
|
|
|
|
|
|
|
Ok(MetadataCreationResult::new(pointer_type_metadata(cx, t, pointee_metadata),
|
|
|
|
false))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-05-13 14:11:52 +00:00
|
|
|
let MetadataCreationResult { metadata, already_stored_in_typemap } = match t.sty {
|
2018-08-22 00:35:02 +00:00
|
|
|
ty::Never |
|
2018-08-22 00:35:55 +00:00
|
|
|
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)
|
|
|
|
}
|
2018-08-22 00:35:02 +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
|
|
|
}
|
2018-08-22 00:35:55 +00:00
|
|
|
ty::Str => {
|
2018-01-05 04:58:34 +00:00
|
|
|
fixed_vec_metadata(cx, unique_type_id, t, cx.tcx.types.i8, usage_site_span)
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
2018-08-22 00:35:02 +00:00
|
|
|
ty::Dynamic(..) => {
|
2015-04-24 04:48:10 +00:00
|
|
|
MetadataCreationResult::new(
|
2018-10-09 13:13:11 +00:00
|
|
|
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(..) => {
|
2017-09-03 18:53:58 +00:00
|
|
|
MetadataCreationResult::new(
|
2018-10-09 13:13:11 +00:00
|
|
|
foreign_type_metadata(cx, t, unique_type_id),
|
2017-09-03 18:53:58 +00:00
|
|
|
false)
|
|
|
|
}
|
2018-08-22 00:35:02 +00:00
|
|
|
ty::RawPtr(ty::TypeAndMut{ty, ..}) |
|
|
|
|
ty::Ref(_, ty, _) => {
|
2017-01-21 14:40:31 +00:00
|
|
|
match ptr_metadata(ty) {
|
|
|
|
Ok(res) => res,
|
|
|
|
Err(metadata) => return metadata,
|
|
|
|
}
|
|
|
|
}
|
2018-08-22 00:35:02 +00:00
|
|
|
ty::Adt(def, _) if def.is_box() => {
|
2017-01-21 14:40:31 +00:00
|
|
|
match ptr_metadata(t.boxed_ty()) {
|
|
|
|
Ok(res) => res,
|
|
|
|
Err(metadata) => return metadata,
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
}
|
2018-08-22 00:35:02 +00:00
|
|
|
ty::FnDef(..) | ty::FnPtr(_) => {
|
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
|
|
|
|
2018-10-09 13:15:41 +00:00
|
|
|
if let Some(metadata) = debug_context(cx).type_map
|
|
|
|
.borrow()
|
|
|
|
.find_metadata_for_unique_id(unique_type_id)
|
|
|
|
{
|
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 }
|
|
|
|
//
|
|
|
|
// See TypeMap::remove_type for more detals
|
|
|
|
// about the workaround
|
|
|
|
|
|
|
|
let temp_type = {
|
|
|
|
unsafe {
|
|
|
|
// The choice of type here is pretty arbitrary -
|
|
|
|
// anything reading the debuginfo for a recursive
|
|
|
|
// type is going to see *somthing* weird - the only
|
|
|
|
// question is what exactly it will see
|
|
|
|
let (size, align) = cx.size_and_align_of(t);
|
|
|
|
llvm::LLVMRustDIBuilderCreateBasicType(
|
|
|
|
DIB(cx),
|
|
|
|
SmallCStr::new("<recur_type>").as_ptr(),
|
|
|
|
size.bits(),
|
|
|
|
align.bits() as u32,
|
|
|
|
DW_ATE_unsigned)
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let type_map = &debug_context(cx).type_map;
|
|
|
|
type_map.borrow_mut().register_type_with_metadata(t, temp_type);
|
|
|
|
|
|
|
|
let fn_metadata = subroutine_type_metadata(cx,
|
|
|
|
unique_type_id,
|
|
|
|
t.fn_sig(cx.tcx),
|
|
|
|
usage_site_span).metadata;
|
|
|
|
|
|
|
|
type_map.borrow_mut().remove_type(t);
|
|
|
|
|
|
|
|
|
2015-07-13 19:50:21 +00:00
|
|
|
// This is actually a function pointer, so wrap it in pointer DI
|
|
|
|
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) => {
|
2018-01-05 04:58:34 +00:00
|
|
|
let upvar_tys : Vec<_> = substs.upvar_tys(def_id, cx.tcx).collect();
|
2015-07-14 17:08:08 +00:00
|
|
|
prepare_tuple_metadata(cx,
|
|
|
|
t,
|
2016-11-03 20:19:33 +00:00
|
|
|
&upvar_tys,
|
2015-07-14 17:08:08 +00:00
|
|
|
unique_type_id,
|
|
|
|
usage_site_span).finalize(cx)
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
2018-08-22 00:35:02 +00:00
|
|
|
ty::Generator(def_id, substs, _) => {
|
2018-01-05 04:58:34 +00:00
|
|
|
let upvar_tys : Vec<_> = substs.field_tys(def_id, cx.tcx).map(|t| {
|
2018-03-03 13:23:28 +00:00
|
|
|
cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)
|
2016-12-26 13:34:03 +00:00
|
|
|
}).collect();
|
|
|
|
prepare_tuple_metadata(cx,
|
|
|
|
t,
|
|
|
|
&upvar_tys,
|
|
|
|
unique_type_id,
|
|
|
|
usage_site_span).finalize(cx)
|
|
|
|
}
|
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 => {
|
|
|
|
prepare_struct_metadata(cx,
|
|
|
|
t,
|
|
|
|
unique_type_id,
|
|
|
|
usage_site_span).finalize(cx)
|
|
|
|
}
|
|
|
|
AdtKind::Union => {
|
|
|
|
prepare_union_metadata(cx,
|
2018-10-09 13:13:11 +00:00
|
|
|
t,
|
|
|
|
unique_type_id,
|
|
|
|
usage_site_span).finalize(cx)
|
2016-09-05 22:26:02 +00:00
|
|
|
}
|
|
|
|
AdtKind::Enum => {
|
|
|
|
prepare_enum_metadata(cx,
|
2018-10-09 13:13:11 +00:00
|
|
|
t,
|
|
|
|
def.did,
|
|
|
|
unique_type_id,
|
|
|
|
usage_site_span).finalize(cx)
|
2016-09-05 22:26:02 +00:00
|
|
|
}
|
|
|
|
},
|
2018-08-22 00:35:02 +00:00
|
|
|
ty::Tuple(ref elements) => {
|
2015-04-24 04:48:10 +00:00
|
|
|
prepare_tuple_metadata(cx,
|
|
|
|
t,
|
|
|
|
&elements[..],
|
|
|
|
unique_type_id,
|
|
|
|
usage_site_span).finalize(cx)
|
|
|
|
}
|
|
|
|
_ => {
|
2017-05-13 14:11:52 +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 {
|
2015-10-07 22:11:25 +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 => {
|
2016-03-28 23:46:02 +00:00
|
|
|
span_bug!(usage_site_span,
|
|
|
|
"Expected type metadata for unique \
|
|
|
|
type id '{}' to already be in \
|
|
|
|
the debuginfo::TypeMap but it \
|
|
|
|
was not. (Ty = {})",
|
2016-11-19 05:55:28 +00:00
|
|
|
type_map.get_unique_type_id_as_string(unique_type_id),
|
2016-03-28 23:46:02 +00:00
|
|
|
t);
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
match type_map.find_metadata_for_type(t) {
|
|
|
|
Some(metadata) => {
|
|
|
|
if metadata != metadata_for_uid {
|
2016-03-28 23:46:02 +00:00
|
|
|
span_bug!(usage_site_span,
|
|
|
|
"Mismatch between Ty and \
|
|
|
|
UniqueTypeId maps in \
|
|
|
|
debuginfo::TypeMap. \
|
|
|
|
UniqueTypeId={}, Ty={}",
|
2016-11-19 05:55:28 +00:00
|
|
|
type_map.get_unique_type_id_as_string(unique_type_id),
|
2016-03-28 23:46:02 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
pub fn file_metadata(cx: &CodegenCx<'ll, '_>,
|
2017-12-14 07:09:19 +00:00
|
|
|
file_name: &FileName,
|
2018-07-04 13:36:49 +00:00
|
|
|
defining_crate: CrateNum) -> &'ll DIFile {
|
2017-04-24 17:01:19 +00:00
|
|
|
debug!("file_metadata: file_name: {}, defining_crate: {}",
|
|
|
|
file_name,
|
|
|
|
defining_crate);
|
2015-04-24 04:48:10 +00:00
|
|
|
|
2017-04-24 17:01:19 +00:00
|
|
|
let directory = if defining_crate == LOCAL_CRATE {
|
2017-12-14 07:09:19 +00:00
|
|
|
&cx.sess().working_dir.0
|
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.
|
2017-12-14 07:09:19 +00:00
|
|
|
Path::new("")
|
2017-04-24 17:01:19 +00:00
|
|
|
};
|
|
|
|
|
2017-12-14 07:09:19 +00:00
|
|
|
file_metadata_raw(cx, &file_name.to_string(), &directory.to_string_lossy())
|
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 {
|
2017-04-24 17:01:19 +00:00
|
|
|
file_metadata_raw(cx, "<unknown>", "")
|
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
|
|
|
fn file_metadata_raw(cx: &CodegenCx<'ll, '_>,
|
2017-04-24 17:01:19 +00:00
|
|
|
file_name: &str,
|
|
|
|
directory: &str)
|
2018-07-04 13:36:49 +00:00
|
|
|
-> &'ll DIFile {
|
2017-04-24 17:01:19 +00:00
|
|
|
let key = (Symbol::intern(file_name), Symbol::intern(directory));
|
|
|
|
|
|
|
|
if let Some(file_metadata) = debug_context(cx).created_files.borrow().get(&key) {
|
2016-06-14 05:43:30 +00:00
|
|
|
return *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
|
|
|
}
|
|
|
|
|
2017-04-24 17:01:19 +00:00
|
|
|
debug!("file_metadata: file_name: {}, directory: {}", file_name, directory);
|
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-08-07 14:04:34 +00:00
|
|
|
let file_name = SmallCStr::new(file_name);
|
|
|
|
let directory = SmallCStr::new(directory);
|
2017-04-24 17:01:19 +00:00
|
|
|
|
2015-04-24 04:48:10 +00:00
|
|
|
let file_metadata = unsafe {
|
2017-04-24 17:01:19 +00:00
|
|
|
llvm::LLVMRustDIBuilderCreateFile(DIB(cx),
|
|
|
|
file_name.as_ptr(),
|
|
|
|
directory.as_ptr())
|
2015-04-24 04:48:10 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
let mut created_files = debug_context(cx).created_files.borrow_mut();
|
2017-04-24 17:01:19 +00:00
|
|
|
created_files.insert(key, 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
|
|
|
file_metadata
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
|
2015-04-24 04:48:10 +00:00
|
|
|
debug!("basic_type_metadata: {:?}", t);
|
|
|
|
|
|
|
|
let (name, encoding) = match t.sty {
|
2018-08-22 00:35:02 +00:00
|
|
|
ty::Never => ("!", DW_ATE_unsigned),
|
|
|
|
ty::Tuple(ref elements) if elements.is_empty() =>
|
2015-11-23 14:59:36 +00:00
|
|
|
("()", DW_ATE_unsigned),
|
2018-08-22 00:35:55 +00:00
|
|
|
ty::Bool => ("bool", DW_ATE_boolean),
|
|
|
|
ty::Char => ("char", DW_ATE_unsigned_char),
|
|
|
|
ty::Int(int_ty) => {
|
2015-11-28 19:02:07 +00:00
|
|
|
(int_ty.ty_to_string(), DW_ATE_signed)
|
2015-04-24 04:48:10 +00:00
|
|
|
},
|
2018-08-22 00:35:55 +00:00
|
|
|
ty::Uint(uint_ty) => {
|
2015-11-28 19:02:07 +00:00
|
|
|
(uint_ty.ty_to_string(), DW_ATE_unsigned)
|
2015-04-24 04:48:10 +00:00
|
|
|
},
|
2018-08-22 00:35:55 +00:00
|
|
|
ty::Float(float_ty) => {
|
2015-11-28 19:02:07 +00:00
|
|
|
(float_ty.ty_to_string(), DW_ATE_float)
|
2015-04-24 04:48:10 +00:00
|
|
|
},
|
2016-03-28 23:46:02 +00:00
|
|
|
_ => bug!("debuginfo::basic_type_metadata - t is invalid type")
|
2015-04-24 04:48:10 +00:00
|
|
|
};
|
|
|
|
|
2017-06-01 18:50:53 +00:00
|
|
|
let (size, align) = cx.size_and_align_of(t);
|
2018-08-07 14:04:34 +00:00
|
|
|
let name = SmallCStr::new(name);
|
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),
|
|
|
|
name.as_ptr(),
|
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
|
|
|
encoding)
|
|
|
|
};
|
|
|
|
|
|
|
|
return ty_metadata;
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
let name = compute_debuginfo_type_name(cx, t, false);
|
2017-06-01 18:50:53 +00:00
|
|
|
create_struct_stub(cx, t, &name, unique_type_id, NO_SCOPE_METADATA)
|
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);
|
2015-04-24 04:48:10 +00:00
|
|
|
let name = compute_debuginfo_type_name(cx, pointer_type, false);
|
2018-08-07 14:04:34 +00:00
|
|
|
let name = SmallCStr::new(&name);
|
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,
|
2015-04-24 04:48:10 +00:00
|
|
|
name.as_ptr())
|
2017-06-01 18:50:53 +00:00
|
|
|
}
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
|
2019-02-25 07:40:18 +00:00
|
|
|
pub fn compile_unit_metadata(tcx: TyCtxt<'_, '_, '_>,
|
2017-05-19 08:55:25 +00:00
|
|
|
codegen_unit_name: &str,
|
2018-07-04 13:36:49 +00:00
|
|
|
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
|
|
|
|
// if multiple object files with the same DW_AT_name are linked together.
|
|
|
|
// 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.
|
2018-01-05 04:14:44 +00:00
|
|
|
if tcx.sess.target.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);
|
2017-03-08 18:08:09 +00:00
|
|
|
// FIXME(#41252) Remove "clang LLVM" if we can get GDB and LLVM to play nice.
|
|
|
|
let producer = format!("clang LLVM (rustc version {})",
|
2015-04-24 04:48:10 +00:00
|
|
|
(option_env!("CFG_VERSION")).expect("CFG_VERSION"));
|
|
|
|
|
2018-08-07 14:04:34 +00:00
|
|
|
let name_in_debuginfo = name_in_debuginfo.to_string_lossy();
|
|
|
|
let name_in_debuginfo = SmallCStr::new(&name_in_debuginfo);
|
|
|
|
let work_dir = SmallCStr::new(&tcx.sess.working_dir.0.to_string_lossy());
|
2017-02-11 21:41:03 +00:00
|
|
|
let producer = CString::new(producer).unwrap();
|
2015-04-24 04:48:10 +00:00
|
|
|
let flags = "\0";
|
|
|
|
let split_name = "\0";
|
2019-01-22 21:01:14 +00:00
|
|
|
let kind = DebugEmissionKind::from_generic(tcx.sess.opts.debuginfo);
|
2017-02-11 21:01:25 +00:00
|
|
|
|
|
|
|
unsafe {
|
|
|
|
let file_metadata = llvm::LLVMRustDIBuilderCreateFile(
|
2017-05-19 08:55:25 +00:00
|
|
|
debug_context.builder, name_in_debuginfo.as_ptr(), work_dir.as_ptr());
|
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,
|
2017-02-11 21:41:03 +00:00
|
|
|
producer.as_ptr(),
|
2018-01-05 04:14:44 +00:00
|
|
|
tcx.sess.opts.optimize != config::OptLevel::No,
|
2015-04-24 04:48:10 +00:00
|
|
|
flags.as_ptr() as *const _,
|
|
|
|
0,
|
2019-01-22 21:01:14 +00:00
|
|
|
split_name.as_ptr() as *const _,
|
|
|
|
kind);
|
2017-02-13 09:57:50 +00:00
|
|
|
|
2018-01-05 04:14:44 +00:00
|
|
|
if tcx.sess.opts.debugging_opts.profile {
|
2017-06-04 16:50:25 +00:00
|
|
|
let cu_desc_metadata = llvm::LLVMRustMetadataAsValue(debug_context.llcontext,
|
|
|
|
unit_metadata);
|
|
|
|
|
|
|
|
let gcov_cu_info = [
|
|
|
|
path_to_mdstring(debug_context.llcontext,
|
2018-01-05 04:14:44 +00:00
|
|
|
&tcx.output_filenames(LOCAL_CRATE).with_extension("gcno")),
|
2017-06-04 18:53:42 +00:00
|
|
|
path_to_mdstring(debug_context.llcontext,
|
2018-01-05 04:14:44 +00:00
|
|
|
&tcx.output_filenames(LOCAL_CRATE).with_extension("gcda")),
|
2017-06-04 16:50:25 +00:00
|
|
|
cu_desc_metadata,
|
|
|
|
];
|
|
|
|
let gcov_metadata = llvm::LLVMMDNodeInContext(debug_context.llcontext,
|
|
|
|
gcov_cu_info.as_ptr(),
|
|
|
|
gcov_cu_info.len() as c_uint);
|
|
|
|
|
2018-08-07 14:03:57 +00:00
|
|
|
let llvm_gcov_ident = const_cstr!("llvm.gcov");
|
2017-06-04 16:50:25 +00:00
|
|
|
llvm::LLVMAddNamedMetadataOperand(debug_context.llmod,
|
|
|
|
llvm_gcov_ident.as_ptr(),
|
|
|
|
gcov_metadata);
|
|
|
|
}
|
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 {
|
|
|
|
llvm::LLVMMDStringInContext(llcx,
|
|
|
|
path_str.as_ptr(),
|
|
|
|
path_str.as_bytes().len() as c_uint)
|
|
|
|
}
|
|
|
|
}
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
struct MetadataCreationResult<'ll> {
|
|
|
|
metadata: &'ll DIType,
|
2015-04-24 04:48:10 +00:00
|
|
|
already_stored_in_typemap: bool
|
|
|
|
}
|
|
|
|
|
2018-07-04 13:36:49 +00:00
|
|
|
impl MetadataCreationResult<'ll> {
|
|
|
|
fn new(metadata: &'ll DIType, already_stored_in_typemap: bool) -> Self {
|
2015-04-24 04:48:10 +00:00
|
|
|
MetadataCreationResult {
|
2017-08-07 05:54:09 +00:00
|
|
|
metadata,
|
|
|
|
already_stored_in_typemap,
|
2015-04-24 04:48:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-04-29 06:14:37 +00:00
|
|
|
|
|
|
|
// Description of a type member, which can either be a regular field (as in
|
|
|
|
// 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>,
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// A factory for MemberDescriptions. It produces a list of member descriptions
|
|
|
|
// for some record-like type. MemberDescriptionFactories 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>),
|
2018-07-04 13:36:49 +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> {
|
|
|
|
fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
|
2018-10-09 13:13:11 +00:00
|
|
|
-> Vec<MemberDescription<'ll>> {
|
2015-04-29 06:14:37 +00:00
|
|
|
match *self {
|
|
|
|
StructMDF(ref this) => {
|
|
|
|
this.create_member_descriptions(cx)
|
|
|
|
}
|
|
|
|
TupleMDF(ref this) => {
|
|
|
|
this.create_member_descriptions(cx)
|
|
|
|
}
|
|
|
|
EnumMDF(ref this) => {
|
|
|
|
this.create_member_descriptions(cx)
|
|
|
|
}
|
2016-08-22 18:11:22 +00:00
|
|
|
UnionMDF(ref this) => {
|
|
|
|
this.create_member_descriptions(cx)
|
|
|
|
}
|
2015-04-29 06:14:37 +00:00
|
|
|
VariantMDF(ref this) => {
|
|
|
|
this.create_member_descriptions(cx)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
// Structs
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Creates MemberDescriptions for the fields of a struct
|
|
|
|
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> {
|
2018-07-04 13:36:49 +00:00
|
|
|
fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
|
2018-10-09 13:13:11 +00:00
|
|
|
-> Vec<MemberDescription<'ll>> {
|
2016-11-21 00:56:51 +00:00
|
|
|
let layout = cx.layout_of(self.ty);
|
2015-08-02 19:52:50 +00:00
|
|
|
self.variant.fields.iter().enumerate().map(|(i, f)| {
|
2016-09-14 21:51:46 +00:00
|
|
|
let name = if self.variant.ctor_kind == CtorKind::Fn {
|
2015-04-29 06:14:37 +00:00
|
|
|
format!("__{}", i)
|
|
|
|
} else {
|
2018-05-25 23:50:15 +00:00
|
|
|
f.ident.to_string()
|
2015-04-29 06:14:37 +00:00
|
|
|
};
|
2017-06-25 09:41:24 +00:00
|
|
|
let field = layout.field(cx, i);
|
2015-04-29 06:14:37 +00:00
|
|
|
MemberDescription {
|
2017-08-07 05:54:09 +00:00
|
|
|
name,
|
2017-06-25 09:41:24 +00:00
|
|
|
type_metadata: type_metadata(cx, field.ty, self.span),
|
2017-09-17 20:37:18 +00:00
|
|
|
offset: layout.fields.offset(i),
|
2018-09-08 19:14:55 +00:00
|
|
|
size: field.size,
|
2018-09-08 22:16:45 +00:00
|
|
|
align: field.align.abi,
|
2016-11-18 22:15:14 +00:00
|
|
|
flags: DIFlags::FlagZero,
|
2017-11-29 21:42:25 +00:00
|
|
|
discriminant: None,
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
}).collect()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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> {
|
2015-04-29 06:14:37 +00:00
|
|
|
let struct_name = compute_debuginfo_type_name(cx, struct_type, false);
|
|
|
|
|
2017-06-25 09:41:24 +00:00
|
|
|
let (struct_def_id, variant) = match struct_type.sty {
|
2018-08-22 00:35:02 +00:00
|
|
|
ty::Adt(def, _) => (def.did, def.non_enum_variant()),
|
2016-09-05 22:26:02 +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
|
|
|
|
|
|
|
let struct_metadata_stub = create_struct_stub(cx,
|
2017-06-01 18:50:53 +00:00
|
|
|
struct_type,
|
2015-05-12 02:41:08 +00:00
|
|
|
&struct_name,
|
2015-04-29 06:14:37 +00:00
|
|
|
unique_type_id,
|
2018-07-04 13:36:49 +00:00
|
|
|
Some(containing_scope));
|
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,
|
2015-04-29 06:14:37 +00:00
|
|
|
StructMDF(StructMemberDescriptionFactory {
|
2016-11-21 00:56:51 +00:00
|
|
|
ty: struct_type,
|
2017-08-07 05:54:09 +00:00
|
|
|
variant,
|
|
|
|
span,
|
2015-04-29 06:14:37 +00:00
|
|
|
})
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
// Tuples
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Creates MemberDescriptions for the fields of a tuple
|
|
|
|
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> {
|
2018-07-04 13:36:49 +00:00
|
|
|
fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
|
2018-10-09 13:13:11 +00:00
|
|
|
-> Vec<MemberDescription<'ll>> {
|
2016-11-21 00:56:51 +00:00
|
|
|
let layout = cx.layout_of(self.ty);
|
2017-06-01 18:50:53 +00:00
|
|
|
self.component_types.iter().enumerate().map(|(i, &component_type)| {
|
|
|
|
let (size, align) = cx.size_and_align_of(component_type);
|
2015-04-29 06:14:37 +00:00
|
|
|
MemberDescription {
|
|
|
|
name: format!("__{}", i),
|
|
|
|
type_metadata: type_metadata(cx, component_type, self.span),
|
2017-09-17 20:37:18 +00:00
|
|
|
offset: layout.fields.offset(i),
|
2017-06-01 18:50:53 +00:00
|
|
|
size,
|
|
|
|
align,
|
2016-11-18 22:15:14 +00:00
|
|
|
flags: DIFlags::FlagZero,
|
2017-11-29 21:42:25 +00:00
|
|
|
discriminant: None,
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
}).collect()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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,
|
|
|
|
) -> RecursiveTypeDescription<'ll, 'tcx> {
|
2015-04-29 06:14:37 +00:00
|
|
|
let tuple_name = compute_debuginfo_type_name(cx, tuple_type, false);
|
|
|
|
|
2017-11-29 21:42:25 +00:00
|
|
|
let struct_stub = create_struct_stub(cx,
|
|
|
|
tuple_type,
|
|
|
|
&tuple_name[..],
|
|
|
|
unique_type_id,
|
|
|
|
NO_SCOPE_METADATA);
|
|
|
|
|
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,
|
2015-04-29 06:14:37 +00:00
|
|
|
})
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2016-08-22 18:11:22 +00:00
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
// Unions
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
struct UnionMemberDescriptionFactory<'tcx> {
|
2017-09-21 17:40:50 +00:00
|
|
|
layout: TyLayout<'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> {
|
2018-07-04 13:36:49 +00:00
|
|
|
fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
|
2018-10-09 13:13:11 +00:00
|
|
|
-> Vec<MemberDescription<'ll>> {
|
2017-06-25 09:41:24 +00:00
|
|
|
self.variant.fields.iter().enumerate().map(|(i, f)| {
|
|
|
|
let field = self.layout.field(cx, i);
|
2016-08-22 18:11:22 +00:00
|
|
|
MemberDescription {
|
2018-05-25 23:50:15 +00:00
|
|
|
name: f.ident.to_string(),
|
2017-06-25 09:41:24 +00:00
|
|
|
type_metadata: type_metadata(cx, field.ty, self.span),
|
2018-05-20 12:14:39 +00:00
|
|
|
offset: Size::ZERO,
|
2018-09-08 19:14:55 +00:00
|
|
|
size: field.size,
|
2018-09-08 22:16:45 +00:00
|
|
|
align: field.align.abi,
|
2016-11-18 22:15:14 +00:00
|
|
|
flags: DIFlags::FlagZero,
|
2017-11-29 21:42:25 +00:00
|
|
|
discriminant: None,
|
2016-08-22 18:11:22 +00:00
|
|
|
}
|
|
|
|
}).collect()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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> {
|
2016-08-22 18:11:22 +00:00
|
|
|
let union_name = compute_debuginfo_type_name(cx, union_type, false);
|
|
|
|
|
2017-06-25 09:41:24 +00:00
|
|
|
let (union_def_id, variant) = match union_type.sty {
|
2018-08-22 00:35:02 +00:00
|
|
|
ty::Adt(def, _) => (def.did, def.non_enum_variant()),
|
2016-09-05 22:26:02 +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
|
|
|
|
|
|
|
let union_metadata_stub = create_union_stub(cx,
|
2017-06-01 18:50:53 +00:00
|
|
|
union_type,
|
2016-08-22 18:11:22 +00:00
|
|
|
&union_name,
|
|
|
|
unique_type_id,
|
|
|
|
containing_scope);
|
|
|
|
|
|
|
|
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,
|
2016-08-22 18:11:22 +00:00
|
|
|
UnionMDF(UnionMemberDescriptionFactory {
|
2017-06-25 09:41:24 +00:00
|
|
|
layout: cx.layout_of(union_type),
|
2017-08-07 05:54:09 +00:00
|
|
|
variant,
|
|
|
|
span,
|
2016-08-22 18:11:22 +00:00
|
|
|
})
|
|
|
|
)
|
|
|
|
}
|
2015-04-29 06:14:37 +00:00
|
|
|
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
// Enums
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
|
2019-03-22 22:08:06 +00:00
|
|
|
// DWARF variant support is only available starting in LLVM 8.
|
2017-11-29 21:42:25 +00:00
|
|
|
// Although the earlier enum debug info output did not work properly
|
|
|
|
// in all situations, it is better for the time being to continue to
|
|
|
|
// sometimes emit the old style rather than emit something completely
|
2019-03-22 22:08:06 +00:00
|
|
|
// useless when rust is compiled against LLVM 6 or older. LLVM 7
|
|
|
|
// contains an early version of the DWARF variant support, and will
|
|
|
|
// crash when handling the new debug info format. This function
|
|
|
|
// decides which representation will be emitted.
|
2019-02-25 07:40:18 +00:00
|
|
|
fn use_enum_fallback(cx: &CodegenCx<'_, '_>) -> bool {
|
2017-11-29 21:42:25 +00:00
|
|
|
// On MSVC we have to use the fallback mode, because LLVM doesn't
|
|
|
|
// lower variant parts to PDB.
|
2018-11-03 14:48:29 +00:00
|
|
|
return cx.sess().target.target.options.is_like_msvc
|
2019-01-22 18:13:53 +00:00
|
|
|
// LLVM version 7 did not release with an important bug fix;
|
2019-01-22 18:44:23 +00:00
|
|
|
// but the required patch is in the LLVM 8. Rust LLVM reports
|
|
|
|
// 8 as well.
|
|
|
|
|| llvm_util::get_major_version() < 8;
|
2017-11-29 21:42:25 +00:00
|
|
|
}
|
|
|
|
|
2015-04-29 06:14:37 +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>,
|
2017-09-22 22:54:45 +00:00
|
|
|
layout: TyLayout<'tcx>,
|
2018-07-04 13:36:49 +00:00
|
|
|
discriminant_type_metadata: Option<&'ll DIType>,
|
|
|
|
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> {
|
|
|
|
fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
|
2018-10-09 13:13:11 +00:00
|
|
|
-> Vec<MemberDescription<'ll>> {
|
2015-08-02 19:52:50 +00:00
|
|
|
let adt = &self.enum_type.ty_adt_def().unwrap();
|
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)
|
|
|
|
};
|
|
|
|
|
2017-09-22 22:54:45 +00:00
|
|
|
match self.layout.variants {
|
2017-09-26 18:34:10 +00:00
|
|
|
layout::Variants::Single { .. } if adt.variants.is_empty() => vec![],
|
|
|
|
layout::Variants::Single { index } => {
|
|
|
|
let (variant_type_metadata, member_description_factory) =
|
|
|
|
describe_enum_variant(cx,
|
|
|
|
self.layout,
|
|
|
|
&adt.variants[index],
|
|
|
|
NoDiscriminant,
|
2017-11-29 21:42:25 +00:00
|
|
|
self_metadata,
|
2017-09-26 18:34:10 +00:00
|
|
|
self.span);
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2017-09-26 18:34:10 +00:00
|
|
|
let member_descriptions =
|
|
|
|
member_description_factory.create_member_descriptions(cx);
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2017-09-26 18:34:10 +00:00
|
|
|
set_members_of_composite_type(cx,
|
2018-10-12 13:34:14 +00:00
|
|
|
self.enum_type,
|
2017-09-26 18:34:10 +00:00
|
|
|
variant_type_metadata,
|
2018-08-07 14:04:34 +00:00
|
|
|
member_descriptions);
|
2017-09-26 18:34:10 +00:00
|
|
|
vec![
|
|
|
|
MemberDescription {
|
2017-11-29 21:42:25 +00:00
|
|
|
name: if fallback {
|
|
|
|
String::new()
|
|
|
|
} else {
|
2018-12-01 02:47:08 +00:00
|
|
|
adt.variants[index].ident.as_str().to_string()
|
2017-11-29 21:42:25 +00:00
|
|
|
},
|
2017-09-26 18:34:10 +00:00
|
|
|
type_metadata: variant_type_metadata,
|
2018-05-20 12:14:39 +00:00
|
|
|
offset: Size::ZERO,
|
2017-09-26 18:34:10 +00:00
|
|
|
size: self.layout.size,
|
2018-09-08 22:16:45 +00:00
|
|
|
align: self.layout.align.abi,
|
2017-11-29 21:42:25 +00:00
|
|
|
flags: DIFlags::FlagZero,
|
|
|
|
discriminant: None,
|
2017-09-26 18:34:10 +00:00
|
|
|
}
|
|
|
|
]
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
2019-03-29 05:44:54 +00:00
|
|
|
layout::Variants::Multiple {
|
|
|
|
discr_kind: layout::DiscriminantKind::Tag,
|
2019-04-02 22:57:50 +00:00
|
|
|
discr_index,
|
2019-03-29 05:44:54 +00:00
|
|
|
ref variants,
|
|
|
|
..
|
|
|
|
} => {
|
2017-11-29 21:42:25 +00:00
|
|
|
let discriminant_info = if fallback {
|
2019-04-02 22:57:50 +00:00
|
|
|
RegularDiscriminant {
|
|
|
|
discr_field: Field::from(discr_index),
|
|
|
|
discr_type_metadata: self.discriminant_type_metadata.unwrap()
|
|
|
|
}
|
2017-11-29 21:42:25 +00:00
|
|
|
} else {
|
|
|
|
// This doesn't matter in this case.
|
|
|
|
NoDiscriminant
|
|
|
|
};
|
2018-11-01 18:03:38 +00:00
|
|
|
variants.iter_enumerated().map(|(i, _)| {
|
2017-09-26 18:34:10 +00:00
|
|
|
let variant = self.layout.for_variant(cx, i);
|
2017-09-22 22:54:45 +00:00
|
|
|
let (variant_type_metadata, member_desc_factory) =
|
|
|
|
describe_enum_variant(cx,
|
|
|
|
variant,
|
|
|
|
&adt.variants[i],
|
|
|
|
discriminant_info,
|
2017-11-29 21:42:25 +00:00
|
|
|
self_metadata,
|
2017-09-22 22:54:45 +00:00
|
|
|
self.span);
|
|
|
|
|
|
|
|
let member_descriptions = member_desc_factory
|
|
|
|
.create_member_descriptions(cx);
|
|
|
|
|
|
|
|
set_members_of_composite_type(cx,
|
2018-10-12 13:34:14 +00:00
|
|
|
self.enum_type,
|
2017-09-22 22:54:45 +00:00
|
|
|
variant_type_metadata,
|
2018-08-07 14:04:34 +00:00
|
|
|
member_descriptions);
|
2017-09-22 22:54:45 +00:00
|
|
|
MemberDescription {
|
2017-11-29 21:42:25 +00:00
|
|
|
name: if fallback {
|
|
|
|
String::new()
|
|
|
|
} else {
|
2018-12-01 02:47:08 +00:00
|
|
|
adt.variants[i].ident.as_str().to_string()
|
2017-11-29 21:42:25 +00:00
|
|
|
},
|
2017-09-22 22:54:45 +00:00
|
|
|
type_metadata: variant_type_metadata,
|
2018-05-20 12:14:39 +00:00
|
|
|
offset: Size::ZERO,
|
2017-11-29 21:42:25 +00:00
|
|
|
size: self.layout.size,
|
2018-09-08 22:16:45 +00:00
|
|
|
align: self.layout.align.abi,
|
2017-11-29 21:42:25 +00:00
|
|
|
flags: DIFlags::FlagZero,
|
|
|
|
discriminant: Some(self.layout.ty.ty_adt_def().unwrap()
|
|
|
|
.discriminant_for_variant(cx.tcx, i)
|
|
|
|
.val as u64),
|
2017-09-22 22:54:45 +00:00
|
|
|
}
|
|
|
|
}).collect()
|
|
|
|
}
|
2019-03-29 05:44:54 +00:00
|
|
|
layout::Variants::Multiple {
|
|
|
|
discr_kind: layout::DiscriminantKind::Niche {
|
|
|
|
ref niche_variants,
|
|
|
|
niche_start,
|
|
|
|
dataful_variant,
|
|
|
|
},
|
|
|
|
ref discr,
|
2017-11-29 21:42:25 +00:00
|
|
|
ref variants,
|
2019-04-02 22:57:50 +00:00
|
|
|
discr_index,
|
2017-11-29 21:42:25 +00:00
|
|
|
} => {
|
|
|
|
if fallback {
|
|
|
|
let variant = self.layout.for_variant(cx, dataful_variant);
|
|
|
|
// Create a description of the non-null variant
|
|
|
|
let (variant_type_metadata, member_description_factory) =
|
|
|
|
describe_enum_variant(cx,
|
|
|
|
variant,
|
|
|
|
&adt.variants[dataful_variant],
|
|
|
|
OptimizedDiscriminant,
|
|
|
|
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
|
|
|
|
2017-11-29 21:42:25 +00:00
|
|
|
set_members_of_composite_type(cx,
|
2018-10-12 13:34:14 +00:00
|
|
|
self.enum_type,
|
2017-11-29 21:42:25 +00:00
|
|
|
variant_type_metadata,
|
|
|
|
variant_member_descriptions);
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
fn compute_field_path<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
|
|
|
name: &mut String,
|
|
|
|
layout: TyLayout<'tcx>,
|
|
|
|
offset: Size,
|
|
|
|
size: Size) {
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
2017-11-29 21:42:25 +00:00
|
|
|
compute_field_path(cx, &mut name,
|
|
|
|
self.layout,
|
2019-04-02 22:57:50 +00:00
|
|
|
self.layout.fields.offset(discr_index),
|
|
|
|
self.layout.field(cx, discr_index).size);
|
2018-12-01 02:47:08 +00:00
|
|
|
name.push_str(&adt.variants[*niche_variants.start()].ident.as_str());
|
2017-11-29 21:42:25 +00:00
|
|
|
|
|
|
|
// Create the (singleton) list of descriptions of union members.
|
|
|
|
vec![
|
|
|
|
MemberDescription {
|
|
|
|
name,
|
|
|
|
type_metadata: variant_type_metadata,
|
|
|
|
offset: Size::ZERO,
|
|
|
|
size: variant.size,
|
2018-09-08 22:16:45 +00:00
|
|
|
align: variant.align.abi,
|
2017-11-29 21:42:25 +00:00
|
|
|
flags: DIFlags::FlagZero,
|
|
|
|
discriminant: None,
|
|
|
|
}
|
|
|
|
]
|
|
|
|
} else {
|
2018-11-01 18:03:38 +00:00
|
|
|
variants.iter_enumerated().map(|(i, _)| {
|
2017-11-29 21:42:25 +00:00
|
|
|
let variant = self.layout.for_variant(cx, i);
|
|
|
|
let (variant_type_metadata, member_desc_factory) =
|
|
|
|
describe_enum_variant(cx,
|
|
|
|
variant,
|
|
|
|
&adt.variants[i],
|
|
|
|
OptimizedDiscriminant,
|
|
|
|
self_metadata,
|
|
|
|
self.span);
|
|
|
|
|
|
|
|
let member_descriptions = member_desc_factory
|
|
|
|
.create_member_descriptions(cx);
|
|
|
|
|
|
|
|
set_members_of_composite_type(cx,
|
2018-10-12 13:34:14 +00:00
|
|
|
self.enum_type,
|
2017-11-29 21:42:25 +00:00
|
|
|
variant_type_metadata,
|
|
|
|
member_descriptions);
|
|
|
|
|
|
|
|
let niche_value = if i == dataful_variant {
|
|
|
|
None
|
|
|
|
} else {
|
2018-11-01 18:03:38 +00:00
|
|
|
let value = (i.as_u32() as u128)
|
|
|
|
.wrapping_sub(niche_variants.start().as_u32() as u128)
|
2018-09-13 12:51:17 +00:00
|
|
|
.wrapping_add(niche_start);
|
2019-03-29 05:44:54 +00:00
|
|
|
let value = truncate(value, discr.value.size(cx));
|
|
|
|
// 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);
|
2018-11-05 15:37:00 +00:00
|
|
|
Some(value as u64)
|
2017-11-29 21:42:25 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
MemberDescription {
|
2018-12-01 02:47:08 +00:00
|
|
|
name: adt.variants[i].ident.as_str().to_string(),
|
2017-11-29 21:42:25 +00:00
|
|
|
type_metadata: variant_type_metadata,
|
|
|
|
offset: Size::ZERO,
|
|
|
|
size: self.layout.size,
|
2018-09-08 22:16:45 +00:00
|
|
|
align: self.layout.align.abi,
|
2017-11-29 21:42:25 +00:00
|
|
|
flags: DIFlags::FlagZero,
|
|
|
|
discriminant: niche_value,
|
|
|
|
}
|
|
|
|
}).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
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Creates MemberDescriptions for the fields of a single enum variant.
|
2018-07-04 13:36:49 +00:00
|
|
|
struct VariantMemberDescriptionFactory<'ll, 'tcx> {
|
2016-11-21 00:56:51 +00:00
|
|
|
// Cloned from the layout::Struct describing the variant.
|
2017-09-10 14:15:29 +00:00
|
|
|
offsets: Vec<layout::Size>,
|
2015-04-29 06:14:37 +00:00
|
|
|
args: Vec<(String, Ty<'tcx>)>,
|
2018-07-04 13:36:49 +00:00
|
|
|
discriminant_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> {
|
|
|
|
fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
|
|
|
|
-> Vec<MemberDescription<'ll>> {
|
2015-04-29 06:14:37 +00:00
|
|
|
self.args.iter().enumerate().map(|(i, &(ref name, ty))| {
|
2017-06-01 18:50:53 +00:00
|
|
|
let (size, align) = cx.size_and_align_of(ty);
|
2015-04-29 06:14:37 +00:00
|
|
|
MemberDescription {
|
|
|
|
name: name.to_string(),
|
2017-11-29 21:42:25 +00:00
|
|
|
type_metadata: if use_enum_fallback(cx) {
|
|
|
|
match self.discriminant_type_metadata {
|
2019-04-02 22:57:50 +00:00
|
|
|
// Discriminant is always the first field of our variant
|
|
|
|
// when using the enum fallback.
|
2017-11-29 21:42:25 +00:00
|
|
|
Some(metadata) if i == 0 => metadata,
|
|
|
|
_ => type_metadata(cx, ty, self.span)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
type_metadata(cx, ty, self.span)
|
2015-04-29 06:14:37 +00:00
|
|
|
},
|
2017-06-01 18:50:53 +00:00
|
|
|
offset: self.offsets[i],
|
|
|
|
size,
|
|
|
|
align,
|
2017-11-29 21:42:25 +00:00
|
|
|
flags: DIFlags::FlagZero,
|
|
|
|
discriminant: None,
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
}).collect()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Copy, Clone)]
|
2018-07-04 13:36:49 +00:00
|
|
|
enum EnumDiscriminantInfo<'ll> {
|
2019-04-02 22:57:50 +00:00
|
|
|
RegularDiscriminant{ discr_field: Field, discr_type_metadata: &'ll DIType },
|
2015-04-29 06:14:37 +00:00
|
|
|
OptimizedDiscriminant,
|
|
|
|
NoDiscriminant
|
|
|
|
}
|
|
|
|
|
2017-11-29 21:42:25 +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>,
|
|
|
|
layout: layout::TyLayout<'tcx>,
|
|
|
|
variant: &'tcx ty::VariantDef,
|
|
|
|
discriminant_info: EnumDiscriminantInfo<'ll>,
|
|
|
|
containing_scope: &'ll DIScope,
|
|
|
|
span: Span,
|
|
|
|
) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) {
|
2018-12-01 02:47:08 +00:00
|
|
|
let variant_name = variant.ident.as_str();
|
2015-04-29 06:14:37 +00:00
|
|
|
let unique_type_id = debug_context(cx).type_map
|
|
|
|
.borrow_mut()
|
|
|
|
.get_unique_type_id_of_enum_variant(
|
|
|
|
cx,
|
2017-09-17 16:34:28 +00:00
|
|
|
layout.ty,
|
2015-07-28 16:07:20 +00:00
|
|
|
&variant_name);
|
2015-04-29 06:14:37 +00:00
|
|
|
|
|
|
|
let metadata_stub = create_struct_stub(cx,
|
2017-09-17 16:34:28 +00:00
|
|
|
layout.ty,
|
2015-07-28 16:07:20 +00:00
|
|
|
&variant_name,
|
2015-04-29 06:14:37 +00:00
|
|
|
unique_type_id,
|
2018-07-04 13:36:49 +00:00
|
|
|
Some(containing_scope));
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2019-04-02 20:51:13 +00:00
|
|
|
let arg_name = |i: usize| {
|
|
|
|
if variant.ctor_kind == CtorKind::Fn {
|
|
|
|
format!("__{}", i)
|
|
|
|
} else {
|
|
|
|
variant.fields[i].ident.to_string()
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
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 {
|
2019-04-02 22:57:50 +00:00
|
|
|
RegularDiscriminant { discr_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);
|
2019-04-02 22:57:50 +00:00
|
|
|
let offset = enum_layout.fields.offset(discr_field.as_usize());
|
|
|
|
let args = (
|
|
|
|
"RUST$ENUM$DISR".to_owned(),
|
|
|
|
enum_layout.field(cx, discr_field.as_usize()).ty);
|
|
|
|
(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
|
|
|
(
|
|
|
|
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| {
|
2019-04-02 20:51:13 +00:00
|
|
|
(arg_name(i), layout.field(cx, i).ty)
|
2017-11-29 21:42:25 +00:00
|
|
|
})).collect()
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
(
|
|
|
|
(0..layout.fields.count()).map(|i| {
|
|
|
|
layout.fields.offset(i)
|
|
|
|
}).collect(),
|
|
|
|
(0..layout.fields.count()).map(|i| {
|
2019-04-02 20:51:13 +00:00
|
|
|
(arg_name(i), layout.field(cx, i).ty)
|
2017-11-29 21:42:25 +00:00
|
|
|
}).collect()
|
|
|
|
)
|
|
|
|
};
|
2015-04-29 06:14:37 +00:00
|
|
|
|
|
|
|
let member_description_factory =
|
|
|
|
VariantMDF(VariantMemberDescriptionFactory {
|
2017-09-10 14:15:29 +00:00
|
|
|
offsets,
|
2017-08-07 05:54:09 +00:00
|
|
|
args,
|
2015-04-29 06:14:37 +00:00
|
|
|
discriminant_type_metadata: match discriminant_info {
|
2019-04-02 22:57:50 +00:00
|
|
|
RegularDiscriminant { discr_type_metadata, .. } => {
|
|
|
|
Some(discr_type_metadata)
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
_ => None
|
|
|
|
},
|
2017-08-07 05:54:09 +00:00
|
|
|
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,
|
|
|
|
) -> RecursiveTypeDescription<'ll, 'tcx> {
|
2015-04-29 06:14:37 +00:00
|
|
|
let enum_name = compute_debuginfo_type_name(cx, enum_type, false);
|
|
|
|
|
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
|
|
|
|
2017-09-16 13:39:53 +00:00
|
|
|
let discriminant_type_metadata = |discr: layout::Primitive| {
|
2017-11-29 21:42:25 +00:00
|
|
|
let def = enum_type.ty_adt_def().unwrap();
|
|
|
|
let enumerators_metadata: Vec<_> = def.discriminants(cx.tcx)
|
|
|
|
.zip(&def.variants)
|
2018-11-01 18:03:38 +00:00
|
|
|
.map(|((_, discr), v)| {
|
2018-12-01 02:47:08 +00:00
|
|
|
let name = SmallCStr::new(&v.ident.as_str());
|
2017-11-29 21:42:25 +00:00
|
|
|
unsafe {
|
|
|
|
Some(llvm::LLVMRustDIBuilderCreateEnumerator(
|
|
|
|
DIB(cx),
|
|
|
|
name.as_ptr(),
|
|
|
|
// FIXME: what if enumeration has i128 discriminant?
|
|
|
|
discr.val as u64))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
|
2017-09-16 09:23:22 +00:00
|
|
|
let disr_type_key = (enum_def_id, discr);
|
2015-04-29 06:14:37 +00:00
|
|
|
let cached_discriminant_type_metadata = debug_context(cx).created_enum_disr_types
|
|
|
|
.borrow()
|
2015-07-16 08:34:13 +00:00
|
|
|
.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 => {
|
|
|
|
let (discriminant_size, discriminant_align) =
|
2017-09-16 09:23:22 +00:00
|
|
|
(discr.size(cx), discr.align(cx));
|
2015-04-29 06:14:37 +00:00
|
|
|
let discriminant_base_type_metadata =
|
2018-01-05 04:58:34 +00:00
|
|
|
type_metadata(cx, discr.to_ty(cx.tcx), syntax_pos::DUMMY_SP);
|
2018-04-11 21:02:41 +00:00
|
|
|
let discriminant_name = get_enum_discriminant_name(cx, enum_def_id).as_str();
|
2015-04-29 06:14:37 +00:00
|
|
|
|
2018-08-07 14:04:34 +00:00
|
|
|
let name = SmallCStr::new(&discriminant_name);
|
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,
|
|
|
|
name.as_ptr(),
|
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),
|
2017-11-29 21:42:25 +00:00
|
|
|
discriminant_base_type_metadata, true)
|
2015-04-29 06:14:37 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
debug_context(cx).created_enum_disr_types
|
|
|
|
.borrow_mut()
|
2015-07-16 08:34:13 +00:00
|
|
|
.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
|
|
|
|
2017-11-29 21:42:25 +00:00
|
|
|
match (&layout.abi, &layout.variants) {
|
2019-03-29 05:44:54 +00:00
|
|
|
(&layout::Abi::Scalar(_), &layout::Variants::Multiple {
|
|
|
|
discr_kind: layout::DiscriminantKind::Tag,
|
|
|
|
ref discr,
|
|
|
|
..
|
|
|
|
}) => return FinalMetadata(discriminant_type_metadata(discr.value)),
|
2017-11-29 21:42:25 +00:00
|
|
|
_ => {}
|
2017-09-16 20:12:39 +00:00
|
|
|
}
|
|
|
|
|
2018-08-07 14:04:34 +00:00
|
|
|
let enum_name = SmallCStr::new(&enum_name);
|
|
|
|
let unique_type_id_str = SmallCStr::new(
|
|
|
|
debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id)
|
|
|
|
);
|
2017-11-29 21:42:25 +00:00
|
|
|
|
|
|
|
if use_enum_fallback(cx) {
|
|
|
|
let discriminant_type_metadata = match layout.variants {
|
|
|
|
layout::Variants::Single { .. } |
|
2019-03-29 05:44:54 +00:00
|
|
|
layout::Variants::Multiple {
|
|
|
|
discr_kind: layout::DiscriminantKind::Niche { .. },
|
|
|
|
..
|
|
|
|
} => None,
|
|
|
|
layout::Variants::Multiple {
|
|
|
|
discr_kind: layout::DiscriminantKind::Tag,
|
|
|
|
ref discr,
|
|
|
|
..
|
|
|
|
} => {
|
|
|
|
Some(discriminant_type_metadata(discr.value))
|
2017-11-29 21:42:25 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let enum_metadata = unsafe {
|
|
|
|
llvm::LLVMRustDIBuilderCreateUnionType(
|
|
|
|
DIB(cx),
|
|
|
|
containing_scope,
|
|
|
|
enum_name.as_ptr(),
|
|
|
|
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,
|
2017-11-29 21:42:25 +00:00
|
|
|
DIFlags::FlagZero,
|
|
|
|
None,
|
|
|
|
0, // RuntimeLang
|
|
|
|
unique_type_id_str.as_ptr())
|
|
|
|
};
|
|
|
|
|
|
|
|
return create_and_register_recursive_type_forward_declaration(
|
|
|
|
cx,
|
|
|
|
enum_type,
|
|
|
|
unique_type_id,
|
|
|
|
enum_metadata,
|
|
|
|
enum_metadata,
|
|
|
|
EnumMDF(EnumMemberDescriptionFactory {
|
|
|
|
enum_type,
|
|
|
|
layout,
|
|
|
|
discriminant_type_metadata,
|
|
|
|
containing_scope,
|
|
|
|
span,
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
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.
|
2019-03-29 05:44:54 +00:00
|
|
|
layout::Variants::Single { .. } => None,
|
2017-11-29 21:42:25 +00:00
|
|
|
|
2019-03-29 05:44:54 +00:00
|
|
|
layout::Variants::Multiple {
|
|
|
|
discr_kind: layout::DiscriminantKind::Niche { .. },
|
|
|
|
ref discr,
|
2019-04-02 22:57:50 +00:00
|
|
|
discr_index,
|
2019-03-29 05:44:54 +00:00
|
|
|
..
|
|
|
|
} => {
|
2017-11-29 21:42:25 +00:00
|
|
|
// Find the integer type of the correct size.
|
2019-03-29 05:44:54 +00:00
|
|
|
let size = discr.value.size(cx);
|
|
|
|
let align = discr.value.align(cx);
|
2018-09-07 15:29:40 +00:00
|
|
|
|
2019-03-29 05:44:54 +00:00
|
|
|
let discr_type = match discr.value {
|
2018-09-07 15:29:40 +00:00
|
|
|
layout::Int(t, _) => t,
|
|
|
|
layout::Float(layout::FloatTy::F32) => Integer::I32,
|
|
|
|
layout::Float(layout::FloatTy::F64) => Integer::I64,
|
|
|
|
layout::Pointer => cx.data_layout().ptr_sized_integer(),
|
|
|
|
}.to_ty(cx.tcx, false);
|
2017-11-29 21:42:25 +00:00
|
|
|
|
|
|
|
let discr_metadata = basic_type_metadata(cx, discr_type);
|
|
|
|
unsafe {
|
|
|
|
Some(llvm::LLVMRustDIBuilderCreateMemberType(
|
|
|
|
DIB(cx),
|
|
|
|
containing_scope,
|
|
|
|
ptr::null_mut(),
|
|
|
|
file_metadata,
|
|
|
|
UNKNOWN_LINE_NUMBER,
|
|
|
|
size.bits(),
|
2018-09-08 21:22:22 +00:00
|
|
|
align.abi.bits() as u32,
|
2019-04-02 22:57:50 +00:00
|
|
|
layout.fields.offset(discr_index).bits(),
|
2017-11-29 21:42:25 +00:00
|
|
|
DIFlags::FlagArtificial,
|
|
|
|
discr_metadata))
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2019-03-29 05:44:54 +00:00
|
|
|
layout::Variants::Multiple {
|
|
|
|
discr_kind: layout::DiscriminantKind::Tag,
|
|
|
|
ref discr,
|
2019-04-02 22:57:50 +00:00
|
|
|
discr_index,
|
2019-03-29 05:44:54 +00:00
|
|
|
..
|
|
|
|
} => {
|
|
|
|
let discr_type = discr.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,
|
|
|
|
ptr::null_mut(),
|
|
|
|
file_metadata,
|
|
|
|
UNKNOWN_LINE_NUMBER,
|
|
|
|
size.bits(),
|
2018-09-08 22:16:45 +00:00
|
|
|
align.bits() as u32,
|
2019-04-02 22:57:50 +00:00
|
|
|
layout.fields.offset(discr_index).bits(),
|
2017-11-29 21:42:25 +00:00
|
|
|
DIFlags::FlagArtificial,
|
|
|
|
discr_metadata))
|
|
|
|
}
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2019-03-27 05:22:37 +00:00
|
|
|
let variant_part_unique_type_id_str = SmallCStr::new(
|
|
|
|
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), &[]);
|
|
|
|
let variant_part = unsafe {
|
|
|
|
llvm::LLVMRustDIBuilderCreateVariantPart(
|
|
|
|
DIB(cx),
|
|
|
|
containing_scope,
|
|
|
|
ptr::null_mut(),
|
|
|
|
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,
|
2017-11-29 21:42:25 +00:00
|
|
|
DIFlags::FlagZero,
|
|
|
|
discriminator_metadata,
|
|
|
|
empty_array,
|
2019-03-27 05:22:37 +00:00
|
|
|
variant_part_unique_type_id_str.as_ptr())
|
2017-11-29 21:42:25 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// The variant part must be wrapped in a struct according to DWARF.
|
|
|
|
let type_array = create_DIArray(DIB(cx), &[Some(variant_part)]);
|
|
|
|
let struct_wrapper = unsafe {
|
|
|
|
llvm::LLVMRustDIBuilderCreateStructType(
|
|
|
|
DIB(cx),
|
|
|
|
Some(containing_scope),
|
|
|
|
enum_name.as_ptr(),
|
|
|
|
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,
|
2017-11-29 21:42:25 +00:00
|
|
|
DIFlags::FlagZero,
|
|
|
|
None,
|
|
|
|
type_array,
|
|
|
|
0,
|
|
|
|
None,
|
|
|
|
unique_type_id_str.as_ptr())
|
2015-04-29 06:14:37 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
return create_and_register_recursive_type_forward_declaration(
|
|
|
|
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,
|
2017-11-29 21:42:25 +00:00
|
|
|
discriminant_type_metadata: None,
|
2017-08-07 05:54:09 +00:00
|
|
|
containing_scope,
|
|
|
|
span,
|
2015-04-29 06:14:37 +00:00
|
|
|
}),
|
|
|
|
);
|
|
|
|
|
2019-02-25 07:40:18 +00:00
|
|
|
fn get_enum_discriminant_name(cx: &CodegenCx<'_, '_>,
|
2015-08-16 10:32:28 +00:00
|
|
|
def_id: DefId)
|
2016-11-16 08:21:52 +00:00
|
|
|
-> InternedString {
|
2018-01-05 04:58:34 +00:00
|
|
|
cx.tcx.item_name(def_id)
|
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 ...
|
|
|
|
let composite_type_metadata = create_struct_stub(cx,
|
2017-06-01 18:50:53 +00:00
|
|
|
composite_type,
|
2015-04-29 06:14:37 +00:00
|
|
|
composite_type_name,
|
|
|
|
composite_type_unique_id,
|
|
|
|
containing_scope);
|
|
|
|
// ... and immediately create and add the member descriptions.
|
|
|
|
set_members_of_composite_type(cx,
|
2018-10-12 13:34:14 +00:00
|
|
|
composite_type,
|
2015-04-29 06:14:37 +00:00
|
|
|
composite_type_metadata,
|
|
|
|
member_descriptions);
|
|
|
|
|
2018-10-09 13:14:38 +00:00
|
|
|
composite_type_metadata
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
|
2018-10-12 13:34:14 +00:00
|
|
|
fn set_members_of_composite_type(cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
composite_type: Ty<'tcx>,
|
2018-07-04 13:36:49 +00:00
|
|
|
composite_type_metadata: &'ll DICompositeType,
|
2018-08-07 14:04:34 +00:00
|
|
|
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();
|
|
|
|
if composite_types_completed.contains(&composite_type_metadata) {
|
2016-03-28 23:46:02 +00:00
|
|
|
bug!("debuginfo::set_members_of_composite_type() - \
|
|
|
|
Already completed forward declaration re-encountered.");
|
2015-04-29 06:14:37 +00:00
|
|
|
} else {
|
|
|
|
composite_types_completed.insert(composite_type_metadata);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-27 10:12:47 +00:00
|
|
|
let member_metadata: Vec<_> = member_descriptions
|
2018-08-07 14:04:34 +00:00
|
|
|
.into_iter()
|
2017-06-01 18:50:53 +00:00
|
|
|
.map(|member_description| {
|
2018-08-07 14:04:34 +00:00
|
|
|
let member_name = CString::new(member_description.name).unwrap();
|
2015-04-29 06:14:37 +00:00
|
|
|
unsafe {
|
2017-11-29 21:42:25 +00:00
|
|
|
Some(llvm::LLVMRustDIBuilderCreateVariantMemberType(
|
2015-04-29 06:14:37 +00:00
|
|
|
DIB(cx),
|
|
|
|
composite_type_metadata,
|
|
|
|
member_name.as_ptr(),
|
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
|
|
|
member_description.size.bits(),
|
2018-09-08 22:16:45 +00:00
|
|
|
member_description.align.bits() as u32,
|
2017-06-01 18:50:53 +00:00
|
|
|
member_description.offset.bits(),
|
2017-11-29 21:42:25 +00:00
|
|
|
match member_description.discriminant {
|
|
|
|
None => None,
|
2018-09-06 18:57:42 +00:00
|
|
|
Some(value) => Some(cx.const_u64(value)),
|
2017-11-29 21:42:25 +00:00
|
|
|
},
|
2015-04-29 06:14:37 +00:00
|
|
|
member_description.flags,
|
2018-06-27 10:12:47 +00:00
|
|
|
member_description.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(
|
|
|
|
DIB(cx), composite_type_metadata, Some(type_array), type_params);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compute the type parameters for a type, if any, for the given
|
|
|
|
// metadata.
|
|
|
|
fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> Option<&'ll DIArray> {
|
|
|
|
if let ty::Adt(def, substs) = ty.sty {
|
|
|
|
if !substs.types().next().is_none() {
|
|
|
|
let generics = cx.tcx.generics_of(def.did);
|
|
|
|
let names = get_parameter_names(cx, generics);
|
|
|
|
let template_params: Vec<_> = substs.iter().zip(names).filter_map(|(kind, name)| {
|
|
|
|
if let UnpackedKind::Type(ty) = kind.unpack() {
|
|
|
|
let actual_type = cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
|
|
|
|
let actual_type_metadata =
|
|
|
|
type_metadata(cx, actual_type, syntax_pos::DUMMY_SP);
|
|
|
|
let name = SmallCStr::new(&name.as_str());
|
|
|
|
Some(unsafe {
|
|
|
|
|
|
|
|
Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
|
|
|
|
DIB(cx),
|
|
|
|
None,
|
|
|
|
name.as_ptr(),
|
|
|
|
actual_type_metadata,
|
|
|
|
unknown_file_metadata(cx),
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
))
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}).collect();
|
|
|
|
|
|
|
|
return Some(create_DIArray(DIB(cx), &template_params[..]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Some(create_DIArray(DIB(cx), &[]));
|
|
|
|
|
2019-02-25 07:40:18 +00:00
|
|
|
fn get_parameter_names(cx: &CodegenCx<'_, '_>,
|
2018-10-12 13:34:14 +00:00
|
|
|
generics: &ty::Generics)
|
|
|
|
-> Vec<InternedString> {
|
|
|
|
let mut names = generics.parent.map_or(vec![], |def_id| {
|
|
|
|
get_parameter_names(cx, cx.tcx.generics_of(def_id))
|
|
|
|
});
|
|
|
|
names.extend(generics.params.iter().map(|param| param.name));
|
|
|
|
names
|
2015-04-29 06:14:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-01 23:35:09 +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>,
|
|
|
|
) -> &'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
|
|
|
|
2018-08-07 14:04:34 +00:00
|
|
|
let name = SmallCStr::new(struct_type_name);
|
|
|
|
let unique_type_id = SmallCStr::new(
|
|
|
|
debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id)
|
|
|
|
);
|
2015-04-29 06:14:37 +00:00
|
|
|
let metadata_stub = unsafe {
|
2016-08-01 23:35:09 +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
|
|
|
|
// later on in llvm/lib/IR/Value.cpp.
|
|
|
|
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,
|
|
|
|
name.as_ptr(),
|
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,
|
2016-11-18 22:15:14 +00:00
|
|
|
DIFlags::FlagZero,
|
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,
|
2015-04-29 06:14:37 +00:00
|
|
|
unique_type_id.as_ptr())
|
|
|
|
};
|
|
|
|
|
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
|
|
|
|
2018-08-07 14:04:34 +00:00
|
|
|
let name = SmallCStr::new(union_type_name);
|
|
|
|
let unique_type_id = SmallCStr::new(
|
|
|
|
debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id)
|
|
|
|
);
|
2016-08-22 18:11:22 +00:00
|
|
|
let metadata_stub = unsafe {
|
|
|
|
// LLVMRustDIBuilderCreateUnionType() wants an empty array. A null
|
|
|
|
// pointer will lead to hard to trace and debug LLVM assertions
|
|
|
|
// later on in llvm/lib/IR/Value.cpp.
|
|
|
|
let empty_array = create_DIArray(DIB(cx), &[]);
|
|
|
|
|
|
|
|
llvm::LLVMRustDIBuilderCreateUnionType(
|
|
|
|
DIB(cx),
|
|
|
|
containing_scope,
|
|
|
|
name.as_ptr(),
|
|
|
|
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
|
|
|
|
unique_type_id.as_ptr())
|
|
|
|
};
|
|
|
|
|
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.
|
2018-07-10 10:28:39 +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;
|
|
|
|
}
|
|
|
|
|
2018-01-05 04:58:34 +00:00
|
|
|
let tcx = cx.tcx;
|
2018-05-08 13:10:16 +00:00
|
|
|
let attrs = tcx.codegen_fn_attrs(def_id);
|
2018-04-12 12:52:09 +00:00
|
|
|
|
2018-05-08 13:10:16 +00:00
|
|
|
if attrs.flags.contains(CodegenFnAttrFlags::NO_DEBUG) {
|
2018-04-12 12:52:09 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-05-08 13:10:16 +00:00
|
|
|
let no_mangle = attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE);
|
2017-12-20 05:18:24 +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() {
|
2015-04-29 06:14:37 +00:00
|
|
|
let loc = span_start(cx, span);
|
2017-04-24 17:01:19 +00:00
|
|
|
(file_metadata(cx, &loc.file.name, LOCAL_CRATE), loc.line as c_uint)
|
2015-04-29 06:14:37 +00:00
|
|
|
} else {
|
2016-07-07 12:15:10 +00:00
|
|
|
(unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
|
2015-04-29 06:14:37 +00:00
|
|
|
};
|
|
|
|
|
2018-02-19 11:41:10 +00:00
|
|
|
let is_local_to_unit = is_node_local_to_unit(cx, def_id);
|
|
|
|
let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx);
|
2015-04-29 06:14:37 +00:00
|
|
|
let type_metadata = type_metadata(cx, variable_type, span);
|
2018-08-07 14:04:34 +00:00
|
|
|
let var_name = SmallCStr::new(&tcx.item_name(def_id).as_str());
|
2017-12-20 05:18:24 +00:00
|
|
|
let linkage_name = if no_mangle {
|
|
|
|
None
|
|
|
|
} else {
|
2018-02-19 11:41:10 +00:00
|
|
|
let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id));
|
2018-08-07 14:04:34 +00:00
|
|
|
Some(SmallCStr::new(&linkage_name.as_str()))
|
2017-12-20 05:18:24 +00:00
|
|
|
};
|
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 {
|
2016-08-01 23:35:09 +00:00
|
|
|
llvm::LLVMRustDIBuilderCreateStaticVariable(DIB(cx),
|
2018-07-04 13:36:49 +00:00
|
|
|
Some(var_scope),
|
2016-08-01 23:35:09 +00:00
|
|
|
var_name.as_ptr(),
|
2017-12-20 05:18:24 +00:00
|
|
|
// If null, linkage_name field is omitted,
|
|
|
|
// which is what we want for no_mangle statics
|
|
|
|
linkage_name.as_ref()
|
|
|
|
.map_or(ptr::null(), |name| name.as_ptr()),
|
2016-08-01 23:35:09 +00:00
|
|
|
file_metadata,
|
|
|
|
line_number,
|
|
|
|
type_metadata,
|
|
|
|
is_local_to_unit,
|
|
|
|
global,
|
2018-06-27 10:12:47 +00:00
|
|
|
None,
|
2018-09-08 22:16:45 +00:00
|
|
|
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.
|
|
|
|
pub fn create_vtable_metadata(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
ty: ty::Ty<'tcx>,
|
|
|
|
vtable: &'ll Value,
|
|
|
|
) {
|
|
|
|
if cx.dbg_cx.is_none() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let type_metadata = type_metadata(cx, ty, syntax_pos::DUMMY_SP);
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
// LLVMRustDIBuilderCreateStructType() wants an empty array. A null
|
|
|
|
// pointer will lead to hard to trace and debug LLVM assertions
|
|
|
|
// later on in llvm/lib/IR/Value.cpp.
|
|
|
|
let empty_array = create_DIArray(DIB(cx), &[]);
|
|
|
|
|
|
|
|
let name = const_cstr!("vtable");
|
|
|
|
|
|
|
|
// Create a new one each time. We don't want metadata caching
|
|
|
|
// here, because each vtable will refer to a unique containing
|
|
|
|
// type.
|
|
|
|
let vtable_type = llvm::LLVMRustDIBuilderCreateStructType(
|
|
|
|
DIB(cx),
|
|
|
|
NO_SCOPE_METADATA,
|
|
|
|
name.as_ptr(),
|
|
|
|
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),
|
|
|
|
name.as_ptr()
|
|
|
|
);
|
|
|
|
|
|
|
|
llvm::LLVMRustDIBuilderCreateStaticVariable(DIB(cx),
|
|
|
|
NO_SCOPE_METADATA,
|
|
|
|
name.as_ptr(),
|
2018-09-24 08:51:13 +00:00
|
|
|
ptr::null(),
|
2018-09-20 13:47:22 +00:00
|
|
|
unknown_file_metadata(cx),
|
|
|
|
UNKNOWN_LINE_NUMBER,
|
|
|
|
vtable_type,
|
|
|
|
true,
|
|
|
|
vtable,
|
|
|
|
None,
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-25 02:34:31 +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,
|
2018-08-18 10:13:52 +00:00
|
|
|
file: &syntax_pos::SourceFile,
|
2018-07-04 13:36:49 +00:00
|
|
|
defining_crate: CrateNum,
|
|
|
|
) -> &'ll DILexicalBlock {
|
2018-01-05 05:04:08 +00:00
|
|
|
let file_metadata = file_metadata(cx, &file.name, defining_crate);
|
2016-08-25 02:34:31 +00:00
|
|
|
unsafe {
|
|
|
|
llvm::LLVMRustDIBuilderCreateLexicalBlockFile(
|
2018-01-05 05:04:08 +00:00
|
|
|
DIB(cx),
|
2016-08-25 02:34:31 +00:00
|
|
|
scope_metadata,
|
|
|
|
file_metadata)
|
|
|
|
}
|
2016-08-26 16:23:42 +00:00
|
|
|
}
|