Fix various bugs in monomorphization
Enough to be able to compile librustc with --monomorphize. Issue #1736
This commit is contained in:
parent
52a741754c
commit
02082be4a7
8 changed files with 81 additions and 64 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"; }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue