diff options
| author | Marijn Haverbeke <marijnh@gmail.com> | 2012-02-09 14:33:00 +0100 |
|---|---|---|
| committer | Marijn Haverbeke <marijnh@gmail.com> | 2012-02-09 15:30:48 +0100 |
| commit | 02082be4a73921702703ca93c8387b040181029a (patch) | |
| tree | 7408fd1ef186320229423bac94468fd9efb6a1b3 | |
| parent | 52a741754c76f147e8a009051c307091efaf45b2 (diff) | |
| download | rust-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.rs | 2 | ||||
| -rw-r--r-- | src/comp/middle/debuginfo.rs | 2 | ||||
| -rw-r--r-- | src/comp/middle/trans/alt.rs | 16 | ||||
| -rw-r--r-- | src/comp/middle/trans/base.rs | 80 | ||||
| -rw-r--r-- | src/comp/middle/trans/closure.rs | 5 | ||||
| -rw-r--r-- | src/comp/middle/trans/common.rs | 10 | ||||
| -rw-r--r-- | src/comp/middle/trans/impl.rs | 16 | ||||
| -rw-r--r-- | src/comp/middle/ty.rs | 14 |
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"; } } } |
