Skip to content

Only retain external static symbols across LTO #30830

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 12, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions src/librustc/middle/cstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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!() }
Expand Down
20 changes: 11 additions & 9 deletions src/librustc/middle/reachable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,16 +229,18 @@ 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
};
let is_extern = attr::contains_extern_indicator(&self.tcx.sess.diagnostic(),
&item.attrs);
if reachable || is_extern {
self.reachable_symbols.insert(search_item);
}
}
} else {
Expand Down
11 changes: 2 additions & 9 deletions src/librustc_metadata/csearch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
40 changes: 21 additions & 19 deletions src/librustc_metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1567,11 +1567,29 @@ 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(tcx.sess.diagnostic(),
&get_attributes(item_doc))
} else {
false
}
}

Expand Down Expand Up @@ -1693,22 +1711,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);
Expand Down
3 changes: 1 addition & 2 deletions src/librustc_trans/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}));
Expand Down
5 changes: 5 additions & 0 deletions src/libsyntax/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,11 @@ pub fn find_export_name_attr(diag: &Handler, attrs: &[Attribute]) -> Option<Inte
})
}

pub fn contains_extern_indicator(diag: &Handler, attrs: &[Attribute]) -> bool {
contains_name(attrs, "no_mangle") ||
find_export_name_attr(diag, attrs).is_some()
}

#[derive(Copy, Clone, PartialEq)]
pub enum InlineAttr {
None,
Expand Down