about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2012-02-09 14:33:00 +0100
committerMarijn Haverbeke <marijnh@gmail.com>2012-02-09 15:30:48 +0100
commit02082be4a73921702703ca93c8387b040181029a (patch)
tree7408fd1ef186320229423bac94468fd9efb6a1b3
parent52a741754c76f147e8a009051c307091efaf45b2 (diff)
downloadrust-02082be4a73921702703ca93c8387b040181029a.tar.gz
rust-02082be4a73921702703ca93c8387b040181029a.zip
Fix various bugs in monomorphization
Enough to be able to compile librustc with --monomorphize.

Issue #1736
-rw-r--r--src/comp/middle/alias.rs2
-rw-r--r--src/comp/middle/debuginfo.rs2
-rw-r--r--src/comp/middle/trans/alt.rs16
-rw-r--r--src/comp/middle/trans/base.rs80
-rw-r--r--src/comp/middle/trans/closure.rs5
-rw-r--r--src/comp/middle/trans/common.rs10
-rw-r--r--src/comp/middle/trans/impl.rs16
-rw-r--r--src/comp/middle/ty.rs14
8 files changed, 81 insertions, 64 deletions
diff --git a/src/comp/middle/alias.rs b/src/comp/middle/alias.rs
index 292700bbbd5..5c5ce3f674c 100644
--- a/src/comp/middle/alias.rs
+++ b/src/comp/middle/alias.rs
@@ -615,7 +615,7 @@ fn pattern_roots(tcx: ty::ctxt, mut: option<unsafe_ty>, pat: @ast::pat)
           ast::pat_rec(fs, _) {
             let ty = ty::node_id_to_type(tcx, pat.id);
             for f in fs {
-                let m = ty::get_field(tcx, ty, f.ident).mt.mut != ast::imm,
+                let m = ty::get_field(ty, f.ident).mt.mut != ast::imm,
                     c = if m { some(contains(ty)) } else { mut };
                 walk(tcx, c, f.pat, set);
             }
diff --git a/src/comp/middle/debuginfo.rs b/src/comp/middle/debuginfo.rs
index fbc3ec44812..3419b6379e3 100644
--- a/src/comp/middle/debuginfo.rs
+++ b/src/comp/middle/debuginfo.rs
@@ -411,7 +411,7 @@ fn create_record(cx: @crate_ctxt, t: ty::t, fields: [ast::ty_field],
                                line_from_span(cx.sess.codemap,
                                               span) as int);
     for field in fields {
-        let field_t = ty::get_field(ccx_tcx(cx), t, field.node.ident).mt.ty;
+        let field_t = ty::get_field(t, field.node.ident).mt.ty;
         let ty_md = create_ty(cx, field_t, field.node.mt.ty);
         let (size, align) = member_size_and_align(cx.tcx, field.node.mt.ty);
         add_member(scx, field.node.ident,
diff --git a/src/comp/middle/trans/alt.rs b/src/comp/middle/trans/alt.rs
index ee9aa243bab..af6c859b039 100644
--- a/src/comp/middle/trans/alt.rs
+++ b/src/comp/middle/trans/alt.rs
@@ -265,7 +265,7 @@ fn extract_variant_args(bcx: @block_ctxt, pat_id: ast::node_id,
     let ccx = bcx.fcx.ccx, bcx = bcx;
     // invariant:
     // pat_id must have the same length ty_param_substs as vdefs?
-    let ty_param_substs = ty::node_id_to_type_params(ccx.tcx, pat_id);
+    let ty_param_substs = node_id_type_params(bcx, pat_id);
     let blobptr = val;
     let variants = ty::enum_variants(ccx.tcx, vdefs.enm);
     let args = [];
@@ -420,8 +420,8 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
     let rec_fields = collect_record_fields(m, col);
     // Separate path for extracting and binding record fields
     if vec::len(rec_fields) > 0u {
-        let rec_ty = ty::node_id_to_type(ccx.tcx, pat_id);
-        let fields = ty::get_fields(ccx.tcx, rec_ty);
+        let rec_ty = node_id_type(bcx, pat_id);
+        let fields = ty::get_fields(rec_ty);
         let rec_vals = [];
         for field_name: ast::ident in rec_fields {
             let ix = option::get(ty::field_idx(field_name, fields));
@@ -435,7 +435,7 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
     }
 
     if any_tup_pat(m, col) {
-        let tup_ty = ty::node_id_to_type(ccx.tcx, pat_id);
+        let tup_ty = node_id_type(bcx, pat_id);
         let n_tup_elts = alt ty::get(tup_ty).struct {
           ty::ty_tup(elts) { vec::len(elts) }
           _ { ccx.sess.bug("Non-tuple type in tuple pattern"); }
@@ -488,7 +488,7 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
           }
           lit(l) {
             test_val = Load(bcx, val);
-            let pty = ty::node_id_to_type(ccx.tcx, pat_id);
+            let pty = node_id_type(bcx, pat_id);
             kind = if ty::type_is_integral(pty) { switch }
                    else { compare };
           }
@@ -539,7 +539,7 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
             let compare_cx = new_scope_block_ctxt(bcx, "compare_scope");
             Br(bcx, compare_cx.llbb);
             bcx = compare_cx;
-            let t = ty::node_id_to_type(ccx.tcx, pat_id);
+            let t = node_id_type(bcx, pat_id);
             let res = trans_opt(bcx, opt);
             alt res {
               single_result(r) {
@@ -622,7 +622,7 @@ fn make_phi_bindings(bcx: @block_ctxt, map: [exit_node],
                         forgot to document an invariant in \
                         make_phi_bindings"); }
                 };
-                let e_ty = ty::node_id_to_type(bcx_tcx(bcx), node_id);
+                let e_ty = node_id_type(bcx, node_id);
                 let {bcx: abcx, val: alloc} = base::alloc_ty(bcx, e_ty);
                 bcx = base::copy_val(abcx, base::INIT, alloc,
                                       load_if_immediate(abcx, local, e_ty),
@@ -739,7 +739,7 @@ fn bind_irrefutable_pat(bcx: @block_ctxt, pat: @ast::pat, val: ValueRef,
       }
       ast::pat_rec(fields, _) {
         let rec_ty = node_id_type(bcx, pat.id);
-        let rec_fields = ty::get_fields(ccx.tcx, rec_ty);
+        let rec_fields = ty::get_fields(rec_ty);
         for f: ast::field_pat in fields {
             let ix = option::get(ty::field_idx(f.ident, rec_fields));
             // how to get rid of this check?
diff --git a/src/comp/middle/trans/base.rs b/src/comp/middle/trans/base.rs
index 2a4876703a2..b17de7f855c 100644
--- a/src/comp/middle/trans/base.rs
+++ b/src/comp/middle/trans/base.rs
@@ -1902,7 +1902,7 @@ fn trans_unary(bcx: @block_ctxt, op: ast::unop, e: @ast::expr,
     alt bcx_ccx(bcx).method_map.find(un_expr.id) {
       some(origin) {
         let callee_id = ast_util::op_expr_callee_id(un_expr);
-        let fty = ty::node_id_to_type(bcx_tcx(bcx), callee_id);
+        let fty = node_id_type(bcx, callee_id);
         ret trans_call_inner(bcx, fty, {|bcx|
             impl::trans_method_callee(bcx, callee_id, e, origin)
         }, [], un_expr.id, dest);
@@ -2036,7 +2036,6 @@ fn trans_eager_binop(cx: @block_ctxt, op: ast::binop, lhs: ValueRef,
 
 fn trans_assign_op(bcx: @block_ctxt, ex: @ast::expr, op: ast::binop,
                    dst: @ast::expr, src: @ast::expr) -> @block_ctxt {
-    let tcx = bcx_tcx(bcx);
     let t = expr_ty(bcx, src);
     let lhs_res = trans_lval(bcx, dst);
     assert (lhs_res.kind == owned);
@@ -2045,7 +2044,7 @@ fn trans_assign_op(bcx: @block_ctxt, ex: @ast::expr, op: ast::binop,
     alt bcx_ccx(bcx).method_map.find(ex.id) {
       some(origin) {
         let callee_id = ast_util::op_expr_callee_id(ex);
-        let fty = ty::node_id_to_type(tcx, callee_id);
+        let fty = node_id_type(bcx, callee_id);
         ret trans_call_inner(bcx, fty, {|bcx|
             // FIXME provide the already-computed address, not the expr
             impl::trans_method_callee(bcx, callee_id, dst, origin)
@@ -2169,7 +2168,7 @@ fn trans_binary(bcx: @block_ctxt, op: ast::binop, lhs: @ast::expr,
     alt bcx_ccx(bcx).method_map.find(ex.id) {
       some(origin) {
         let callee_id = ast_util::op_expr_callee_id(ex);
-        let fty = ty::node_id_to_type(bcx_tcx(bcx), callee_id);
+        let fty = node_id_type(bcx, callee_id);
         ret trans_call_inner(bcx, fty, {|bcx|
             impl::trans_method_callee(bcx, callee_id, lhs, origin)
         }, [rhs], ex.id, dest);
@@ -2452,59 +2451,58 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
     let tpt = ty::lookup_item_type(ccx.tcx, fn_id);
     let mono_ty = ty::substitute_type_params(ccx.tcx, substs, tpt.ty);
     let llfty = type_of_fn_from_ty(ccx, mono_ty, []);
-    let lldecl;
+
+    let map_node = ccx.tcx.items.get(fn_id.node);
+    // Get the path so that we can create a symbol
+    let (pt, name) = alt map_node {
+      ast_map::node_item(i, pt) { (pt, i.ident) }
+      ast_map::node_variant(v, _, pt) { (pt, v.node.name) }
+      ast_map::node_method(m, _, pt) { (pt, m.ident) }
+      // We can't monomorphize native functions
+      ast_map::node_native_item(_, _) { ret none; }
+      _ { fail "Unexpected node type"; }
+    };
+    let pt = *pt + [path_name(ccx.names(name))];
+    let s = mangle_exported_name(ccx, pt, mono_ty);
+    let lldecl = decl_cdecl_fn(ccx.llmod, s, llfty);
+    ccx.monomorphized.insert(hash_id, {llfn: lldecl, fty: mono_ty});
+
     let psubsts = some({tys: substs, dicts: dicts, bounds: tpt.bounds});
-    alt ccx.tcx.items.get(fn_id.node) {
-      ast_map::node_item(item, pt) {
-        let pt = *pt + [path_name(item.ident)];
-        let s = mangle_exported_name(ccx, pt, mono_ty);
-        lldecl = decl_cdecl_fn(ccx.llmod, s, llfty);
-        alt item.node {
-          ast::item_fn(decl, _, body) {
-            trans_fn(ccx, pt, decl, body, lldecl, no_self, [],
-                     psubsts, fn_id.node);
-          }
-          ast::item_res(decl, _, _, _, ctor_id) {
-            trans_res_ctor(ccx, pt, decl, ctor_id, [], psubsts, lldecl);
-          }
-          _ { fail "Unexpected item type"; }
-        }
+    alt map_node {
+      ast_map::node_item(@{node: ast::item_fn(decl, _, body), _}, _) {
+        trans_fn(ccx, pt, decl, body, lldecl, no_self, [],
+                 psubsts, fn_id.node);
+      }
+      ast_map::node_item(@{node: ast::item_res(decl, _, _, _, _), _}, _) {
+        trans_res_ctor(ccx, pt, decl, fn_id.node, [], psubsts, lldecl);
       }
-      ast_map::node_variant(v, enum_id, pt) {
-        let pt = *pt + [path_name(v.node.name)];
-        let s = mangle_exported_name(ccx, pt, mono_ty);
-        lldecl = decl_cdecl_fn(ccx.llmod, s, llfty);
+      ast_map::node_variant(v, enum_id, _) {
         let tvs = ty::enum_variants(ccx.tcx, enum_id);
         let this_tv = option::get(vec::find(*tvs, {|tv|
             tv.id.node == fn_id.node}));
         trans_enum_variant(ccx, enum_id.node, v, this_tv.disr_val,
                            vec::len(*tvs) == 1u, [], psubsts, lldecl);
       }
-      ast_map::node_method(mth, impl_id, pt) {
-        let pt = *pt + [path_name(mth.ident)];
-        let s = mangle_exported_name(ccx, pt, mono_ty);
-        lldecl = decl_cdecl_fn(ccx.llmod, s, llfty);
+      ast_map::node_method(mth, impl_id, _) {
         let selfty = ty::node_id_to_type(ccx.tcx, impl_id);
         let selfty = ty::substitute_type_params(ccx.tcx, substs, selfty);
         trans_fn(ccx, pt, mth.decl, mth.body, lldecl,
                  impl_self(selfty), [], psubsts, fn_id.node);
       }
-      ast_map::node_native_item(_, _) {
-        ret none;
-      }
-      _ { fail "Unexpected node type"; }
+      _ { fail; }
     }
-    let val = {llfn: lldecl, fty: mono_ty};
-    ccx.monomorphized.insert(hash_id, val);
-    some(val)
+    some({llfn: lldecl, fty: mono_ty})
 }
 
 fn lval_static_fn(bcx: @block_ctxt, fn_id: ast::def_id, id: ast::node_id,
                   substs: option<([ty::t], typeck::dict_res)>)
     -> lval_maybe_callee {
     let ccx = bcx_ccx(bcx);
-    let tys = ty::node_id_to_type_params(ccx.tcx, id);
+    let tys = node_id_type_params(bcx, id);
     let tpt = ty::lookup_item_type(ccx.tcx, fn_id);
+    // The awkwardness below mostly stems from the fact that we're mixing
+    // monomorphized and non-monomorphized functions at the moment. If
+    // monomorphizing becomes the only approach, this'll be much simpler.
     if ccx.sess.opts.monomorphize &&
        (option::is_some(substs) || vec::len(tys) > 0u) &&
        fn_id.crate == ast::local_crate &&
@@ -2634,7 +2632,7 @@ fn trans_var(cx: @block_ctxt, def: ast::def, id: ast::node_id)
             ret lval_static_fn(cx, vid, id, none);
         } else {
             // Nullary variant.
-            let enum_ty = ty::node_id_to_type(ccx.tcx, id);
+            let enum_ty = node_id_type(cx, id);
             let alloc_result = alloc_ty(cx, enum_ty);
             let llenumblob = alloc_result.val;
             let llenumty = type_of_enum(ccx, tid, enum_ty);
@@ -2652,7 +2650,7 @@ fn trans_var(cx: @block_ctxt, def: ast::def, id: ast::node_id)
             assert (ccx.consts.contains_key(did.node));
             ret lval_no_env(cx, ccx.consts.get(did.node), owned);
         } else {
-            let tp = ty::node_id_to_type(ccx.tcx, id);
+            let tp = node_id_type(cx, id);
             let val = trans_external_path(cx, did, {bounds: @[], ty: tp});
             ret lval_no_env(cx, load_if_immediate(cx, val, tp), owned_imm);
         }
@@ -3129,8 +3127,6 @@ fn trans_call_inner(in_cx: @block_ctxt, fn_expr_ty: ty::t,
     // NB: 'f' isn't necessarily a function; it might be an entire self-call
     // expression because of the hack that allows us to process self-calls
     // with trans_call.
-    let tcx = bcx_tcx(in_cx);
-
     let cx = new_scope_block_ctxt(in_cx, "call");
     Br(in_cx, cx.llbb);
     let f_res = get_callee(cx);
@@ -3157,7 +3153,7 @@ fn trans_call_inner(in_cx: @block_ctxt, fn_expr_ty: ty::t,
       }
     }
 
-    let ret_ty = ty::node_id_to_type(tcx, id);
+    let ret_ty = node_id_type(bcx, id);
     let args_res =
         trans_args(bcx, llenv, f_res.generic, args, fn_expr_ty, dest);
     bcx = args_res.bcx;
@@ -3520,7 +3516,7 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
         // If it is here, it's not an lval, so this is a user-defined index op
         let origin = bcx_ccx(bcx).method_map.get(e.id);
         let callee_id = ast_util::op_expr_callee_id(e);
-        let fty = ty::node_id_to_type(tcx, callee_id);
+        let fty = node_id_type(bcx, callee_id);
         ret trans_call_inner(bcx, fty, {|bcx|
             impl::trans_method_callee(bcx, callee_id, base, origin)
         }, [idx], e.id, dest);
diff --git a/src/comp/middle/trans/closure.rs b/src/comp/middle/trans/closure.rs
index f46000b921d..5ff02b63217 100644
--- a/src/comp/middle/trans/closure.rs
+++ b/src/comp/middle/trans/closure.rs
@@ -16,6 +16,7 @@ import back::link::{
 import util::ppaux::ty_to_str;
 import shape::{size_of};
 import ast_map::{path, path_mod, path_name};
+import driver::session::session;
 
 // ___Good to know (tm)__________________________________________________
 //
@@ -362,7 +363,7 @@ fn build_closure(bcx0: @block_ctxt,
     vec::iter(cap_vars) { |cap_var|
         let lv = trans_local_var(bcx, cap_var.def);
         let nid = ast_util::def_id_of_def(cap_var.def).node;
-        let ty = ty::node_id_to_type(tcx, nid);
+        let ty = node_id_type(bcx, nid);
         alt cap_var.mode {
           capture::cap_ref {
             assert ck == ty::ck_block;
@@ -486,7 +487,7 @@ fn trans_bind(cx: @block_ctxt, f: @ast::expr, args: [option<@ast::expr>],
               id: ast::node_id, dest: dest) -> @block_ctxt {
     let f_res = trans_callee(cx, f);
     ret trans_bind_1(cx, expr_ty(cx, f), f_res, args,
-                     ty::node_id_to_type(bcx_tcx(cx), id), dest);
+                     node_id_type(cx, id), dest);
 }
 
 fn trans_bind_1(cx: @block_ctxt, outgoing_fty: ty::t,
diff --git a/src/comp/middle/trans/common.rs b/src/comp/middle/trans/common.rs
index 4497b4abae0..7d7b5b25b47 100644
--- a/src/comp/middle/trans/common.rs
+++ b/src/comp/middle/trans/common.rs
@@ -910,6 +910,16 @@ fn node_id_type(bcx: @block_ctxt, id: ast::node_id) -> ty::t {
 fn expr_ty(bcx: @block_ctxt, ex: @ast::expr) -> ty::t {
     node_id_type(bcx, ex.id)
 }
+fn node_id_type_params(bcx: @block_ctxt, id: ast::node_id) -> [ty::t] {
+    let tcx = bcx_tcx(bcx);
+    let params = ty::node_id_to_type_params(tcx, id);
+    alt bcx.fcx.param_substs {
+      some(substs) {
+        vec::map(params) {|t| ty::substitute_type_params(tcx, substs.tys, t) }
+      }
+      _ { params }
+    }
+}
 
 //
 // Local Variables:
diff --git a/src/comp/middle/trans/impl.rs b/src/comp/middle/trans/impl.rs
index dc2ca12b513..41d6a47d75f 100644
--- a/src/comp/middle/trans/impl.rs
+++ b/src/comp/middle/trans/impl.rs
@@ -116,7 +116,7 @@ fn trans_vtable_callee(bcx: @block_ctxt, self: ValueRef, dict: ValueRef,
     let bcx = bcx, ccx = bcx_ccx(bcx), tcx = ccx.tcx;
     let method = ty::iface_methods(tcx, iface_id)[n_method];
     let {ty: fty, llty: llfty} =
-        wrapper_fn_ty(ccx, val_ty(dict), ty::node_id_to_type(tcx, callee_id),
+        wrapper_fn_ty(ccx, val_ty(dict), node_id_type(bcx, callee_id),
                       method.tps);
     let vtable = PointerCast(bcx, Load(bcx, GEPi(bcx, dict, [0, 0])),
                              T_ptr(T_array(T_ptr(llfty), n_method + 1u)));
@@ -124,7 +124,7 @@ fn trans_vtable_callee(bcx: @block_ctxt, self: ValueRef, dict: ValueRef,
     let generic = generic_none;
     if vec::len(*method.tps) > 0u || ty::type_has_params(fty) {
         let tydescs = [], tis = [];
-        let tptys = ty::node_id_to_type_params(tcx, callee_id);
+        let tptys = node_id_type_params(bcx, callee_id);
         for t in vec::tail_n(tptys, vec::len(tptys) - vec::len(*method.tps)) {
             let ti = none;
             let td = get_tydesc(bcx, t, true, ti).result;
@@ -246,7 +246,17 @@ fn resolve_dicts_in_fn_ctxt(fcx: @fn_ctxt, dicts: typeck::dict_res)
         result += [alt dict {
           typeck::dict_static(iid, tys, sub) {
             alt resolve_dicts_in_fn_ctxt(fcx, sub) {
-              some(sub) { typeck::dict_static(iid, tys, sub) }
+              some(sub) {
+                let tys = alt fcx.param_substs {
+                  some(substs) {
+                    vec::map(tys, {|t|
+                        ty::substitute_type_params(fcx.ccx.tcx, substs.tys, t)
+                    })
+                  }
+                  _ { tys }
+                };
+                typeck::dict_static(iid, tys, sub)
+              }
               none { ret none; }
             }
           }
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs
index 80ad164fab5..11f5c2ac3a0 100644
--- a/src/comp/middle/ty.rs
+++ b/src/comp/middle/ty.rs
@@ -1339,18 +1339,18 @@ fn field_idx(id: ast::ident, fields: [field]) -> option<uint> {
     ret none;
 }
 
-fn get_field(tcx: ctxt, rec_ty: t, id: ast::ident) -> field {
-    alt vec::find(get_fields(tcx, rec_ty), {|f| str::eq(f.ident, id) }) {
-         some(f) { ret f; }
-         _ { tcx.sess.bug(#fmt("get_field: bad field id %s", id)); }
+fn get_field(rec_ty: t, id: ast::ident) -> field {
+    alt vec::find(get_fields(rec_ty), {|f| str::eq(f.ident, id) }) {
+      some(f) { f }
+      _ { fail #fmt("get_field: bad field id %s", id); }
     }
 }
 
 // TODO: could have a precondition instead of failing
-fn get_fields(tcx:ctxt, rec_ty:t) -> [field] {
+fn get_fields(rec_ty:t) -> [field] {
     alt get(rec_ty).struct {
-       ty_rec(fields) { fields }
-       _ { tcx.sess.bug("get_fields called on non-record type"); }
+      ty_rec(fields) { fields }
+      _ { fail "get_fields called on non-record type"; }
     }
 }