Fix various bugs in monomorphization

Enough to be able to compile librustc with --monomorphize.

Issue #1736
This commit is contained in:
Marijn Haverbeke 2012-02-09 14:33:00 +01:00
parent 52a741754c
commit 02082be4a7
8 changed files with 81 additions and 64 deletions

View file

@ -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);
}

View file

@ -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,

View file

@ -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?

View file

@ -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_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_item(@{node: ast::item_res(decl, _, _, _, _), _}, _) {
trans_res_ctor(ccx, pt, decl, fn_id.node, [], psubsts, lldecl);
}
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);

View file

@ -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,

View file

@ -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:

View file

@ -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; }
}
}

View file

@ -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"; }
}
}