From 5b093ebab2595a50ccb47ff4ec854917aa1838fe Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 4 Nov 2016 17:37:42 -0400 Subject: [PATCH 1/4] Make names of types used in LLVM IR stable. Before this PR, type names could depend on the cratenum being used for a given crate and also on the source location of closures. Both are undesirable for incremental compilation where we cache LLVM IR and don't want it to depend on formatting or in which order crates are loaded. --- src/librustc_data_structures/base_n.rs | 64 +++++ src/librustc_data_structures/lib.rs | 1 + src/librustc_incremental/persist/fs.rs | 55 +--- src/librustc_trans/base.rs | 12 +- src/librustc_trans/collector.rs | 20 +- src/librustc_trans/context.rs | 7 +- src/librustc_trans/trans_item.rs | 377 +++++++++++++------------ src/librustc_trans/type_of.rs | 30 +- 8 files changed, 318 insertions(+), 248 deletions(-) create mode 100644 src/librustc_data_structures/base_n.rs diff --git a/src/librustc_data_structures/base_n.rs b/src/librustc_data_structures/base_n.rs new file mode 100644 index 0000000000000..bf3e682f86f69 --- /dev/null +++ b/src/librustc_data_structures/base_n.rs @@ -0,0 +1,64 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/// Convert unsigned integers into a string representation with some base. +/// Bases up to and including 36 can be used for case-insensitive things. + +use std::str; + +pub const MAX_BASE: u64 = 64; +const BASE_64: &'static [u8; MAX_BASE as usize] = + b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@$"; + +#[inline] +pub fn push_str(mut n: u64, base: u64, output: &mut String) { + debug_assert!(base >= 2 && base <= MAX_BASE); + let mut s = [0u8; 64]; + let mut index = 0; + + loop { + s[index] = BASE_64[(n % base) as usize]; + index += 1; + n /= base; + + if n == 0 { + break; + } + } + &mut s[0..index].reverse(); + output.push_str(str::from_utf8(&s[0..index]).unwrap()); +} + +#[inline] +pub fn encode(n: u64, base: u64) -> String { + let mut s = String::with_capacity(13); + push_str(n, base, &mut s); + s +} + +#[test] +fn test_encode() { + fn test(n: u64, base: u64) { + assert_eq!(Ok(n), u64::from_str_radix(&encode(n, base)[..], base as u32)); + } + + for base in 2..37 { + test(0, base); + test(1, base); + test(35, base); + test(36, base); + test(37, base); + test(u64::max_value(), base); + + for i in 0 .. 1_000 { + test(i * 983, base); + } + } +} diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 2e4206d2ee1ee..de13b9bf4be10 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -47,6 +47,7 @@ extern crate libc; pub mod array_vec; pub mod accumulate_vec; pub mod small_vec; +pub mod base_n; pub mod bitslice; pub mod blake2b; pub mod bitvec; diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs index ca9c119202322..223200957cb7c 100644 --- a/src/librustc_incremental/persist/fs.rs +++ b/src/librustc_incremental/persist/fs.rs @@ -119,7 +119,7 @@ use rustc::hir::svh::Svh; use rustc::session::Session; use rustc::ty::TyCtxt; use rustc::util::fs as fs_util; -use rustc_data_structures::flock; +use rustc_data_structures::{flock, base_n}; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use std::ffi::OsString; @@ -135,6 +135,12 @@ const DEP_GRAPH_FILENAME: &'static str = "dep-graph.bin"; const WORK_PRODUCTS_FILENAME: &'static str = "work-products.bin"; const METADATA_HASHES_FILENAME: &'static str = "metadata.bin"; +// We encode integers using the following base, so they are shorter than decimal +// or hexadecimal numbers (we want short file and directory names). Since these +// numbers will be used in file names, we choose an encoding that is not +// case-sensitive (as opposed to base64, for example). +const INT_ENCODE_BASE: u64 = 36; + pub fn dep_graph_path(sess: &Session) -> PathBuf { in_incr_comp_dir_sess(sess, DEP_GRAPH_FILENAME) } @@ -327,7 +333,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Svh) { let mut new_sub_dir_name = String::from(&old_sub_dir_name[.. dash_indices[2] + 1]); // Append the svh - new_sub_dir_name.push_str(&encode_base_36(svh.as_u64())); + base_n::push_str(svh.as_u64(), INT_ENCODE_BASE, &mut new_sub_dir_name); // Create the full path let new_path = incr_comp_session_dir.parent().unwrap().join(new_sub_dir_name); @@ -433,7 +439,8 @@ fn generate_session_dir_path(crate_dir: &Path) -> PathBuf { let directory_name = format!("s-{}-{}-working", timestamp, - encode_base_36(random_number as u64)); + base_n::encode(random_number as u64, + INT_ENCODE_BASE)); debug!("generate_session_dir_path: directory_name = {}", directory_name); let directory_path = crate_dir.join(directory_name); debug!("generate_session_dir_path: directory_path = {}", directory_path.display()); @@ -562,27 +569,11 @@ fn extract_timestamp_from_session_dir(directory_name: &str) string_to_timestamp(&directory_name[dash_indices[0]+1 .. dash_indices[1]]) } -const BASE_36: &'static [u8] = b"0123456789abcdefghijklmnopqrstuvwxyz"; - -fn encode_base_36(mut n: u64) -> String { - let mut s = Vec::with_capacity(13); - loop { - s.push(BASE_36[(n % 36) as usize]); - n /= 36; - - if n == 0 { - break; - } - } - s.reverse(); - String::from_utf8(s).unwrap() -} - fn timestamp_to_string(timestamp: SystemTime) -> String { let duration = timestamp.duration_since(UNIX_EPOCH).unwrap(); let micros = duration.as_secs() * 1_000_000 + (duration.subsec_nanos() as u64) / 1000; - encode_base_36(micros) + base_n::encode(micros, INT_ENCODE_BASE) } fn string_to_timestamp(s: &str) -> Result { @@ -629,7 +620,7 @@ pub fn find_metadata_hashes_for(tcx: TyCtxt, cnum: CrateNum) -> Option }; let target_svh = tcx.sess.cstore.crate_hash(cnum); - let target_svh = encode_base_36(target_svh.as_u64()); + let target_svh = base_n::encode(target_svh.as_u64(), INT_ENCODE_BASE); let sub_dir = find_metadata_hashes_iter(&target_svh, dir_entries.filter_map(|e| { e.ok().map(|e| e.file_name().to_string_lossy().into_owned()) @@ -677,7 +668,9 @@ fn crate_path(sess: &Session, let mut hasher = DefaultHasher::new(); crate_disambiguator.hash(&mut hasher); - let crate_name = format!("{}-{}", crate_name, encode_base_36(hasher.finish())); + let crate_name = format!("{}-{}", + crate_name, + base_n::encode(hasher.finish(), INT_ENCODE_BASE)); incr_dir.join(crate_name) } @@ -1049,21 +1042,3 @@ fn test_find_metadata_hashes_iter() None ); } - -#[test] -fn test_encode_base_36() { - fn test(n: u64) { - assert_eq!(Ok(n), u64::from_str_radix(&encode_base_36(n)[..], 36)); - } - - test(0); - test(1); - test(35); - test(36); - test(37); - test(u64::max_value()); - - for i in 0 .. 1_000 { - test(i * 983); - } -} diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index c7cad6455bc30..0c0b7fbf4afea 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -74,7 +74,7 @@ use monomorphize::{self, Instance}; use partitioning::{self, PartitioningStrategy, CodegenUnit}; use symbol_map::SymbolMap; use symbol_names_test; -use trans_item::TransItem; +use trans_item::{TransItem, DefPathBasedNames}; use type_::Type; use type_of; use value::Value; @@ -1004,7 +1004,15 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> { } pub fn trans_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, instance: Instance<'tcx>) { - let _s = StatRecorder::new(ccx, ccx.tcx().item_path_str(instance.def)); + let _s = if ccx.sess().trans_stats() { + let mut instance_name = String::new(); + DefPathBasedNames::new(ccx.tcx(), true, true) + .push_def_path(instance.def, &mut instance_name); + Some(StatRecorder::new(ccx, instance_name)) + } else { + None + }; + // this is an info! to allow collecting monomorphization statistics // and to allow finding the last function before LLVM aborts from // release builds. diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 2728a666556e4..0fc6436e63cd8 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -213,7 +213,7 @@ use glue::{self, DropGlueKind}; use monomorphize::{self, Instance}; use util::nodemap::{FxHashSet, FxHashMap, DefIdMap}; -use trans_item::{TransItem, type_to_string, def_id_to_string}; +use trans_item::{TransItem, DefPathBasedNames}; #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)] pub enum TransItemCollectionMode { @@ -1234,3 +1234,21 @@ fn visit_mir_and_promoted<'tcx, V: MirVisitor<'tcx>>(mut visitor: V, mir: &mir:: visitor.visit_mir(promoted); } } + +fn def_id_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> String { + let mut output = String::new(); + let printer = DefPathBasedNames::new(tcx, false, false); + printer.push_def_path(def_id, &mut output); + output +} + +fn type_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + ty: ty::Ty<'tcx>) + -> String { + let mut output = String::new(); + let printer = DefPathBasedNames::new(tcx, false, false); + printer.push_type_name(ty, &mut output); + output +} diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 3930bcbdd9aea..f7af2d6b855df 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -26,6 +26,7 @@ use monomorphize::Instance; use partitioning::CodegenUnit; use trans_item::TransItem; use type_::Type; +use rustc_data_structures::base_n; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; use session::config::NoDebugInfo; @@ -975,7 +976,11 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { self.local().local_gen_sym_counter.set(idx + 1); // Include a '.' character, so there can be no accidental conflicts with // user defined names - format!("{}.{}", prefix, idx) + let mut name = String::with_capacity(prefix.len() + 6); + name.push_str(prefix); + name.push_str("."); + base_n::push_str(idx as u64, base_n::MAX_BASE, &mut name); + name } } diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index c5a7dbbcf5480..94a68de7f8670 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -34,6 +34,7 @@ use type_of; use glue; use abi::{Abi, FnType}; use back::symbol_names; +use std::fmt::Write; #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)] pub enum TransItem<'tcx> { @@ -307,7 +308,8 @@ impl<'a, 'tcx> TransItem<'tcx> { DropGlueKind::Ty(_) => s.push_str("drop-glue "), DropGlueKind::TyContents(_) => s.push_str("drop-glue-contents "), }; - push_unique_type_name(tcx, dg.ty(), &mut s); + let printer = DefPathBasedNames::new(tcx, false, false); + printer.push_type_name(dg.ty(), &mut s); s } TransItem::Fn(instance) => { @@ -326,7 +328,8 @@ impl<'a, 'tcx> TransItem<'tcx> { -> String { let mut result = String::with_capacity(32); result.push_str(prefix); - push_instance_as_string(tcx, instance, &mut result); + let printer = DefPathBasedNames::new(tcx, false, false); + printer.push_instance_as_string(instance, &mut result); result } } @@ -367,209 +370,219 @@ impl<'a, 'tcx> TransItem<'tcx> { /// Same as `unique_type_name()` but with the result pushed onto the given /// `output` parameter. -pub fn push_unique_type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - t: Ty<'tcx>, - output: &mut String) { - match t.sty { - ty::TyBool => output.push_str("bool"), - ty::TyChar => output.push_str("char"), - ty::TyStr => output.push_str("str"), - ty::TyNever => output.push_str("!"), - ty::TyInt(ast::IntTy::Is) => output.push_str("isize"), - ty::TyInt(ast::IntTy::I8) => output.push_str("i8"), - ty::TyInt(ast::IntTy::I16) => output.push_str("i16"), - ty::TyInt(ast::IntTy::I32) => output.push_str("i32"), - ty::TyInt(ast::IntTy::I64) => output.push_str("i64"), - ty::TyUint(ast::UintTy::Us) => output.push_str("usize"), - ty::TyUint(ast::UintTy::U8) => output.push_str("u8"), - ty::TyUint(ast::UintTy::U16) => output.push_str("u16"), - ty::TyUint(ast::UintTy::U32) => output.push_str("u32"), - ty::TyUint(ast::UintTy::U64) => output.push_str("u64"), - ty::TyFloat(ast::FloatTy::F32) => output.push_str("f32"), - ty::TyFloat(ast::FloatTy::F64) => output.push_str("f64"), - ty::TyAdt(adt_def, substs) => { - push_item_name(tcx, adt_def.did, output); - push_type_params(tcx, substs, &[], output); - }, - ty::TyTuple(component_types) => { - output.push('('); - for &component_type in component_types { - push_unique_type_name(tcx, component_type, output); - output.push_str(", "); - } - if !component_types.is_empty() { - output.pop(); - output.pop(); - } - output.push(')'); - }, - ty::TyBox(inner_type) => { - output.push_str("Box<"); - push_unique_type_name(tcx, inner_type, output); - output.push('>'); - }, - ty::TyRawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => { - output.push('*'); - match mutbl { - hir::MutImmutable => output.push_str("const "), - hir::MutMutable => output.push_str("mut "), - } +pub struct DefPathBasedNames<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + omit_disambiguators: bool, + omit_local_crate_name: bool, +} - push_unique_type_name(tcx, inner_type, output); - }, - ty::TyRef(_, ty::TypeAndMut { ty: inner_type, mutbl }) => { - output.push('&'); - if mutbl == hir::MutMutable { - output.push_str("mut "); - } +impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, + omit_disambiguators: bool, + omit_local_crate_name: bool) + -> Self { + DefPathBasedNames { + tcx: tcx, + omit_disambiguators: omit_disambiguators, + omit_local_crate_name: omit_local_crate_name, + } + } - push_unique_type_name(tcx, inner_type, output); - }, - ty::TyArray(inner_type, len) => { - output.push('['); - push_unique_type_name(tcx, inner_type, output); - output.push_str(&format!("; {}", len)); - output.push(']'); - }, - ty::TySlice(inner_type) => { - output.push('['); - push_unique_type_name(tcx, inner_type, output); - output.push(']'); - }, - ty::TyTrait(ref trait_data) => { - push_item_name(tcx, trait_data.principal.def_id(), output); - push_type_params(tcx, - trait_data.principal.skip_binder().substs, - &trait_data.projection_bounds, - output); - }, - ty::TyFnDef(.., &ty::BareFnTy{ unsafety, abi, ref sig } ) | - ty::TyFnPtr(&ty::BareFnTy{ unsafety, abi, ref sig } ) => { - if unsafety == hir::Unsafety::Unsafe { - output.push_str("unsafe "); - } + pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) { + match t.sty { + ty::TyBool => output.push_str("bool"), + ty::TyChar => output.push_str("char"), + ty::TyStr => output.push_str("str"), + ty::TyNever => output.push_str("!"), + ty::TyInt(ast::IntTy::Is) => output.push_str("isize"), + ty::TyInt(ast::IntTy::I8) => output.push_str("i8"), + ty::TyInt(ast::IntTy::I16) => output.push_str("i16"), + ty::TyInt(ast::IntTy::I32) => output.push_str("i32"), + ty::TyInt(ast::IntTy::I64) => output.push_str("i64"), + ty::TyUint(ast::UintTy::Us) => output.push_str("usize"), + ty::TyUint(ast::UintTy::U8) => output.push_str("u8"), + ty::TyUint(ast::UintTy::U16) => output.push_str("u16"), + ty::TyUint(ast::UintTy::U32) => output.push_str("u32"), + ty::TyUint(ast::UintTy::U64) => output.push_str("u64"), + ty::TyFloat(ast::FloatTy::F32) => output.push_str("f32"), + ty::TyFloat(ast::FloatTy::F64) => output.push_str("f64"), + ty::TyAdt(adt_def, substs) => { + self.push_def_path(adt_def.did, output); + self.push_type_params(substs, &[], output); + }, + ty::TyTuple(component_types) => { + output.push('('); + for &component_type in component_types { + self.push_type_name(component_type, output); + output.push_str(", "); + } + if !component_types.is_empty() { + output.pop(); + output.pop(); + } + output.push(')'); + }, + ty::TyBox(inner_type) => { + output.push_str("Box<"); + self.push_type_name(inner_type, output); + output.push('>'); + }, + ty::TyRawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => { + output.push('*'); + match mutbl { + hir::MutImmutable => output.push_str("const "), + hir::MutMutable => output.push_str("mut "), + } - if abi != ::abi::Abi::Rust { - output.push_str("extern \""); - output.push_str(abi.name()); - output.push_str("\" "); - } + self.push_type_name(inner_type, output); + }, + ty::TyRef(_, ty::TypeAndMut { ty: inner_type, mutbl }) => { + output.push('&'); + if mutbl == hir::MutMutable { + output.push_str("mut "); + } - output.push_str("fn("); + self.push_type_name(inner_type, output); + }, + ty::TyArray(inner_type, len) => { + output.push('['); + self.push_type_name(inner_type, output); + write!(output, "; {}", len).unwrap(); + output.push(']'); + }, + ty::TySlice(inner_type) => { + output.push('['); + self.push_type_name(inner_type, output); + output.push(']'); + }, + ty::TyTrait(ref trait_data) => { + self.push_def_path(trait_data.principal.def_id(), output); + self.push_type_params(trait_data.principal.skip_binder().substs, + &trait_data.projection_bounds, + output); + }, + ty::TyFnDef(.., &ty::BareFnTy{ unsafety, abi, ref sig } ) | + ty::TyFnPtr(&ty::BareFnTy{ unsafety, abi, ref sig } ) => { + if unsafety == hir::Unsafety::Unsafe { + output.push_str("unsafe "); + } - let sig = tcx.erase_late_bound_regions_and_normalize(sig); - if !sig.inputs.is_empty() { - for ¶meter_type in &sig.inputs { - push_unique_type_name(tcx, parameter_type, output); - output.push_str(", "); + if abi != ::abi::Abi::Rust { + output.push_str("extern \""); + output.push_str(abi.name()); + output.push_str("\" "); } - output.pop(); - output.pop(); - } - if sig.variadic { - if !sig.inputs.is_empty() { - output.push_str(", ..."); - } else { - output.push_str("..."); + output.push_str("fn("); + + let ty::FnSig { + inputs: sig_inputs, + output: sig_output, + variadic: sig_variadic + } = self.tcx.erase_late_bound_regions_and_normalize(sig); + + if !sig_inputs.is_empty() { + for ¶meter_type in &sig_inputs { + self.push_type_name(parameter_type, output); + output.push_str(", "); + } + output.pop(); + output.pop(); + } + + if sig_variadic { + if !sig_inputs.is_empty() { + output.push_str(", ..."); + } else { + output.push_str("..."); + } } - } - output.push(')'); + output.push(')'); - if !sig.output.is_nil() { - output.push_str(" -> "); - push_unique_type_name(tcx, sig.output, output); + if !sig_output.is_nil() { + output.push_str(" -> "); + self.push_type_name(sig_output, output); + } + }, + ty::TyClosure(def_id, ref closure_substs) => { + self.push_def_path(def_id, output); + let generics = self.tcx.item_generics(self.tcx.closure_base_def_id(def_id)); + let substs = closure_substs.substs.truncate_to(self.tcx, generics); + self.push_type_params(substs, &[], output); + } + ty::TyError | + ty::TyInfer(_) | + ty::TyProjection(..) | + ty::TyParam(_) | + ty::TyAnon(..) => { + bug!("DefPathBasedNames: Trying to create type name for \ + unexpected type: {:?}", t); } - }, - ty::TyClosure(def_id, closure_substs) => { - push_item_name(tcx, def_id, output); - output.push_str("{"); - output.push_str(&format!("{}:{}", def_id.krate, def_id.index.as_usize())); - output.push_str("}"); - let generics = tcx.item_generics(tcx.closure_base_def_id(def_id)); - let substs = closure_substs.substs.truncate_to(tcx, generics); - push_type_params(tcx, substs, &[], output); - } - ty::TyError | - ty::TyInfer(_) | - ty::TyProjection(..) | - ty::TyParam(_) | - ty::TyAnon(..) => { - bug!("debuginfo: Trying to create type name for \ - unexpected type: {:?}", t); } } -} - -fn push_item_name(tcx: TyCtxt, - def_id: DefId, - output: &mut String) { - let def_path = tcx.def_path(def_id); - // some_crate:: - output.push_str(&tcx.crate_name(def_path.krate)); - output.push_str("::"); + pub fn push_def_path(&self, + def_id: DefId, + output: &mut String) { + let def_path = self.tcx.def_path(def_id); - // foo::bar::ItemName:: - for part in tcx.def_path(def_id).data { - output.push_str(&format!("{}[{}]::", - part.data.as_interned_str(), - part.disambiguator)); - } + // some_crate:: + if !(self.omit_local_crate_name && def_id.is_local()) { + output.push_str(&self.tcx.crate_name(def_path.krate)); + output.push_str("::"); + } - // remove final "::" - output.pop(); - output.pop(); -} + // foo::bar::ItemName:: + for part in self.tcx.def_path(def_id).data { + if self.omit_disambiguators { + write!(output, "{}::", part.data.as_interned_str()).unwrap(); + } else { + write!(output, "{}[{}]::", + part.data.as_interned_str(), + part.disambiguator).unwrap(); + } + } -fn push_type_params<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - substs: &Substs<'tcx>, - projections: &[ty::PolyExistentialProjection<'tcx>], - output: &mut String) { - if substs.types().next().is_none() && projections.is_empty() { - return; + // remove final "::" + output.pop(); + output.pop(); } - output.push('<'); - - for type_parameter in substs.types() { - push_unique_type_name(tcx, type_parameter, output); - output.push_str(", "); - } + pub fn push_type_params(&self, + substs: &Substs<'tcx>, + projections: &[ty::PolyExistentialProjection<'tcx>], + output: &mut String) { + if substs.types().next().is_none() && projections.is_empty() { + return; + } - for projection in projections { - let projection = projection.skip_binder(); - let name = &projection.item_name.as_str(); - output.push_str(name); - output.push_str("="); - push_unique_type_name(tcx, projection.ty, output); - output.push_str(", "); - } + output.push('<'); - output.pop(); - output.pop(); + for type_parameter in substs.types() { + self.push_type_name(type_parameter, output); + output.push_str(", "); + } - output.push('>'); -} + for projection in projections { + let projection = projection.skip_binder(); + let name = &projection.item_name.as_str(); + output.push_str(name); + output.push_str("="); + self.push_type_name(projection.ty, output); + output.push_str(", "); + } -fn push_instance_as_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - instance: Instance<'tcx>, - output: &mut String) { - push_item_name(tcx, instance.def, output); - push_type_params(tcx, instance.substs, &[], output); -} + output.pop(); + output.pop(); -pub fn def_id_to_string(tcx: TyCtxt, def_id: DefId) -> String { - let mut output = String::new(); - push_item_name(tcx, def_id, &mut output); - output -} + output.push('>'); + } -pub fn type_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - ty: Ty<'tcx>) - -> String { - let mut output = String::new(); - push_unique_type_name(tcx, ty, &mut output); - output + pub fn push_instance_as_string(&self, + instance: Instance<'tcx>, + output: &mut String) { + self.push_def_path(instance.def, output); + self.push_type_params(instance.substs, &[], output); + } } diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs index dc794d5946a69..16d4f97200cb2 100644 --- a/src/librustc_trans/type_of.rs +++ b/src/librustc_trans/type_of.rs @@ -10,14 +10,12 @@ #![allow(non_camel_case_types)] -use rustc::hir::def_id::DefId; use abi::FnType; use adt; use common::*; use machine; use rustc::ty::{self, Ty, TypeFoldable}; -use rustc::ty::subst::Substs; - +use trans_item::DefPathBasedNames; use type_::Type; use syntax::ast; @@ -282,12 +280,12 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> let n = t.simd_size(cx.tcx()) as u64; Type::vector(&llet, n) } - ty::TyAdt(def, substs) => { + ty::TyAdt(..) => { // Only create the named struct, but don't fill it in. We // fill it in *after* placing it into the type cache. This // avoids creating more than one copy of the enum when one // of the enum's variants refers to the enum itself. - let name = llvm_type_name(cx, def.did, substs); + let name = llvm_type_name(cx, t); adt::incomplete_type_of(cx, t, &name[..]) } @@ -319,21 +317,9 @@ pub fn align_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) layout.align(&cx.tcx().data_layout).abi() as machine::llalign } -fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, - did: DefId, - substs: &Substs<'tcx>) - -> String { - let base = cx.tcx().item_path_str(did); - let strings: Vec = substs.types().map(|t| t.to_string()).collect(); - let tstr = if strings.is_empty() { - base - } else { - format!("{}<{}>", base, strings.join(", ")) - }; - - if did.is_local() { - tstr - } else { - format!("{}.{}", did.krate, tstr) - } +fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> String { + let mut name = String::with_capacity(32); + let printer = DefPathBasedNames::new(cx.tcx(), true, true); + printer.push_type_name(ty, &mut name); + name } From fd4ee0021e6df93f47ba779b15a2bfaf61ebe1e2 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 8 Nov 2016 13:23:57 -0500 Subject: [PATCH 2/4] Fix codegen test after change of llvm type naming scheme --- src/test/codegen/lifetime_start_end.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/codegen/lifetime_start_end.rs b/src/test/codegen/lifetime_start_end.rs index 81f6cf309da50..e3b35cf355250 100644 --- a/src/test/codegen/lifetime_start_end.rs +++ b/src/test/codegen/lifetime_start_end.rs @@ -27,16 +27,16 @@ pub fn test() { let b = &Some(a); &b; // keep variable in an alloca -// CHECK: [[S_b:%[0-9]+]] = bitcast %"2.std::option::Option"** %b to i8* +// CHECK: [[S_b:%[0-9]+]] = bitcast %"core::option::Option"** %b to i8* // CHECK: call void @llvm.lifetime.start(i{{[0-9 ]+}}, i8* [[S_b]]) -// CHECK: [[S__5:%[0-9]+]] = bitcast %"2.std::option::Option"* %_5 to i8* +// CHECK: [[S__5:%[0-9]+]] = bitcast %"core::option::Option"* %_5 to i8* // CHECK: call void @llvm.lifetime.start(i{{[0-9 ]+}}, i8* [[S__5]]) -// CHECK: [[E__5:%[0-9]+]] = bitcast %"2.std::option::Option"* %_5 to i8* +// CHECK: [[E__5:%[0-9]+]] = bitcast %"core::option::Option"* %_5 to i8* // CHECK: call void @llvm.lifetime.end(i{{[0-9 ]+}}, i8* [[E__5]]) -// CHECK: [[E_b:%[0-9]+]] = bitcast %"2.std::option::Option"** %b to i8* +// CHECK: [[E_b:%[0-9]+]] = bitcast %"core::option::Option"** %b to i8* // CHECK: call void @llvm.lifetime.end(i{{[0-9 ]+}}, i8* [[E_b]]) } From 790a2f9b00602f951e903ac8b21f69e91737225c Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 7 Nov 2016 13:33:21 -0500 Subject: [PATCH 3/4] Adapt accidentally fixed test case. --- src/test/incremental/change_private_fn_cc/struct_point.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/test/incremental/change_private_fn_cc/struct_point.rs b/src/test/incremental/change_private_fn_cc/struct_point.rs index d6d2b5436ff30..ded87dd27f410 100644 --- a/src/test/incremental/change_private_fn_cc/struct_point.rs +++ b/src/test/incremental/change_private_fn_cc/struct_point.rs @@ -23,10 +23,7 @@ #![rustc_partition_reused(module="struct_point-fn_calls_methods_in_another_impl", cfg="rpass2")] #![rustc_partition_reused(module="struct_point-fn_read_field", cfg="rpass2")] #![rustc_partition_reused(module="struct_point-fn_write_field", cfg="rpass2")] - -// FIXME(#37335) -- should be reused, but an errant Krate edge causes -// it to get translated (at least I *think* this is that same problem) -#![rustc_partition_translated(module="struct_point-fn_make_struct", cfg="rpass2")] +#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="rpass2")] extern crate point; From 276f052a804888e5c1d321183199bf37a42a94c2 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 7 Nov 2016 14:40:52 -0500 Subject: [PATCH 4/4] Remove unused method CrateContext::rotate(). --- src/librustc_trans/context.rs | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index f7af2d6b855df..7657fc7d1c8b0 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -701,22 +701,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { &self.local_ccxs[self.index] } - /// Get a (possibly) different `CrateContext` from the same - /// `SharedCrateContext`. - pub fn rotate(&'b self) -> CrateContext<'b, 'tcx> { - let (_, index) = - self.local_ccxs - .iter() - .zip(0..self.local_ccxs.len()) - .min_by_key(|&(local_ccx, _idx)| local_ccx.n_llvm_insns.get()) - .unwrap(); - CrateContext { - shared: self.shared, - index: index, - local_ccxs: &self.local_ccxs[..], - } - } - /// Either iterate over only `self`, or iterate over all `CrateContext`s in /// the `SharedCrateContext`. The iterator produces `(ccx, is_origin)` /// pairs, where `is_origin` is `true` if `ccx` is `self` and `false`