Only retain external static symbols across LTO

This commit is contained in:
arcnmx 2015-11-07 12:22:04 -05:00
parent a91ff1c9d1
commit e6f0f7d52d
6 changed files with 41 additions and 43 deletions

View File

@ -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!() }

View File

@ -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 {

View File

@ -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
{
fn is_extern_item(&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
{
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

View File

@ -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);

View File

@ -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)
}));

View File

@ -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,