diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 6ede414e83758..809c55c1c8464 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -810,7 +810,8 @@ fn encode_info_for_method(ecx: &EncodeContext, encode_inlined_item(ecx, rbml_w, IIMethodRef(local_def(parent_id), false, &*ast_method)); - } else { + } + if !any_types { encode_symbol(ecx, rbml_w, m.def_id.node); } encode_method_argument_names(rbml_w, &*ast_method.pe_fn_decl()); @@ -965,7 +966,8 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_attributes(rbml_w, item.attrs.as_slice()); if tps_len > 0u || should_inline(item.attrs.as_slice()) { encode_inlined_item(ecx, rbml_w, IIItemRef(item)); - } else { + } + if tps_len == 0 { encode_symbol(ecx, rbml_w, item.id); } encode_visibility(rbml_w, vis); @@ -1291,9 +1293,8 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext, encode_name(rbml_w, nitem.ident.name); if abi == abi::RustIntrinsic { encode_inlined_item(ecx, rbml_w, IIForeignRef(nitem)); - } else { - encode_symbol(ecx, rbml_w, nitem.id); } + encode_symbol(ecx, rbml_w, nitem.id); } ForeignItemStatic(_, mutbl) => { if mutbl { diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index f1e84b8da8105..1b8d55a40cc54 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2311,6 +2311,14 @@ pub fn create_entry_wrapper(ccx: &CrateContext, fn exported_name(ccx: &CrateContext, id: ast::NodeId, ty: ty::t, attrs: &[ast::Attribute]) -> String { + match ccx.external_srcs.borrow().find(&id) { + Some(&did) => { + debug!("found item in other crate..."); + return csearch::get_symbol(&ccx.sess().cstore, did) + } + None => {} + } + match attr::first_attr_value_str_by_name(attrs, "export_name") { // Use provided name Some(name) => name.get().to_string(), @@ -2354,16 +2362,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { // using the current crate's name/version // information in the hash of the symbol debug!("making {}", sym); - let (sym, is_local) = { - match ccx.external_srcs.borrow().find(&i.id) { - Some(&did) => { - debug!("but found in other crate..."); - (csearch::get_symbol(&ccx.sess().cstore, - did), false) - } - None => (sym, true) - } - }; + let is_local = !ccx.external_srcs.borrow().contains_key(&id); // We need the translated value here, because for enums the // LLVM type is not fully determined by the Rust type. diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs index 877dd647c3b20..66014aedaa115 100644 --- a/src/librustc/middle/trans/inline.rs +++ b/src/librustc/middle/trans/inline.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use llvm::{AvailableExternallyLinkage, SetLinkage}; +use llvm::{AvailableExternallyLinkage, InternalLinkage, SetLinkage}; use metadata::csearch; use middle::astencode; use middle::trans::base::{push_ctxt, trans_item, get_item_val, trans_fn}; @@ -53,26 +53,44 @@ pub fn maybe_instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId) ccx.stats.n_inlines.set(ccx.stats.n_inlines.get() + 1); trans_item(ccx, &*item); - // We're bringing an external global into this crate, but we don't - // want to create two copies of the global. If we do this, then if - // you take the address of the global in two separate crates you get - // two different addresses. This is bad for things like conditions, - // but it could possibly have other adverse side effects. We still - // want to achieve the optimizations related to this global, - // however, so we use the available_externally linkage which llvm - // provides - match item.node { + let linkage = match item.node { + ast::ItemFn(_, _, _, ref generics, _) => { + if generics.is_type_parameterized() { + // Generics have no symbol, so they can't be given any + // linkage. + None + } else { + // Use available_externally when possible. This allows + // LLVM to inline the function into its callers, but + // doesn't produce duplicate code if LLVM chooses not + // to inline at some call sites. + Some(AvailableExternallyLinkage) + } + } ast::ItemStatic(_, mutbl, _) => { - let g = get_item_val(ccx, item.id); - // see the comment in get_item_val() as to why this check is - // performed here. - if ast_util::static_has_significant_address( - mutbl, - item.attrs.as_slice()) { - SetLinkage(g, AvailableExternallyLinkage); + if !ast_util::static_has_significant_address(mutbl, item.attrs.as_slice()) { + // Inlined static items use internal linkage when + // possible, so that LLVM will coalesce globals with + // identical initializers. (It only does this for + // globals with unnamed_addr and either internal or + // private linkage.) + Some(InternalLinkage) + } else { + // The address is significant, so we can't create an + // internal copy of the static. (The copy would have a + // different address from the original.) + Some(AvailableExternallyLinkage) } } - _ => {} + _ => unreachable!(), + }; + + match linkage { + Some(linkage) => { + let g = get_item_val(ccx, item.id); + SetLinkage(g, linkage); + } + None => {} } local_def(item.id) @@ -130,12 +148,13 @@ pub fn maybe_instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId) impl_tpt.generics.types.is_empty() && mth.pe_generics().ty_params.is_empty(); - if unparameterized { - let llfn = get_item_val(ccx, mth.id); + if unparameterized { + let llfn = get_item_val(ccx, mth.id); trans_fn(ccx, &*mth.pe_fn_decl(), &*mth.pe_body(), llfn, - ¶m_substs::empty(), mth.id, [], TranslateItems); - } - local_def(mth.id) + ¶m_substs::empty(), mth.id, [], TranslateItems); + SetLinkage(llfn, AvailableExternallyLinkage); + } + local_def(mth.id) } }; }