2015-04-24 16:48:10 +12:00
|
|
|
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
2015-04-24 17:25:35 +12:00
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
2015-04-24 16:48:10 +12:00
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
2015-04-24 17:25:35 +12:00
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
2015-04-24 16:48:10 +12:00
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2015-04-29 18:14:37 +12:00
|
|
|
use self::RecursiveTypeDescription::*;
|
|
|
|
use self::MemberDescriptionFactory::*;
|
|
|
|
use self::EnumDiscriminantInfo::*;
|
|
|
|
|
2017-06-01 21:50:53 +03:00
|
|
|
use super::utils::{debug_context, DIB, span_start,
|
2017-07-07 14:23:38 +02:00
|
|
|
get_namespace_for_item, create_DIArray, is_node_local_to_unit};
|
2018-02-19 12:41:10 +01:00
|
|
|
use super::namespace::mangled_name_of_instance;
|
2016-10-21 17:56:36 -04:00
|
|
|
use super::type_names::compute_debuginfo_type_name;
|
2016-08-16 17:41:38 +03:00
|
|
|
use super::{CrateDebugContext};
|
2017-05-27 13:46:42 -06:00
|
|
|
use abi;
|
2018-07-10 13:28:39 +03:00
|
|
|
use value::Value;
|
2015-04-29 18:14:37 +12:00
|
|
|
|
2018-07-10 13:28:39 +03:00
|
|
|
use llvm;
|
2018-07-04 16:36:49 +03:00
|
|
|
use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor,
|
2016-11-18 17:15:14 -05:00
|
|
|
DICompositeType, DILexicalBlock, DIFlags};
|
2015-04-29 18:14:37 +12:00
|
|
|
|
2018-05-17 19:43:36 -04:00
|
|
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
2018-05-08 16:10:16 +03:00
|
|
|
use rustc::hir::CodegenFnAttrFlags;
|
2016-09-15 00:51:46 +03:00
|
|
|
use rustc::hir::def::CtorKind;
|
2017-04-24 19:01:19 +02:00
|
|
|
use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
|
2018-05-08 07:52:01 -04:00
|
|
|
use rustc::ich::{Fingerprint, NodeIdHashingMode};
|
2017-10-30 08:36:03 +01:00
|
|
|
use rustc::ty::Instance;
|
2018-01-05 07:01:54 +02:00
|
|
|
use common::CodegenCx;
|
2018-03-03 08:23:28 -05:00
|
|
|
use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
|
2017-12-18 16:18:36 +02:00
|
|
|
use rustc::ty::layout::{self, Align, LayoutOf, PrimitiveExt, Size, TyLayout};
|
2018-01-05 06:14:44 +02:00
|
|
|
use rustc::session::config;
|
2017-05-27 20:48:09 +02:00
|
|
|
use rustc::util::nodemap::FxHashMap;
|
2018-08-03 15:37:15 -06:00
|
|
|
use rustc_fs_util::path2cstr;
|
2015-04-24 16:48:10 +12:00
|
|
|
|
|
|
|
use libc::{c_uint, c_longlong};
|
|
|
|
use std::ffi::CString;
|
2018-07-04 16:36:49 +03:00
|
|
|
use std::fmt::{self, Write};
|
|
|
|
use std::hash::{Hash, Hasher};
|
2018-07-26 17:11:10 +02:00
|
|
|
use std::iter;
|
2015-04-24 16:48:10 +12:00
|
|
|
use std::ptr;
|
2017-12-14 08:09:19 +01:00
|
|
|
use std::path::{Path, PathBuf};
|
2018-04-12 14:52:09 +02:00
|
|
|
use syntax::ast;
|
2017-04-24 19:01:19 +02:00
|
|
|
use syntax::symbol::{Interner, InternedString, Symbol};
|
2017-12-14 08:09:19 +01:00
|
|
|
use syntax_pos::{self, Span, FileName};
|
2015-04-24 16:48:10 +12:00
|
|
|
|
2018-07-04 16:36:49 +03:00
|
|
|
impl PartialEq for llvm::Metadata {
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
|
|
|
self as *const _ == other as *const _
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
(self as *const Self).fmt(f)
|
|
|
|
}
|
|
|
|
}
|
2016-10-21 17:56:36 -04:00
|
|
|
|
2016-03-18 15:30:15 -06:00
|
|
|
// From DWARF 5.
|
|
|
|
// See http://www.dwarfstd.org/ShowIssue.php?issue=140129.1
|
|
|
|
const DW_LANG_RUST: c_uint = 0x1c;
|
2015-04-24 16:48:10 +12: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 18:14:37 +12:00
|
|
|
pub const UNKNOWN_LINE_NUMBER: c_uint = 0;
|
|
|
|
pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0;
|
|
|
|
|
2018-07-04 16:36:49 +03:00
|
|
|
pub const NO_SCOPE_METADATA: Option<&DIScope> = None;
|
2015-04-29 18:14:37 +12: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-07-04 16:36:49 +03:00
|
|
|
pub struct TypeMap<'ll, 'tcx> {
|
2015-04-29 18:14:37 +12:00
|
|
|
// The UniqueTypeIds created so far
|
2016-07-11 08:00:48 +00:00
|
|
|
unique_id_interner: Interner,
|
2015-04-29 18:14:37 +12:00
|
|
|
// A map from UniqueTypeId to debuginfo metadata for that type. This is a 1:1 mapping.
|
2018-07-04 16:36:49 +03:00
|
|
|
unique_id_to_metadata: FxHashMap<UniqueTypeId, &'ll DIType>,
|
2015-04-29 18:14:37 +12:00
|
|
|
// A map from types to debuginfo metadata. This is a N:1 mapping.
|
2018-07-04 16:36:49 +03:00
|
|
|
type_to_metadata: FxHashMap<Ty<'tcx>, &'ll DIType>,
|
2015-04-29 18:14:37 +12:00
|
|
|
// A map from types to UniqueTypeId. This is a N:1 mapping.
|
2016-11-08 14:02:55 +11:00
|
|
|
type_to_unique_id: FxHashMap<Ty<'tcx>, UniqueTypeId>
|
2015-04-29 18:14:37 +12:00
|
|
|
}
|
|
|
|
|
2018-07-04 16:36:49 +03:00
|
|
|
impl TypeMap<'ll, 'tcx> {
|
|
|
|
pub fn new() -> Self {
|
2015-04-29 18:14:37 +12:00
|
|
|
TypeMap {
|
|
|
|
unique_id_interner: Interner::new(),
|
2016-11-08 14:02:55 +11:00
|
|
|
type_to_metadata: FxHashMap(),
|
|
|
|
unique_id_to_metadata: FxHashMap(),
|
|
|
|
type_to_unique_id: FxHashMap(),
|
2015-04-29 18:14:37 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Adds a Ty to metadata mapping to the TypeMap. The method will fail if
|
|
|
|
// the mapping already exists.
|
2018-07-04 16:36:49 +03:00
|
|
|
fn register_type_with_metadata(
|
|
|
|
&mut self,
|
|
|
|
type_: Ty<'tcx>,
|
|
|
|
metadata: &'ll DIType,
|
|
|
|
) {
|
2015-04-29 18:14:37 +12:00
|
|
|
if self.type_to_metadata.insert(type_, metadata).is_some() {
|
2016-03-29 01:46:02 +02:00
|
|
|
bug!("Type metadata for Ty '{}' is already in the TypeMap!", type_);
|
2015-04-29 18:14:37 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Adds a UniqueTypeId to metadata mapping to the TypeMap. The method will
|
|
|
|
// fail if the mapping already exists.
|
2018-07-04 16:36:49 +03:00
|
|
|
fn register_unique_id_with_metadata(
|
|
|
|
&mut self,
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
metadata: &'ll DIType,
|
|
|
|
) {
|
2015-04-29 18:14:37 +12:00
|
|
|
if self.unique_id_to_metadata.insert(unique_type_id, metadata).is_some() {
|
2016-03-29 01:46:02 +02: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 18:14:37 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-04 16:36:49 +03:00
|
|
|
fn find_metadata_for_type(&self, type_: Ty<'tcx>) -> Option<&'ll DIType> {
|
2015-04-29 18:14:37 +12:00
|
|
|
self.type_to_metadata.get(&type_).cloned()
|
|
|
|
}
|
|
|
|
|
2018-07-04 16:36:49 +03:00
|
|
|
fn find_metadata_for_unique_id(&self, unique_type_id: UniqueTypeId) -> Option<&'ll DIType> {
|
2015-04-29 18:14:37 +12: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 18:14:37 +12: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 07:01:54 +02:00
|
|
|
fn get_unique_type_id_of_type<'a>(&mut self, cx: &CodegenCx<'a, 'tcx>,
|
2015-04-29 18:14:37 +12:00
|
|
|
type_: Ty<'tcx>) -> UniqueTypeId {
|
2016-10-21 17:56:36 -04:00
|
|
|
// Let's see if we already have something in the cache
|
2015-04-29 18:14:37 +12:00
|
|
|
match self.type_to_unique_id.get(&type_).cloned() {
|
|
|
|
Some(unique_type_id) => return unique_type_id,
|
|
|
|
None => { /* generate one */}
|
|
|
|
};
|
|
|
|
|
2016-10-26 22:42:48 -04: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 07:52:01 -04: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 14:43:36 +02:00
|
|
|
|
2016-10-12 20:54:41 +03:00
|
|
|
let key = self.unique_id_interner.intern(&unique_type_id);
|
2015-04-29 18:14:37 +12: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 07:01:54 +02:00
|
|
|
cx: &CodegenCx<'a, 'tcx>,
|
2015-04-29 18:14:37 +12: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 18:14:37 +12:00
|
|
|
variant_name);
|
2016-10-12 20:54:41 +03:00
|
|
|
let interner_key = self.unique_id_interner.intern(&enum_variant_type_id);
|
2015-04-29 18:14:37 +12:00
|
|
|
UniqueTypeId(interner_key)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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 16:36:49 +03:00
|
|
|
enum RecursiveTypeDescription<'ll, 'tcx> {
|
2015-04-29 18:14:37 +12:00
|
|
|
UnfinishedMetadata {
|
|
|
|
unfinished_type: Ty<'tcx>,
|
|
|
|
unique_type_id: UniqueTypeId,
|
2018-07-04 16:36:49 +03:00
|
|
|
metadata_stub: &'ll DICompositeType,
|
|
|
|
member_description_factory: MemberDescriptionFactory<'ll, 'tcx>,
|
2015-04-29 18:14:37 +12:00
|
|
|
},
|
2018-07-04 16:36:49 +03:00
|
|
|
FinalMetadata(&'ll DICompositeType)
|
2015-04-29 18:14:37 +12:00
|
|
|
}
|
|
|
|
|
2018-07-04 16:36:49 +03:00
|
|
|
fn create_and_register_recursive_type_forward_declaration(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
2015-04-29 18:14:37 +12:00
|
|
|
unfinished_type: Ty<'tcx>,
|
|
|
|
unique_type_id: UniqueTypeId,
|
2018-07-04 16:36:49 +03:00
|
|
|
metadata_stub: &'ll DICompositeType,
|
|
|
|
member_description_factory: MemberDescriptionFactory<'ll, 'tcx>,
|
|
|
|
) -> RecursiveTypeDescription<'ll, 'tcx> {
|
2015-04-29 18:14:37 +12: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-29 01:46:02 +02: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 18:14:37 +12:00
|
|
|
|
|
|
|
UnfinishedMetadata {
|
2017-08-06 22:54:09 -07:00
|
|
|
unfinished_type,
|
|
|
|
unique_type_id,
|
|
|
|
metadata_stub,
|
|
|
|
member_description_factory,
|
2015-04-29 18:14:37 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-04 16:36:49 +03:00
|
|
|
impl RecursiveTypeDescription<'ll, 'tcx> {
|
2015-04-29 18:14:37 +12: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 16:36:49 +03:00
|
|
|
fn finalize(&self, cx: &CodegenCx<'ll, 'tcx>) -> MetadataCreationResult<'ll> {
|
2015-04-29 18:14:37 +12:00
|
|
|
match *self {
|
|
|
|
FinalMetadata(metadata) => MetadataCreationResult::new(metadata, false),
|
|
|
|
UnfinishedMetadata {
|
|
|
|
unfinished_type,
|
|
|
|
unique_type_id,
|
|
|
|
metadata_stub,
|
|
|
|
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-29 01:46:02 +02:00
|
|
|
bug!("Forward declaration of potentially recursive type \
|
|
|
|
'{:?}' was not found in TypeMap!",
|
|
|
|
unfinished_type);
|
2015-04-29 18:14:37 +12: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,
|
|
|
|
metadata_stub,
|
|
|
|
&member_descriptions[..]);
|
|
|
|
return MetadataCreationResult::new(metadata_stub, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-04-24 16:48:10 +12: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) => (
|
|
|
|
match debug_context($cx).type_map
|
|
|
|
.borrow()
|
|
|
|
.find_metadata_for_unique_id($unique_type_id) {
|
|
|
|
Some(metadata) => return MetadataCreationResult::new(metadata, true),
|
|
|
|
None => { /* proceed normally */ }
|
2015-10-21 18:20:46 +02:00
|
|
|
}
|
2015-04-24 16:48:10 +12:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2018-07-04 16:36:49 +03: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 16:48:10 +12:00
|
|
|
let element_type_metadata = type_metadata(cx, element_type, span);
|
|
|
|
|
|
|
|
return_if_metadata_created_in_meantime!(cx, unique_type_id);
|
|
|
|
|
2017-06-01 21:50:53 +03:00
|
|
|
let (size, align) = cx.size_and_align_of(array_or_slice_type);
|
2015-04-24 16:48:10 +12:00
|
|
|
|
2017-06-01 21:50:53 +03:00
|
|
|
let upper_bound = match array_or_slice_type.sty {
|
|
|
|
ty::TyArray(_, len) => {
|
2018-04-26 09:18:19 +02:00
|
|
|
len.unwrap_usize(cx.tcx) as c_longlong
|
2017-06-01 21:50:53 +03:00
|
|
|
}
|
|
|
|
_ => -1
|
2015-04-24 16:48:10 +12:00
|
|
|
};
|
|
|
|
|
|
|
|
let subrange = unsafe {
|
2018-07-04 16:36:49 +03:00
|
|
|
Some(llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound))
|
2015-04-24 16:48:10 +12:00
|
|
|
};
|
|
|
|
|
|
|
|
let subscripts = create_DIArray(DIB(cx), &[subrange]);
|
|
|
|
let metadata = unsafe {
|
2016-08-02 02:35:09 +03:00
|
|
|
llvm::LLVMRustDIBuilderCreateArrayType(
|
2015-04-24 16:48:10 +12:00
|
|
|
DIB(cx),
|
2017-06-01 21:50:53 +03:00
|
|
|
size.bits(),
|
|
|
|
align.abi_bits() as u32,
|
2015-04-24 16:48:10 +12:00
|
|
|
element_type_metadata,
|
|
|
|
subscripts)
|
|
|
|
};
|
|
|
|
|
|
|
|
return MetadataCreationResult::new(metadata, false);
|
|
|
|
}
|
|
|
|
|
2018-07-04 16:36:49 +03: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 06:58:34 +02:00
|
|
|
let data_ptr_type = cx.tcx.mk_imm_ptr(element_type);
|
2015-04-24 16:48:10 +12:00
|
|
|
|
2017-06-01 21:50:53 +03:00
|
|
|
let data_ptr_metadata = type_metadata(cx, data_ptr_type, span);
|
2015-04-24 16:48:10 +12:00
|
|
|
|
|
|
|
return_if_metadata_created_in_meantime!(cx, unique_type_id);
|
|
|
|
|
2017-06-01 21:50:53 +03: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 06:58:34 +02:00
|
|
|
let (usize_size, usize_align) = cx.size_and_align_of(cx.tcx.types.usize);
|
2015-04-24 16:48:10 +12:00
|
|
|
|
|
|
|
let member_descriptions = [
|
|
|
|
MemberDescription {
|
|
|
|
name: "data_ptr".to_string(),
|
2017-06-01 21:50:53 +03:00
|
|
|
type_metadata: data_ptr_metadata,
|
2018-05-20 14:14:39 +02:00
|
|
|
offset: Size::ZERO,
|
2017-06-01 21:50:53 +03:00
|
|
|
size: pointer_size,
|
|
|
|
align: pointer_align,
|
2016-11-18 17:15:14 -05:00
|
|
|
flags: DIFlags::FlagZero,
|
2015-04-24 16:48:10 +12:00
|
|
|
},
|
|
|
|
MemberDescription {
|
|
|
|
name: "length".to_string(),
|
2018-01-05 06:58:34 +02:00
|
|
|
type_metadata: type_metadata(cx, cx.tcx.types.usize, span),
|
2017-06-01 21:50:53 +03:00
|
|
|
offset: pointer_size,
|
|
|
|
size: usize_size,
|
|
|
|
align: usize_align,
|
2016-11-18 17:15:14 -05:00
|
|
|
flags: DIFlags::FlagZero,
|
2015-04-24 16:48:10 +12:00
|
|
|
},
|
|
|
|
];
|
|
|
|
|
2017-04-24 19:01:19 +02:00
|
|
|
let file_metadata = unknown_file_metadata(cx);
|
2015-04-24 16:48:10 +12:00
|
|
|
|
|
|
|
let metadata = composite_type_metadata(cx,
|
2017-06-01 21:50:53 +03:00
|
|
|
slice_ptr_type,
|
2015-04-24 16:48:10 +12:00
|
|
|
&slice_type_name[..],
|
|
|
|
unique_type_id,
|
|
|
|
&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 13:53:59 +02:00
|
|
|
NO_SCOPE_METADATA,
|
2015-04-24 16:48:10 +12:00
|
|
|
file_metadata,
|
|
|
|
span);
|
2017-06-01 21:50:53 +03:00
|
|
|
MetadataCreationResult::new(metadata, false)
|
2015-04-24 16:48:10 +12:00
|
|
|
}
|
|
|
|
|
2018-07-04 16:36:49 +03:00
|
|
|
fn subroutine_type_metadata(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
signature: ty::PolyFnSig<'tcx>,
|
|
|
|
span: Span,
|
|
|
|
) -> MetadataCreationResult<'ll> {
|
2018-03-03 08:23:28 -05:00
|
|
|
let signature = cx.tcx.normalize_erasing_late_bound_regions(
|
|
|
|
ty::ParamEnv::reveal_all(),
|
|
|
|
&signature,
|
|
|
|
);
|
2015-04-24 16:48:10 +12:00
|
|
|
|
2018-06-27 13:12:47 +03:00
|
|
|
let signature_metadata: Vec<_> = iter::once(
|
2018-07-26 17:11:10 +02:00
|
|
|
// return type
|
|
|
|
match signature.output().sty {
|
2018-06-27 13:12:47 +03:00
|
|
|
ty::TyTuple(ref tys) if tys.is_empty() => None,
|
2018-07-04 16:36:49 +03:00
|
|
|
_ => Some(type_metadata(cx, signature.output(), span))
|
2018-07-26 17:11:10 +02:00
|
|
|
}
|
|
|
|
).chain(
|
|
|
|
// regular arguments
|
2018-06-27 13:12:47 +03:00
|
|
|
signature.inputs().iter().map(|argument_type| {
|
2018-07-04 16:36:49 +03:00
|
|
|
Some(type_metadata(cx, argument_type, span))
|
2018-06-27 13:12:47 +03:00
|
|
|
})
|
2018-07-26 17:11:10 +02:00
|
|
|
).collect();
|
2015-04-24 16:48:10 +12:00
|
|
|
|
|
|
|
return_if_metadata_created_in_meantime!(cx, unique_type_id);
|
|
|
|
|
|
|
|
return MetadataCreationResult::new(
|
|
|
|
unsafe {
|
2016-08-02 02:35:09 +03:00
|
|
|
llvm::LLVMRustDIBuilderCreateSubroutineType(
|
2015-04-24 16:48:10 +12:00
|
|
|
DIB(cx),
|
2016-07-07 08:15:10 -04:00
|
|
|
unknown_file_metadata(cx),
|
2015-04-24 16:48:10 +12: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 16:36:49 +03: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 16:48:10 +12: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 15:46:16 -07:00
|
|
|
let containing_scope = match trait_type.sty {
|
2016-11-16 09:21:49 -07:00
|
|
|
ty::TyDynamic(ref data, ..) => if let Some(principal) = data.principal() {
|
2016-11-12 15:46:16 -07:00
|
|
|
let def_id = principal.def_id();
|
2018-07-04 16:36:49 +03:00
|
|
|
Some(get_namespace_for_item(cx, def_id))
|
2016-11-12 15:46:16 -07:00
|
|
|
} else {
|
|
|
|
NO_SCOPE_METADATA
|
|
|
|
},
|
2015-04-24 16:48:10 +12:00
|
|
|
_ => {
|
2016-03-29 01:46:02 +02:00
|
|
|
bug!("debuginfo: Unexpected trait-object type in \
|
|
|
|
trait_pointer_metadata(): {:?}",
|
|
|
|
trait_type);
|
2015-04-24 16:48:10 +12: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 08:15:10 -04:00
|
|
|
let file_metadata = unknown_file_metadata(cx);
|
2015-04-24 16:48:10 +12:00
|
|
|
|
2018-01-05 06:58:34 +02:00
|
|
|
let layout = cx.layout_of(cx.tcx.mk_mut_ptr(trait_type));
|
2017-05-27 13:46:42 -06:00
|
|
|
|
|
|
|
assert_eq!(abi::FAT_PTR_ADDR, 0);
|
|
|
|
assert_eq!(abi::FAT_PTR_EXTRA, 1);
|
2017-06-01 21:50:53 +03:00
|
|
|
|
|
|
|
let data_ptr_field = layout.field(cx, 0);
|
|
|
|
let vtable_field = layout.field(cx, 1);
|
2017-05-27 13:46:42 -06:00
|
|
|
let member_descriptions = [
|
|
|
|
MemberDescription {
|
|
|
|
name: "pointer".to_string(),
|
2017-06-01 21:50:53 +03:00
|
|
|
type_metadata: type_metadata(cx,
|
2018-01-05 06:58:34 +02:00
|
|
|
cx.tcx.mk_mut_ptr(cx.tcx.types.u8),
|
2017-06-01 21:50:53 +03:00
|
|
|
syntax_pos::DUMMY_SP),
|
2017-09-13 14:35:04 +03:00
|
|
|
offset: layout.fields.offset(0),
|
2017-09-22 22:44:40 +03:00
|
|
|
size: data_ptr_field.size,
|
|
|
|
align: data_ptr_field.align,
|
2017-05-27 13:46:42 -06:00
|
|
|
flags: DIFlags::FlagArtificial,
|
|
|
|
},
|
|
|
|
MemberDescription {
|
|
|
|
name: "vtable".to_string(),
|
2017-06-01 21:50:53 +03:00
|
|
|
type_metadata: type_metadata(cx, vtable_field.ty, syntax_pos::DUMMY_SP),
|
2017-09-13 14:35:04 +03:00
|
|
|
offset: layout.fields.offset(1),
|
2017-09-22 22:44:40 +03:00
|
|
|
size: vtable_field.size,
|
|
|
|
align: vtable_field.align,
|
2017-05-27 13:46:42 -06:00
|
|
|
flags: DIFlags::FlagArtificial,
|
|
|
|
},
|
|
|
|
];
|
|
|
|
|
2015-04-24 16:48:10 +12:00
|
|
|
composite_type_metadata(cx,
|
2017-06-01 21:50:53 +03:00
|
|
|
trait_object_type,
|
2015-04-24 16:48:10 +12:00
|
|
|
&trait_type_name[..],
|
|
|
|
unique_type_id,
|
2017-05-27 13:46:42 -06:00
|
|
|
&member_descriptions,
|
2015-04-24 16:48:10 +12:00
|
|
|
containing_scope,
|
2016-07-07 08:15:10 -04:00
|
|
|
file_metadata,
|
2016-06-21 18:08:13 -04:00
|
|
|
syntax_pos::DUMMY_SP)
|
2015-04-24 16:48:10 +12:00
|
|
|
}
|
|
|
|
|
2018-07-04 16:36:49 +03:00
|
|
|
pub fn type_metadata(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
t: Ty<'tcx>,
|
|
|
|
usage_site_span: Span,
|
|
|
|
) -> &'ll DIType {
|
2015-04-24 16:48:10 +12: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
|
|
|
|
// an equivalent type (e.g. only differing in region arguments).
|
|
|
|
// In order to find out, generate the unique type id and look
|
|
|
|
// that up.
|
|
|
|
let unique_type_id = type_map.get_unique_type_id_of_type(cx, t);
|
|
|
|
match type_map.find_metadata_for_unique_id(unique_type_id) {
|
|
|
|
Some(metadata) => {
|
|
|
|
// There is already an equivalent type in the TypeMap.
|
|
|
|
// Register this Ty as an alias in the cache and
|
|
|
|
// return the cached metadata.
|
2016-03-29 01:46:02 +02:00
|
|
|
type_map.register_type_with_metadata(t, metadata);
|
2015-04-24 16:48:10 +12: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 17:40:31 +03:00
|
|
|
let ptr_metadata = |ty: Ty<'tcx>| {
|
|
|
|
match ty.sty {
|
|
|
|
ty::TySlice(typ) => {
|
|
|
|
Ok(vec_slice_metadata(cx, t, typ, unique_type_id, usage_site_span))
|
|
|
|
}
|
|
|
|
ty::TyStr => {
|
2018-01-05 06:58:34 +02:00
|
|
|
Ok(vec_slice_metadata(cx, t, cx.tcx.types.u8, unique_type_id, usage_site_span))
|
2017-01-21 17:40:31 +03:00
|
|
|
}
|
|
|
|
ty::TyDynamic(..) => {
|
|
|
|
Ok(MetadataCreationResult::new(
|
|
|
|
trait_pointer_metadata(cx, ty, Some(t), unique_type_id),
|
|
|
|
false))
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
let pointee_metadata = type_metadata(cx, ty, usage_site_span);
|
|
|
|
|
|
|
|
match debug_context(cx).type_map
|
|
|
|
.borrow()
|
|
|
|
.find_metadata_for_unique_id(unique_type_id) {
|
|
|
|
Some(metadata) => return Err(metadata),
|
|
|
|
None => { /* proceed normally */ }
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok(MetadataCreationResult::new(pointer_type_metadata(cx, t, pointee_metadata),
|
|
|
|
false))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-05-13 17:11:52 +03:00
|
|
|
let MetadataCreationResult { metadata, already_stored_in_typemap } = match t.sty {
|
2016-08-02 15:56:20 +08:00
|
|
|
ty::TyNever |
|
2015-06-11 16:21:46 -07:00
|
|
|
ty::TyBool |
|
|
|
|
ty::TyChar |
|
|
|
|
ty::TyInt(_) |
|
|
|
|
ty::TyUint(_) |
|
|
|
|
ty::TyFloat(_) => {
|
2015-04-24 16:48:10 +12:00
|
|
|
MetadataCreationResult::new(basic_type_metadata(cx, t), false)
|
|
|
|
}
|
2018-01-21 13:33:21 +08:00
|
|
|
ty::TyTuple(ref elements) if elements.is_empty() => {
|
2015-04-24 16:48:10 +12:00
|
|
|
MetadataCreationResult::new(basic_type_metadata(cx, t), false)
|
|
|
|
}
|
2017-06-01 21:50:53 +03:00
|
|
|
ty::TyArray(typ, _) |
|
2015-06-12 16:50:13 -07:00
|
|
|
ty::TySlice(typ) => {
|
2017-06-01 21:50:53 +03:00
|
|
|
fixed_vec_metadata(cx, unique_type_id, t, typ, usage_site_span)
|
2015-04-24 16:48:10 +12:00
|
|
|
}
|
2015-06-11 16:21:46 -07:00
|
|
|
ty::TyStr => {
|
2018-01-05 06:58:34 +02:00
|
|
|
fixed_vec_metadata(cx, unique_type_id, t, cx.tcx.types.i8, usage_site_span)
|
2015-04-24 16:48:10 +12:00
|
|
|
}
|
2016-11-16 09:21:49 -07:00
|
|
|
ty::TyDynamic(..) => {
|
2015-04-24 16:48:10 +12:00
|
|
|
MetadataCreationResult::new(
|
|
|
|
trait_pointer_metadata(cx, t, None, unique_type_id),
|
|
|
|
false)
|
|
|
|
}
|
2017-09-03 19:53:58 +01:00
|
|
|
ty::TyForeign(..) => {
|
|
|
|
MetadataCreationResult::new(
|
|
|
|
foreign_type_metadata(cx, t, unique_type_id),
|
|
|
|
false)
|
|
|
|
}
|
2015-07-10 19:16:35 -07:00
|
|
|
ty::TyRawPtr(ty::TypeAndMut{ty, ..}) |
|
2018-05-02 15:21:05 +02:00
|
|
|
ty::TyRef(_, ty, _) => {
|
2017-01-21 17:40:31 +03:00
|
|
|
match ptr_metadata(ty) {
|
|
|
|
Ok(res) => res,
|
|
|
|
Err(metadata) => return metadata,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ty::TyAdt(def, _) if def.is_box() => {
|
|
|
|
match ptr_metadata(t.boxed_ty()) {
|
|
|
|
Ok(res) => res,
|
|
|
|
Err(metadata) => return metadata,
|
2015-04-24 16:48:10 +12:00
|
|
|
}
|
|
|
|
}
|
2017-05-13 17:11:52 +03:00
|
|
|
ty::TyFnDef(..) | ty::TyFnPtr(_) => {
|
2015-07-13 21:50:21 +02:00
|
|
|
let fn_metadata = subroutine_type_metadata(cx,
|
|
|
|
unique_type_id,
|
2018-01-05 06:58:34 +02:00
|
|
|
t.fn_sig(cx.tcx),
|
2015-07-13 21:50:21 +02:00
|
|
|
usage_site_span).metadata;
|
|
|
|
match debug_context(cx).type_map
|
|
|
|
.borrow()
|
|
|
|
.find_metadata_for_unique_id(unique_type_id) {
|
|
|
|
Some(metadata) => return metadata,
|
|
|
|
None => { /* proceed normally */ }
|
|
|
|
};
|
|
|
|
|
|
|
|
// 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 16:48:10 +12:00
|
|
|
}
|
2016-11-03 22:19:33 +02:00
|
|
|
ty::TyClosure(def_id, substs) => {
|
2018-01-05 06:58:34 +02:00
|
|
|
let upvar_tys : Vec<_> = substs.upvar_tys(def_id, cx.tcx).collect();
|
2015-07-14 19:08:08 +02:00
|
|
|
prepare_tuple_metadata(cx,
|
|
|
|
t,
|
2016-11-03 22:19:33 +02:00
|
|
|
&upvar_tys,
|
2015-07-14 19:08:08 +02:00
|
|
|
unique_type_id,
|
|
|
|
usage_site_span).finalize(cx)
|
2015-04-24 16:48:10 +12:00
|
|
|
}
|
2018-05-02 13:14:30 +02:00
|
|
|
ty::TyGenerator(def_id, substs, _) => {
|
2018-01-05 06:58:34 +02:00
|
|
|
let upvar_tys : Vec<_> = substs.field_tys(def_id, cx.tcx).map(|t| {
|
2018-03-03 08:23:28 -05:00
|
|
|
cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)
|
2016-12-26 14:34:03 +01:00
|
|
|
}).collect();
|
|
|
|
prepare_tuple_metadata(cx,
|
|
|
|
t,
|
|
|
|
&upvar_tys,
|
|
|
|
unique_type_id,
|
|
|
|
usage_site_span).finalize(cx)
|
|
|
|
}
|
2016-09-06 01:26:02 +03:00
|
|
|
ty::TyAdt(def, ..) => match def.adt_kind() {
|
|
|
|
AdtKind::Struct => {
|
|
|
|
prepare_struct_metadata(cx,
|
|
|
|
t,
|
|
|
|
unique_type_id,
|
|
|
|
usage_site_span).finalize(cx)
|
|
|
|
}
|
|
|
|
AdtKind::Union => {
|
|
|
|
prepare_union_metadata(cx,
|
2015-04-24 16:48:10 +12:00
|
|
|
t,
|
|
|
|
unique_type_id,
|
|
|
|
usage_site_span).finalize(cx)
|
2016-09-06 01:26:02 +03:00
|
|
|
}
|
|
|
|
AdtKind::Enum => {
|
|
|
|
prepare_enum_metadata(cx,
|
|
|
|
t,
|
|
|
|
def.did,
|
|
|
|
unique_type_id,
|
|
|
|
usage_site_span).finalize(cx)
|
|
|
|
}
|
|
|
|
},
|
2018-01-21 13:33:21 +08:00
|
|
|
ty::TyTuple(ref elements) => {
|
2015-04-24 16:48:10 +12:00
|
|
|
prepare_tuple_metadata(cx,
|
|
|
|
t,
|
|
|
|
&elements[..],
|
|
|
|
unique_type_id,
|
|
|
|
usage_site_span).finalize(cx)
|
|
|
|
}
|
|
|
|
_ => {
|
2017-05-13 17:11:52 +03:00
|
|
|
bug!("debuginfo: unexpected type in type_metadata: {:?}", t)
|
2015-04-24 16:48:10 +12:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
{
|
|
|
|
let mut type_map = debug_context(cx).type_map.borrow_mut();
|
|
|
|
|
|
|
|
if already_stored_in_typemap {
|
2015-10-07 23:11:25 +01:00
|
|
|
// Also make sure that we already have a TypeMap entry for the unique type id.
|
2015-04-24 16:48:10 +12:00
|
|
|
let metadata_for_uid = match type_map.find_metadata_for_unique_id(unique_type_id) {
|
|
|
|
Some(metadata) => metadata,
|
|
|
|
None => {
|
2016-03-29 01:46:02 +02: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-29 01:46:02 +02:00
|
|
|
t);
|
2015-04-24 16:48:10 +12:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
match type_map.find_metadata_for_type(t) {
|
|
|
|
Some(metadata) => {
|
|
|
|
if metadata != metadata_for_uid {
|
2016-03-29 01:46:02 +02: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-29 01:46:02 +02:00
|
|
|
t);
|
2015-04-24 16:48:10 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
None => {
|
2016-03-29 01:46:02 +02:00
|
|
|
type_map.register_type_with_metadata(t, metadata);
|
2015-04-24 16:48:10 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2016-03-29 01:46:02 +02:00
|
|
|
type_map.register_type_with_metadata(t, metadata);
|
|
|
|
type_map.register_unique_id_with_metadata(unique_type_id, metadata);
|
2015-04-24 16:48:10 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
metadata
|
|
|
|
}
|
|
|
|
|
2018-07-04 16:36:49 +03:00
|
|
|
pub fn file_metadata(cx: &CodegenCx<'ll, '_>,
|
2017-12-14 08:09:19 +01:00
|
|
|
file_name: &FileName,
|
2018-07-04 16:36:49 +03:00
|
|
|
defining_crate: CrateNum) -> &'ll DIFile {
|
2017-04-24 19:01:19 +02:00
|
|
|
debug!("file_metadata: file_name: {}, defining_crate: {}",
|
|
|
|
file_name,
|
|
|
|
defining_crate);
|
2015-04-24 16:48:10 +12:00
|
|
|
|
2017-04-24 19:01:19 +02:00
|
|
|
let directory = if defining_crate == LOCAL_CRATE {
|
2017-12-14 08:09:19 +01:00
|
|
|
&cx.sess().working_dir.0
|
2017-04-24 19:01:19 +02: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 08:09:19 +01:00
|
|
|
Path::new("")
|
2017-04-24 19:01:19 +02:00
|
|
|
};
|
|
|
|
|
2017-12-14 08:09:19 +01: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 13:53:59 +02:00
|
|
|
}
|
|
|
|
|
2018-07-04 16:36:49 +03:00
|
|
|
pub fn unknown_file_metadata(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile {
|
2017-04-24 19:01:19 +02: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 13:53:59 +02:00
|
|
|
}
|
|
|
|
|
2018-07-04 16:36:49 +03:00
|
|
|
fn file_metadata_raw(cx: &CodegenCx<'ll, '_>,
|
2017-04-24 19:01:19 +02:00
|
|
|
file_name: &str,
|
|
|
|
directory: &str)
|
2018-07-04 16:36:49 +03:00
|
|
|
-> &'ll DIFile {
|
2017-04-24 19:01:19 +02: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-13 22:43:30 -07: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 13:53:59 +02:00
|
|
|
}
|
|
|
|
|
2017-04-24 19:01:19 +02: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 13:53:59 +02:00
|
|
|
|
2015-04-24 16:48:10 +12:00
|
|
|
let file_name = CString::new(file_name).unwrap();
|
2017-04-24 19:01:19 +02:00
|
|
|
let directory = CString::new(directory).unwrap();
|
|
|
|
|
2015-04-24 16:48:10 +12:00
|
|
|
let file_metadata = unsafe {
|
2017-04-24 19:01:19 +02:00
|
|
|
llvm::LLVMRustDIBuilderCreateFile(DIB(cx),
|
|
|
|
file_name.as_ptr(),
|
|
|
|
directory.as_ptr())
|
2015-04-24 16:48:10 +12:00
|
|
|
};
|
|
|
|
|
|
|
|
let mut created_files = debug_context(cx).created_files.borrow_mut();
|
2017-04-24 19:01:19 +02: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 13:53:59 +02:00
|
|
|
file_metadata
|
2015-04-24 16:48:10 +12:00
|
|
|
}
|
|
|
|
|
2018-07-04 16:36:49 +03:00
|
|
|
fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
|
2015-04-24 16:48:10 +12:00
|
|
|
debug!("basic_type_metadata: {:?}", t);
|
|
|
|
|
|
|
|
let (name, encoding) = match t.sty {
|
2016-08-02 15:56:20 +08:00
|
|
|
ty::TyNever => ("!", DW_ATE_unsigned),
|
2018-01-21 13:33:21 +08:00
|
|
|
ty::TyTuple(ref elements) if elements.is_empty() =>
|
2015-11-23 15:59:36 +01:00
|
|
|
("()", DW_ATE_unsigned),
|
|
|
|
ty::TyBool => ("bool", DW_ATE_boolean),
|
|
|
|
ty::TyChar => ("char", DW_ATE_unsigned_char),
|
|
|
|
ty::TyInt(int_ty) => {
|
2015-11-28 19:02:07 +00:00
|
|
|
(int_ty.ty_to_string(), DW_ATE_signed)
|
2015-04-24 16:48:10 +12:00
|
|
|
},
|
2015-11-23 15:59:36 +01:00
|
|
|
ty::TyUint(uint_ty) => {
|
2015-11-28 19:02:07 +00:00
|
|
|
(uint_ty.ty_to_string(), DW_ATE_unsigned)
|
2015-04-24 16:48:10 +12:00
|
|
|
},
|
2015-11-23 15:59:36 +01:00
|
|
|
ty::TyFloat(float_ty) => {
|
2015-11-28 19:02:07 +00:00
|
|
|
(float_ty.ty_to_string(), DW_ATE_float)
|
2015-04-24 16:48:10 +12:00
|
|
|
},
|
2016-03-29 01:46:02 +02:00
|
|
|
_ => bug!("debuginfo::basic_type_metadata - t is invalid type")
|
2015-04-24 16:48:10 +12:00
|
|
|
};
|
|
|
|
|
2017-06-01 21:50:53 +03:00
|
|
|
let (size, align) = cx.size_and_align_of(t);
|
2015-04-24 16:48:10 +12:00
|
|
|
let name = CString::new(name).unwrap();
|
|
|
|
let ty_metadata = unsafe {
|
2016-08-02 02:35:09 +03:00
|
|
|
llvm::LLVMRustDIBuilderCreateBasicType(
|
2015-04-24 16:48:10 +12:00
|
|
|
DIB(cx),
|
|
|
|
name.as_ptr(),
|
2017-06-01 21:50:53 +03:00
|
|
|
size.bits(),
|
|
|
|
align.abi_bits() as u32,
|
2015-04-24 16:48:10 +12:00
|
|
|
encoding)
|
|
|
|
};
|
|
|
|
|
|
|
|
return ty_metadata;
|
|
|
|
}
|
|
|
|
|
2018-07-04 16:36:49 +03:00
|
|
|
fn foreign_type_metadata(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
t: Ty<'tcx>,
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
) -> &'ll DIType {
|
2017-09-03 19:53:58 +01:00
|
|
|
debug!("foreign_type_metadata: {:?}", t);
|
|
|
|
|
|
|
|
let name = compute_debuginfo_type_name(cx, t, false);
|
2017-06-01 21:50:53 +03:00
|
|
|
create_struct_stub(cx, t, &name, unique_type_id, NO_SCOPE_METADATA)
|
2017-09-03 19:53:58 +01:00
|
|
|
}
|
|
|
|
|
2018-07-04 16:36:49 +03:00
|
|
|
fn pointer_type_metadata(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
pointer_type: Ty<'tcx>,
|
|
|
|
pointee_type_metadata: &'ll DIType,
|
|
|
|
) -> &'ll DIType {
|
2017-06-01 21:50:53 +03:00
|
|
|
let (pointer_size, pointer_align) = cx.size_and_align_of(pointer_type);
|
2015-04-24 16:48:10 +12:00
|
|
|
let name = compute_debuginfo_type_name(cx, pointer_type, false);
|
|
|
|
let name = CString::new(name).unwrap();
|
2017-06-01 21:50:53 +03:00
|
|
|
unsafe {
|
2016-08-02 02:35:09 +03:00
|
|
|
llvm::LLVMRustDIBuilderCreatePointerType(
|
2015-04-24 16:48:10 +12:00
|
|
|
DIB(cx),
|
|
|
|
pointee_type_metadata,
|
2017-06-01 21:50:53 +03:00
|
|
|
pointer_size.bits(),
|
|
|
|
pointer_align.abi_bits() as u32,
|
2015-04-24 16:48:10 +12:00
|
|
|
name.as_ptr())
|
2017-06-01 21:50:53 +03:00
|
|
|
}
|
2015-04-24 16:48:10 +12:00
|
|
|
}
|
|
|
|
|
2018-01-05 06:14:44 +02:00
|
|
|
pub fn compile_unit_metadata(tcx: TyCtxt,
|
2017-05-19 10:55:25 +02:00
|
|
|
codegen_unit_name: &str,
|
2018-07-04 16:36:49 +03:00
|
|
|
debug_context: &CrateDebugContext<'ll, '_>)
|
|
|
|
-> &'ll DIDescriptor {
|
2018-01-05 06:14:44 +02:00
|
|
|
let mut name_in_debuginfo = match tcx.sess.local_crate_source_file {
|
2017-05-19 10:55:25 +02:00
|
|
|
Some(ref path) => path.clone(),
|
2018-01-05 06:14:44 +02:00
|
|
|
None => PathBuf::from(&*tcx.crate_name(LOCAL_CRATE).as_str()),
|
2015-04-24 16:48:10 +12:00
|
|
|
};
|
|
|
|
|
2017-05-19 10:55:25 +02: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 06:14:44 +02:00
|
|
|
if tcx.sess.target.target.options.is_like_osx {
|
2017-12-14 08:09:19 +01:00
|
|
|
name_in_debuginfo.push("@");
|
|
|
|
name_in_debuginfo.push(codegen_unit_name);
|
2017-05-19 10:55:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
debug!("compile_unit_metadata: {:?}", name_in_debuginfo);
|
2017-03-08 20:08:09 +02: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 16:48:10 +12:00
|
|
|
(option_env!("CFG_VERSION")).expect("CFG_VERSION"));
|
|
|
|
|
2017-12-14 08:09:19 +01:00
|
|
|
let name_in_debuginfo = name_in_debuginfo.to_string_lossy().into_owned();
|
2017-05-19 10:55:25 +02:00
|
|
|
let name_in_debuginfo = CString::new(name_in_debuginfo).unwrap();
|
2018-01-05 06:14:44 +02:00
|
|
|
let work_dir = CString::new(&tcx.sess.working_dir.0.to_string_lossy()[..]).unwrap();
|
2017-02-11 15:41:03 -06:00
|
|
|
let producer = CString::new(producer).unwrap();
|
2015-04-24 16:48:10 +12:00
|
|
|
let flags = "\0";
|
|
|
|
let split_name = "\0";
|
2017-02-11 15:01:25 -06:00
|
|
|
|
|
|
|
unsafe {
|
|
|
|
let file_metadata = llvm::LLVMRustDIBuilderCreateFile(
|
2017-05-19 10:55:25 +02:00
|
|
|
debug_context.builder, name_in_debuginfo.as_ptr(), work_dir.as_ptr());
|
2017-02-11 15:01:25 -06:00
|
|
|
|
2017-02-13 09:57:50 +00:00
|
|
|
let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit(
|
2016-07-13 00:40:38 +02:00
|
|
|
debug_context.builder,
|
2015-04-24 16:48:10 +12:00
|
|
|
DW_LANG_RUST,
|
2017-02-11 15:01:25 -06:00
|
|
|
file_metadata,
|
2017-02-11 15:41:03 -06:00
|
|
|
producer.as_ptr(),
|
2018-01-05 06:14:44 +02:00
|
|
|
tcx.sess.opts.optimize != config::OptLevel::No,
|
2015-04-24 16:48:10 +12:00
|
|
|
flags.as_ptr() as *const _,
|
|
|
|
0,
|
2017-02-13 09:57:50 +00:00
|
|
|
split_name.as_ptr() as *const _);
|
|
|
|
|
2018-01-05 06:14:44 +02:00
|
|
|
if tcx.sess.opts.debugging_opts.profile {
|
2017-06-04 17:50:25 +01: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 06:14:44 +02:00
|
|
|
&tcx.output_filenames(LOCAL_CRATE).with_extension("gcno")),
|
2017-06-04 19:53:42 +01:00
|
|
|
path_to_mdstring(debug_context.llcontext,
|
2018-01-05 06:14:44 +02:00
|
|
|
&tcx.output_filenames(LOCAL_CRATE).with_extension("gcda")),
|
2017-06-04 17:50:25 +01:00
|
|
|
cu_desc_metadata,
|
|
|
|
];
|
|
|
|
let gcov_metadata = llvm::LLVMMDNodeInContext(debug_context.llcontext,
|
|
|
|
gcov_cu_info.as_ptr(),
|
|
|
|
gcov_cu_info.len() as c_uint);
|
|
|
|
|
|
|
|
let llvm_gcov_ident = CString::new("llvm.gcov").unwrap();
|
|
|
|
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 16:48:10 +12:00
|
|
|
};
|
|
|
|
|
2018-07-10 13:28:39 +03:00
|
|
|
fn path_to_mdstring(llcx: &'ll llvm::Context, path: &Path) -> &'ll Value {
|
2017-02-13 09:57:50 +00:00
|
|
|
let path_str = path2cstr(path);
|
|
|
|
unsafe {
|
|
|
|
llvm::LLVMMDStringInContext(llcx,
|
|
|
|
path_str.as_ptr(),
|
|
|
|
path_str.as_bytes().len() as c_uint)
|
|
|
|
}
|
|
|
|
}
|
2015-04-24 16:48:10 +12:00
|
|
|
}
|
|
|
|
|
2018-07-04 16:36:49 +03:00
|
|
|
struct MetadataCreationResult<'ll> {
|
|
|
|
metadata: &'ll DIType,
|
2015-04-24 16:48:10 +12:00
|
|
|
already_stored_in_typemap: bool
|
|
|
|
}
|
|
|
|
|
2018-07-04 16:36:49 +03:00
|
|
|
impl MetadataCreationResult<'ll> {
|
|
|
|
fn new(metadata: &'ll DIType, already_stored_in_typemap: bool) -> Self {
|
2015-04-24 16:48:10 +12:00
|
|
|
MetadataCreationResult {
|
2017-08-06 22:54:09 -07:00
|
|
|
metadata,
|
|
|
|
already_stored_in_typemap,
|
2015-04-24 16:48:10 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-04-29 18:14:37 +12: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 14:41:08 +12:00
|
|
|
#[derive(Debug)]
|
2018-07-04 16:36:49 +03:00
|
|
|
struct MemberDescription<'ll> {
|
2015-04-29 18:14:37 +12:00
|
|
|
name: String,
|
2018-07-04 16:36:49 +03:00
|
|
|
type_metadata: &'ll DIType,
|
2017-06-01 21:50:53 +03:00
|
|
|
offset: Size,
|
|
|
|
size: Size,
|
|
|
|
align: Align,
|
2016-11-18 17:15:14 -05:00
|
|
|
flags: DIFlags,
|
2015-04-29 18:14:37 +12: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 16:36:49 +03:00
|
|
|
enum MemberDescriptionFactory<'ll, 'tcx> {
|
2015-04-29 18:14:37 +12:00
|
|
|
StructMDF(StructMemberDescriptionFactory<'tcx>),
|
|
|
|
TupleMDF(TupleMemberDescriptionFactory<'tcx>),
|
2018-07-04 16:36:49 +03:00
|
|
|
EnumMDF(EnumMemberDescriptionFactory<'ll, 'tcx>),
|
2016-08-22 21:11:22 +03:00
|
|
|
UnionMDF(UnionMemberDescriptionFactory<'tcx>),
|
2018-07-04 16:36:49 +03:00
|
|
|
VariantMDF(VariantMemberDescriptionFactory<'ll, 'tcx>)
|
2015-04-29 18:14:37 +12:00
|
|
|
}
|
|
|
|
|
2018-07-04 16:36:49 +03:00
|
|
|
impl MemberDescriptionFactory<'ll, 'tcx> {
|
|
|
|
fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
|
|
|
|
-> Vec<MemberDescription<'ll>> {
|
2015-04-29 18:14:37 +12: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 21:11:22 +03:00
|
|
|
UnionMDF(ref this) => {
|
|
|
|
this.create_member_descriptions(cx)
|
|
|
|
}
|
2015-04-29 18:14:37 +12:00
|
|
|
VariantMDF(ref this) => {
|
|
|
|
this.create_member_descriptions(cx)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
// Structs
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Creates MemberDescriptions for the fields of a struct
|
|
|
|
struct StructMemberDescriptionFactory<'tcx> {
|
2016-11-20 19:56:51 -05:00
|
|
|
ty: Ty<'tcx>,
|
2016-11-25 01:33:29 +02:00
|
|
|
variant: &'tcx ty::VariantDef,
|
2015-04-29 18:14:37 +12:00
|
|
|
span: Span,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> StructMemberDescriptionFactory<'tcx> {
|
2018-07-04 16:36:49 +03:00
|
|
|
fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
|
|
|
|
-> Vec<MemberDescription<'ll>> {
|
2016-11-20 19:56:51 -05:00
|
|
|
let layout = cx.layout_of(self.ty);
|
2015-08-02 22:52:50 +03:00
|
|
|
self.variant.fields.iter().enumerate().map(|(i, f)| {
|
2016-09-15 00:51:46 +03:00
|
|
|
let name = if self.variant.ctor_kind == CtorKind::Fn {
|
2015-04-29 18:14:37 +12:00
|
|
|
format!("__{}", i)
|
|
|
|
} else {
|
2018-05-26 02:50:15 +03:00
|
|
|
f.ident.to_string()
|
2015-04-29 18:14:37 +12:00
|
|
|
};
|
2017-06-25 12:41:24 +03:00
|
|
|
let field = layout.field(cx, i);
|
2017-09-22 22:44:40 +03:00
|
|
|
let (size, align) = field.size_and_align();
|
2015-04-29 18:14:37 +12:00
|
|
|
MemberDescription {
|
2017-08-06 22:54:09 -07:00
|
|
|
name,
|
2017-06-25 12:41:24 +03:00
|
|
|
type_metadata: type_metadata(cx, field.ty, self.span),
|
2017-09-17 23:37:18 +03:00
|
|
|
offset: layout.fields.offset(i),
|
2017-06-01 21:50:53 +03:00
|
|
|
size,
|
|
|
|
align,
|
2016-11-18 17:15:14 -05:00
|
|
|
flags: DIFlags::FlagZero,
|
2015-04-29 18:14:37 +12:00
|
|
|
}
|
|
|
|
}).collect()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-07-04 16:36:49 +03: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 18:14:37 +12:00
|
|
|
let struct_name = compute_debuginfo_type_name(cx, struct_type, false);
|
|
|
|
|
2017-06-25 12:41:24 +03:00
|
|
|
let (struct_def_id, variant) = match struct_type.sty {
|
2018-01-07 22:41:41 +01:00
|
|
|
ty::TyAdt(def, _) => (def.did, def.non_enum_variant()),
|
2016-09-06 01:26:02 +03:00
|
|
|
_ => bug!("prepare_struct_metadata on a non-ADT")
|
2015-08-02 22:52:50 +03:00
|
|
|
};
|
|
|
|
|
2017-07-07 14:23:38 +02:00
|
|
|
let containing_scope = get_namespace_for_item(cx, struct_def_id);
|
2015-04-29 18:14:37 +12:00
|
|
|
|
|
|
|
let struct_metadata_stub = create_struct_stub(cx,
|
2017-06-01 21:50:53 +03:00
|
|
|
struct_type,
|
2015-05-12 14:41:08 +12:00
|
|
|
&struct_name,
|
2015-04-29 18:14:37 +12:00
|
|
|
unique_type_id,
|
2018-07-04 16:36:49 +03:00
|
|
|
Some(containing_scope));
|
2015-04-29 18:14:37 +12:00
|
|
|
|
|
|
|
create_and_register_recursive_type_forward_declaration(
|
|
|
|
cx,
|
|
|
|
struct_type,
|
|
|
|
unique_type_id,
|
|
|
|
struct_metadata_stub,
|
|
|
|
StructMDF(StructMemberDescriptionFactory {
|
2016-11-20 19:56:51 -05:00
|
|
|
ty: struct_type,
|
2017-08-06 22:54:09 -07:00
|
|
|
variant,
|
|
|
|
span,
|
2015-04-29 18:14:37 +12:00
|
|
|
})
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
// Tuples
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Creates MemberDescriptions for the fields of a tuple
|
|
|
|
struct TupleMemberDescriptionFactory<'tcx> {
|
2016-11-20 19:56:51 -05:00
|
|
|
ty: Ty<'tcx>,
|
2015-04-29 18:14:37 +12:00
|
|
|
component_types: Vec<Ty<'tcx>>,
|
|
|
|
span: Span,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> TupleMemberDescriptionFactory<'tcx> {
|
2018-07-04 16:36:49 +03:00
|
|
|
fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
|
|
|
|
-> Vec<MemberDescription<'ll>> {
|
2016-11-20 19:56:51 -05:00
|
|
|
let layout = cx.layout_of(self.ty);
|
2017-06-01 21:50:53 +03:00
|
|
|
self.component_types.iter().enumerate().map(|(i, &component_type)| {
|
|
|
|
let (size, align) = cx.size_and_align_of(component_type);
|
2015-04-29 18:14:37 +12:00
|
|
|
MemberDescription {
|
|
|
|
name: format!("__{}", i),
|
|
|
|
type_metadata: type_metadata(cx, component_type, self.span),
|
2017-09-17 23:37:18 +03:00
|
|
|
offset: layout.fields.offset(i),
|
2017-06-01 21:50:53 +03:00
|
|
|
size,
|
|
|
|
align,
|
2016-11-18 17:15:14 -05:00
|
|
|
flags: DIFlags::FlagZero,
|
2015-04-29 18:14:37 +12:00
|
|
|
}
|
|
|
|
}).collect()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-04 16:36:49 +03: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 18:14:37 +12:00
|
|
|
let tuple_name = compute_debuginfo_type_name(cx, tuple_type, false);
|
|
|
|
|
|
|
|
create_and_register_recursive_type_forward_declaration(
|
|
|
|
cx,
|
|
|
|
tuple_type,
|
|
|
|
unique_type_id,
|
|
|
|
create_struct_stub(cx,
|
2017-06-01 21:50:53 +03:00
|
|
|
tuple_type,
|
2015-04-29 18:14:37 +12:00
|
|
|
&tuple_name[..],
|
|
|
|
unique_type_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 13:53:59 +02:00
|
|
|
NO_SCOPE_METADATA),
|
2015-04-29 18:14:37 +12:00
|
|
|
TupleMDF(TupleMemberDescriptionFactory {
|
2016-11-20 19:56:51 -05:00
|
|
|
ty: tuple_type,
|
2015-04-29 18:14:37 +12:00
|
|
|
component_types: component_types.to_vec(),
|
2017-08-06 22:54:09 -07:00
|
|
|
span,
|
2015-04-29 18:14:37 +12:00
|
|
|
})
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2016-08-22 21:11:22 +03:00
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
// Unions
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
struct UnionMemberDescriptionFactory<'tcx> {
|
2017-09-21 20:40:50 +03:00
|
|
|
layout: TyLayout<'tcx>,
|
2016-11-25 01:33:29 +02:00
|
|
|
variant: &'tcx ty::VariantDef,
|
2016-08-22 21:11:22 +03:00
|
|
|
span: Span,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> UnionMemberDescriptionFactory<'tcx> {
|
2018-07-04 16:36:49 +03:00
|
|
|
fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
|
|
|
|
-> Vec<MemberDescription<'ll>> {
|
2017-06-25 12:41:24 +03:00
|
|
|
self.variant.fields.iter().enumerate().map(|(i, f)| {
|
|
|
|
let field = self.layout.field(cx, i);
|
2017-09-22 22:44:40 +03:00
|
|
|
let (size, align) = field.size_and_align();
|
2016-08-22 21:11:22 +03:00
|
|
|
MemberDescription {
|
2018-05-26 02:50:15 +03:00
|
|
|
name: f.ident.to_string(),
|
2017-06-25 12:41:24 +03:00
|
|
|
type_metadata: type_metadata(cx, field.ty, self.span),
|
2018-05-20 14:14:39 +02:00
|
|
|
offset: Size::ZERO,
|
2017-06-01 21:50:53 +03:00
|
|
|
size,
|
|
|
|
align,
|
2016-11-18 17:15:14 -05:00
|
|
|
flags: DIFlags::FlagZero,
|
2016-08-22 21:11:22 +03:00
|
|
|
}
|
|
|
|
}).collect()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-04 16:36:49 +03: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 21:11:22 +03:00
|
|
|
let union_name = compute_debuginfo_type_name(cx, union_type, false);
|
|
|
|
|
2017-06-25 12:41:24 +03:00
|
|
|
let (union_def_id, variant) = match union_type.sty {
|
2018-01-07 22:41:41 +01:00
|
|
|
ty::TyAdt(def, _) => (def.did, def.non_enum_variant()),
|
2016-09-06 01:26:02 +03:00
|
|
|
_ => bug!("prepare_union_metadata on a non-ADT")
|
2016-08-22 21:11:22 +03:00
|
|
|
};
|
|
|
|
|
2017-07-07 14:23:38 +02:00
|
|
|
let containing_scope = get_namespace_for_item(cx, union_def_id);
|
2016-08-22 21:11:22 +03:00
|
|
|
|
|
|
|
let union_metadata_stub = create_union_stub(cx,
|
2017-06-01 21:50:53 +03:00
|
|
|
union_type,
|
2016-08-22 21:11:22 +03:00
|
|
|
&union_name,
|
|
|
|
unique_type_id,
|
|
|
|
containing_scope);
|
|
|
|
|
|
|
|
create_and_register_recursive_type_forward_declaration(
|
|
|
|
cx,
|
|
|
|
union_type,
|
|
|
|
unique_type_id,
|
|
|
|
union_metadata_stub,
|
|
|
|
UnionMDF(UnionMemberDescriptionFactory {
|
2017-06-25 12:41:24 +03:00
|
|
|
layout: cx.layout_of(union_type),
|
2017-08-06 22:54:09 -07:00
|
|
|
variant,
|
|
|
|
span,
|
2016-08-22 21:11:22 +03:00
|
|
|
})
|
|
|
|
)
|
|
|
|
}
|
2015-04-29 18:14:37 +12:00
|
|
|
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
// Enums
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// 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 16:36:49 +03:00
|
|
|
struct EnumMemberDescriptionFactory<'ll, 'tcx> {
|
2015-04-29 18:14:37 +12:00
|
|
|
enum_type: Ty<'tcx>,
|
2017-09-23 01:54:45 +03:00
|
|
|
layout: TyLayout<'tcx>,
|
2018-07-04 16:36:49 +03:00
|
|
|
discriminant_type_metadata: Option<&'ll DIType>,
|
|
|
|
containing_scope: &'ll DIScope,
|
2015-04-29 18:14:37 +12:00
|
|
|
span: Span,
|
|
|
|
}
|
|
|
|
|
2018-07-04 16:36:49 +03:00
|
|
|
impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
|
|
|
fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
|
|
|
|
-> Vec<MemberDescription<'ll>> {
|
2015-08-02 22:52:50 +03:00
|
|
|
let adt = &self.enum_type.ty_adt_def().unwrap();
|
2017-09-23 01:54:45 +03:00
|
|
|
match self.layout.variants {
|
2017-09-26 21:34:10 +03: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,
|
|
|
|
self.containing_scope,
|
|
|
|
self.span);
|
2015-04-29 18:14:37 +12:00
|
|
|
|
2017-09-26 21:34:10 +03:00
|
|
|
let member_descriptions =
|
|
|
|
member_description_factory.create_member_descriptions(cx);
|
2015-04-29 18:14:37 +12:00
|
|
|
|
2017-09-26 21:34:10 +03:00
|
|
|
set_members_of_composite_type(cx,
|
|
|
|
variant_type_metadata,
|
|
|
|
&member_descriptions[..]);
|
|
|
|
vec![
|
|
|
|
MemberDescription {
|
|
|
|
name: "".to_string(),
|
|
|
|
type_metadata: variant_type_metadata,
|
2018-05-20 14:14:39 +02:00
|
|
|
offset: Size::ZERO,
|
2017-09-26 21:34:10 +03:00
|
|
|
size: self.layout.size,
|
|
|
|
align: self.layout.align,
|
|
|
|
flags: DIFlags::FlagZero
|
|
|
|
}
|
|
|
|
]
|
2015-04-29 18:14:37 +12:00
|
|
|
}
|
2017-09-23 01:54:45 +03:00
|
|
|
layout::Variants::Tagged { ref variants, .. } => {
|
|
|
|
let discriminant_info = RegularDiscriminant(self.discriminant_type_metadata
|
|
|
|
.expect(""));
|
|
|
|
(0..variants.len()).map(|i| {
|
2017-09-26 21:34:10 +03:00
|
|
|
let variant = self.layout.for_variant(cx, i);
|
2017-09-23 01:54:45 +03:00
|
|
|
let (variant_type_metadata, member_desc_factory) =
|
|
|
|
describe_enum_variant(cx,
|
|
|
|
variant,
|
|
|
|
&adt.variants[i],
|
|
|
|
discriminant_info,
|
|
|
|
self.containing_scope,
|
|
|
|
self.span);
|
|
|
|
|
|
|
|
let member_descriptions = member_desc_factory
|
|
|
|
.create_member_descriptions(cx);
|
|
|
|
|
|
|
|
set_members_of_composite_type(cx,
|
|
|
|
variant_type_metadata,
|
|
|
|
&member_descriptions);
|
|
|
|
MemberDescription {
|
|
|
|
name: "".to_string(),
|
|
|
|
type_metadata: variant_type_metadata,
|
2018-05-20 14:14:39 +02:00
|
|
|
offset: Size::ZERO,
|
2017-09-23 01:54:45 +03:00
|
|
|
size: variant.size,
|
|
|
|
align: variant.align,
|
|
|
|
flags: DIFlags::FlagZero
|
|
|
|
}
|
|
|
|
}).collect()
|
|
|
|
}
|
2017-10-12 03:55:49 +03:00
|
|
|
layout::Variants::NicheFilling { dataful_variant, ref niche_variants, .. } => {
|
2017-09-26 21:34:10 +03:00
|
|
|
let variant = self.layout.for_variant(cx, dataful_variant);
|
2015-04-29 18:14:37 +12:00
|
|
|
// Create a description of the non-null variant
|
2017-06-01 21:50:53 +03:00
|
|
|
let (variant_type_metadata, member_description_factory) =
|
2015-04-29 18:14:37 +12:00
|
|
|
describe_enum_variant(cx,
|
2017-09-17 19:34:28 +03:00
|
|
|
variant,
|
2017-09-24 12:12:26 +03:00
|
|
|
&adt.variants[dataful_variant],
|
2015-04-29 18:14:37 +12:00
|
|
|
OptimizedDiscriminant,
|
|
|
|
self.containing_scope,
|
|
|
|
self.span);
|
|
|
|
|
|
|
|
let variant_member_descriptions =
|
|
|
|
member_description_factory.create_member_descriptions(cx);
|
|
|
|
|
|
|
|
set_members_of_composite_type(cx,
|
|
|
|
variant_type_metadata,
|
|
|
|
&variant_member_descriptions[..]);
|
|
|
|
|
|
|
|
// Encode the information about the null variant in the union
|
|
|
|
// member's name.
|
2017-09-11 22:31:16 +03:00
|
|
|
let mut name = String::from("RUST$ENCODED$ENUM$");
|
|
|
|
// HACK(eddyb) the debuggers should just handle offset+size
|
|
|
|
// of discriminant instead of us having to recover its path.
|
2017-10-12 03:55:49 +03:00
|
|
|
// Right now it's not even going to work for `niche_start > 0`,
|
|
|
|
// and for multiple niche variants it only supports the first.
|
2018-01-05 07:04:08 +02:00
|
|
|
fn compute_field_path<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
2017-09-11 22:31:16 +03:00
|
|
|
name: &mut String,
|
2017-09-21 20:40:50 +03:00
|
|
|
layout: TyLayout<'tcx>,
|
2017-09-11 22:31:16 +03:00
|
|
|
offset: Size,
|
|
|
|
size: Size) {
|
2017-09-13 14:35:04 +03:00
|
|
|
for i in 0..layout.fields.count() {
|
|
|
|
let field_offset = layout.fields.offset(i);
|
2017-09-11 22:31:16 +03:00
|
|
|
if field_offset > offset {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
let inner_offset = offset - field_offset;
|
2018-01-05 07:04:08 +02:00
|
|
|
let field = layout.field(cx, i);
|
2017-09-22 22:44:40 +03:00
|
|
|
if inner_offset + size <= field.size {
|
2017-09-11 22:31:16 +03:00
|
|
|
write!(name, "{}$", i).unwrap();
|
2018-01-05 07:04:08 +02:00
|
|
|
compute_field_path(cx, name, field, inner_offset, size);
|
2017-09-11 22:31:16 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
compute_field_path(cx, &mut name,
|
2017-09-23 01:54:45 +03:00
|
|
|
self.layout,
|
|
|
|
self.layout.fields.offset(0),
|
2017-09-24 12:12:26 +03:00
|
|
|
self.layout.field(cx, 0).size);
|
2018-04-06 05:21:47 +08:00
|
|
|
name.push_str(&adt.variants[*niche_variants.start()].name.as_str());
|
2015-04-29 18:14:37 +12:00
|
|
|
|
|
|
|
// Create the (singleton) list of descriptions of union members.
|
|
|
|
vec![
|
|
|
|
MemberDescription {
|
2017-09-11 22:31:16 +03:00
|
|
|
name,
|
2015-04-29 18:14:37 +12:00
|
|
|
type_metadata: variant_type_metadata,
|
2018-05-20 14:14:39 +02:00
|
|
|
offset: Size::ZERO,
|
2017-09-22 22:44:40 +03:00
|
|
|
size: variant.size,
|
|
|
|
align: variant.align,
|
2016-11-18 17:15:14 -05:00
|
|
|
flags: DIFlags::FlagZero
|
2015-04-29 18:14:37 +12:00
|
|
|
}
|
|
|
|
]
|
2017-09-23 01:54:45 +03:00
|
|
|
}
|
2015-04-29 18:14:37 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Creates MemberDescriptions for the fields of a single enum variant.
|
2018-07-04 16:36:49 +03:00
|
|
|
struct VariantMemberDescriptionFactory<'ll, 'tcx> {
|
2016-11-20 19:56:51 -05:00
|
|
|
// Cloned from the layout::Struct describing the variant.
|
2017-09-10 17:15:29 +03:00
|
|
|
offsets: Vec<layout::Size>,
|
2015-04-29 18:14:37 +12:00
|
|
|
args: Vec<(String, Ty<'tcx>)>,
|
2018-07-04 16:36:49 +03:00
|
|
|
discriminant_type_metadata: Option<&'ll DIType>,
|
2015-04-29 18:14:37 +12:00
|
|
|
span: Span,
|
|
|
|
}
|
|
|
|
|
2018-07-04 16:36:49 +03:00
|
|
|
impl VariantMemberDescriptionFactory<'ll, 'tcx> {
|
|
|
|
fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
|
|
|
|
-> Vec<MemberDescription<'ll>> {
|
2015-04-29 18:14:37 +12:00
|
|
|
self.args.iter().enumerate().map(|(i, &(ref name, ty))| {
|
2017-06-01 21:50:53 +03:00
|
|
|
let (size, align) = cx.size_and_align_of(ty);
|
2015-04-29 18:14:37 +12:00
|
|
|
MemberDescription {
|
|
|
|
name: name.to_string(),
|
|
|
|
type_metadata: match self.discriminant_type_metadata {
|
|
|
|
Some(metadata) if i == 0 => metadata,
|
|
|
|
_ => type_metadata(cx, ty, self.span)
|
|
|
|
},
|
2017-06-01 21:50:53 +03:00
|
|
|
offset: self.offsets[i],
|
|
|
|
size,
|
|
|
|
align,
|
2016-11-18 17:15:14 -05:00
|
|
|
flags: DIFlags::FlagZero
|
2015-04-29 18:14:37 +12:00
|
|
|
}
|
|
|
|
}).collect()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Copy, Clone)]
|
2018-07-04 16:36:49 +03:00
|
|
|
enum EnumDiscriminantInfo<'ll> {
|
|
|
|
RegularDiscriminant(&'ll DIType),
|
2015-04-29 18:14:37 +12:00
|
|
|
OptimizedDiscriminant,
|
|
|
|
NoDiscriminant
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns a tuple of (1) type_metadata_stub of the variant, (2) the llvm_type
|
|
|
|
// of the variant, and (3) a MemberDescriptionFactory for producing the
|
|
|
|
// descriptions of the fields of the variant. This is a rudimentary version of a
|
|
|
|
// full RecursiveTypeDescription.
|
2018-07-04 16:36:49 +03: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>) {
|
2015-08-02 22:52:50 +03:00
|
|
|
let variant_name = variant.name.as_str();
|
2015-04-29 18:14:37 +12:00
|
|
|
let unique_type_id = debug_context(cx).type_map
|
|
|
|
.borrow_mut()
|
|
|
|
.get_unique_type_id_of_enum_variant(
|
|
|
|
cx,
|
2017-09-17 19:34:28 +03:00
|
|
|
layout.ty,
|
2015-07-28 18:07:20 +02:00
|
|
|
&variant_name);
|
2015-04-29 18:14:37 +12:00
|
|
|
|
|
|
|
let metadata_stub = create_struct_stub(cx,
|
2017-09-17 19:34:28 +03:00
|
|
|
layout.ty,
|
2015-07-28 18:07:20 +02:00
|
|
|
&variant_name,
|
2015-04-29 18:14:37 +12:00
|
|
|
unique_type_id,
|
2018-07-04 16:36:49 +03:00
|
|
|
Some(containing_scope));
|
2015-04-29 18:14:37 +12:00
|
|
|
|
|
|
|
// If this is not a univariant enum, there is also the discriminant field.
|
2017-09-17 19:34:28 +03:00
|
|
|
let (discr_offset, discr_arg) = match discriminant_info {
|
2017-09-10 17:15:29 +03:00
|
|
|
RegularDiscriminant(_) => {
|
2017-09-17 19:34:28 +03:00
|
|
|
let enum_layout = cx.layout_of(layout.ty);
|
|
|
|
(Some(enum_layout.fields.offset(0)),
|
|
|
|
Some(("RUST$ENUM$DISR".to_string(), enum_layout.field(cx, 0).ty)))
|
2017-09-10 17:15:29 +03:00
|
|
|
}
|
2017-09-17 19:34:28 +03:00
|
|
|
_ => (None, None),
|
2015-04-29 18:14:37 +12:00
|
|
|
};
|
2017-09-17 19:34:28 +03:00
|
|
|
let offsets = discr_offset.into_iter().chain((0..layout.fields.count()).map(|i| {
|
|
|
|
layout.fields.offset(i)
|
|
|
|
})).collect();
|
2015-04-29 18:14:37 +12:00
|
|
|
|
|
|
|
// Build an array of (field name, field type) pairs to be captured in the factory closure.
|
2017-09-17 19:34:28 +03:00
|
|
|
let args = discr_arg.into_iter().chain((0..layout.fields.count()).map(|i| {
|
|
|
|
let name = if variant.ctor_kind == CtorKind::Fn {
|
|
|
|
format!("__{}", i)
|
|
|
|
} else {
|
2018-05-26 02:50:15 +03:00
|
|
|
variant.fields[i].ident.to_string()
|
2017-09-17 19:34:28 +03:00
|
|
|
};
|
|
|
|
(name, layout.field(cx, i).ty)
|
|
|
|
})).collect();
|
2015-04-29 18:14:37 +12:00
|
|
|
|
|
|
|
let member_description_factory =
|
|
|
|
VariantMDF(VariantMemberDescriptionFactory {
|
2017-09-10 17:15:29 +03:00
|
|
|
offsets,
|
2017-08-06 22:54:09 -07:00
|
|
|
args,
|
2015-04-29 18:14:37 +12:00
|
|
|
discriminant_type_metadata: match discriminant_info {
|
|
|
|
RegularDiscriminant(discriminant_type_metadata) => {
|
|
|
|
Some(discriminant_type_metadata)
|
|
|
|
}
|
|
|
|
_ => None
|
|
|
|
},
|
2017-08-06 22:54:09 -07:00
|
|
|
span,
|
2015-04-29 18:14:37 +12:00
|
|
|
});
|
|
|
|
|
2017-06-01 21:50:53 +03:00
|
|
|
(metadata_stub, member_description_factory)
|
2015-04-29 18:14:37 +12:00
|
|
|
}
|
|
|
|
|
2018-07-04 16:36:49 +03: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 18:14:37 +12:00
|
|
|
let enum_name = compute_debuginfo_type_name(cx, enum_type, false);
|
|
|
|
|
2017-07-07 14:23:38 +02: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 13:53:59 +02: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 18:14:37 +12:00
|
|
|
|
2017-02-05 07:01:48 +02:00
|
|
|
let def = enum_type.ty_adt_def().unwrap();
|
2018-06-27 13:12:47 +03:00
|
|
|
let enumerators_metadata: Vec<_> = def.discriminants(cx.tcx)
|
2017-02-05 07:01:48 +02:00
|
|
|
.zip(&def.variants)
|
|
|
|
.map(|(discr, v)| {
|
2015-07-28 18:07:20 +02:00
|
|
|
let token = v.name.as_str();
|
2015-04-29 18:14:37 +12:00
|
|
|
let name = CString::new(token.as_bytes()).unwrap();
|
|
|
|
unsafe {
|
2018-07-04 16:36:49 +03:00
|
|
|
Some(llvm::LLVMRustDIBuilderCreateEnumerator(
|
2015-04-29 18:14:37 +12:00
|
|
|
DIB(cx),
|
|
|
|
name.as_ptr(),
|
2016-08-23 03:56:52 +03:00
|
|
|
// FIXME: what if enumeration has i128 discriminant?
|
2018-06-27 13:12:47 +03:00
|
|
|
discr.val as u64))
|
2015-04-29 18:14:37 +12:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
|
2017-09-16 16:39:53 +03:00
|
|
|
let discriminant_type_metadata = |discr: layout::Primitive| {
|
2017-09-16 12:23:22 +03:00
|
|
|
let disr_type_key = (enum_def_id, discr);
|
2015-04-29 18:14:37 +12:00
|
|
|
let cached_discriminant_type_metadata = debug_context(cx).created_enum_disr_types
|
|
|
|
.borrow()
|
2015-07-16 01:34:13 -07:00
|
|
|
.get(&disr_type_key).cloned();
|
2015-04-29 18:14:37 +12:00
|
|
|
match cached_discriminant_type_metadata {
|
|
|
|
Some(discriminant_type_metadata) => discriminant_type_metadata,
|
|
|
|
None => {
|
|
|
|
let (discriminant_size, discriminant_align) =
|
2017-09-16 12:23:22 +03:00
|
|
|
(discr.size(cx), discr.align(cx));
|
2015-04-29 18:14:37 +12:00
|
|
|
let discriminant_base_type_metadata =
|
2018-01-05 06:58:34 +02:00
|
|
|
type_metadata(cx, discr.to_ty(cx.tcx), syntax_pos::DUMMY_SP);
|
2018-04-11 23:02:41 +02:00
|
|
|
let discriminant_name = get_enum_discriminant_name(cx, enum_def_id).as_str();
|
2015-04-29 18:14:37 +12:00
|
|
|
|
|
|
|
let name = CString::new(discriminant_name.as_bytes()).unwrap();
|
|
|
|
let discriminant_type_metadata = unsafe {
|
2016-08-02 02:35:09 +03:00
|
|
|
llvm::LLVMRustDIBuilderCreateEnumerationType(
|
2015-04-29 18:14:37 +12:00
|
|
|
DIB(cx),
|
|
|
|
containing_scope,
|
|
|
|
name.as_ptr(),
|
2016-07-07 08:15:10 -04:00
|
|
|
file_metadata,
|
2015-04-29 18:14:37 +12:00
|
|
|
UNKNOWN_LINE_NUMBER,
|
2017-06-01 21:50:53 +03:00
|
|
|
discriminant_size.bits(),
|
|
|
|
discriminant_align.abi_bits() as u32,
|
2015-04-29 18:14:37 +12:00
|
|
|
create_DIArray(DIB(cx), &enumerators_metadata),
|
|
|
|
discriminant_base_type_metadata)
|
|
|
|
};
|
|
|
|
|
|
|
|
debug_context(cx).created_enum_disr_types
|
|
|
|
.borrow_mut()
|
2015-07-16 01:34:13 -07:00
|
|
|
.insert(disr_type_key, discriminant_type_metadata);
|
2015-04-29 18:14:37 +12:00
|
|
|
|
|
|
|
discriminant_type_metadata
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-09-23 01:54:45 +03:00
|
|
|
let layout = cx.layout_of(enum_type);
|
2015-04-29 18:14:37 +12:00
|
|
|
|
2017-09-23 01:54:45 +03:00
|
|
|
let discriminant_type_metadata = match layout.variants {
|
|
|
|
layout::Variants::Single { .. } |
|
|
|
|
layout::Variants::NicheFilling { .. } => None,
|
2018-05-04 22:32:08 +12:00
|
|
|
layout::Variants::Tagged { ref tag, .. } => {
|
|
|
|
Some(discriminant_type_metadata(tag.value))
|
2017-09-26 14:41:06 +03:00
|
|
|
}
|
2015-04-29 18:14:37 +12:00
|
|
|
};
|
|
|
|
|
2017-09-26 14:41:06 +03:00
|
|
|
match (&layout.abi, discriminant_type_metadata) {
|
|
|
|
(&layout::Abi::Scalar(_), Some(discr)) => return FinalMetadata(discr),
|
2017-09-16 23:12:39 +03:00
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
2017-09-23 01:54:45 +03:00
|
|
|
let (enum_type_size, enum_type_align) = layout.size_and_align();
|
2015-04-29 18:14:37 +12:00
|
|
|
|
|
|
|
let enum_name = CString::new(enum_name).unwrap();
|
2016-11-19 05:55:28 +00:00
|
|
|
let unique_type_id_str = CString::new(
|
|
|
|
debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id).as_bytes()
|
|
|
|
).unwrap();
|
2015-04-29 18:14:37 +12:00
|
|
|
let enum_metadata = unsafe {
|
2016-08-02 02:35:09 +03:00
|
|
|
llvm::LLVMRustDIBuilderCreateUnionType(
|
2015-04-29 18:14:37 +12:00
|
|
|
DIB(cx),
|
|
|
|
containing_scope,
|
|
|
|
enum_name.as_ptr(),
|
rustc: Update LLVM
This commit updates the LLVM submodule in use to the current HEAD of the LLVM
repository. This is primarily being done to start picking up unwinding support
for MSVC, which is currently unimplemented in the revision of LLVM we are using.
Along the way a few changes had to be made:
* As usual, lots of C++ debuginfo bindings in LLVM changed, so there were some
significant changes to our RustWrapper.cpp
* As usual, some pass management changed in LLVM, so clang was re-scrutinized to
ensure that we're doing the same thing as clang.
* Some optimization options are now passed directly into the
`PassManagerBuilder` instead of through CLI switches to LLVM.
* The `NoFramePointerElim` option was removed from LLVM, favoring instead the
`no-frame-pointer-elim` function attribute instead.
Additionally, LLVM has picked up some new optimizations which required fixing an
existing soundness hole in the IR we generate. It appears that the current LLVM
we use does not expose this hole. When an enum is moved, the previous slot in
memory is overwritten with a bit pattern corresponding to "dropped". When the
drop glue for this slot is run, however, the switch on the discriminant can
often start executing the `unreachable` block of the switch due to the
discriminant now being outside the normal range. This was patched over locally
for now by having the `unreachable` block just change to a `ret void`.
2015-05-14 12:10:43 -07:00
|
|
|
file_metadata,
|
2015-04-29 18:14:37 +12:00
|
|
|
UNKNOWN_LINE_NUMBER,
|
2017-06-01 21:50:53 +03:00
|
|
|
enum_type_size.bits(),
|
|
|
|
enum_type_align.abi_bits() as u32,
|
2016-11-18 17:15:14 -05:00
|
|
|
DIFlags::FlagZero,
|
2018-06-27 13:12:47 +03:00
|
|
|
None,
|
2015-04-29 18:14:37 +12:00
|
|
|
0, // RuntimeLang
|
|
|
|
unique_type_id_str.as_ptr())
|
|
|
|
};
|
|
|
|
|
|
|
|
return create_and_register_recursive_type_forward_declaration(
|
|
|
|
cx,
|
|
|
|
enum_type,
|
|
|
|
unique_type_id,
|
|
|
|
enum_metadata,
|
|
|
|
EnumMDF(EnumMemberDescriptionFactory {
|
2017-08-06 22:54:09 -07:00
|
|
|
enum_type,
|
2017-09-23 01:54:45 +03:00
|
|
|
layout,
|
2017-08-06 22:54:09 -07:00
|
|
|
discriminant_type_metadata,
|
|
|
|
containing_scope,
|
|
|
|
span,
|
2015-04-29 18:14:37 +12:00
|
|
|
}),
|
|
|
|
);
|
|
|
|
|
2018-01-05 07:01:54 +02:00
|
|
|
fn get_enum_discriminant_name(cx: &CodegenCx,
|
2015-08-16 06:32:28 -04:00
|
|
|
def_id: DefId)
|
2016-11-16 08:21:52 +00:00
|
|
|
-> InternedString {
|
2018-01-05 06:58:34 +02:00
|
|
|
cx.tcx.item_name(def_id)
|
2015-04-29 18:14:37 +12: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 16:36:49 +03:00
|
|
|
fn composite_type_metadata(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
composite_type: Ty<'tcx>,
|
|
|
|
composite_type_name: &str,
|
|
|
|
composite_type_unique_id: UniqueTypeId,
|
|
|
|
member_descriptions: &[MemberDescription<'ll>],
|
|
|
|
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 18:14:37 +12:00
|
|
|
// Create the (empty) struct metadata node ...
|
|
|
|
let composite_type_metadata = create_struct_stub(cx,
|
2017-06-01 21:50:53 +03:00
|
|
|
composite_type,
|
2015-04-29 18:14:37 +12:00
|
|
|
composite_type_name,
|
|
|
|
composite_type_unique_id,
|
|
|
|
containing_scope);
|
|
|
|
// ... and immediately create and add the member descriptions.
|
|
|
|
set_members_of_composite_type(cx,
|
|
|
|
composite_type_metadata,
|
|
|
|
member_descriptions);
|
|
|
|
|
|
|
|
return composite_type_metadata;
|
|
|
|
}
|
|
|
|
|
2018-07-04 16:36:49 +03:00
|
|
|
fn set_members_of_composite_type(cx: &CodegenCx<'ll, '_>,
|
|
|
|
composite_type_metadata: &'ll DICompositeType,
|
|
|
|
member_descriptions: &[MemberDescription<'ll>]) {
|
2015-04-29 18:14:37 +12: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-29 01:46:02 +02:00
|
|
|
bug!("debuginfo::set_members_of_composite_type() - \
|
|
|
|
Already completed forward declaration re-encountered.");
|
2015-04-29 18:14:37 +12:00
|
|
|
} else {
|
|
|
|
composite_types_completed.insert(composite_type_metadata);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-27 13:12:47 +03:00
|
|
|
let member_metadata: Vec<_> = member_descriptions
|
2015-04-29 18:14:37 +12:00
|
|
|
.iter()
|
2017-06-01 21:50:53 +03:00
|
|
|
.map(|member_description| {
|
2015-04-29 18:14:37 +12:00
|
|
|
let member_name = member_description.name.as_bytes();
|
|
|
|
let member_name = CString::new(member_name).unwrap();
|
|
|
|
unsafe {
|
2018-07-04 16:36:49 +03:00
|
|
|
Some(llvm::LLVMRustDIBuilderCreateMemberType(
|
2015-04-29 18:14:37 +12:00
|
|
|
DIB(cx),
|
|
|
|
composite_type_metadata,
|
|
|
|
member_name.as_ptr(),
|
2016-07-07 08:15:10 -04:00
|
|
|
unknown_file_metadata(cx),
|
2015-04-29 18:14:37 +12:00
|
|
|
UNKNOWN_LINE_NUMBER,
|
2017-06-01 21:50:53 +03:00
|
|
|
member_description.size.bits(),
|
|
|
|
member_description.align.abi_bits() as u32,
|
|
|
|
member_description.offset.bits(),
|
2015-04-29 18:14:37 +12:00
|
|
|
member_description.flags,
|
2018-06-27 13:12:47 +03:00
|
|
|
member_description.type_metadata))
|
2015-04-29 18:14:37 +12:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
let type_array = create_DIArray(DIB(cx), &member_metadata[..]);
|
2016-08-02 02:35:09 +03:00
|
|
|
llvm::LLVMRustDICompositeTypeSetTypeArray(
|
|
|
|
DIB(cx), composite_type_metadata, type_array);
|
2015-04-29 18:14:37 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-02 02:35:09 +03: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 16:36:49 +03: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 21:50:53 +03:00
|
|
|
let (struct_size, struct_align) = cx.size_and_align_of(struct_type);
|
2015-04-29 18:14:37 +12:00
|
|
|
|
|
|
|
let name = CString::new(struct_type_name).unwrap();
|
2016-11-19 05:55:28 +00:00
|
|
|
let unique_type_id = CString::new(
|
|
|
|
debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id).as_bytes()
|
|
|
|
).unwrap();
|
2015-04-29 18:14:37 +12:00
|
|
|
let metadata_stub = unsafe {
|
2016-08-02 02:35:09 +03:00
|
|
|
// LLVMRustDIBuilderCreateStructType() wants an empty array. A null
|
2015-04-29 18:14:37 +12: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-02 02:35:09 +03:00
|
|
|
llvm::LLVMRustDIBuilderCreateStructType(
|
2015-04-29 18:14:37 +12:00
|
|
|
DIB(cx),
|
|
|
|
containing_scope,
|
|
|
|
name.as_ptr(),
|
2016-07-07 08:15:10 -04:00
|
|
|
unknown_file_metadata(cx),
|
2015-04-29 18:14:37 +12:00
|
|
|
UNKNOWN_LINE_NUMBER,
|
2017-06-01 21:50:53 +03:00
|
|
|
struct_size.bits(),
|
|
|
|
struct_align.abi_bits() as u32,
|
2016-11-18 17:15:14 -05:00
|
|
|
DIFlags::FlagZero,
|
2018-06-27 13:12:47 +03:00
|
|
|
None,
|
2015-04-29 18:14:37 +12:00
|
|
|
empty_array,
|
|
|
|
0,
|
2018-06-27 13:12:47 +03:00
|
|
|
None,
|
2015-04-29 18:14:37 +12:00
|
|
|
unique_type_id.as_ptr())
|
|
|
|
};
|
|
|
|
|
|
|
|
return metadata_stub;
|
|
|
|
}
|
|
|
|
|
2018-07-04 16:36:49 +03: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 21:50:53 +03:00
|
|
|
let (union_size, union_align) = cx.size_and_align_of(union_type);
|
2016-08-22 21:11:22 +03:00
|
|
|
|
|
|
|
let name = CString::new(union_type_name).unwrap();
|
2016-11-19 05:55:28 +00:00
|
|
|
let unique_type_id = CString::new(
|
|
|
|
debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id).as_bytes()
|
|
|
|
).unwrap();
|
2016-08-22 21:11:22 +03: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 21:50:53 +03:00
|
|
|
union_size.bits(),
|
|
|
|
union_align.abi_bits() as u32,
|
2016-11-18 17:15:14 -05:00
|
|
|
DIFlags::FlagZero,
|
2018-07-04 16:36:49 +03:00
|
|
|
Some(empty_array),
|
2016-08-22 21:11:22 +03:00
|
|
|
0, // RuntimeLang
|
|
|
|
unique_type_id.as_ptr())
|
|
|
|
};
|
|
|
|
|
|
|
|
return metadata_stub;
|
|
|
|
}
|
|
|
|
|
2015-04-29 18:14:37 +12:00
|
|
|
/// Creates debug information for the given global variable.
|
|
|
|
///
|
|
|
|
/// Adds the created metadata nodes directly to the crate's IR.
|
2018-07-10 13:28:39 +03:00
|
|
|
pub fn create_global_var_metadata(
|
|
|
|
cx: &CodegenCx<'ll, '_>,
|
|
|
|
def_id: DefId,
|
|
|
|
global: &'ll Value,
|
|
|
|
) {
|
2018-01-05 06:58:34 +02:00
|
|
|
if cx.dbg_cx.is_none() {
|
2015-04-29 18:14:37 +12:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-01-05 06:58:34 +02:00
|
|
|
let tcx = cx.tcx;
|
2018-05-08 16:10:16 +03:00
|
|
|
let attrs = tcx.codegen_fn_attrs(def_id);
|
2018-04-12 14:52:09 +02:00
|
|
|
|
2018-05-08 16:10:16 +03:00
|
|
|
if attrs.flags.contains(CodegenFnAttrFlags::NO_DEBUG) {
|
2018-04-12 14:52:09 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-05-08 16:10:16 +03:00
|
|
|
let no_mangle = attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE);
|
2017-12-19 21:18:24 -08: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 12:41:10 +01:00
|
|
|
let var_scope = get_namespace_for_item(cx, def_id);
|
2018-04-12 14:52:09 +02:00
|
|
|
let span = tcx.def_span(def_id);
|
2015-04-29 18:14:37 +12:00
|
|
|
|
2018-06-25 01:00:21 +03:00
|
|
|
let (file_metadata, line_number) = if !span.is_dummy() {
|
2015-04-29 18:14:37 +12:00
|
|
|
let loc = span_start(cx, span);
|
2017-04-24 19:01:19 +02:00
|
|
|
(file_metadata(cx, &loc.file.name, LOCAL_CRATE), loc.line as c_uint)
|
2015-04-29 18:14:37 +12:00
|
|
|
} else {
|
2016-07-07 08:15:10 -04:00
|
|
|
(unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
|
2015-04-29 18:14:37 +12:00
|
|
|
};
|
|
|
|
|
2018-02-19 12:41:10 +01: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 18:14:37 +12:00
|
|
|
let type_metadata = type_metadata(cx, variable_type, span);
|
2018-02-19 12:41:10 +01:00
|
|
|
let var_name = tcx.item_name(def_id).to_string();
|
2015-04-29 18:14:37 +12:00
|
|
|
let var_name = CString::new(var_name).unwrap();
|
2017-12-19 21:18:24 -08:00
|
|
|
let linkage_name = if no_mangle {
|
|
|
|
None
|
|
|
|
} else {
|
2018-02-19 12:41:10 +01:00
|
|
|
let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id));
|
2017-12-20 21:28:10 -08:00
|
|
|
Some(CString::new(linkage_name.to_string()).unwrap())
|
2017-12-19 21:18:24 -08:00
|
|
|
};
|
2016-11-18 11:11:18 -05:00
|
|
|
|
2017-03-02 05:35:25 +02:00
|
|
|
let global_align = cx.align_of(variable_type);
|
2016-11-18 11:11:18 -05:00
|
|
|
|
2015-04-29 18:14:37 +12:00
|
|
|
unsafe {
|
2016-08-02 02:35:09 +03:00
|
|
|
llvm::LLVMRustDIBuilderCreateStaticVariable(DIB(cx),
|
2018-07-04 16:36:49 +03:00
|
|
|
Some(var_scope),
|
2016-08-02 02:35:09 +03:00
|
|
|
var_name.as_ptr(),
|
2017-12-19 21:18:24 -08: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-02 02:35:09 +03:00
|
|
|
file_metadata,
|
|
|
|
line_number,
|
|
|
|
type_metadata,
|
|
|
|
is_local_to_unit,
|
|
|
|
global,
|
2018-06-27 13:12:47 +03:00
|
|
|
None,
|
2017-06-01 21:50:53 +03:00
|
|
|
global_align.abi() as u32,
|
2016-11-18 11:11:18 -05:00
|
|
|
);
|
2015-04-29 18:14:37 +12:00
|
|
|
}
|
|
|
|
}
|
2016-08-24 19:34:31 -07:00
|
|
|
|
|
|
|
// Creates an "extension" of an existing DIScope into another file.
|
2018-07-04 16:36:49 +03:00
|
|
|
pub fn extend_scope_to_file(
|
|
|
|
cx: &CodegenCx<'ll, '_>,
|
|
|
|
scope_metadata: &'ll DIScope,
|
|
|
|
file: &syntax_pos::FileMap,
|
|
|
|
defining_crate: CrateNum,
|
|
|
|
) -> &'ll DILexicalBlock {
|
2018-01-05 07:04:08 +02:00
|
|
|
let file_metadata = file_metadata(cx, &file.name, defining_crate);
|
2016-08-24 19:34:31 -07:00
|
|
|
unsafe {
|
|
|
|
llvm::LLVMRustDIBuilderCreateLexicalBlockFile(
|
2018-01-05 07:04:08 +02:00
|
|
|
DIB(cx),
|
2016-08-24 19:34:31 -07:00
|
|
|
scope_metadata,
|
|
|
|
file_metadata)
|
|
|
|
}
|
2016-08-26 19:23:42 +03:00
|
|
|
}
|
2017-05-27 13:46:42 -06: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.
|
2018-07-10 13:28:39 +03:00
|
|
|
pub fn create_vtable_metadata(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
ty: ty::Ty<'tcx>,
|
|
|
|
vtable: &'ll Value,
|
|
|
|
) {
|
2018-01-05 06:58:34 +02:00
|
|
|
if cx.dbg_cx.is_none() {
|
2017-05-27 13:46:42 -06:00
|
|
|
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 = CString::new("vtable").unwrap();
|
|
|
|
|
|
|
|
// 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,
|
2018-05-20 14:14:39 +02:00
|
|
|
Size::ZERO.bits(),
|
2018-01-05 06:58:34 +02:00
|
|
|
cx.tcx.data_layout.pointer_align.abi_bits() as u32,
|
2017-05-27 13:46:42 -06:00
|
|
|
DIFlags::FlagArtificial,
|
2018-06-27 13:12:47 +03:00
|
|
|
None,
|
2017-05-27 13:46:42 -06:00
|
|
|
empty_array,
|
|
|
|
0,
|
2018-07-04 16:36:49 +03:00
|
|
|
Some(type_metadata),
|
2017-05-27 13:46:42 -06:00
|
|
|
name.as_ptr()
|
|
|
|
);
|
|
|
|
|
|
|
|
llvm::LLVMRustDIBuilderCreateStaticVariable(DIB(cx),
|
|
|
|
NO_SCOPE_METADATA,
|
|
|
|
name.as_ptr(),
|
|
|
|
// LLVM 3.9
|
|
|
|
// doesn't accept
|
|
|
|
// null here, so
|
|
|
|
// pass the name
|
|
|
|
// as the linkage
|
|
|
|
// name.
|
|
|
|
name.as_ptr(),
|
|
|
|
unknown_file_metadata(cx),
|
|
|
|
UNKNOWN_LINE_NUMBER,
|
|
|
|
vtable_type,
|
|
|
|
true,
|
|
|
|
vtable,
|
2018-06-27 13:12:47 +03:00
|
|
|
None,
|
2017-05-27 13:46:42 -06:00
|
|
|
0);
|
|
|
|
}
|
|
|
|
}
|