about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMichael Woerister <michaelwoerister@posteo.net>2016-09-15 11:40:16 -0400
committerMichael Woerister <michaelwoerister@posteo.net>2016-09-15 11:40:16 -0400
commitc10176ef66b00af7cdfdcf85e2351381f8b38d07 (patch)
tree2fcd00f8411f47d4c9ea17bb058349188ef135ba /src
parent97b561a0944141a02a0cebe577c3c69e436abcf4 (diff)
downloadrust-c10176ef66b00af7cdfdcf85e2351381f8b38d07.tar.gz
rust-c10176ef66b00af7cdfdcf85e2351381f8b38d07.zip
trans: Only translate #[inline] functions if they are used somewhere.
Diffstat (limited to 'src')
-rw-r--r--src/librustc_trans/base.rs6
-rw-r--r--src/librustc_trans/collector.rs2
-rw-r--r--src/librustc_trans/partitioning.rs71
-rw-r--r--src/librustc_trans/trans_item.rs33
4 files changed, 25 insertions, 87 deletions
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index a6581ae605b..fcfe53d0c85 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -1591,7 +1591,11 @@ pub fn filter_reachable_ids(tcx: TyCtxt, reachable: NodeSet) -> NodeSet {
                 node: hir::ImplItemKind::Method(..), .. }) => {
                 let def_id = tcx.map.local_def_id(id);
                 let generics = tcx.lookup_generics(def_id);
-                generics.parent_types == 0 && generics.types.is_empty()
+                let attributes = tcx.get_attrs(def_id);
+                (generics.parent_types == 0 && generics.types.is_empty()) &&
+                // Functions marked with #[inline] are only ever translated
+                // with "internal" linkage and are never exported.
+                !attr::requests_inline(&attributes[..])
             }
 
             _ => false
diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs
index 5a8ab62a2aa..f193c0482f7 100644
--- a/src/librustc_trans/collector.rs
+++ b/src/librustc_trans/collector.rs
@@ -401,7 +401,7 @@ fn record_inlining_canditates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, '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)
+        trans_item.needs_local_copy(tcx)
     };
 
     let inlining_candidates = callees.into_iter()
diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs
index a161bd199b1..798e883c955 100644
--- a/src/librustc_trans/partitioning.rs
+++ b/src/librustc_trans/partitioning.rs
@@ -261,12 +261,6 @@ pub fn partition<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>,
 {
     let tcx = scx.tcx();
 
-    if let PartitioningStrategy::FixedUnitCount(1) = strategy {
-        // If there is only a single codegen-unit, we can use a very simple
-        // scheme and don't have to bother with doing much analysis.
-        return vec![single_codegen_unit(tcx, trans_items, reachable)];
-    }
-
     // In the first step, we place all regular translation items into their
     // respective 'home' codegen unit. Regular translation items are all
     // functions and statics defined in the local crate.
@@ -320,7 +314,7 @@ fn place_root_translation_items<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>,
     let mut codegen_units = FnvHashMap();
 
     for trans_item in trans_items {
-        let is_root = !trans_item.is_instantiated_only_on_demand();
+        let is_root = !trans_item.is_instantiated_only_on_demand(tcx);
 
         if is_root {
             let characteristic_def_id = characteristic_def_id_of_trans_item(scx, trans_item);
@@ -454,7 +448,6 @@ fn place_inlined_translation_items<'tcx>(initial_partitioning: PreInliningPartit
                 // reliably in that case.
                 new_codegen_unit.items.insert(trans_item, llvm::InternalLinkage);
             } else {
-                assert!(trans_item.is_instantiated_only_on_demand());
                 // We can't be sure if this will also be instantiated
                 // somewhere else, so we add an instance here with
                 // InternalLinkage so we don't get any conflicts.
@@ -550,68 +543,6 @@ fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     return token::intern_and_get_ident(&mod_path[..]);
 }
 
-fn single_codegen_unit<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                    trans_items: I,
-                                    reachable: &NodeSet)
-                                    -> CodegenUnit<'tcx>
-    where I: Iterator<Item = TransItem<'tcx>>
-{
-    let mut items = FnvHashMap();
-
-    for trans_item in trans_items {
-        let linkage = trans_item.explicit_linkage(tcx).unwrap_or_else(|| {
-            match trans_item {
-                TransItem::Static(node_id) => {
-                    if reachable.contains(&node_id) {
-                        llvm::ExternalLinkage
-                    } else {
-                        llvm::PrivateLinkage
-                    }
-                }
-                TransItem::DropGlue(_) => {
-                    llvm::InternalLinkage
-                }
-                TransItem::Fn(instance) => {
-                    if trans_item.is_generic_fn() {
-                        // FIXME(mw): Assigning internal linkage to all
-                        // monomorphizations is potentially a waste of space
-                        // since monomorphizations could be shared between
-                        // crates. The main reason for making them internal is
-                        // a limitation in MingW's binutils that cannot deal
-                        // with COFF object that have more than 2^15 sections,
-                        // which is something that can happen for large programs
-                        // when every function gets put into its own COMDAT
-                        // section.
-                        llvm::InternalLinkage
-                    } else if trans_item.is_from_extern_crate() {
-                        // FIXME(mw): It would be nice if we could mark these as
-                        // `AvailableExternallyLinkage`, since they should have
-                        // been instantiated in the extern crate. But this
-                        // sometimes leads to crashes on Windows because LLVM
-                        // does not handle exception handling table instantiation
-                        // reliably in that case.
-                        llvm::InternalLinkage
-                    } else if reachable.contains(&tcx.map
-                                                     .as_local_node_id(instance.def)
-                                                     .unwrap()) {
-                        llvm::ExternalLinkage
-                    } else {
-                        // Functions that are not visible outside this crate can
-                        // be marked as internal.
-                        llvm::InternalLinkage
-                    }
-                }
-            }
-        });
-
-        items.insert(trans_item, linkage);
-    }
-
-    CodegenUnit::new(
-        numbered_codegen_unit_name(&tcx.crate_name[..], 0),
-        items)
-}
-
 fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString {
     token::intern_and_get_ident(&format!("{}{}{}",
         crate_name,
diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs
index 44e613c4c2b..bde393b77e1 100644
--- a/src/librustc_trans/trans_item.rs
+++ b/src/librustc_trans/trans_item.rs
@@ -241,19 +241,6 @@ impl<'a, 'tcx> TransItem<'tcx> {
         }
     }
 
-    pub fn requests_inline(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
-        match *self {
-            TransItem::Fn(ref instance) => {
-                instance.substs.types().next().is_some() || {
-                    let attributes = tcx.get_attrs(instance.def);
-                    attr::requests_inline(&attributes[..])
-                }
-            }
-            TransItem::DropGlue(..) => true,
-            TransItem::Static(..)   => false,
-        }
-    }
-
     pub fn is_from_extern_crate(&self) -> bool {
         match *self {
             TransItem::Fn(ref instance) => !instance.def.is_local(),
@@ -262,10 +249,14 @@ impl<'a, 'tcx> TransItem<'tcx> {
         }
     }
 
-    pub fn is_instantiated_only_on_demand(&self) -> bool {
+    /// True if the translation item should only be translated to LLVM IR if
+    /// it is referenced somewhere (like inline functions, for example).
+    pub fn is_instantiated_only_on_demand(&self, tcx: TyCtxt) -> bool {
         match *self {
             TransItem::Fn(ref instance) => {
-                !instance.def.is_local() || instance.substs.types().next().is_some()
+                !instance.def.is_local() ||
+                instance.substs.types().next().is_some() ||
+                attr::requests_inline(&tcx.get_attrs(instance.def)[..])
             }
             TransItem::DropGlue(..) => true,
             TransItem::Static(..)   => false,
@@ -282,6 +273,18 @@ impl<'a, 'tcx> TransItem<'tcx> {
         }
     }
 
+    /// Returns true if there has to be a local copy of this TransItem in every
+    /// codegen unit that references it (as with inlined functions, for example)
+    pub fn needs_local_copy(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
+        // Currently everything that is instantiated only on demand is done so
+        // with "internal" linkage, so we need a copy to be present in every
+        // codegen unit.
+        // This is coincidental: We could also instantiate something only if it
+        // is referenced (e.g. a regular, private function) but place it in its
+        // own codegen unit with "external" linkage.
+        self.is_instantiated_only_on_demand(tcx)
+    }
+
     pub fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<llvm::Linkage> {
         let def_id = match *self {
             TransItem::Fn(ref instance) => instance.def,