about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorarcnmx <arcnmx@users.noreply.github.com>2015-11-07 12:22:04 -0500
committerarcnmx <arcnmx@users.noreply.github.com>2016-02-11 12:45:52 -0500
commite6f0f7d52d69d0c4f290ac32c6eebf92bbf6dd81 (patch)
treeeed6c22c1a4a2ab9925546d91f317728b6ef0898 /src
parenta91ff1c9d1842918329ef7a81afd3848854d53c7 (diff)
downloadrust-e6f0f7d52d69d0c4f290ac32c6eebf92bbf6dd81.tar.gz
rust-e6f0f7d52d69d0c4f290ac32c6eebf92bbf6dd81.zip
Only retain external static symbols across LTO
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/cstore.rs6
-rw-r--r--src/librustc/middle/reachable.rs18
-rw-r--r--src/librustc_metadata/csearch.rs11
-rw-r--r--src/librustc_metadata/decoder.rs39
-rw-r--r--src/librustc_trans/trans/base.rs3
-rw-r--r--src/libsyntax/attr.rs7
6 files changed, 41 insertions, 43 deletions
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index 1e21d6aabe9..c2c23f6a032 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -187,8 +187,7 @@ pub trait CrateStore<'tcx> : Any {
     fn is_defaulted_trait(&self, did: DefId) -> bool;
     fn is_impl(&self, did: DefId) -> bool;
     fn is_default_impl(&self, impl_did: DefId) -> bool;
-    fn is_extern_fn(&self, tcx: &ty::ctxt<'tcx>, did: DefId) -> bool;
-    fn is_static(&self, did: DefId) -> bool;
+    fn is_extern_item(&self, tcx: &ty::ctxt<'tcx>, did: DefId) -> bool;
     fn is_static_method(&self, did: DefId) -> bool;
     fn is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool;
     fn is_typedef(&self, did: DefId) -> bool;
@@ -357,8 +356,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
     fn is_defaulted_trait(&self, did: DefId) -> bool { unimplemented!() }
     fn is_impl(&self, did: DefId) -> bool { unimplemented!() }
     fn is_default_impl(&self, impl_did: DefId) -> bool { unimplemented!() }
-    fn is_extern_fn(&self, tcx: &ty::ctxt<'tcx>, did: DefId) -> bool { unimplemented!() }
-    fn is_static(&self, did: DefId) -> bool { unimplemented!() }
+    fn is_extern_item(&self, tcx: &ty::ctxt<'tcx>, did: DefId) -> bool { unimplemented!() }
     fn is_static_method(&self, did: DefId) -> bool { unimplemented!() }
     fn is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool { false }
     fn is_typedef(&self, did: DefId) -> bool { unimplemented!() }
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index d34c3b74217..5486172b830 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -229,16 +229,16 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
     fn propagate_node(&mut self, node: &ast_map::Node,
                       search_item: ast::NodeId) {
         if !self.any_library {
-            // If we are building an executable, then there's no need to flag
-            // anything as external except for `extern fn` types. These
-            // functions may still participate in some form of native interface,
-            // but all other rust-only interfaces can be private (they will not
-            // participate in linkage after this product is produced)
+            // If we are building an executable, only explicitly extern
+            // types need to be exported.
             if let ast_map::NodeItem(item) = *node {
-                if let hir::ItemFn(_, _, _, abi, _, _) = item.node {
-                    if abi != Abi::Rust {
-                        self.reachable_symbols.insert(search_item);
-                    }
+                let reachable = if let hir::ItemFn(_, _, _, abi, _, _) = item.node {
+                    abi != Abi::Rust
+                } else {
+                    false
+                };
+                if reachable || attr::contains_extern_indicator(&item.attrs) {
+                    self.reachable_symbols.insert(search_item);
                 }
             }
         } else {
diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs
index 06a2727ea28..5eade3bc0a5 100644
--- a/src/librustc_metadata/csearch.rs
+++ b/src/librustc_metadata/csearch.rs
@@ -260,16 +260,9 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
         decoder::is_default_impl(&*cdata, impl_did.index)
     }
 
-    fn is_extern_fn(&self, tcx: &ty::ctxt<'tcx>, did: DefId) -> bool
-    {
-        let cdata = self.get_crate_data(did.krate);
-        decoder::is_extern_fn(&*cdata, did.index, tcx)
-    }
-
-    fn is_static(&self, did: DefId) -> bool
-    {
+    fn is_extern_item(&self, tcx: &ty::ctxt<'tcx>, did: DefId) -> bool {
         let cdata = self.get_crate_data(did.krate);
-        decoder::is_static(&*cdata, did.index)
+        decoder::is_extern_item(&*cdata, did.index, tcx)
     }
 
     fn is_static_method(&self, def: DefId) -> bool
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 5ba9e566e00..3ec32635a4b 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -1567,11 +1567,28 @@ pub fn is_const_fn(cdata: Cmd, id: DefIndex) -> bool {
     }
 }
 
-pub fn is_static(cdata: Cmd, id: DefIndex) -> bool {
-    let item_doc = cdata.lookup_item(id);
-    match item_family(item_doc) {
+pub fn is_extern_item(cdata: Cmd, id: DefIndex, tcx: &ty::ctxt) -> bool {
+    let item_doc = match cdata.get_item(id) {
+        Some(doc) => doc,
+        None => return false,
+    };
+    let applicable = match item_family(item_doc) {
         ImmStatic | MutStatic => true,
+        Fn => {
+            let ty::TypeScheme { generics, ty } = get_type(cdata, id, tcx);
+            let no_generics = generics.types.is_empty();
+            match ty.sty {
+                ty::TyBareFn(_, fn_ty) if fn_ty.abi != Abi::Rust => return no_generics,
+                _ => no_generics,
+            }
+        },
         _ => false,
+    };
+
+    if applicable {
+        attr::contains_extern_indicator(&get_attributes(item_doc))
+    } else {
+        false
     }
 }
 
@@ -1693,22 +1710,6 @@ pub fn get_imported_filemaps(metadata: &[u8]) -> Vec<codemap::FileMap> {
     }).collect()
 }
 
-pub fn is_extern_fn(cdata: Cmd, id: DefIndex, tcx: &ty::ctxt) -> bool {
-    let item_doc = match cdata.get_item(id) {
-        Some(doc) => doc,
-        None => return false,
-    };
-    if let Fn = item_family(item_doc) {
-        let ty::TypeScheme { generics, ty } = get_type(cdata, id, tcx);
-        generics.types.is_empty() && match ty.sty {
-            ty::TyBareFn(_, fn_ty) => fn_ty.abi != Abi::Rust,
-            _ => false,
-        }
-    } else {
-        false
-    }
-}
-
 pub fn closure_kind(cdata: Cmd, closure_id: DefIndex) -> ty::ClosureKind {
     let closure_doc = cdata.lookup_item(closure_id);
     let closure_kind_doc = reader::get_doc(closure_doc, tag_items_closure_kind);
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index c2d962b032f..4748c62921d 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -3281,8 +3281,7 @@ pub fn trans_crate<'tcx>(tcx: &ty::ctxt<'tcx>,
         for cnum in sess.cstore.crates() {
             let syms = sess.cstore.reachable_ids(cnum);
             reachable_symbols.extend(syms.into_iter().filter(|did| {
-                sess.cstore.is_extern_fn(shared_ccx.tcx(), *did) ||
-                sess.cstore.is_static(*did)
+                sess.cstore.is_extern_item(shared_ccx.tcx(), *did)
             }).map(|did| {
                 sess.cstore.item_symbol(did)
             }));
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index cc5f30e2184..e2654375736 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -316,6 +316,13 @@ pub fn find_export_name_attr(diag: &Handler, attrs: &[Attribute]) -> Option<Inte
     })
 }
 
+pub fn contains_extern_indicator(attrs: &[Attribute]) -> bool {
+    contains_name(attrs, "no_mangle") ||
+        contains_name(attrs, "link_section") ||
+        contains_name(attrs, "linkage") ||
+        contains_name(attrs, "export_name")
+}
+
 #[derive(Copy, Clone, PartialEq)]
 pub enum InlineAttr {
     None,