From: Michael Woerister Date: Fri, 21 Oct 2016 21:56:36 +0000 (-0400) Subject: debuginfo: Use TypeIdHasher to create global type identifiers for debuginfo. X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=c52836c888c73df53c58a154342292798f729c0a;p=rust.git debuginfo: Use TypeIdHasher to create global type identifiers for debuginfo. --- diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 570b844f80a..11355761a9c 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -16,7 +16,7 @@ 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; @@ -26,8 +26,11 @@ 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; @@ -38,6 +41,7 @@ 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; @@ -46,6 +50,7 @@ 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; @@ -138,219 +143,58 @@ fn get_unique_type_id_as_string(&self, unique_type_id: UniqueTypeId) -> Rc // 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 -> { :store-sigil: |(:param-uid:),* <,_...>| -> \ - // :return-type-uid: : (:bounds:)*} - // function -> { 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 } } }