diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index ced47bb5681b1..93c16b159f5c0 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1139,7 +1139,9 @@ pub fn trans_stmt(cx: block, s: ast::stmt) -> block { } } } - ast::decl_item(i) => trans_item(cx.fcx.ccx, *i) + ast::decl_item(i) => { + trans_item(cx.fcx.ccx, *i, DontForceInternal) + } } } ast::stmt_mac(*) => cx.tcx().sess.bug(~"unexpanded macro") @@ -1972,10 +1974,14 @@ pub fn trans_struct_dtor(ccx: @crate_ctxt, lldecl } -pub fn trans_enum_def(ccx: @crate_ctxt, enum_definition: ast::enum_def, - id: ast::node_id, degen: bool, - path: @ast_map::path, vi: @~[ty::VariantInfo], - i: &mut uint) { +pub fn trans_enum_def(ccx: @crate_ctxt, + enum_definition: ast::enum_def, + id: ast::node_id, + degen: bool, + path: @ast_map::path, + vi: @~[ty::VariantInfo], + i: &mut uint, + force_internal: ForceInternalFlag) { for vec::each(enum_definition.variants) |variant| { let disr_val = vi[*i].disr_val; *i += 1; @@ -1983,6 +1989,9 @@ pub fn trans_enum_def(ccx: @crate_ctxt, enum_definition: ast::enum_def, match variant.node.kind { ast::tuple_variant_kind(ref args) if args.len() > 0 => { let llfn = get_item_val(ccx, variant.node.id); + if force_internal == ForceInternal { + internalize_item(llfn); + } trans_enum_variant(ccx, id, *variant, /*bad*/copy *args, disr_val, degen, None, llfn); } @@ -1990,8 +1999,11 @@ pub fn trans_enum_def(ccx: @crate_ctxt, enum_definition: ast::enum_def, // Nothing to do. } ast::struct_variant_kind(struct_def) => { - trans_struct_def(ccx, struct_def, path, - variant.node.id); + trans_struct_def(ccx, + struct_def, + path, + variant.node.id, + force_internal); } ast::enum_variant_kind(ref enum_definition) => { trans_enum_def(ccx, @@ -2000,13 +2012,28 @@ pub fn trans_enum_def(ccx: @crate_ctxt, enum_definition: ast::enum_def, degen, path, vi, - &mut *i); + &mut *i, + force_internal); } } } } -pub fn trans_item(ccx: @crate_ctxt, item: ast::item) { +#[deriving_eq] +pub enum ForceInternalFlag { + DontForceInternal, + ForceInternal, +} + +// Marks the LLVM ValueRef corresponding to the given item as internal, so +// that if it gets inlined away LLVM won't bother translating it. +pub fn internalize_item(llval: ValueRef) { + lib::llvm::SetLinkage(llval, lib::llvm::InternalLinkage); +} + +pub fn trans_item(ccx: @crate_ctxt, + item: ast::item, + force_internal: ForceInternalFlag) { let _icx = ccx.insn_ctxt("trans_item"); let path = match ccx.tcx.items.get(&item.id) { ast_map::node_item(_, p) => p, @@ -2017,6 +2044,9 @@ pub fn trans_item(ccx: @crate_ctxt, item: ast::item) { ast::item_fn(ref decl, purity, ref tps, ref body) => { if purity == ast::extern_fn { let llfndecl = get_item_val(ccx, item.id); + if force_internal == ForceInternal { + internalize_item(llfndecl); + } foreign::trans_foreign_fn(ccx, vec::append( /*bad*/copy *path, @@ -2024,6 +2054,9 @@ pub fn trans_item(ccx: @crate_ctxt, item: ast::item) { decl, body, llfndecl, item.id); } else if tps.is_empty() { let llfndecl = get_item_val(ccx, item.id); + if force_internal == ForceInternal { + internalize_item(llfndecl); + } trans_fn(ccx, vec::append(/*bad*/copy *path, ~[path_name(item.ident)]), decl, body, llfndecl, no_self, None, item.id, None); @@ -2032,7 +2065,7 @@ pub fn trans_item(ccx: @crate_ctxt, item: ast::item) { match stmt.node { ast::stmt_decl(@codemap::spanned { node: ast::decl_item(i), _ }, _) => { - trans_item(ccx, *i); + trans_item(ccx, *i, DontForceInternal); } _ => () } @@ -2040,8 +2073,14 @@ pub fn trans_item(ccx: @crate_ctxt, item: ast::item) { } } ast::item_impl(tps, _, _, ms) => { - meth::trans_impl(ccx, /*bad*/copy *path, item.ident, ms, tps, None, - item.id); + meth::trans_impl(ccx, + /*bad*/copy *path, + item.ident, + ms, + tps, + None, + item.id, + force_internal); } ast::item_mod(m) => { trans_mod(ccx, m); @@ -2051,8 +2090,14 @@ pub fn trans_item(ccx: @crate_ctxt, item: ast::item) { let degen = (*enum_definition).variants.len() == 1u; let vi = ty::enum_variants(ccx.tcx, local_def(item.id)); let mut i = 0; - trans_enum_def(ccx, (*enum_definition), item.id, - degen, path, vi, &mut i); + trans_enum_def(ccx, + *enum_definition, + item.id, + degen, + path, + vi, + &mut i, + force_internal); } } ast::item_const(_, expr) => consts::trans_const(ccx, expr, item.id), @@ -2066,16 +2111,22 @@ pub fn trans_item(ccx: @crate_ctxt, item: ast::item) { } ast::item_struct(struct_def, tps) => { if tps.is_empty() { - trans_struct_def(ccx, struct_def, path, item.id); + trans_struct_def(ccx, + struct_def, + path, + item.id, + DontForceInternal); } } _ => {/* fall through */ } } } -pub fn trans_struct_def(ccx: @crate_ctxt, struct_def: @ast::struct_def, +pub fn trans_struct_def(ccx: @crate_ctxt, + struct_def: @ast::struct_def, path: @ast_map::path, - id: ast::node_id) { + id: ast::node_id, + force_internal: ForceInternalFlag) { // Translate the destructor. do option::iter(&struct_def.dtor) |dtor| { trans_struct_dtor(ccx, /*bad*/copy *path, &dtor.node.body, @@ -2088,6 +2139,9 @@ pub fn trans_struct_def(ccx: @crate_ctxt, struct_def: @ast::struct_def, // otherwise this is a unit-like struct. Some(ctor_id) if struct_def.fields.len() > 0 => { let llfndecl = get_item_val(ccx, ctor_id); + if force_internal == ForceInternal { + internalize_item(llfndecl); + } trans_tuple_struct(ccx, /*bad*/copy struct_def.fields, ctor_id, None, llfndecl); } @@ -2103,7 +2157,7 @@ pub fn trans_struct_def(ccx: @crate_ctxt, struct_def: @ast::struct_def, pub fn trans_mod(ccx: @crate_ctxt, m: ast::_mod) { let _icx = ccx.insn_ctxt("trans_mod"); for vec::each(m.items) |item| { - trans_item(ccx, **item); + trans_item(ccx, **item, DontForceInternal); } } @@ -2477,8 +2531,9 @@ pub fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef { ccx.sess.bug(~"get_item_val(): unexpected variant") } }; - if !(exprt || ccx.reachable.contains_key(&id)) { - lib::llvm::SetLinkage(val, lib::llvm::InternalLinkage); + if !*ccx.sess.building_library || + (!exprt && !ccx.reachable.contains_key(&id)) { + internalize_item(val); } ccx.item_vals.insert(id, val); val diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs index c094db4ecca1f..0be8dbe88da4e 100644 --- a/src/librustc/middle/trans/inline.rs +++ b/src/librustc/middle/trans/inline.rs @@ -11,7 +11,7 @@ use core::prelude::*; use middle::astencode; -use middle::trans::base::{get_insn_ctxt}; +use middle::trans::base::{ForceInternal, get_insn_ctxt, internalize_item}; use middle::trans::base::{impl_owned_self, impl_self, no_self}; use middle::trans::base::{trans_item, get_item_val, self_arg, trans_fn}; use middle::trans::common::*; @@ -54,7 +54,7 @@ pub fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id, csearch::found(ast::ii_item(item)) => { ccx.external.insert(fn_id, Some(item.id)); ccx.stats.n_inlines += 1; - if translate { trans_item(ccx, *item); } + if translate { trans_item(ccx, *item, ForceInternal); } local_def(item.id) } csearch::found(ast::ii_foreign(item)) => { @@ -64,9 +64,10 @@ pub fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id, csearch::found_parent(parent_id, ast::ii_item(item)) => { ccx.external.insert(parent_id, Some(item.id)); let mut my_id = 0; + let vs_here; match item.node { ast::item_enum(_, _) => { - let vs_here = ty::enum_variants(ccx.tcx, local_def(item.id)); + vs_here = ty::enum_variants(ccx.tcx, local_def(item.id)); let vs_there = ty::enum_variants(ccx.tcx, parent_id); for vec::each2(*vs_here, *vs_there) |here, there| { if there.id == fn_id { my_id = here.id.node; } @@ -76,7 +77,7 @@ pub fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id, _ => ccx.sess.bug(~"maybe_instantiate_inline: item has a \ non-enum parent") } - if translate { trans_item(ccx, *item); } + if translate { trans_item(ccx, *item, ForceInternal); } local_def(my_id) } csearch::found_parent(_, _) => { @@ -90,6 +91,7 @@ pub fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id, ty::lookup_item_type(ccx.tcx, impl_did); if translate && (*impl_bnds).len() + mth.tps.len() == 0u { let llfn = get_item_val(ccx, mth.id); + internalize_item(llfn); let path = vec::append( ty::item_path(ccx.tcx, impl_did), ~[path_name(mth.ident)]); @@ -119,7 +121,7 @@ pub fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id, local_def(mth.id) } csearch::found(ast::ii_dtor(ref dtor, _, _, _)) => { - ccx.external.insert(fn_id, Some((*dtor).node.id)); + ccx.external.insert(fn_id, Some(dtor.node.id)); local_def((*dtor).node.id) } } diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index fb487b98e152f..310409a05ea0c 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -50,15 +50,23 @@ for non-monomorphized methods only. Other methods will be generated once they are invoked with specific type parameters, see `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`. */ -pub fn trans_impl(ccx: @crate_ctxt, +path: path, name: ast::ident, - methods: ~[@ast::method], tps: ~[ast::ty_param], - self_ty: Option, id: ast::node_id) { +pub fn trans_impl(ccx: @crate_ctxt, + +path: path, + name: ast::ident, + methods: ~[@ast::method], + tps: ~[ast::ty_param], + self_ty: Option, + id: ast::node_id, + force_internal: ForceInternalFlag) { let _icx = ccx.insn_ctxt("impl::trans_impl"); if tps.len() > 0u { return; } let sub_path = vec::append_one(path, path_name(name)); for vec::each(methods) |method| { if method.tps.len() == 0u { let llfn = get_item_val(ccx, method.id); + if force_internal == ForceInternal { + internalize_item(llfn); + } let path = vec::append_one(/*bad*/copy sub_path, path_name(method.ident));