about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-07-30 20:51:22 +0000
committerbors <bors@rust-lang.org>2014-07-30 20:51:22 +0000
commit7c28dd080ce4253d8b0126d6cf9bfc2ba0004cf8 (patch)
tree64151d916e814fc6f1724e7ce15f493016f04dfb /src
parent7a25cf3f30fa5fae2e868fa910ecc850f5e9ee65 (diff)
parentf97f65f7b70e455c1c3e72e620120c9f1a96d89a (diff)
downloadrust-7c28dd080ce4253d8b0126d6cf9bfc2ba0004cf8.tar.gz
rust-7c28dd080ce4253d8b0126d6cf9bfc2ba0004cf8.zip
auto merge of #16059 : epdtry/rust/mono-item-dedup, r=alexcrichton
Currently, each time a function is monomorphized, all items within that function are translated.  This is unnecessary work because the inner items already get translated when the function declaration is visited by `trans_item`.  This patch adds a flag to the `FunctionContext` to prevent translation of items during monomorphization.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/trans/base.rs23
-rw-r--r--src/librustc/middle/trans/callee.rs3
-rw-r--r--src/librustc/middle/trans/closure.rs8
-rw-r--r--src/librustc/middle/trans/common.rs9
-rw-r--r--src/librustc/middle/trans/controlflow.rs7
-rw-r--r--src/librustc/middle/trans/foreign.rs3
-rw-r--r--src/librustc/middle/trans/glue.rs2
-rw-r--r--src/librustc/middle/trans/inline.rs2
-rw-r--r--src/librustc/middle/trans/meth.rs3
-rw-r--r--src/librustc/middle/trans/monomorphize.rs8
-rw-r--r--src/librustc/middle/trans/reflect.rs2
-rw-r--r--src/test/run-make/issue-7349/Makefile11
-rw-r--r--src/test/run-make/issue-7349/foo.rs21
13 files changed, 81 insertions, 21 deletions
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 5433923441a..ea301784c93 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<Span>,
-                       block_arena: &'a TypedArena<Block<'a>>)
+                       block_arena: &'a TypedArena<Block<'a>>,
+                       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: &param_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,
                      &param_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 b95bd08dd16..f186af48321 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 a65d208d4d2..98b2ebb70f3 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 320e291e928..71ddc2e4045 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -221,6 +221,12 @@ impl<T:Subst+Clone> SubstP for T {
 pub type RvalueDatum = datum::Datum<datum::Rvalue>;
 pub type LvalueDatum = datum::Datum<datum::Lvalue>;
 
+#[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<Vec<cleanup::CleanupScope<'a>> >,
+
+    // 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 d8a8cc1c561..dd8fe5e9303 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 f305ae90d46..cb46d62fca9 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, &param_substs::empty(), id, []);
+        base::trans_fn(ccx, decl, body, llfn, &param_substs::empty(), id, [],
+                       TranslateItems);
         llfn
     }
 
diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs
index 5c978d505cb..40288a33930 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 bf39f3a6aa3..877dd647c3b 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,
-                       &param_substs::empty(), mth.id, []);
+                       &param_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 53f89c9d8b8..4e6250883eb 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,
                      &param_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 dac3b6bd8ee..986d3328f2c 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 7d8700b9426..eb0d77da551 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 00000000000..18ba80a712d
--- /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 00000000000..775b7314841
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn outer<T>() {
+    #[allow(dead_code)]
+    fn inner() -> uint {
+        8675309
+    }
+}
+
+fn main() {
+    outer::<int>();
+    outer::<uint>();
+}