diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 5433923441a7b..ea301784c930e 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1235,7 +1235,8 @@ pub fn new_fn_ctxt<'a>(ccx: &'a CrateContext, output_type: ty::t, param_substs: &'a param_substs, sp: Option, - block_arena: &'a TypedArena>) + block_arena: &'a TypedArena>, + handle_items: HandleItemsFlag) -> FunctionContext<'a> { param_substs.validate(); @@ -1268,7 +1269,8 @@ pub fn new_fn_ctxt<'a>(ccx: &'a CrateContext, block_arena: block_arena, ccx: ccx, debug_context: debug_context, - scopes: RefCell::new(Vec::new()) + scopes: RefCell::new(Vec::new()), + handle_items: handle_items, }; if has_env { @@ -1579,7 +1581,8 @@ pub fn trans_closure(ccx: &CrateContext, abi: Abi, has_env: bool, is_unboxed_closure: IsUnboxedClosureFlag, - maybe_load_env: <'a> |&'a Block<'a>| -> &'a Block<'a>) { + maybe_load_env: <'a> |&'a Block<'a>| -> &'a Block<'a>, + handle_items: HandleItemsFlag) { ccx.stats.n_closures.set(ccx.stats.n_closures.get() + 1); let _icx = push_ctxt("trans_closure"); @@ -1596,7 +1599,8 @@ pub fn trans_closure(ccx: &CrateContext, output_type, param_substs, Some(body.span), - &arena); + &arena, + handle_items); let mut bcx = init_function(&fcx, false, output_type); // cleanup scope for the incoming arguments @@ -1698,7 +1702,8 @@ pub fn trans_fn(ccx: &CrateContext, llfndecl: ValueRef, param_substs: ¶m_substs, id: ast::NodeId, - attrs: &[ast::Attribute]) { + attrs: &[ast::Attribute], + handle_items: HandleItemsFlag) { let _s = StatRecorder::new(ccx, ccx.tcx.map.path_to_string(id).to_string()); debug!("trans_fn(param_substs={})", param_substs.repr(ccx.tcx())); let _icx = push_ctxt("trans_fn"); @@ -1718,7 +1723,8 @@ pub fn trans_fn(ccx: &CrateContext, abi, false, NotUnboxedClosure, - |bcx| bcx); + |bcx| bcx, + handle_items); } pub fn trans_enum_variant(ccx: &CrateContext, @@ -1824,7 +1830,7 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext, let arena = TypedArena::new(); let fcx = new_fn_ctxt(ccx, llfndecl, ctor_id, false, result_ty, - param_substs, None, &arena); + param_substs, None, &arena, TranslateItems); let bcx = init_function(&fcx, false, result_ty); let arg_tys = ty::ty_fn_args(ctor_ty); @@ -1925,7 +1931,8 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) { llfn, ¶m_substs::empty(), item.id, - item.attrs.as_slice()); + item.attrs.as_slice(), + TranslateItems); } else { // Be sure to travel more than just one layer deep to catch nested // items in blocks and such. diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index b95bd08dd1642..f186af48321c3 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -339,7 +339,8 @@ pub fn trans_unboxing_shim(bcx: &Block, return_type, &empty_param_substs, None, - &block_arena); + &block_arena, + TranslateItems); let mut bcx = init_function(&fcx, false, return_type); // Create the substituted versions of the self type. diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index a65d208d4d287..98b2ebb70f3cb 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -394,7 +394,8 @@ pub fn trans_expr_fn<'a>( ty::ty_fn_abi(fty), true, NotUnboxedClosure, - |bcx| load_environment(bcx, cdata_ty, &freevars, store)); + |bcx| load_environment(bcx, cdata_ty, &freevars, store), + bcx.fcx.handle_items); fill_fn_pair(bcx, dest_addr, llfn, llbox); bcx } @@ -486,7 +487,8 @@ pub fn trans_unboxed_closure<'a>( ty::ty_fn_abi(function_type), true, IsUnboxedClosure, - |bcx| load_unboxed_closure_environment(bcx, freevars_ptr)); + |bcx| load_unboxed_closure_environment(bcx, freevars_ptr), + bcx.fcx.handle_items); // Don't hoist this to the top of the function. It's perfectly legitimate // to have a zero-size unboxed closure (in which case dest will be @@ -573,7 +575,7 @@ pub fn get_wrapper_for_bare_fn(ccx: &CrateContext, let arena = TypedArena::new(); let empty_param_substs = param_substs::empty(); let fcx = new_fn_ctxt(ccx, llfn, -1, true, f.sig.output, - &empty_param_substs, None, &arena); + &empty_param_substs, None, &arena, TranslateItems); let bcx = init_function(&fcx, true, f.sig.output); let args = create_datums_for_fn_args(&fcx, diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 320e291e92865..71ddc2e40459c 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -221,6 +221,12 @@ impl SubstP for T { pub type RvalueDatum = datum::Datum; pub type LvalueDatum = datum::Datum; +#[deriving(Clone, Eq, PartialEq)] +pub enum HandleItemsFlag { + IgnoreItems, + TranslateItems, +} + // Function context. Every LLVM function we create will have one of // these. pub struct FunctionContext<'a> { @@ -289,6 +295,9 @@ pub struct FunctionContext<'a> { // Cleanup scopes. pub scopes: RefCell> >, + + // How to handle items encountered during translation of this function. + pub handle_items: HandleItemsFlag, } impl<'a> FunctionContext<'a> { diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs index d8a8cc1c561a9..dd8fe5e9303a5 100644 --- a/src/librustc/middle/trans/controlflow.rs +++ b/src/librustc/middle/trans/controlflow.rs @@ -68,7 +68,12 @@ pub fn trans_stmt<'a>(cx: &'a Block<'a>, debuginfo::create_local_var_metadata(bcx, &**local); } } - ast::DeclItem(ref i) => trans_item(cx.fcx.ccx, &**i) + ast::DeclItem(ref i) => { + match fcx.handle_items { + TranslateItems => trans_item(cx.fcx.ccx, &**i), + IgnoreItems => {} + } + } } } ast::StmtMac(..) => cx.tcx().sess.bug("unexpanded macro") diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index f305ae90d46af..cb46d62fca9e9 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -601,7 +601,8 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: &CrateContext, let llfn = base::decl_internal_rust_fn(ccx, t, ps.as_slice()); base::set_llvm_fn_attrs(attrs, llfn); - base::trans_fn(ccx, decl, body, llfn, ¶m_substs::empty(), id, []); + base::trans_fn(ccx, decl, body, llfn, ¶m_substs::empty(), id, [], + TranslateItems); llfn } diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 5c978d505cb76..40288a33930e5 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -468,7 +468,7 @@ fn make_generic_glue(ccx: &CrateContext, let arena = TypedArena::new(); let empty_param_substs = param_substs::empty(); let fcx = new_fn_ctxt(ccx, llfn, -1, false, ty::mk_nil(), - &empty_param_substs, None, &arena); + &empty_param_substs, None, &arena, TranslateItems); let bcx = init_function(&fcx, false, ty::mk_nil()); diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs index bf39f3a6aa385..877dd647c3b20 100644 --- a/src/librustc/middle/trans/inline.rs +++ b/src/librustc/middle/trans/inline.rs @@ -133,7 +133,7 @@ pub fn maybe_instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId) 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, []); + ¶m_substs::empty(), mth.id, [], TranslateItems); } local_def(mth.id) } diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index 53f89c9d8b879..4e6250883ebf0 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -75,7 +75,8 @@ pub fn trans_impl(ccx: &CrateContext, llfn, ¶m_substs::empty(), method.id, - []); + [], + TranslateItems); } else { let mut v = TransItemVisitor{ ccx: ccx }; visit::walk_method_helper(&mut v, &**method, ()); diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index dac3b6bd8eee4..986d3328f2c3a 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -149,7 +149,8 @@ pub fn monomorphic_fn(ccx: &CrateContext, } => { let d = mk_lldecl(); set_llvm_fn_attrs(i.attrs.as_slice(), d); - trans_fn(ccx, &**decl, &**body, d, &psubsts, fn_id.node, []); + trans_fn(ccx, &**decl, &**body, d, &psubsts, fn_id.node, [], + IgnoreItems); d } _ => { @@ -181,7 +182,8 @@ pub fn monomorphic_fn(ccx: &CrateContext, ast_map::NodeMethod(mth) => { let d = mk_lldecl(); set_llvm_fn_attrs(mth.attrs.as_slice(), d); - trans_fn(ccx, &*mth.pe_fn_decl(), &*mth.pe_body(), d, &psubsts, mth.id, []); + trans_fn(ccx, &*mth.pe_fn_decl(), &*mth.pe_body(), d, &psubsts, mth.id, [], + IgnoreItems); d } ast_map::NodeTraitMethod(method) => { @@ -190,7 +192,7 @@ pub fn monomorphic_fn(ccx: &CrateContext, let d = mk_lldecl(); set_llvm_fn_attrs(mth.attrs.as_slice(), d); trans_fn(ccx, &*mth.pe_fn_decl(), &*mth.pe_body(), d, - &psubsts, mth.id, []); + &psubsts, mth.id, [], IgnoreItems); d } _ => { diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index 7d8700b942609..eb0d77da5519f 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -312,7 +312,7 @@ impl<'a, 'b> Reflector<'a, 'b> { let empty_param_substs = param_substs::empty(); let fcx = new_fn_ctxt(ccx, llfdecl, -1, false, ty::mk_u64(), &empty_param_substs, - None, &arena); + None, &arena, TranslateItems); let bcx = init_function(&fcx, false, ty::mk_u64()); // we know the return type of llfdecl is an int here, so diff --git a/src/test/run-make/issue-7349/Makefile b/src/test/run-make/issue-7349/Makefile new file mode 100644 index 0000000000000..18ba80a712d11 --- /dev/null +++ b/src/test/run-make/issue-7349/Makefile @@ -0,0 +1,11 @@ +-include ../tools.mk + +# Test to make sure that inner functions within a polymorphic outer function +# don't get re-translated when the outer function is monomorphized. The test +# code monomorphizes the outer function several times, but the magic constant +# `8675309` used in the inner function should appear only once in the generated +# IR. + +all: + $(RUSTC) foo.rs --emit=ir + [ "$$(grep -c 8675309 "$(TMPDIR)/foo.ll")" -eq "1" ] diff --git a/src/test/run-make/issue-7349/foo.rs b/src/test/run-make/issue-7349/foo.rs new file mode 100644 index 0000000000000..775b7314841cc --- /dev/null +++ b/src/test/run-make/issue-7349/foo.rs @@ -0,0 +1,21 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn outer() { + #[allow(dead_code)] + fn inner() -> uint { + 8675309 + } +} + +fn main() { + outer::(); + outer::(); +}