summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2012-03-06 11:33:25 +0100
committerMarijn Haverbeke <marijnh@gmail.com>2012-03-06 14:00:21 +0100
commit19508c7d531910c309cd63e9ade2fe1be80ff71b (patch)
tree6939af62adaf2bcf8f4515e4e372c286fefc0389 /src/rustc
parent9b882197233c06454e376fd80adca7f4a80264ca (diff)
downloadrust-19508c7d531910c309cd63e9ade2fe1be80ff71b.tar.gz
rust-19508c7d531910c309cd63e9ade2fe1be80ff71b.zip
Make trans pass responsible for pulling in inlined functions
This makes the logic for finding the inlinable items much easier --
they are simply pulled in lazily when encountered.
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/driver/driver.rs9
-rw-r--r--src/rustc/middle/inline.rs100
-rw-r--r--src/rustc/middle/trans/base.rs164
-rw-r--r--src/rustc/middle/trans/common.rs5
-rw-r--r--src/rustc/middle/trans/native.rs5
-rw-r--r--src/rustc/rustc.rc1
6 files changed, 75 insertions, 209 deletions
diff --git a/src/rustc/driver/driver.rs b/src/rustc/driver/driver.rs
index 55dcd2daf75..eed65357449 100644
--- a/src/rustc/driver/driver.rs
+++ b/src/rustc/driver/driver.rs
@@ -6,7 +6,7 @@ import syntax::parse::{parser};
 import syntax::{ast, codemap};
 import front::attr;
 import middle::{trans, resolve, freevars, kind, ty, typeck, fn_usage,
-                last_use, lint, inline};
+                last_use, lint};
 import syntax::print::{pp, pprust};
 import util::{ppaux, filesearch};
 import back::link;
@@ -177,16 +177,11 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
                 last_uses: last_uses, impl_map: impl_map,
                 method_map: method_map, dict_map: dict_map};
 
-    let ienbld = sess.opts.inline;
-    let inline_map =
-        time(time_passes, "inline",
-             bind inline::instantiate_inlines(ienbld, ty_cx, maps, crate));
-
     let (llmod, link_meta) =
         time(time_passes, "translation",
              bind trans::base::trans_crate(
                  sess, crate, ty_cx, outputs.obj_filename,
-                 exp_map, maps, inline_map));
+                 exp_map, maps));
     time(time_passes, "LLVM passes",
          bind link::write::run_passes(sess, llmod, outputs.obj_filename));
 
diff --git a/src/rustc/middle/inline.rs b/src/rustc/middle/inline.rs
deleted file mode 100644
index 91d69168faf..00000000000
--- a/src/rustc/middle/inline.rs
+++ /dev/null
@@ -1,100 +0,0 @@
-import std::map::hashmap;
-import syntax::ast;
-import syntax::ast_util;
-import syntax::ast_util::inlined_item_methods;
-import syntax::visit;
-import middle::typeck::method_map;
-import middle::trans::common::maps;
-import metadata::csearch;
-
-export inline_map;
-export instantiate_inlines;
-
-type inline_map = hashmap<ast::def_id, ast::inlined_item>;
-
-enum ctxt = {
-    tcx: ty::ctxt,
-    maps: maps,
-    inline_map: inline_map,
-    mut to_process: [ast::inlined_item]
-};
-
-fn instantiate_inlines(enabled: bool,
-                       tcx: ty::ctxt,
-                       maps: maps,
-                       crate: @ast::crate) -> inline_map {
-    let vt = visit::mk_vt(@{
-        visit_expr: fn@(e: @ast::expr, cx: ctxt, vt: visit::vt<ctxt>) {
-            visit::visit_expr(e, cx, vt);
-            cx.visit_expr(e);
-        }
-        with *visit::default_visitor::<ctxt>()
-    });
-    let inline_map = ast_util::new_def_id_hash();
-    let cx = ctxt({tcx: tcx, maps: maps,
-                   inline_map: inline_map, mutable to_process: []});
-    if enabled { visit::visit_crate(*crate, cx, vt); }
-    while !vec::is_empty(cx.to_process) {
-        let to_process = [];
-        to_process <-> cx.to_process;
-        #debug["Recursively looking at inlined items"];
-        vec::iter(to_process) {|ii|
-            ii.accept(cx, vt);
-        }
-    }
-    ret inline_map;
-}
-
-impl methods for ctxt {
-    fn visit_expr(e: @ast::expr) {
-
-        // Look for fn items or methods that are referenced which
-        // ought to be inlined.
-
-        alt e.node {
-          ast::expr_path(_) {
-            alt self.tcx.def_map.get(e.id) {
-              ast::def_fn(did, _) {
-                self.maybe_enqueue_fn(did);
-              }
-              _ { /* not a fn item, fallthrough */ }
-            }
-          }
-          ast::expr_field(_, _, _) {
-            alt self.maps.method_map.find(e.id) {
-              some(origin) {
-                self.maybe_enqueue_impl_method(origin);
-              }
-              _ { /* not an impl method, fallthrough */ }
-            }
-          }
-          _ { /* fallthrough */ }
-        }
-    }
-
-    fn maybe_enqueue_fn(did: ast::def_id) {
-        if did.crate == ast::local_crate { ret; }
-        if self.inline_map.contains_key(did) { ret; }
-        alt csearch::maybe_get_item_ast(self.tcx, self.maps, did) {
-          none {
-            /* no AST attached, do not inline */
-            #debug["No AST attached to def %s",
-                   ty::item_path_str(self.tcx, did)];
-          }
-          some(ii) { /* Found an AST, add to table: */
-            #debug["Inlining def %s", ty::item_path_str(self.tcx, did)];
-            self.to_process += [ii];
-            self.inline_map.insert(did, ii);
-          }
-        }
-    }
-
-    fn maybe_enqueue_impl_method(method_origin: typeck::method_origin) {
-        alt method_origin {
-          typeck::method_static(did) { self.maybe_enqueue_fn(did); }
-          typeck::method_param(_, _, _, _) | typeck::method_iface(_, _) {
-            /* fallthrough */
-          }
-        }
-    }
-}
diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs
index 9baae720f47..5d36d077edf 100644
--- a/src/rustc/middle/trans/base.rs
+++ b/src/rustc/middle/trans/base.rs
@@ -20,7 +20,6 @@ import std::map::{new_int_hash, new_str_hash};
 import driver::session;
 import session::session;
 import front::attr;
-import middle::inline::inline_map;
 import back::{link, abi, upcall};
 import syntax::{ast, ast_util, codemap};
 import ast_util::inlined_item_methods;
@@ -651,20 +650,11 @@ fn set_inline_hint(f: ValueRef) {
                               0u as c_uint);
 }
 
-fn set_inline_hint_if_appr(ccx: crate_ctxt,
-                           attrs: [ast::attribute],
-                           id: ast::node_id) {
+fn set_inline_hint_if_appr(attrs: [ast::attribute],
+                           llfn: ValueRef) {
     alt attr::find_inline_attr(attrs) {
-      attr::ia_hint {
-        #debug["Setting inline mode for %s to 'hint'",
-               ty::item_path_str(ccx.tcx, ast_util::local_def(id))];
-        set_inline_hint(ccx.item_ids.get(id))
-      }
-      attr::ia_always {
-        #debug["Setting inline mode for %s to 'always'",
-               ty::item_path_str(ccx.tcx, ast_util::local_def(id))];
-        set_always_inline(ccx.item_ids.get(id))
-      }
+      attr::ia_hint { set_inline_hint(llfn); }
+      attr::ia_always { set_always_inline(llfn); }
       attr::ia_none { /* fallthrough */ }
     }
 }
@@ -2152,6 +2142,40 @@ fn monomorphic_fn(ccx: crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
     some({llfn: lldecl, fty: mono_ty})
 }
 
+// FIXME[mono] Only actually translate things that are not generic
+fn maybe_instantiate_inline(ccx: crate_ctxt, fn_id: ast::def_id)
+    -> ast::def_id {
+    alt ccx.external.find(fn_id) {
+      some(some(node_id)) { local_def(node_id) } // Already inline
+      some(none) { fn_id } // Not inlinable
+      none { // Not seen yet
+        alt csearch::maybe_get_item_ast(ccx.tcx, ccx.maps, fn_id) {
+          none { ccx.external.insert(fn_id, none); fn_id }
+          some(ast::ii_item(item)) {
+            ccx.external.insert(fn_id, some(item.id));
+            collect_item(ccx, @mutable none, item);
+            trans_item(ccx, *item);
+            local_def(item.id)
+          }
+          some(ast::ii_method(impl_did, mth)) {
+            ccx.external.insert(fn_id, some(mth.id));
+            compute_ii_method_info(ccx, impl_did, mth) {|ty, bounds, path|
+                let mth_ty = ty::node_id_to_type(ccx.tcx, mth.id);
+                let llfn = register_fn_full(ccx, mth.span, path,
+                                            "impl_method", bounds,
+                                            mth.id, mth_ty);
+                set_inline_hint_if_appr(mth.attrs, llfn);
+                trans_fn(ccx, path, mth.decl, mth.body,
+                         llfn, impl_self(ty), bounds,
+                         none, mth.id, none);
+            }
+            local_def(mth.id)
+          }
+        }
+      }
+    }
+}
+
 fn lval_static_fn(bcx: block, fn_id: ast::def_id, id: ast::node_id,
                   substs: option<([ty::t], typeck::dict_res)>)
     -> lval_maybe_callee {
@@ -2162,22 +2186,9 @@ fn lval_static_fn(bcx: block, fn_id: ast::def_id, id: ast::node_id,
 
     // Check whether this fn has an inlined copy and, if so, redirect fn_id to
     // the local id of the inlined copy.
-    let fn_id = {
-        if fn_id.crate == ast::local_crate {
-            fn_id
-        } else {
-            alt ccx.inline_map.find(fn_id) {
-              none { fn_id }
-              some(ii) {
-                #debug["Found inlined version of %s with id %d",
-                       ty::item_path_str(tcx, fn_id),
-                       ii.id()];
-                {crate: ast::local_crate,
-                 node: ii.id()}
-              }
-            }
-        }
-    };
+    let fn_id = if fn_id.crate != ast::local_crate && ccx.sess.opts.inline {
+        maybe_instantiate_inline(ccx, fn_id)
+    } else { fn_id };
 
     // The awkwardness below mostly stems from the fact that we're mixing
     // monomorphized and non-monomorphized functions at the moment. If
@@ -4478,35 +4489,17 @@ fn compute_ii_method_info(ccx: crate_ctxt,
     f(impl_ty, m_bounds, m_path);
 }
 
-fn trans_inlined_items(ccx: crate_ctxt, inline_map: inline_map) {
-    inline_map.values {|ii|
-        alt ii {
-          ast::ii_item(item) {
-            trans_item(ccx, *item)
-          }
-          ast::ii_method(impl_did, m) {
-            compute_ii_method_info(ccx, impl_did, m) {
-                |impl_ty, m_bounds, m_path|
-                let llfndecl = ccx.item_ids.get(m.id);
-                trans_fn(ccx, m_path, m.decl, m.body,
-                         llfndecl, impl_self(impl_ty), m_bounds,
-                         none, m.id, none);
-            }
-          }
-        }
-    }
-}
-
 fn get_pair_fn_ty(llpairty: TypeRef) -> TypeRef {
     // Bit of a kludge: pick the fn typeref out of the pair.
     ret struct_elt(llpairty, 0u);
 }
 
 fn register_fn(ccx: crate_ctxt, sp: span, path: path, flav: str,
-               ty_params: [ast::ty_param], node_id: ast::node_id) {
+               ty_params: [ast::ty_param], node_id: ast::node_id)
+    -> ValueRef {
     let t = ty::node_id_to_type(ccx.tcx, node_id);
     let bnds = param_bounds(ccx, ty_params);
-    register_fn_full(ccx, sp, path, flav, bnds, node_id, t);
+    register_fn_full(ccx, sp, path, flav, bnds, node_id, t)
 }
 
 fn param_bounds(ccx: crate_ctxt, tps: [ast::ty_param]) -> [ty::param_bounds] {
@@ -4515,15 +4508,15 @@ fn param_bounds(ccx: crate_ctxt, tps: [ast::ty_param]) -> [ty::param_bounds] {
 
 fn register_fn_full(ccx: crate_ctxt, sp: span, path: path, flav: str,
                     bnds: [ty::param_bounds], node_id: ast::node_id,
-                    node_type: ty::t) {
+                    node_type: ty::t) -> ValueRef {
     let llfty = type_of_fn_from_ty(ccx, node_type, bnds);
     register_fn_fuller(ccx, sp, path, flav, node_id, node_type,
-                       lib::llvm::CCallConv, llfty);
+                       lib::llvm::CCallConv, llfty)
 }
 
 fn register_fn_fuller(ccx: crate_ctxt, sp: span, path: path, _flav: str,
                       node_id: ast::node_id, node_type: ty::t,
-                      cc: lib::llvm::CallConv, llfty: TypeRef) {
+                      cc: lib::llvm::CallConv, llfty: TypeRef) -> ValueRef {
     let ps: str = mangle_exported_name(ccx, path, node_type);
     let llfn: ValueRef = decl_fn(ccx.llmod, ps, cc, llfty);
     ccx.item_ids.insert(node_id, llfn);
@@ -4534,6 +4527,7 @@ fn register_fn_fuller(ccx: crate_ctxt, sp: span, path: path, _flav: str,
 
     let is_main = is_main_name(path) && !ccx.sess.building_library;
     if is_main { create_main_wrapper(ccx, sp, llfn, node_type); }
+    llfn
 }
 
 // Create a _rust_main(args: [str]) function which will be called from the
@@ -4713,39 +4707,39 @@ fn collect_item(ccx: crate_ctxt, abi: @mutable option<ast::native_abi>,
         }
       }
       ast::item_fn(decl, tps, _) {
-        if decl.purity != ast::crust_fn {
-            register_fn(ccx, i.span, my_path, "fn", tps,
-                        i.id);
+        let llfn = if decl.purity != ast::crust_fn {
+            register_fn(ccx, i.span, my_path, "fn", tps, i.id)
         } else {
-            native::register_crust_fn(ccx, i.span, my_path, i.id);
-        }
+            native::register_crust_fn(ccx, i.span, my_path, i.id)
+        };
 
-        set_inline_hint_if_appr(ccx, i.attrs, i.id);
+        set_inline_hint_if_appr(i.attrs, llfn);
       }
       ast::item_impl(tps, _, _, methods) {
         let path = my_path + [path_name(int::str(i.id))];
         for m in methods {
-            register_fn(ccx, i.span,
-                        path + [path_name(m.ident)],
-                        "impl_method", tps + m.tps, m.id);
-
-            set_inline_hint_if_appr(ccx, m.attrs, m.id);
+            let llm  = register_fn(ccx, i.span,
+                                   path + [path_name(m.ident)],
+                                   "impl_method", tps + m.tps, m.id);
+            set_inline_hint_if_appr(m.attrs, llm);
         }
       }
       ast::item_res(_, tps, _, dtor_id, ctor_id) {
-        register_fn(ccx, i.span, my_path, "res_ctor", tps, ctor_id);
+        let llctor = register_fn(ccx, i.span, my_path, "res_ctor", tps,
+                                 ctor_id);
 
         // Note that the destructor is associated with the item's id, not
         // the dtor_id. This is a bit counter-intuitive, but simplifies
         // ty_res, which would have to carry around two def_ids otherwise
         // -- one to identify the type, and one to find the dtor symbol.
         let t = ty::node_id_to_type(ccx.tcx, dtor_id);
-        register_fn_full(ccx, i.span, my_path + [path_name("dtor")],
-                         "res_dtor", param_bounds(ccx, tps), i.id, t);
+        let lldtor = register_fn_full(ccx, i.span, my_path +
+                                      [path_name("dtor")], "res_dtor",
+                                      param_bounds(ccx, tps), i.id, t);
 
         // give hints that resource ctors/dtors ought to be inlined
-        set_inline_hint(ccx.item_ids.get(ctor_id));
-        set_inline_hint(ccx.item_ids.get(i.id));
+        set_inline_hint(llctor);
+        set_inline_hint(lldtor);
       }
       ast::item_enum(variants, tps) {
         for variant in variants {
@@ -4767,7 +4761,7 @@ fn collect_item(ccx: crate_ctxt, abi: @mutable option<ast::native_abi>,
 }
 
 fn collect_items(ccx: crate_ctxt, crate: @ast::crate) {
-    let abi = @mutable none::<ast::native_abi>;
+    let abi = @mutable none;
     visit::visit_crate(*crate, (), visit::mk_simple_visitor(@{
         visit_native_item: bind collect_native_item(ccx, abi, _),
         visit_item: bind collect_item(ccx, abi, _)
@@ -4775,27 +4769,6 @@ fn collect_items(ccx: crate_ctxt, crate: @ast::crate) {
     }));
 }
 
-fn collect_inlined_items(ccx: crate_ctxt, inline_map: inline::inline_map) {
-    let abi = @mutable none::<ast::native_abi>;
-    inline_map.values {|ii|
-        alt ii {
-          ast::ii_item(item) {
-            collect_item(ccx, abi, item);
-          }
-
-          ast::ii_method(impl_did, m) {
-            compute_ii_method_info(ccx, impl_did, m) {
-                |_impl_ty, m_bounds, m_path|
-                let mthd_ty = ty::node_id_to_type(ccx.tcx, m.id);
-                register_fn_full(ccx, m.span, m_path, "impl_method",
-                                 m_bounds, m.id, mthd_ty);
-                set_inline_hint_if_appr(ccx, m.attrs, m.id);
-            }
-          }
-        }
-    }
-}
-
 // The constant translation pass.
 fn trans_constant(ccx: crate_ctxt, it: @ast::item) {
     alt it.node {
@@ -4995,8 +4968,7 @@ fn write_abi_version(ccx: crate_ctxt) {
 }
 
 fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
-               output: str, emap: resolve::exp_map, maps: maps,
-               inline_map: inline::inline_map)
+               output: str, emap: resolve::exp_map, maps: maps)
     -> (ModuleRef, link::link_meta) {
     let sha = std::sha1::mk_sha1();
     let link_meta = link::build_link_meta(sess, *crate, output, sha);
@@ -5063,6 +5035,7 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
           consts: new_int_hash::<ValueRef>(),
           tydescs: ty::new_ty_hash(),
           dicts: map::mk_hashmap(hash_dict_id, {|a, b| a == b}),
+          external: util::common::new_def_hash(),
           monomorphized: map::mk_hashmap(hash_mono_id, {|a, b| a == b}),
           module_data: new_str_hash::<ValueRef>(),
           lltypes: ty::new_ty_hash(),
@@ -5072,7 +5045,6 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
           type_short_names: ty::new_ty_hash(),
           tcx: tcx,
           maps: maps,
-          inline_map: inline_map,
           stats:
               {mutable n_static_tydescs: 0u,
                mutable n_derived_tydescs: 0u,
@@ -5094,10 +5066,8 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
           dbg_cx: dbg_cx,
           mutable do_not_commit_warning_issued: false};
     collect_items(ccx, crate);
-    collect_inlined_items(ccx, inline_map);
     trans_constants(ccx, crate);
     trans_mod(ccx, crate.node.module);
-    trans_inlined_items(ccx, inline_map);
     fill_crate_map(ccx, crate_map);
     emit_tydescs(ccx);
     gen_shape_tables(ccx);
diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs
index 7b42ca61699..5bb2dfb885f 100644
--- a/src/rustc/middle/trans/common.rs
+++ b/src/rustc/middle/trans/common.rs
@@ -19,7 +19,6 @@ import lib::llvm::{ModuleRef, ValueRef, TypeRef, BasicBlockRef, BuilderRef};
 import lib::llvm::{True, False, Bool};
 import metadata::csearch;
 import ast_map::path;
-import middle::inline::inline_map;
 
 type namegen = fn@(str) -> str;
 fn new_namegen() -> namegen {
@@ -93,6 +92,9 @@ type crate_ctxt = @{
      consts: hashmap<ast::node_id, ValueRef>,
      tydescs: hashmap<ty::t, @tydesc_info>,
      dicts: hashmap<dict_id, ValueRef>,
+     // Track mapping of external ids to local items imported for inlining
+     external: hashmap<ast::def_id, option<ast::node_id>>,
+     // Cache instances of monomorphized functions
      monomorphized: hashmap<mono_id, {llfn: ValueRef, fty: ty::t}>,
      module_data: hashmap<str, ValueRef>,
      lltypes: hashmap<ty::t, TypeRef>,
@@ -102,7 +104,6 @@ type crate_ctxt = @{
      type_short_names: hashmap<ty::t, str>,
      tcx: ty::ctxt,
      maps: maps,
-     inline_map: inline_map,
      stats: stats,
      upcalls: @upcall::upcalls,
      tydesc_type: TypeRef,
diff --git a/src/rustc/middle/trans/native.rs b/src/rustc/middle/trans/native.rs
index 9753ef6bd33..26621158f77 100644
--- a/src/rustc/middle/trans/native.rs
+++ b/src/rustc/middle/trans/native.rs
@@ -351,10 +351,11 @@ fn trans_crust_fn(ccx: crate_ctxt, path: ast_map::path, decl: ast::fn_decl,
 }
 
 fn register_crust_fn(ccx: crate_ctxt, sp: span,
-                     path: ast_map::path, node_id: ast::node_id) {
+                     path: ast_map::path, node_id: ast::node_id)
+    -> ValueRef {
     let t = ty::node_id_to_type(ccx.tcx, node_id);
     let (llargtys, llretty, _) = c_arg_and_ret_lltys(ccx, node_id);
     let llfty = T_fn(llargtys, llretty);
     register_fn_fuller(ccx, sp, path, "crust fn", node_id,
-                       t, lib::llvm::CCallConv, llfty);
+                       t, lib::llvm::CCallConv, llfty)
 }
\ No newline at end of file
diff --git a/src/rustc/rustc.rc b/src/rustc/rustc.rc
index 8102e4d8cd8..a8b398066ec 100644
--- a/src/rustc/rustc.rc
+++ b/src/rustc/rustc.rc
@@ -28,7 +28,6 @@ mod middle {
         mod shape;
         mod debuginfo;
     }
-    mod inline;
     mod ty;
     mod ast_map;
     mod resolve;