diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 99c059d0b53..65c3aa12ba6 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -80,7 +80,7 @@ use machine::{llalign_of_min, llsize_of, llsize_of_real}; use meth; use mir; use monomorphize::{self, Instance}; -use partitioning::{self, PartitioningStrategy, InstantiationMode, CodegenUnit}; +use partitioning::{self, PartitioningStrategy, CodegenUnit}; use symbol_names_test; use trans_item::TransItem; use tvec; @@ -2942,8 +2942,8 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a None => TransItemCollectionMode::Lazy }; - let (items, reference_map) = time(time_passes, "translation item collection", || { - collector::collect_crate_translation_items(scx, collection_mode) + let (items, inlining_map) = time(time_passes, "translation item collection", || { + collector::collect_crate_translation_items(&scx, collection_mode) }); let strategy = if scx.sess().opts.debugging_opts.incremental.is_some() { @@ -2956,7 +2956,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a partitioning::partition(scx.tcx(), items.iter().cloned(), strategy, - &reference_map) + &inlining_map) }); if scx.sess().opts.debugging_opts.print_trans_items.is_some() { @@ -2984,18 +2984,17 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a output.push_str(&cgu_name[..]); let linkage_abbrev = match linkage { - InstantiationMode::Def(llvm::ExternalLinkage) => "External", - InstantiationMode::Def(llvm::AvailableExternallyLinkage) => "Available", - InstantiationMode::Def(llvm::LinkOnceAnyLinkage) => "OnceAny", - InstantiationMode::Def(llvm::LinkOnceODRLinkage) => "OnceODR", - InstantiationMode::Def(llvm::WeakAnyLinkage) => "WeakAny", - InstantiationMode::Def(llvm::WeakODRLinkage) => "WeakODR", - InstantiationMode::Def(llvm::AppendingLinkage) => "Appending", - InstantiationMode::Def(llvm::InternalLinkage) => "Internal", - InstantiationMode::Def(llvm::PrivateLinkage) => "Private", - InstantiationMode::Def(llvm::ExternalWeakLinkage) => "ExternalWeak", - InstantiationMode::Def(llvm::CommonLinkage) => "Common", - InstantiationMode::Decl => "Declaration", + llvm::ExternalLinkage => "External", + llvm::AvailableExternallyLinkage => "Available", + llvm::LinkOnceAnyLinkage => "OnceAny", + llvm::LinkOnceODRLinkage => "OnceODR", + llvm::WeakAnyLinkage => "WeakAny", + llvm::WeakODRLinkage => "WeakODR", + llvm::AppendingLinkage => "Appending", + llvm::InternalLinkage => "Internal", + llvm::PrivateLinkage => "Private", + llvm::ExternalWeakLinkage => "ExternalWeak", + llvm::CommonLinkage => "Common", }; output.push_str("["); diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index a6efc9030bf..0614c29aaed 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -188,8 +188,6 @@ //! this is not implemented however: a translation item will be produced //! regardless of whether it is actually needed or not. -use rustc_data_structures::bitvec::BitVector; - use rustc::hir; use rustc::hir::intravisit as hir_visit; @@ -226,42 +224,33 @@ pub enum TransItemCollectionMode { /// Maps every translation item to all translation items it references in its /// body. -pub struct ReferenceMap<'tcx> { - // Maps a source translation item to a range of target translation items. +pub struct InliningMap<'tcx> { + // Maps a source translation item to a range of target translation items + // that are potentially inlined by LLVM into the source. // The two numbers in the tuple are the start (inclusive) and - // end index (exclusive) within the `targets` and the `inlined` vecs. + // end index (exclusive) within the `targets` vecs. index: FnvHashMap, (usize, usize)>, targets: Vec>, - inlined: BitVector } -impl<'tcx> ReferenceMap<'tcx> { +impl<'tcx> InliningMap<'tcx> { - fn new() -> ReferenceMap<'tcx> { - ReferenceMap { + fn new() -> InliningMap<'tcx> { + InliningMap { index: FnvHashMap(), targets: Vec::new(), - inlined: BitVector::new(64 * 256), } } - fn record_references(&mut self, source: TransItem<'tcx>, targets: I) - where I: Iterator, bool)> + fn record_inlining_canditates(&mut self, + source: TransItem<'tcx>, + targets: I) + where I: Iterator> { assert!(!self.index.contains_key(&source)); let start_index = self.targets.len(); - - for (target, inlined) in targets { - let index = self.targets.len(); - self.targets.push(target); - self.inlined.grow(index + 1); - - if inlined { - self.inlined.insert(index); - } - } - + self.targets.extend(targets); let end_index = self.targets.len(); self.index.insert(source, (start_index, end_index)); } @@ -272,28 +261,17 @@ impl<'tcx> ReferenceMap<'tcx> { where F: FnMut(TransItem<'tcx>) { if let Some(&(start_index, end_index)) = self.index.get(&source) { - for index in start_index .. end_index { - if self.inlined.contains(index) { - f(self.targets[index]) - } + for candidate in &self.targets[start_index .. end_index] { + f(*candidate) } } } - - pub fn get_direct_references_from(&self, source: TransItem<'tcx>) -> &[TransItem<'tcx>] - { - if let Some(&(start_index, end_index)) = self.index.get(&source) { - &self.targets[start_index .. end_index] - } else { - &self.targets[0 .. 0] - } - } } pub fn collect_crate_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, mode: TransItemCollectionMode) -> (FnvHashSet>, - ReferenceMap<'tcx>) { + InliningMap<'tcx>) { // We are not tracking dependencies of this pass as it has to be re-executed // every time no matter what. scx.tcx().dep_graph.with_ignore(|| { @@ -302,17 +280,17 @@ pub fn collect_crate_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a, 't debug!("Building translation item graph, beginning at roots"); let mut visited = FnvHashSet(); let mut recursion_depths = DefIdMap(); - let mut reference_map = ReferenceMap::new(); + let mut inlining_map = InliningMap::new(); for root in roots { collect_items_rec(scx, root, &mut visited, &mut recursion_depths, - &mut reference_map); + &mut inlining_map); } - (visited, reference_map) + (visited, inlining_map) }) } @@ -343,7 +321,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>, starting_point: TransItem<'tcx>, visited: &mut FnvHashSet>, recursion_depths: &mut DefIdMap, - reference_map: &mut ReferenceMap<'tcx>) { + inlining_map: &mut InliningMap<'tcx>) { if !visited.insert(starting_point.clone()) { // We've been here already, no need to search again. return; @@ -390,10 +368,10 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>, } } - record_references(scx.tcx(), starting_point, &neighbors[..], reference_map); + record_inlining_canditates(scx.tcx(), starting_point, &neighbors[..], inlining_map); for neighbour in neighbors { - collect_items_rec(scx, neighbour, visited, recursion_depths, reference_map); + collect_items_rec(scx, neighbour, visited, recursion_depths, inlining_map); } if let Some((def_id, depth)) = recursion_depth_reset { @@ -403,17 +381,19 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>, debug!("END collect_items_rec({})", starting_point.to_string(scx.tcx())); } -fn record_references<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - caller: TransItem<'tcx>, - callees: &[TransItem<'tcx>], - reference_map: &mut ReferenceMap<'tcx>) { - let iter = callees.into_iter() - .map(|callee| { - let is_inlining_candidate = callee.is_from_extern_crate() || - callee.requests_inline(tcx); - (*callee, is_inlining_candidate) - }); - reference_map.record_references(caller, iter); +fn record_inlining_canditates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + caller: TransItem<'tcx>, + callees: &[TransItem<'tcx>], + inlining_map: &mut InliningMap<'tcx>) { + let is_inlining_candidate = |trans_item: &TransItem<'tcx>| { + trans_item.is_from_extern_crate() || trans_item.requests_inline(tcx) + }; + + let inlining_candidates = callees.into_iter() + .map(|x| *x) + .filter(is_inlining_candidate); + + inlining_map.record_inlining_canditates(caller, inlining_candidates); } fn check_recursion_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index eeff280a7d6..098ba759247 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -116,7 +116,7 @@ //! source-level module, functions from the same module will be available for //! inlining, even when they are not marked #[inline]. -use collector::ReferenceMap; +use collector::InliningMap; use llvm; use monomorphize; use rustc::hir::def_id::DefId; @@ -127,20 +127,9 @@ use syntax::parse::token::{self, InternedString}; use trans_item::TransItem; use util::nodemap::{FnvHashMap, FnvHashSet}; -#[derive(Clone, Copy, Eq, PartialEq, Debug)] -pub enum InstantiationMode { - /// This variant indicates that a translation item should be placed in some - /// codegen unit as a definition and with the given linkage. - Def(llvm::Linkage), - - /// This variant indicates that only a declaration of some translation item - /// should be placed in a given codegen unit. - Decl -} - pub struct CodegenUnit<'tcx> { pub name: InternedString, - pub items: FnvHashMap, InstantiationMode>, + pub items: FnvHashMap, llvm::Linkage>, } pub enum PartitioningStrategy { @@ -157,7 +146,7 @@ const FALLBACK_CODEGEN_UNIT: &'static str = "__rustc_fallback_codegen_unit"; pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trans_items: I, strategy: PartitioningStrategy, - reference_map: &ReferenceMap<'tcx>) + inlining_map: &InliningMap<'tcx>) -> Vec> where I: Iterator> { @@ -177,13 +166,8 @@ pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // translation items can be drop-glue, functions from external crates, and // local functions the definition of which is marked with #[inline]. let post_inlining = place_inlined_translation_items(initial_partitioning, - reference_map); - - // Now we know all *definitions* within all codegen units, thus we can - // easily determine which declarations need to be placed within each one. - let post_declarations = place_declarations(post_inlining, reference_map); - - post_declarations.0 + inlining_map); + post_inlining.0 } struct PreInliningPartitioning<'tcx> { @@ -192,7 +176,6 @@ struct PreInliningPartitioning<'tcx> { } struct PostInliningPartitioning<'tcx>(Vec>); -struct PostDeclarationsPartitioning<'tcx>(Vec>); fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trans_items: I) @@ -240,8 +223,7 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } }; - codegen_unit.items.insert(trans_item, - InstantiationMode::Def(linkage)); + codegen_unit.items.insert(trans_item, linkage); roots.insert(trans_item); } } @@ -295,7 +277,7 @@ fn merge_codegen_units<'tcx>(initial_partitioning: &mut PreInliningPartitioning< } fn place_inlined_translation_items<'tcx>(initial_partitioning: PreInliningPartitioning<'tcx>, - reference_map: &ReferenceMap<'tcx>) + inlining_map: &InliningMap<'tcx>) -> PostInliningPartitioning<'tcx> { let mut new_partitioning = Vec::new(); @@ -303,7 +285,7 @@ fn place_inlined_translation_items<'tcx>(initial_partitioning: PreInliningPartit // Collect all items that need to be available in this codegen unit let mut reachable = FnvHashSet(); for root in codegen_unit.items.keys() { - follow_inlining(*root, reference_map, &mut reachable); + follow_inlining(*root, inlining_map, &mut reachable); } let mut new_codegen_unit = CodegenUnit { @@ -313,22 +295,22 @@ fn place_inlined_translation_items<'tcx>(initial_partitioning: PreInliningPartit // Add all translation items that are not already there for trans_item in reachable { - if let Some(instantiation_mode) = codegen_unit.items.get(&trans_item) { + if let Some(linkage) = codegen_unit.items.get(&trans_item) { // This is a root, just copy it over - new_codegen_unit.items.insert(trans_item, *instantiation_mode); + new_codegen_unit.items.insert(trans_item, *linkage); } else { if initial_partitioning.roots.contains(&trans_item) { // This item will be instantiated in some other codegen unit, // so we just add it here with AvailableExternallyLinkage new_codegen_unit.items.insert(trans_item, - InstantiationMode::Def(llvm::AvailableExternallyLinkage)); + llvm::AvailableExternallyLinkage); } else { // We can't be sure if this will also be instantiated // somewhere else, so we add an instance here with // LinkOnceODRLinkage. That way the item can be discarded if // it's not needed (inlined) after all. new_codegen_unit.items.insert(trans_item, - InstantiationMode::Def(llvm::LinkOnceODRLinkage)); + llvm::LinkOnceODRLinkage); } } } @@ -339,43 +321,18 @@ fn place_inlined_translation_items<'tcx>(initial_partitioning: PreInliningPartit return PostInliningPartitioning(new_partitioning); fn follow_inlining<'tcx>(trans_item: TransItem<'tcx>, - reference_map: &ReferenceMap<'tcx>, + inlining_map: &InliningMap<'tcx>, visited: &mut FnvHashSet>) { if !visited.insert(trans_item) { return; } - reference_map.with_inlining_candidates(trans_item, |target| { - follow_inlining(target, reference_map, visited); + inlining_map.with_inlining_candidates(trans_item, |target| { + follow_inlining(target, inlining_map, visited); }); } } -fn place_declarations<'tcx>(codegen_units: PostInliningPartitioning<'tcx>, - reference_map: &ReferenceMap<'tcx>) - -> PostDeclarationsPartitioning<'tcx> { - let PostInliningPartitioning(mut codegen_units) = codegen_units; - - for codegen_unit in codegen_units.iter_mut() { - let mut declarations = FnvHashSet(); - - for (trans_item, _) in &codegen_unit.items { - for referenced_item in reference_map.get_direct_references_from(*trans_item) { - if !codegen_unit.items.contains_key(referenced_item) { - declarations.insert(*referenced_item); - } - } - } - - codegen_unit.items - .extend(declarations.iter() - .map(|trans_item| (*trans_item, - InstantiationMode::Decl))); - } - - PostDeclarationsPartitioning(codegen_units) -} - fn characteristic_def_id_of_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trans_item: TransItem<'tcx>) -> Option { diff --git a/src/test/codegen-units/partitioning/local-drop-glue.rs b/src/test/codegen-units/partitioning/local-drop-glue.rs index 1edc3d5d2e2..04ebef645ec 100644 --- a/src/test/codegen-units/partitioning/local-drop-glue.rs +++ b/src/test/codegen-units/partitioning/local-drop-glue.rs @@ -23,7 +23,7 @@ struct Struct { } impl Drop for Struct { - //~ TRANS_ITEM fn local_drop_glue::{{impl}}[0]::drop[0] @@ local_drop_glue[WeakODR] local_drop_glue-mod1[Declaration] + //~ TRANS_ITEM fn local_drop_glue::{{impl}}[0]::drop[0] @@ local_drop_glue[WeakODR] fn drop(&mut self) {} } diff --git a/src/test/codegen-units/partitioning/local-generic.rs b/src/test/codegen-units/partitioning/local-generic.rs index 4c762ebdc2e..e38e676b95c 100644 --- a/src/test/codegen-units/partitioning/local-generic.rs +++ b/src/test/codegen-units/partitioning/local-generic.rs @@ -19,10 +19,10 @@ // Used in different modules/codegen units but always instantiated in the same // codegen unit. -//~ TRANS_ITEM fn local_generic::generic[0] @@ local_generic.volatile[WeakODR] local_generic[Declaration] -//~ TRANS_ITEM fn local_generic::generic[0] @@ local_generic.volatile[WeakODR] local_generic-mod1[Declaration] -//~ TRANS_ITEM fn local_generic::generic[0] @@ local_generic.volatile[WeakODR] local_generic-mod1-mod1[Declaration] -//~ TRANS_ITEM fn local_generic::generic[0]<&str> @@ local_generic.volatile[WeakODR] local_generic-mod2[Declaration] +//~ TRANS_ITEM fn local_generic::generic[0] @@ local_generic.volatile[WeakODR] +//~ TRANS_ITEM fn local_generic::generic[0] @@ local_generic.volatile[WeakODR] +//~ TRANS_ITEM fn local_generic::generic[0] @@ local_generic.volatile[WeakODR] +//~ TRANS_ITEM fn local_generic::generic[0]<&str> @@ local_generic.volatile[WeakODR] pub fn generic(x: T) -> T { x } //~ TRANS_ITEM fn local_generic::user[0] @@ local_generic[WeakODR] diff --git a/src/test/codegen-units/partitioning/methods-are-with-self-type.rs b/src/test/codegen-units/partitioning/methods-are-with-self-type.rs index 390bade153c..99dda0e38ba 100644 --- a/src/test/codegen-units/partitioning/methods-are-with-self-type.rs +++ b/src/test/codegen-units/partitioning/methods-are-with-self-type.rs @@ -61,19 +61,19 @@ mod type2 { //~ TRANS_ITEM fn methods_are_with_self_type::main[0] fn main() { - //~ TRANS_ITEM fn methods_are_with_self_type::mod1[0]::{{impl}}[1]::method[0] @@ methods_are_with_self_type.volatile[WeakODR] methods_are_with_self_type[Declaration] + //~ TRANS_ITEM fn methods_are_with_self_type::mod1[0]::{{impl}}[1]::method[0] @@ methods_are_with_self_type.volatile[WeakODR] SomeGenericType(0u32, 0u64).method(); - //~ TRANS_ITEM fn methods_are_with_self_type::mod1[0]::{{impl}}[1]::associated_fn[0] @@ methods_are_with_self_type.volatile[WeakODR] methods_are_with_self_type[Declaration] + //~ TRANS_ITEM fn methods_are_with_self_type::mod1[0]::{{impl}}[1]::associated_fn[0] @@ methods_are_with_self_type.volatile[WeakODR] SomeGenericType::associated_fn('c', "&str"); - //~ TRANS_ITEM fn methods_are_with_self_type::{{impl}}[0]::foo[0] @@ methods_are_with_self_type-type1.volatile[WeakODR] methods_are_with_self_type[Declaration] + //~ TRANS_ITEM fn methods_are_with_self_type::{{impl}}[0]::foo[0] @@ methods_are_with_self_type-type1.volatile[WeakODR] type1::Struct.foo(); - //~ TRANS_ITEM fn methods_are_with_self_type::{{impl}}[0]::foo[0] @@ methods_are_with_self_type-type2.volatile[WeakODR] methods_are_with_self_type[Declaration] + //~ TRANS_ITEM fn methods_are_with_self_type::{{impl}}[0]::foo[0] @@ methods_are_with_self_type-type2.volatile[WeakODR] type2::Struct.foo(); - //~ TRANS_ITEM fn methods_are_with_self_type::Trait[0]::default[0] @@ methods_are_with_self_type-type1.volatile[WeakODR] methods_are_with_self_type[Declaration] + //~ TRANS_ITEM fn methods_are_with_self_type::Trait[0]::default[0] @@ methods_are_with_self_type-type1.volatile[WeakODR] type1::Struct.default(); - //~ TRANS_ITEM fn methods_are_with_self_type::Trait[0]::default[0] @@ methods_are_with_self_type-type2.volatile[WeakODR] methods_are_with_self_type[Declaration] + //~ TRANS_ITEM fn methods_are_with_self_type::Trait[0]::default[0] @@ methods_are_with_self_type-type2.volatile[WeakODR] type2::Struct.default(); }