use super::utils::{debug_context, DIB, span_start, bytes_to_bits, size_and_align_of,
get_namespace_and_span_for_item, create_DIArray, is_node_local_to_unit};
use super::namespace::mangled_name_of_item;
-use super::type_names::{compute_debuginfo_type_name, push_debuginfo_type_name};
+use super::type_names::compute_debuginfo_type_name;
use super::{CrateDebugContext};
use context::SharedCrateContext;
use session::Session;
use rustc::hir::def::CtorKind;
use rustc::hir::def_id::DefId;
+use rustc::ty::fold::TypeVisitor;
use rustc::ty::subst::Substs;
+use rustc::ty::util::TypeIdHasher;
use rustc::hir;
+use rustc_data_structures::blake2b;
use {type_of, machine, monomorphize};
use common::CrateContext;
use type_::Type;
use libc::{c_uint, c_longlong};
use std::ffi::CString;
+use std::fmt::Write;
use std::path::Path;
use std::ptr;
use std::rc::Rc;
use syntax::parse::token;
use syntax_pos::{self, Span};
+
// From DWARF 5.
// See http://www.dwarfstd.org/ShowIssue.php?issue=140129.1
const DW_LANG_RUST: c_uint = 0x1c;
// ID will be generated and stored for later lookup.
fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>,
type_: Ty<'tcx>) -> UniqueTypeId {
-
- // basic type -> {:name of the type:}
- // tuple -> {tuple_(:param-uid:)*}
- // struct -> {struct_:svh: / :node-id:_<(:param-uid:),*> }
- // enum -> {enum_:svh: / :node-id:_<(:param-uid:),*> }
- // enum variant -> {variant_:variant-name:_:enum-uid:}
- // reference (&) -> {& :pointee-uid:}
- // mut reference (&mut) -> {&mut :pointee-uid:}
- // ptr (*) -> {* :pointee-uid:}
- // mut ptr (*mut) -> {*mut :pointee-uid:}
- // unique ptr (box) -> {box :pointee-uid:}
- // @-ptr (@) -> {@ :pointee-uid:}
- // sized vec ([T; x]) -> {[:size:] :element-uid:}
- // unsized vec ([T]) -> {[] :element-uid:}
- // trait (T) -> {trait_:svh: / :node-id:_<(:param-uid:),*> }
- // closure -> {<unsafe_> <once_> :store-sigil: |(:param-uid:),* <,_...>| -> \
- // :return-type-uid: : (:bounds:)*}
- // function -> {<unsafe_> <abi_> fn( (:param-uid:)* <,_...> ) -> \
- // :return-type-uid:}
-
+ // Let's see if we already have something in the cache
match self.type_to_unique_id.get(&type_).cloned() {
Some(unique_type_id) => return unique_type_id,
None => { /* generate one */}
};
- let mut unique_type_id = String::with_capacity(256);
- unique_type_id.push('{');
-
- match type_.sty {
- ty::TyNever |
- ty::TyBool |
- ty::TyChar |
- ty::TyStr |
- ty::TyInt(_) |
- ty::TyUint(_) |
- ty::TyFloat(_) => {
- push_debuginfo_type_name(cx, type_, false, &mut unique_type_id);
- },
- ty::TyAdt(def, substs) => {
- unique_type_id.push_str(&(String::from(def.descr()) + " "));
- from_def_id_and_substs(self, cx, def.did, substs, &mut unique_type_id);
- }
- ty::TyTuple(component_types) if component_types.is_empty() => {
- push_debuginfo_type_name(cx, type_, false, &mut unique_type_id);
- },
- ty::TyTuple(component_types) => {
- unique_type_id.push_str("tuple ");
- for &component_type in component_types {
- let component_type_id =
- self.get_unique_type_id_of_type(cx, component_type);
- let component_type_id =
- self.get_unique_type_id_as_string(component_type_id);
- unique_type_id.push_str(&component_type_id[..]);
- }
- },
- ty::TyBox(inner_type) => {
- unique_type_id.push_str("box ");
- let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
- let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
- unique_type_id.push_str(&inner_type_id[..]);
- },
- ty::TyRawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => {
- unique_type_id.push('*');
- if mutbl == hir::MutMutable {
- unique_type_id.push_str("mut");
- }
+ let mut type_id_hasher = TypeIdHasher::new(cx.tcx(),
+ DebugInfoTypeIdHasher::new());
+ type_id_hasher.visit_ty(type_);
+ let hash = type_id_hasher.into_inner().into_hash();
- let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
- let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
- unique_type_id.push_str(&inner_type_id[..]);
- },
- ty::TyRef(_, ty::TypeAndMut { ty: inner_type, mutbl }) => {
- unique_type_id.push('&');
- if mutbl == hir::MutMutable {
- unique_type_id.push_str("mut");
- }
+ let mut unique_type_id = String::with_capacity(TYPE_ID_HASH_LENGTH * 2);
- let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
- let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
- unique_type_id.push_str(&inner_type_id[..]);
- },
- ty::TyArray(inner_type, len) => {
- unique_type_id.push_str(&format!("[{}]", len));
-
- let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
- let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
- unique_type_id.push_str(&inner_type_id[..]);
- },
- ty::TySlice(inner_type) => {
- unique_type_id.push_str("[]");
-
- let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
- let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
- unique_type_id.push_str(&inner_type_id[..]);
- },
- ty::TyTrait(ref trait_data) => {
- unique_type_id.push_str("trait ");
-
- let principal = cx.tcx().erase_late_bound_regions_and_normalize(
- &trait_data.principal);
-
- from_def_id_and_substs(self,
- cx,
- principal.def_id,
- principal.substs,
- &mut unique_type_id);
- },
- ty::TyFnDef(.., &ty::BareFnTy{ unsafety, abi, ref sig } ) |
- ty::TyFnPtr(&ty::BareFnTy{ unsafety, abi, ref sig } ) => {
- if unsafety == hir::Unsafety::Unsafe {
- unique_type_id.push_str("unsafe ");
- }
-
- unique_type_id.push_str(abi.name());
+ for byte in hash.into_iter() {
+ write!(&mut unique_type_id, "{:x}", byte).unwrap();
+ }
- unique_type_id.push_str(" fn(");
+ let key = self.unique_id_interner.intern(&unique_type_id);
+ self.type_to_unique_id.insert(type_, UniqueTypeId(key));
- let sig = cx.tcx().erase_late_bound_regions_and_normalize(sig);
+ return UniqueTypeId(key);
- for ¶meter_type in &sig.inputs {
- let parameter_type_id =
- self.get_unique_type_id_of_type(cx, parameter_type);
- let parameter_type_id =
- self.get_unique_type_id_as_string(parameter_type_id);
- unique_type_id.push_str(¶meter_type_id[..]);
- unique_type_id.push(',');
- }
+ // The hasher we are using to generate the UniqueTypeId. We want
+ // something that provides more than the 64 bits of the DefaultHasher.
+ const TYPE_ID_HASH_LENGTH: usize = 20;
- if sig.variadic {
- unique_type_id.push_str("...");
- }
+ struct DebugInfoTypeIdHasher {
+ state: blake2b::Blake2bCtx
+ }
- unique_type_id.push_str(")->");
- let return_type_id = self.get_unique_type_id_of_type(cx, sig.output);
- let return_type_id = self.get_unique_type_id_as_string(return_type_id);
- unique_type_id.push_str(&return_type_id[..]);
- },
- ty::TyClosure(_, substs) if substs.upvar_tys.is_empty() => {
- push_debuginfo_type_name(cx, type_, false, &mut unique_type_id);
- },
- ty::TyClosure(_, substs) => {
- unique_type_id.push_str("closure ");
- for upvar_type in substs.upvar_tys {
- let upvar_type_id =
- self.get_unique_type_id_of_type(cx, upvar_type);
- let upvar_type_id =
- self.get_unique_type_id_as_string(upvar_type_id);
- unique_type_id.push_str(&upvar_type_id[..]);
- }
- },
- _ => {
- bug!("get_unique_type_id_of_type() - unexpected type: {:?}",
- type_)
+ impl ::std::hash::Hasher for DebugInfoTypeIdHasher {
+ fn finish(&self) -> u64 {
+ unimplemented!()
}
- };
-
- unique_type_id.push('}');
- // Trim to size before storing permanently
- unique_type_id.shrink_to_fit();
-
- let key = self.unique_id_interner.intern(&unique_type_id);
- self.type_to_unique_id.insert(type_, UniqueTypeId(key));
-
- return UniqueTypeId(key);
-
- fn from_def_id_and_substs<'a, 'tcx>(type_map: &mut TypeMap<'tcx>,
- cx: &CrateContext<'a, 'tcx>,
- def_id: DefId,
- substs: &Substs<'tcx>,
- output: &mut String) {
- // First, find out the 'real' def_id of the type. Items inlined from
- // other crates have to be mapped back to their source.
- let def_id = if let Some(node_id) = cx.tcx().map.as_local_node_id(def_id) {
- if cx.tcx().map.is_inlined_node_id(node_id) {
- // The given def_id identifies the inlined copy of a
- // type definition, let's take the source of the copy.
- cx.defid_for_inlined_node(node_id).unwrap()
- } else {
- def_id
- }
- } else {
- def_id
- };
+ #[inline]
+ fn write(&mut self, bytes: &[u8]) {
+ blake2b::blake2b_update(&mut self.state, bytes);
+ }
+ }
- // Get the crate name/disambiguator as first part of the identifier.
- let crate_name = if def_id.is_local() {
- cx.tcx().crate_name.clone()
- } else {
- cx.sess().cstore.original_crate_name(def_id.krate)
- };
- let crate_disambiguator = cx.tcx().crate_disambiguator(def_id.krate);
-
- output.push_str(&crate_name[..]);
- output.push_str("/");
- output.push_str(&crate_disambiguator[..]);
- output.push_str("/");
- // Add the def-index as the second part
- output.push_str(&format!("{:x}", def_id.index.as_usize()));
-
- if substs.types().next().is_some() {
- output.push('<');
-
- for type_parameter in substs.types() {
- let param_type_id =
- type_map.get_unique_type_id_of_type(cx, type_parameter);
- let param_type_id =
- type_map.get_unique_type_id_as_string(param_type_id);
- output.push_str(¶m_type_id[..]);
- output.push(',');
+ impl DebugInfoTypeIdHasher {
+ fn new() -> DebugInfoTypeIdHasher {
+ DebugInfoTypeIdHasher {
+ state: blake2b::blake2b_new(TYPE_ID_HASH_LENGTH, &[])
}
+ }
- output.push('>');
+ fn into_hash(self) -> [u8; TYPE_ID_HASH_LENGTH] {
+ let mut hash = [0u8; TYPE_ID_HASH_LENGTH];
+ blake2b::blake2b_final(self.state, &mut hash);
+ hash
}
}
}