From c59d89f14a3e2461f4925dab6fc189ef2c969e2d Mon Sep 17 00:00:00 2001 From: arcnmx Date: Sat, 7 Nov 2015 12:22:04 -0500 Subject: [PATCH 1/2] Only retain no_mangle static symbols across LTO --- src/librustc/metadata/csearch.rs | 4 ++-- src/librustc/metadata/decoder.rs | 7 +++++-- src/librustc_trans/trans/base.rs | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index 09dec375a69a5..e6bce562c0a80 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -344,9 +344,9 @@ pub fn is_const_fn(cstore: &cstore::CStore, did: DefId) -> bool { decoder::is_const_fn(&*cdata, did.index) } -pub fn is_static(cstore: &cstore::CStore, did: DefId) -> bool { +pub fn is_extern_static(cstore: &cstore::CStore, did: DefId) -> bool { let cdata = cstore.get_crate_data(did.krate); - decoder::is_static(&*cdata, did.index) + decoder::is_extern_static(&*cdata, did.index) } pub fn is_impl(cstore: &cstore::CStore, did: DefId) -> bool { diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index b102213eff021..538a29b1c1249 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -1425,10 +1425,13 @@ pub fn is_const_fn(cdata: Cmd, id: DefIndex) -> bool { } } -pub fn is_static(cdata: Cmd, id: DefIndex) -> bool { +pub fn is_extern_static(cdata: Cmd, id: DefIndex) -> bool { let item_doc = cdata.lookup_item(id); match item_family(item_doc) { - ImmStatic | MutStatic => true, + ImmStatic | MutStatic => { + let attrs = get_attributes(item_doc); + attr::contains_name(&attrs, "no_mangle") + }, _ => false, } } diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 4a99f2142d790..d95bec67add22 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -2876,7 +2876,7 @@ pub fn trans_crate<'tcx>(tcx: &ty::ctxt<'tcx>, let syms = csearch::get_reachable_ids(&sess.cstore, cnum); reachable_symbols.extend(syms.into_iter().filter(|did| { csearch::is_extern_fn(&sess.cstore, *did, shared_ccx.tcx()) || - csearch::is_static(&sess.cstore, *did) + csearch::is_extern_static(&sess.cstore, *did) }).map(|did| { csearch::get_symbol(&sess.cstore, did) })); From 70b49d8cca23805107681924df174086530ee522 Mon Sep 17 00:00:00 2001 From: arcnmx Date: Wed, 11 Nov 2015 16:32:59 -0500 Subject: [PATCH 2/2] Rework the extern detection --- src/librustc/metadata/csearch.rs | 10 ++------ src/librustc/metadata/decoder.rs | 42 +++++++++++++++----------------- src/librustc/middle/reachable.rs | 18 +++++++------- src/librustc_trans/trans/base.rs | 3 +-- src/libsyntax/attr.rs | 9 +++++++ 5 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index e6bce562c0a80..539b0fe694e59 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -344,9 +344,9 @@ pub fn is_const_fn(cstore: &cstore::CStore, did: DefId) -> bool { decoder::is_const_fn(&*cdata, did.index) } -pub fn is_extern_static(cstore: &cstore::CStore, did: DefId) -> bool { +pub fn is_extern_item(cstore: &cstore::CStore, did: DefId, tcx: &ty::ctxt) -> bool { let cdata = cstore.get_crate_data(did.krate); - decoder::is_extern_static(&*cdata, did.index) + decoder::is_extern_item(&*cdata, did.index, tcx) } pub fn is_impl(cstore: &cstore::CStore, did: DefId) -> bool { @@ -381,12 +381,6 @@ pub fn is_default_impl(cstore: &cstore::CStore, impl_did: DefId) -> bool { decoder::is_default_impl(&*cdata, impl_did.index) } -pub fn is_extern_fn(cstore: &cstore::CStore, did: DefId, - tcx: &ty::ctxt) -> bool { - let cdata = cstore.get_crate_data(did.krate); - decoder::is_extern_fn(&*cdata, did.index, tcx) -} - pub fn closure_kind<'tcx>(tcx: &ty::ctxt<'tcx>, def_id: DefId) -> ty::ClosureKind { assert!(!def_id.is_local()); let cdata = tcx.sess.cstore.get_crate_data(def_id.krate); diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 538a29b1c1249..062e6e240d366 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -1425,14 +1425,28 @@ pub fn is_const_fn(cdata: Cmd, id: DefIndex) -> bool { } } -pub fn is_extern_static(cdata: Cmd, id: DefIndex) -> bool { - let item_doc = cdata.lookup_item(id); - match item_family(item_doc) { - ImmStatic | MutStatic => { - let attrs = get_attributes(item_doc); - attr::contains_name(&attrs, "no_mangle") +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 } } @@ -1552,22 +1566,6 @@ pub fn get_imported_filemaps(metadata: &[u8]) -> Vec { }).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/middle/reachable.rs b/src/librustc/middle/reachable.rs index 7175fbe0e570d..92685da61311a 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -235,16 +235,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_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index d95bec67add22..815cb9602980e 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -2875,8 +2875,7 @@ pub fn trans_crate<'tcx>(tcx: &ty::ctxt<'tcx>, sess.cstore.iter_crate_data(|cnum, _| { let syms = csearch::get_reachable_ids(&sess.cstore, cnum); reachable_symbols.extend(syms.into_iter().filter(|did| { - csearch::is_extern_fn(&sess.cstore, *did, shared_ccx.tcx()) || - csearch::is_extern_static(&sess.cstore, *did) + csearch::is_extern_item(&sess.cstore, *did, shared_ccx.tcx()) }).map(|did| { csearch::get_symbol(&sess.cstore, did) })); diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 571f950643792..b937b2f047bee 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -312,6 +312,15 @@ pub fn find_export_name_attr(diag: &SpanHandler, attrs: &[Attribute]) -> Option< }) } +pub fn contains_extern_indicator(attrs: &[Attribute]) -> bool { + contains_name(attrs, "no_mangle") || + contains_name(attrs, "export_name") || + first_attr_value_str_by_name(attrs, "linkage").map(|v| match &*v { + "external" | "extern_weak" => true, + _ => false, + }).unwrap_or(false) +} + #[derive(Copy, Clone, PartialEq)] pub enum InlineAttr { None,