Never pass tydesc to functions
My assumption that native generics needed them was wrong, so tydescs can be eliminated from function signatures completely.
This commit is contained in:
parent
47f35c9d34
commit
9aa78e34e4
@ -865,7 +865,7 @@ fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id, substs: [ty::t])
|
||||
maybe_instantiate_inline(ccx, did)
|
||||
} else { did };
|
||||
assert did.crate == ast::local_crate;
|
||||
option::get(monomorphic_fn(ccx, did, substs, none))
|
||||
monomorphic_fn(ccx, did, substs, none)
|
||||
}
|
||||
|
||||
fn trans_res_drop(bcx: block, rs: ValueRef, did: ast::def_id,
|
||||
@ -1951,8 +1951,7 @@ enum callee_env {
|
||||
type lval_maybe_callee = {bcx: block,
|
||||
val: ValueRef,
|
||||
kind: lval_kind,
|
||||
env: callee_env,
|
||||
tds: option<[ValueRef]>};
|
||||
env: callee_env};
|
||||
|
||||
fn null_env_ptr(bcx: block) -> ValueRef {
|
||||
C_null(T_opaque_box_ptr(bcx.ccx()))
|
||||
@ -1971,20 +1970,21 @@ fn lval_temp(bcx: block, val: ValueRef) -> lval_result {
|
||||
|
||||
fn lval_no_env(bcx: block, val: ValueRef, kind: lval_kind)
|
||||
-> lval_maybe_callee {
|
||||
ret {bcx: bcx, val: val, kind: kind, env: is_closure, tds: none};
|
||||
ret {bcx: bcx, val: val, kind: kind, env: is_closure};
|
||||
}
|
||||
|
||||
fn trans_external_path(cx: block, did: ast::def_id,
|
||||
tpt: ty::ty_param_bounds_and_ty) -> ValueRef {
|
||||
let ccx = cx.fcx.ccx;
|
||||
fn trans_external_path(ccx: @crate_ctxt, did: ast::def_id, t: ty::t)
|
||||
-> ValueRef {
|
||||
let name = csearch::get_symbol(ccx.sess.cstore, did);
|
||||
ret get_extern_const(ccx.externs, ccx.llmod, name,
|
||||
type_of_ty_param_bounds_and_ty(ccx, tpt));
|
||||
let llty = alt ty::get(t).struct {
|
||||
ty::ty_fn(_) { type_of_fn_from_ty(ccx, t) }
|
||||
_ { type_of(ccx, t) }
|
||||
};
|
||||
ret get_extern_const(ccx.externs, ccx.llmod, name, llty);
|
||||
}
|
||||
|
||||
fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
|
||||
vtables: option<typeck::vtable_res>)
|
||||
-> option<ValueRef> {
|
||||
vtables: option<typeck::vtable_res>) -> ValueRef {
|
||||
let substs = vec::map(substs, {|t|
|
||||
alt ty::get(t).struct {
|
||||
ty::ty_box(mt) { ty::mk_opaque_box(ccx.tcx) }
|
||||
@ -1996,7 +1996,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
|
||||
none { no_vts }
|
||||
}};
|
||||
alt ccx.monomorphized.find(hash_id) {
|
||||
some(val) { ret some(val); }
|
||||
some(val) { ret val; }
|
||||
none {}
|
||||
}
|
||||
|
||||
@ -2017,8 +2017,10 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
|
||||
}
|
||||
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; }
|
||||
ast_map::node_native_item(_, _, _) {
|
||||
// Natives don't have to be monomorphized.
|
||||
ret get_item_val(ccx, fn_id.node);
|
||||
}
|
||||
ast_map::node_ctor(i) {
|
||||
alt check ccx.tcx.items.get(i.id) {
|
||||
ast_map::node_item(i, pt) { (pt, i.ident) }
|
||||
@ -2027,7 +2029,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
|
||||
_ { fail "unexpected node type"; }
|
||||
};
|
||||
let mono_ty = ty::substitute_type_params(ccx.tcx, substs, item_ty);
|
||||
let llfty = type_of_fn_from_ty(ccx, mono_ty, 0u);
|
||||
let llfty = type_of_fn_from_ty(ccx, mono_ty);
|
||||
|
||||
let pt = *pt + [path_name(ccx.names(name))];
|
||||
let s = mangle_exported_name(ccx, pt, mono_ty);
|
||||
@ -2071,7 +2073,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
|
||||
}
|
||||
}
|
||||
}
|
||||
some(lldecl)
|
||||
lldecl
|
||||
}
|
||||
|
||||
fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id)
|
||||
@ -2142,39 +2144,18 @@ fn lval_static_fn(bcx: block, fn_id: ast::def_id, id: ast::node_id,
|
||||
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
|
||||
// monomorphizing becomes the only approach, this'll be much simpler.
|
||||
if fn_id.crate == ast::local_crate {
|
||||
let mono = alt substs {
|
||||
some((stys, vtables)) {
|
||||
if stys.len() > 0u {
|
||||
monomorphic_fn(ccx, fn_id, stys, some(vtables))
|
||||
} else { none }
|
||||
}
|
||||
none {
|
||||
alt ccx.maps.vtable_map.find(id) {
|
||||
some(vtables) {
|
||||
let rvtables = impl::resolve_vtables_in_fn_ctxt(
|
||||
bcx.fcx, vtables);
|
||||
monomorphic_fn(ccx, fn_id, tys, some(rvtables))
|
||||
}
|
||||
none {
|
||||
if tys.len() == 0u { none }
|
||||
else { monomorphic_fn(ccx, fn_id, tys, none) }
|
||||
}
|
||||
}
|
||||
}
|
||||
let (tys, vtables) = alt substs {
|
||||
some((tys, vts)) { (tys, some(vts)) }
|
||||
none { (tys, option::map(ccx.maps.vtable_map.find(id), {|vts|
|
||||
impl::resolve_vtables_in_fn_ctxt(bcx.fcx, vts)})) }
|
||||
};
|
||||
alt mono {
|
||||
some(llfn) {
|
||||
let cast = PointerCast(bcx, llfn, T_ptr(type_of_fn_from_ty(
|
||||
ccx, node_id_type(bcx, id), 0u)));
|
||||
if tys.len() > 0u {
|
||||
let val = monomorphic_fn(ccx, fn_id, tys, vtables);
|
||||
let cast = PointerCast(bcx, val, T_ptr(type_of_fn_from_ty(
|
||||
ccx, node_id_type(bcx, id))));
|
||||
ret {bcx: bcx, val: cast,
|
||||
kind: owned, env: null_env,
|
||||
tds: none};
|
||||
}
|
||||
none {}
|
||||
kind: owned, env: null_env};
|
||||
}
|
||||
}
|
||||
|
||||
@ -2183,8 +2164,14 @@ fn lval_static_fn(bcx: block, fn_id: ast::def_id, id: ast::node_id,
|
||||
get_item_val(ccx, fn_id.node)
|
||||
} else {
|
||||
// External reference.
|
||||
trans_external_path(bcx, fn_id, tpt)
|
||||
trans_external_path(ccx, fn_id, tpt.ty)
|
||||
};
|
||||
if tys.len() > 0u {
|
||||
// This is supposed to be an external native function.
|
||||
// Unfortunately, I found no easy/cheap way to assert that.
|
||||
val = PointerCast(bcx, val, T_ptr(type_of_fn_from_ty(
|
||||
ccx, node_id_type(bcx, id))));
|
||||
}
|
||||
|
||||
// FIXME: Need to support external crust functions
|
||||
if fn_id.crate == ast::local_crate {
|
||||
@ -2198,22 +2185,7 @@ fn lval_static_fn(bcx: block, fn_id: ast::def_id, id: ast::node_id,
|
||||
}
|
||||
}
|
||||
|
||||
let tds = none, bcx = bcx;
|
||||
// FIXME[mono] ensure this is a native function
|
||||
if tys.len() > 0u {
|
||||
val = PointerCast(bcx, val, T_ptr(type_of_fn_from_ty(
|
||||
ccx, node_id_type(bcx, id), tys.len())));
|
||||
let tydescs = [];
|
||||
for t in tys {
|
||||
let ti = none;
|
||||
let td = get_tydesc(bcx, t, ti);
|
||||
lazily_emit_all_tydesc_glue(ccx, ti);
|
||||
bcx = td.bcx;
|
||||
tydescs += [td.val];
|
||||
}
|
||||
tds = some(tydescs);
|
||||
}
|
||||
ret {bcx: bcx, val: val, kind: owned, env: null_env, tds: tds};
|
||||
ret {bcx: bcx, val: val, kind: owned, env: null_env};
|
||||
}
|
||||
|
||||
fn lookup_discriminant(ccx: @crate_ctxt, vid: ast::def_id) -> ValueRef {
|
||||
@ -2313,7 +2285,7 @@ fn trans_var(cx: block, def: ast::def, id: ast::node_id, path: @ast::path)
|
||||
ret lval_no_env(cx, get_item_val(ccx, did.node), owned);
|
||||
} else {
|
||||
let tp = node_id_type(cx, id);
|
||||
let val = trans_external_path(cx, did, {bounds: @[], ty: tp});
|
||||
let val = trans_external_path(ccx, did, tp);
|
||||
ret lval_no_env(cx, load_if_immediate(cx, val, tp), owned_imm);
|
||||
}
|
||||
}
|
||||
@ -2466,8 +2438,7 @@ fn trans_lval(cx: block, e: @ast::expr) -> lval_result {
|
||||
}
|
||||
|
||||
fn lval_maybe_callee_to_lval(c: lval_maybe_callee, ty: ty::t) -> lval_result {
|
||||
let must_bind = option::is_some(c.tds) ||
|
||||
alt c.env { self_env(_, _) { true } _ { false } };
|
||||
let must_bind = alt c.env { self_env(_, _) { true } _ { false } };
|
||||
if must_bind {
|
||||
let n_args = ty::ty_fn_args(ty).len();
|
||||
let args = vec::from_elem(n_args, none);
|
||||
@ -2662,12 +2633,10 @@ fn trans_arg_expr(cx: block, arg: ty::arg, lldestty: TypeRef, e: @ast::expr,
|
||||
// - create_llargs_for_fn_args.
|
||||
// - new_fn_ctxt
|
||||
// - trans_args
|
||||
fn trans_args(cx: block, llenv: ValueRef,
|
||||
tds: option<[ValueRef]>, es: [@ast::expr], fn_ty: ty::t,
|
||||
dest: dest)
|
||||
-> {bcx: block,
|
||||
args: [ValueRef],
|
||||
retslot: ValueRef} {
|
||||
fn trans_args(cx: block, llenv: ValueRef, es: [@ast::expr], fn_ty: ty::t,
|
||||
dest: dest) -> {bcx: block,
|
||||
args: [ValueRef],
|
||||
retslot: ValueRef} {
|
||||
|
||||
let temp_cleanups = [];
|
||||
let args = ty::ty_fn_args(fn_ty);
|
||||
@ -2701,12 +2670,6 @@ fn trans_args(cx: block, llenv: ValueRef,
|
||||
// Arg 1: Env (closure-bindings / self value)
|
||||
llargs += [llenv];
|
||||
|
||||
// Args >2: ty_params ...
|
||||
alt tds {
|
||||
some(tds) { llargs += tds; }
|
||||
none {}
|
||||
}
|
||||
|
||||
// ... then explicit args.
|
||||
|
||||
// First we figure out the caller's view of the types of the arguments.
|
||||
@ -2770,8 +2733,7 @@ fn trans_call_inner(in_cx: block, fn_expr_ty: ty::t,
|
||||
};
|
||||
|
||||
let ret_ty = node_id_type(bcx, id);
|
||||
let args_res =
|
||||
trans_args(bcx, llenv, f_res.tds, args, fn_expr_ty, dest);
|
||||
let args_res = trans_args(bcx, llenv, args, fn_expr_ty, dest);
|
||||
bcx = args_res.bcx;
|
||||
let llargs = args_res.args;
|
||||
let llretslot = args_res.retslot;
|
||||
@ -3883,7 +3845,7 @@ fn create_llargs_for_fn_args(cx: fn_ctxt,
|
||||
args: [ast::arg],
|
||||
tps_bounds: [ty::param_bounds]) {
|
||||
// Skip the implicit arguments 0, and 1.
|
||||
let arg_n = first_tp_arg;
|
||||
let arg_n = first_real_arg;
|
||||
alt ty_self {
|
||||
impl_self(tt) {
|
||||
cx.llself = some({v: cx.llenv, t: tt});
|
||||
@ -4417,11 +4379,9 @@ fn get_pair_fn_ty(llpairty: TypeRef) -> TypeRef {
|
||||
}
|
||||
|
||||
fn register_fn(ccx: @crate_ctxt, sp: span, path: path, flav: str,
|
||||
ty_params: [ast::ty_param], node_id: ast::node_id)
|
||||
-> ValueRef {
|
||||
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, node_id, t)
|
||||
}
|
||||
|
||||
fn param_bounds(ccx: @crate_ctxt, tps: [ast::ty_param])
|
||||
@ -4430,9 +4390,8 @@ fn param_bounds(ccx: @crate_ctxt, tps: [ast::ty_param])
|
||||
}
|
||||
|
||||
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) -> ValueRef {
|
||||
let llfty = type_of_fn_from_ty(ccx, node_type, bnds.len());
|
||||
node_id: ast::node_id, node_type: ty::t) -> ValueRef {
|
||||
let llfty = type_of_fn_from_ty(ccx, node_type);
|
||||
register_fn_fuller(ccx, sp, path, flav, node_id, node_type,
|
||||
lib::llvm::CCallConv, llfty)
|
||||
}
|
||||
@ -4479,7 +4438,7 @@ fn create_main_wrapper(ccx: @crate_ctxt, sp: span, main_llfn: ValueRef,
|
||||
{mode: ast::expl(ast::by_val),
|
||||
ty: ty::mk_vec(ccx.tcx, {ty: unit_ty, mutbl: ast::m_imm})};
|
||||
let nt = ty::mk_nil(ccx.tcx);
|
||||
let llfty = type_of_fn(ccx, [vecarg_ty], nt, 0u);
|
||||
let llfty = type_of_fn(ccx, [vecarg_ty], nt);
|
||||
let llfdecl = decl_fn(ccx.llmod, "_rust_main",
|
||||
lib::llvm::CCallConv, llfty);
|
||||
|
||||
@ -4575,16 +4534,16 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
|
||||
ccx.item_symbols.insert(i.id, s);
|
||||
g
|
||||
}
|
||||
ast::item_fn(decl, tps, _) {
|
||||
ast::item_fn(decl, _, _) {
|
||||
let llfn = if decl.purity != ast::crust_fn {
|
||||
register_fn(ccx, i.span, my_path, "fn", tps, i.id)
|
||||
register_fn(ccx, i.span, my_path, "fn", i.id)
|
||||
} else {
|
||||
native::register_crust_fn(ccx, i.span, my_path, i.id)
|
||||
};
|
||||
set_inline_hint_if_appr(i.attrs, llfn);
|
||||
llfn
|
||||
}
|
||||
ast::item_res(_, tps, _, dtor_id, _) {
|
||||
ast::item_res(_, _, _, dtor_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
|
||||
@ -4592,17 +4551,15 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
|
||||
// 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)
|
||||
"res_dtor", i.id, t)
|
||||
}
|
||||
}
|
||||
}
|
||||
ast_map::node_method(m, impl_id, pth) {
|
||||
let mty = ty::node_id_to_type(ccx.tcx, id);
|
||||
let impl_tps = *ty::lookup_item_type(ccx.tcx, impl_id).bounds;
|
||||
let pth = *pth + [path_name(int::str(impl_id.node)),
|
||||
path_name(m.ident)];
|
||||
let llfn = register_fn_full(ccx, m.span, pth, "impl_method",
|
||||
impl_tps + param_bounds(ccx, m.tps),
|
||||
id, mty);
|
||||
set_inline_hint_if_appr(m.attrs, llfn);
|
||||
llfn
|
||||
@ -4612,15 +4569,15 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
|
||||
}
|
||||
ast_map::node_ctor(i) {
|
||||
alt check i.node {
|
||||
ast::item_res(_, tps, _, _, _) {
|
||||
ast::item_res(_, _, _, _, _) {
|
||||
let my_path = item_path(ccx, i);
|
||||
let llctor = register_fn(ccx, i.span, my_path, "res_ctor",
|
||||
tps, id);
|
||||
id);
|
||||
set_inline_hint(llctor);
|
||||
llctor
|
||||
}
|
||||
ast::item_class(tps, _, ctor) {
|
||||
register_fn(ccx, i.span, item_path(ccx, i), "ctor", tps, id)
|
||||
ast::item_class(_, _, ctor) {
|
||||
register_fn(ccx, i.span, item_path(ccx, i), "ctor", id)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4628,8 +4585,8 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
|
||||
assert v.node.args.len() != 0u;
|
||||
let pth = *pth + [path_name(enm.ident), path_name(v.node.name)];
|
||||
let llfn = alt check enm.node {
|
||||
ast::item_enum(_, tps) {
|
||||
register_fn(ccx, v.span, pth, "enum", tps, id)
|
||||
ast::item_enum(_, _) {
|
||||
register_fn(ccx, v.span, pth, "enum", id)
|
||||
}
|
||||
};
|
||||
set_inline_hint(llfn);
|
||||
|
@ -130,17 +130,10 @@ fn mk_tuplified_uniq_cbox_ty(tcx: ty::ctxt, cdata_ty: ty::t) -> ty::t {
|
||||
|
||||
// Given a closure ty, emits a corresponding tuple ty
|
||||
fn mk_closure_tys(tcx: ty::ctxt,
|
||||
ck: ty::closure_kind,
|
||||
ty_params: option<[ValueRef]>,
|
||||
bound_values: [environment_value])
|
||||
-> (ty::t, [ty::t]) {
|
||||
let bound_tys = [];
|
||||
|
||||
// Compute the closed over tydescs
|
||||
let n_param_ptrs = alt ty_params {
|
||||
some(tds) { tds.len() } none { 0u }
|
||||
};
|
||||
|
||||
// Compute the closed over data
|
||||
for bv in bound_values {
|
||||
bound_tys += [alt bv {
|
||||
@ -151,9 +144,8 @@ fn mk_closure_tys(tcx: ty::ctxt,
|
||||
}];
|
||||
}
|
||||
let bound_data_ty = ty::mk_tup(tcx, bound_tys);
|
||||
|
||||
let typtrs = vec::from_elem(n_param_ptrs, mk_tydesc_ty(tcx, ck));
|
||||
let cdata_ty = ty::mk_tup(tcx, [ty::mk_tup(tcx, typtrs),
|
||||
// FIXME[mono] remove tuple of tydescs from closure types
|
||||
let cdata_ty = ty::mk_tup(tcx, [ty::mk_tup(tcx, []),
|
||||
bound_data_ty]);
|
||||
#debug["cdata_ty=%s", ty_to_str(tcx, cdata_ty)];
|
||||
ret (cdata_ty, bound_tys);
|
||||
@ -237,11 +229,9 @@ fn cast_if_we_can(bcx: block, llbox: ValueRef, t: ty::t) -> ValueRef {
|
||||
// construct a closure out of them. If copying is true, it is a
|
||||
// heap allocated closure that copies the upvars into environment.
|
||||
// Otherwise, it is stack allocated and copies pointers to the upvars.
|
||||
fn store_environment(
|
||||
bcx: block, lltyparams: option<[ValueRef]>,
|
||||
bound_values: [environment_value],
|
||||
ck: ty::closure_kind)
|
||||
-> closure_result {
|
||||
fn store_environment(bcx: block,
|
||||
bound_values: [environment_value],
|
||||
ck: ty::closure_kind) -> closure_result {
|
||||
|
||||
fn maybe_clone_tydesc(bcx: block,
|
||||
ck: ty::closure_kind,
|
||||
@ -260,7 +250,7 @@ fn store_environment(
|
||||
|
||||
// compute the shape of the closure
|
||||
let (cdata_ty, bound_tys) =
|
||||
mk_closure_tys(tcx, ck, lltyparams, bound_values);
|
||||
mk_closure_tys(tcx, bound_values);
|
||||
|
||||
// allocate closure in the heap
|
||||
let (bcx, llbox, temp_cleanups) =
|
||||
@ -274,18 +264,6 @@ fn store_environment(
|
||||
let llbox = cast_if_we_can(bcx, llbox, cboxptr_ty);
|
||||
#debug["tuplify_box_ty = %s", ty_to_str(tcx, cbox_ty)];
|
||||
|
||||
// If necessary, copy tydescs describing type parameters into the
|
||||
// appropriate slot in the closure.
|
||||
let {bcx:bcx, val:ty_params_slot} =
|
||||
GEP_tup_like(bcx, cbox_ty, llbox,
|
||||
[0, abi::box_field_body, abi::closure_body_ty_params]);
|
||||
option::may(lltyparams) {|tds|
|
||||
vec::iteri(tds) {|i, td|
|
||||
let cloned_td = maybe_clone_tydesc(bcx, ck, td);
|
||||
Store(bcx, cloned_td, GEPi(bcx, ty_params_slot, [0, i as int]));
|
||||
}
|
||||
}
|
||||
|
||||
// Copy expr values into boxed bindings.
|
||||
vec::iteri(bound_values) { |i, bv|
|
||||
#debug["Copy %s into closure", ev_to_str(ccx, bv)];
|
||||
@ -377,7 +355,7 @@ fn build_closure(bcx0: block,
|
||||
}
|
||||
}
|
||||
}
|
||||
ret store_environment(bcx, none, env_vals, ck);
|
||||
ret store_environment(bcx, env_vals, ck);
|
||||
}
|
||||
|
||||
// Given an enclosing block context, a new function context, a closure type,
|
||||
@ -426,11 +404,11 @@ fn trans_expr_fn(bcx: block,
|
||||
if dest == ignore { ret bcx; }
|
||||
let ccx = bcx.ccx(), bcx = bcx;
|
||||
let fty = node_id_type(bcx, id);
|
||||
let llfnty = type_of_fn_from_ty(ccx, fty, 0u);
|
||||
let llfnty = type_of_fn_from_ty(ccx, fty);
|
||||
let sub_path = bcx.fcx.path + [path_name("anon")];
|
||||
let s = mangle_internal_name_by_path(ccx, sub_path);
|
||||
let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty);
|
||||
register_fn(ccx, sp, sub_path, "anon fn", [], id);
|
||||
register_fn(ccx, sp, sub_path, "anon fn", id);
|
||||
|
||||
let trans_closure_env = fn@(ck: ty::closure_kind) -> ValueRef {
|
||||
let cap_vars = capture::compute_capture_vars(
|
||||
@ -479,7 +457,7 @@ fn trans_bind_1(cx: block, outgoing_fty: ty::t,
|
||||
ret bcx;
|
||||
}
|
||||
|
||||
if bound.len() == 0u && option::is_none(f_res.tds) &&
|
||||
if bound.len() == 0u &&
|
||||
(f_res.env == null_env || f_res.env == is_closure) {
|
||||
// Trivial 'binding': just return the closure
|
||||
let lv = lval_maybe_callee_to_lval(f_res, pair_ty);
|
||||
@ -505,15 +483,13 @@ fn trans_bind_1(cx: block, outgoing_fty: ty::t,
|
||||
|
||||
// Actually construct the closure
|
||||
let {llbox, cdata_ty, bcx} = store_environment(
|
||||
bcx, f_res.tds,
|
||||
env_vals + vec::map(bound, {|x| env_expr(x, expr_ty(bcx, x))}),
|
||||
bcx, env_vals + vec::map(bound, {|x| env_expr(x, expr_ty(bcx, x))}),
|
||||
ty::ck_box);
|
||||
|
||||
// Make thunk
|
||||
let llthunk = trans_bind_thunk(
|
||||
cx.fcx.ccx, cx.fcx.path, pair_ty, outgoing_fty, args,
|
||||
cdata_ty, target_info,
|
||||
alt f_res.tds { some(x) { x.len() } _ { 0u } });
|
||||
cdata_ty, target_info);
|
||||
|
||||
// Fill the function pair
|
||||
fill_fn_pair(bcx, get_dest_addr(dest), llthunk.val, llbox);
|
||||
@ -665,8 +641,7 @@ fn trans_bind_thunk(ccx: @crate_ctxt,
|
||||
outgoing_fty: ty::t,
|
||||
args: [option<@ast::expr>],
|
||||
cdata_ty: ty::t,
|
||||
target_info: target_info,
|
||||
n_tps: uint)
|
||||
target_info: target_info)
|
||||
-> {val: ValueRef, ty: TypeRef} {
|
||||
let tcx = ccx.tcx;
|
||||
#debug["trans_bind_thunk[incoming_fty=%s,outgoing_fty=%s,\
|
||||
@ -769,18 +744,7 @@ fn trans_bind_thunk(ccx: @crate_ctxt,
|
||||
// Set up the three implicit arguments to the thunk.
|
||||
let llargs: [ValueRef] = [llretptr, lltargetenv];
|
||||
|
||||
// Copy in the type parameters.
|
||||
let {bcx: l_bcx, val: param_record} =
|
||||
GEP_tup_like(l_bcx, cdata_ty, llcdata,
|
||||
[0, abi::closure_body_ty_params]);
|
||||
let i = 0u;
|
||||
while i < n_tps {
|
||||
let dsc = Load(l_bcx, GEPi(l_bcx, param_record, [0, i as int]));
|
||||
llargs += [dsc];
|
||||
fcx.lltyparams += [{desc: dsc, vtables: none}];
|
||||
}
|
||||
|
||||
let a: uint = first_tp_arg; // retptr, env come first
|
||||
let a: uint = first_real_arg; // retptr, env come first
|
||||
let b: int = starting_idx;
|
||||
let outgoing_arg_index: uint = 0u;
|
||||
let llout_arg_tys: [TypeRef] =
|
||||
@ -838,7 +802,7 @@ fn trans_bind_thunk(ccx: @crate_ctxt,
|
||||
// in the closure does not know how many type descriptors the function
|
||||
// needs to take.
|
||||
let lltargetty =
|
||||
type_of_fn_from_ty(ccx, outgoing_fty, 0u);
|
||||
type_of_fn_from_ty(ccx, outgoing_fty);
|
||||
lltargetfn = PointerCast(bcx, lltargetfn, T_ptr(lltargetty));
|
||||
Call(bcx, lltargetfn, llargs);
|
||||
build_return(bcx);
|
||||
|
@ -352,7 +352,7 @@ type block = @{
|
||||
};
|
||||
|
||||
// First two args are retptr, env
|
||||
const first_tp_arg: uint = 2u;
|
||||
const first_real_arg: uint = 2u;
|
||||
|
||||
// FIXME move blocks to a class once those are finished, and simply use
|
||||
// option<block> for this.
|
||||
|
@ -74,23 +74,16 @@ fn trans_static_callee(bcx: block, callee_id: ast::node_id,
|
||||
with lval_static_fn(bcx, did, callee_id, substs)}
|
||||
}
|
||||
|
||||
fn wrapper_fn_ty(ccx: @crate_ctxt, vtable_ty: TypeRef, fty: ty::t,
|
||||
tps: @[ty::param_bounds]) -> {ty: ty::t, llty: TypeRef} {
|
||||
let bare_fn_ty = type_of_fn_from_ty(ccx, fty, (*tps).len());
|
||||
let {inputs, output} = llfn_arg_tys(bare_fn_ty);
|
||||
{ty: fty, llty: T_fn([vtable_ty] + inputs, output)}
|
||||
}
|
||||
|
||||
fn trans_vtable_callee(bcx: block, env: callee_env, vtable: ValueRef,
|
||||
callee_id: ast::node_id, n_method: uint)
|
||||
-> lval_maybe_callee {
|
||||
let bcx = bcx, ccx = bcx.ccx();
|
||||
let fty = node_id_type(bcx, callee_id);
|
||||
let llfty = type_of::type_of_fn_from_ty(ccx, fty, 0u);
|
||||
let llfty = type_of::type_of_fn_from_ty(ccx, fty);
|
||||
let vtable = PointerCast(bcx, vtable,
|
||||
T_ptr(T_array(T_ptr(llfty), n_method + 1u)));
|
||||
let mptr = Load(bcx, GEPi(bcx, vtable, [0, n_method as int]));
|
||||
{bcx: bcx, val: mptr, kind: owned, env: env, tds: none}
|
||||
{bcx: bcx, val: mptr, kind: owned, env: env}
|
||||
}
|
||||
|
||||
fn method_with_name(ccx: @crate_ctxt, impl_id: ast::def_id,
|
||||
@ -106,7 +99,7 @@ fn method_with_name(ccx: @crate_ctxt, impl_id: ast::def_id,
|
||||
}
|
||||
}
|
||||
|
||||
fn method_ty_param_count(ccx: crate_ctxt, m_id: ast::def_id) -> uint {
|
||||
fn method_ty_param_count(ccx: @crate_ctxt, m_id: ast::def_id) -> uint {
|
||||
if m_id.crate == ast::local_crate {
|
||||
alt check ccx.tcx.items.get(m_id.node) {
|
||||
ast_map::node_method(m, _, _) { vec::len(m.tps) }
|
||||
@ -128,7 +121,7 @@ fn trans_monomorphized_callee(bcx: block, callee_id: ast::node_id,
|
||||
let n_m_tps = method_ty_param_count(ccx, mth_id);
|
||||
let node_substs = node_id_type_params(bcx, callee_id);
|
||||
let ty_substs = impl_substs +
|
||||
vec::tail_n(node_substs, node_substs.len() - n_m_tps);
|
||||
vec::tailn(node_substs, node_substs.len() - n_m_tps);
|
||||
ret trans_static_callee(bcx, callee_id, base, mth_id,
|
||||
some((ty_substs, sub_origins)));
|
||||
}
|
||||
@ -255,161 +248,14 @@ fn make_impl_vtable(ccx: @crate_ctxt, impl_id: ast::def_id, substs: [ty::t],
|
||||
let fty = ty::substitute_type_params(tcx, substs,
|
||||
ty::mk_fn(tcx, im.fty));
|
||||
if (*im.tps).len() > 0u || ty::type_has_vars(fty) {
|
||||
C_null(type_of_fn_from_ty(ccx, fty, 0u))
|
||||
C_null(type_of_fn_from_ty(ccx, fty))
|
||||
} else {
|
||||
let m_id = method_with_name(ccx, impl_id, im.ident);
|
||||
option::get(monomorphic_fn(ccx, m_id, substs, some(vtables)))
|
||||
monomorphic_fn(ccx, m_id, substs, some(vtables))
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
/*
|
||||
fn make_iface_vtable(ccx: @crate_ctxt, pt: path, it: @ast::item) {
|
||||
let new_pt = pt + [path_name(it.ident), path_name(int::str(it.id))];
|
||||
let i_did = local_def(it.id), i = 0u;
|
||||
let ptrs = vec::map(*ty::iface_methods(ccx.tcx, i_did), {|m|
|
||||
let w = trans_iface_wrapper(ccx, new_pt + [path_name(m.ident)], m, i);
|
||||
i += 1u;
|
||||
w
|
||||
});
|
||||
let s = link::mangle_internal_name_by_path(
|
||||
ccx, new_pt + [path_name("!vtable")]);
|
||||
trans_vtable(ccx, it.id, s, ptrs);
|
||||
}
|
||||
|
||||
fn dict_is_static(tcx: ty::ctxt, origin: typeck::dict_origin) -> bool {
|
||||
alt origin {
|
||||
typeck::dict_static(_, ts, origs) {
|
||||
vec::all(ts, {|t| !ty::type_has_params(t)}) &&
|
||||
vec::all(*origs, {|o| dict_is_static(tcx, o)})
|
||||
}
|
||||
typeck::dict_iface(_) { true }
|
||||
_ { false }
|
||||
}
|
||||
}
|
||||
|
||||
fn get_dict(bcx: block, origin: typeck::dict_origin) -> result {
|
||||
let ccx = bcx.ccx();
|
||||
alt origin {
|
||||
typeck::dict_static(impl_did, tys, sub_origins) {
|
||||
if dict_is_static(ccx.tcx, origin) {
|
||||
ret rslt(bcx, get_static_dict(bcx, origin));
|
||||
}
|
||||
let {bcx, ptrs} = get_dict_ptrs(bcx, origin);
|
||||
let pty = T_ptr(T_i8()), dict_ty = T_array(pty, ptrs.len());
|
||||
let dict = alloca(bcx, dict_ty), i = 0;
|
||||
for ptr in ptrs {
|
||||
Store(bcx, PointerCast(bcx, ptr, pty), GEPi(bcx, dict, [0, i]));
|
||||
i += 1;
|
||||
}
|
||||
dict = Call(bcx, ccx.upcalls.intern_dict,
|
||||
[C_uint(ccx, ptrs.len()),
|
||||
PointerCast(bcx, dict, T_ptr(T_dict()))]);
|
||||
rslt(bcx, dict)
|
||||
}
|
||||
typeck::dict_param(n_param, n_bound) {
|
||||
rslt(bcx, option::get(bcx.fcx.lltyparams[n_param].dicts)[n_bound])
|
||||
}
|
||||
typeck::dict_iface(did) {
|
||||
ret rslt(bcx, get_static_dict(bcx, origin));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn dict_id(tcx: ty::ctxt, origin: typeck::dict_origin) -> dict_id {
|
||||
alt origin {
|
||||
typeck::dict_static(did, ts, origs) {
|
||||
let d_params = [], orig = 0u;
|
||||
if ts.len() == 0u { ret @{def: did, params: d_params}; }
|
||||
let impl_params = ty::lookup_item_type(tcx, did).bounds;
|
||||
vec::iter2(ts, *impl_params) {|t, bounds|
|
||||
d_params += [dict_param_ty(t)];
|
||||
for bound in *bounds {
|
||||
alt bound {
|
||||
ty::bound_iface(_) {
|
||||
d_params += [dict_param_dict(dict_id(tcx, origs[orig]))];
|
||||
orig += 1u;
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@{def: did, params: d_params}
|
||||
}
|
||||
typeck::dict_iface(did) {
|
||||
@{def: did, params: []}
|
||||
}
|
||||
_ {
|
||||
tcx.sess.bug("unexpected dict_param in dict_id");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_static_dict(bcx: block, origin: typeck::dict_origin)
|
||||
-> ValueRef {
|
||||
let ccx = bcx.ccx();
|
||||
let id = dict_id(ccx.tcx, origin);
|
||||
alt ccx.dicts.find(id) {
|
||||
some(d) { ret d; }
|
||||
none {}
|
||||
}
|
||||
let ptrs = C_struct(get_dict_ptrs(bcx, origin).ptrs);
|
||||
let name = ccx.names("dict");
|
||||
let gvar = str::as_c_str(name, {|buf|
|
||||
llvm::LLVMAddGlobal(ccx.llmod, val_ty(ptrs), buf)
|
||||
});
|
||||
llvm::LLVMSetGlobalConstant(gvar, lib::llvm::True);
|
||||
llvm::LLVMSetInitializer(gvar, ptrs);
|
||||
lib::llvm::SetLinkage(gvar, lib::llvm::InternalLinkage);
|
||||
let cast = llvm::LLVMConstPointerCast(gvar, T_ptr(T_dict()));
|
||||
ccx.dicts.insert(id, cast);
|
||||
cast
|
||||
}
|
||||
|
||||
fn get_dict_ptrs(bcx: block, origin: typeck::dict_origin)
|
||||
-> {bcx: block, ptrs: [ValueRef]} {
|
||||
let ccx = bcx.ccx();
|
||||
fn get_vtable(ccx: @crate_ctxt, did: ast::def_id) -> ValueRef {
|
||||
if did.crate == ast::local_crate {
|
||||
get_item_val(ccx, did.node)
|
||||
} else {
|
||||
let name = csearch::get_symbol(ccx.sess.cstore, did);
|
||||
get_extern_const(ccx.externs, ccx.llmod, name, T_ptr(T_i8()))
|
||||
}
|
||||
}
|
||||
alt origin {
|
||||
typeck::dict_static(impl_did, tys, sub_origins) {
|
||||
let impl_params = ty::lookup_item_type(ccx.tcx, impl_did).bounds;
|
||||
let ptrs = [get_vtable(ccx, impl_did)];
|
||||
let origin = 0u, bcx = bcx;
|
||||
vec::iter2(*impl_params, tys) {|param, ty|
|
||||
let rslt = get_tydesc_simple(bcx, ty, true);
|
||||
ptrs += [rslt.val];
|
||||
bcx = rslt.bcx;
|
||||
for bound in *param {
|
||||
alt bound {
|
||||
ty::bound_iface(_) {
|
||||
let res = get_dict(bcx, sub_origins[origin]);
|
||||
ptrs += [res.val];
|
||||
bcx = res.bcx;
|
||||
origin += 1u;
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
}
|
||||
{bcx: bcx, ptrs: ptrs}
|
||||
}
|
||||
typeck::dict_iface(did) {
|
||||
{bcx: bcx, ptrs: [get_vtable(ccx, did)]}
|
||||
}
|
||||
_ {
|
||||
bcx.tcx().sess.bug("unexpected dict_param in get_dict_ptrs");
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
fn trans_cast(bcx: block, val: @ast::expr, id: ast::node_id, dest: dest)
|
||||
-> block {
|
||||
if dest == ignore { ret trans_expr(bcx, val, ignore); }
|
||||
|
@ -206,15 +206,13 @@ fn trans_native_mod(ccx: @crate_ctxt,
|
||||
|
||||
fn build_wrap_fn(ccx: @crate_ctxt,
|
||||
tys: @c_stack_tys,
|
||||
num_tps: uint,
|
||||
llshimfn: ValueRef,
|
||||
llwrapfn: ValueRef) {
|
||||
|
||||
fn build_args(bcx: block, tys: @c_stack_tys,
|
||||
llwrapfn: ValueRef, llargbundle: ValueRef,
|
||||
num_tps: uint) {
|
||||
llwrapfn: ValueRef, llargbundle: ValueRef) {
|
||||
let i = 0u, n = vec::len(tys.arg_tys);
|
||||
let implicit_args = first_tp_arg + num_tps; // ret + env
|
||||
let implicit_args = first_real_arg; // ret + env
|
||||
while i < n {
|
||||
let llargval = llvm::LLVMGetParam(
|
||||
llwrapfn,
|
||||
@ -233,8 +231,7 @@ fn trans_native_mod(ccx: @crate_ctxt,
|
||||
|
||||
build_wrap_fn_(ccx, tys, llshimfn, llwrapfn,
|
||||
ccx.upcalls.call_shim_on_c_stack,
|
||||
bind build_args(_, _ ,_ , _, num_tps),
|
||||
build_ret);
|
||||
build_args, build_ret);
|
||||
}
|
||||
|
||||
let cc = lib::llvm::CCallConv;
|
||||
@ -249,12 +246,12 @@ fn trans_native_mod(ccx: @crate_ctxt,
|
||||
|
||||
for native_item in native_mod.items {
|
||||
alt native_item.node {
|
||||
ast::native_item_fn(fn_decl, tps) {
|
||||
ast::native_item_fn(fn_decl, _) {
|
||||
let id = native_item.id;
|
||||
let tys = c_stack_tys(ccx, id);
|
||||
let llwrapfn = get_item_val(ccx, id);
|
||||
let llshimfn = build_shim_fn(ccx, native_item, tys, cc);
|
||||
build_wrap_fn(ccx, tys, vec::len(tps), llshimfn, llwrapfn);
|
||||
build_wrap_fn(ccx, tys, llshimfn, llwrapfn);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -269,7 +266,7 @@ fn trans_crust_fn(ccx: @crate_ctxt, path: ast_map::path, decl: ast::fn_decl,
|
||||
let t = ty::node_id_to_type(ccx.tcx, id);
|
||||
let ps = link::mangle_internal_name_by_path(
|
||||
ccx, path + [ast_map::path_name("__rust_abi")]);
|
||||
let llty = type_of_fn_from_ty(ccx, t, 0u);
|
||||
let llty = type_of_fn_from_ty(ccx, t);
|
||||
let llfndecl = decl_internal_cdecl_fn(ccx.llmod, ps, llty);
|
||||
trans_fn(ccx, path, decl, body, llfndecl, no_self, none, id,
|
||||
none);
|
||||
@ -377,13 +374,13 @@ fn abi_of_native_fn(ccx: @crate_ctxt, i: @ast::native_item)
|
||||
fn decl_native_fn(ccx: @crate_ctxt, i: @ast::native_item,
|
||||
pth: ast_map::path) -> ValueRef {
|
||||
alt i.node {
|
||||
ast::native_item_fn(_, tps) {
|
||||
ast::native_item_fn(_, _) {
|
||||
let node_type = ty::node_id_to_type(ccx.tcx, i.id);
|
||||
alt abi_of_native_fn(ccx, i) {
|
||||
ast::native_abi_rust_intrinsic {
|
||||
// For intrinsics: link the function directly to the intrinsic
|
||||
// function itself.
|
||||
let fn_type = type_of_fn_from_ty(ccx, node_type, tps.len());
|
||||
let fn_type = type_of_fn_from_ty(ccx, node_type);
|
||||
let ri_name = "rust_intrinsic_" + native::link_name(i);
|
||||
ccx.item_symbols.insert(i.id, ri_name);
|
||||
get_extern_fn(ccx.externs, ccx.llmod, ri_name,
|
||||
@ -394,7 +391,7 @@ fn decl_native_fn(ccx: @crate_ctxt, i: @ast::native_item,
|
||||
// For true external functions: create a rust wrapper
|
||||
// and link to that. The rust wrapper will handle
|
||||
// switching to the C stack.
|
||||
register_fn(ccx, i.span, pth, "native fn", tps, i.id)
|
||||
register_fn(ccx, i.span, pth, "native fn", i.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,7 @@ fn type_of_explicit_args(cx: @crate_ctxt, inputs: [ty::arg]) -> [TypeRef] {
|
||||
}
|
||||
}
|
||||
|
||||
fn type_of_fn(cx: @crate_ctxt, inputs: [ty::arg],
|
||||
output: ty::t, n_ty_params: uint) -> TypeRef {
|
||||
fn type_of_fn(cx: @crate_ctxt, inputs: [ty::arg], output: ty::t) -> TypeRef {
|
||||
let atys: [TypeRef] = [];
|
||||
|
||||
// Arg 0: Output pointer.
|
||||
@ -28,21 +27,14 @@ fn type_of_fn(cx: @crate_ctxt, inputs: [ty::arg],
|
||||
// Arg 1: Environment
|
||||
atys += [T_opaque_box_ptr(cx)];
|
||||
|
||||
// Args >2: ty params, if not acquired via capture...
|
||||
let i = 0u;
|
||||
while i < n_ty_params {
|
||||
atys += [T_ptr(cx.tydesc_type)];
|
||||
i += 1u;
|
||||
}
|
||||
// ... then explicit args.
|
||||
atys += type_of_explicit_args(cx, inputs);
|
||||
ret T_fn(atys, llvm::LLVMVoidType());
|
||||
}
|
||||
|
||||
// Given a function type and a count of ty params, construct an llvm type
|
||||
fn type_of_fn_from_ty(cx: @crate_ctxt, fty: ty::t, n_ty_params: uint)
|
||||
-> TypeRef {
|
||||
type_of_fn(cx, ty::ty_fn_args(fty), ty::ty_fn_ret(fty), n_ty_params)
|
||||
fn type_of_fn_from_ty(cx: @crate_ctxt, fty: ty::t) -> TypeRef {
|
||||
type_of_fn(cx, ty::ty_fn_args(fty), ty::ty_fn_ret(fty))
|
||||
}
|
||||
|
||||
fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
|
||||
@ -89,7 +81,7 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
|
||||
T_struct(tys)
|
||||
}
|
||||
ty::ty_fn(_) {
|
||||
T_fn_pair(cx, type_of_fn_from_ty(cx, t, 0u))
|
||||
T_fn_pair(cx, type_of_fn_from_ty(cx, t))
|
||||
}
|
||||
ty::ty_iface(_, _) { T_opaque_iface(cx) }
|
||||
ty::ty_res(_, sub, tps) {
|
||||
@ -146,20 +138,6 @@ fn type_of_enum(cx: @crate_ctxt, did: ast::def_id, t: ty::t)
|
||||
}
|
||||
}
|
||||
|
||||
fn type_of_ty_param_bounds_and_ty
|
||||
(ccx: @crate_ctxt, tpt: ty::ty_param_bounds_and_ty) -> TypeRef {
|
||||
let t = tpt.ty;
|
||||
alt ty::get(t).struct {
|
||||
ty::ty_fn(_) {
|
||||
ret type_of_fn_from_ty(ccx, t, (*tpt.bounds).len());
|
||||
}
|
||||
_ {
|
||||
// fall through
|
||||
}
|
||||
}
|
||||
type_of(ccx, t)
|
||||
}
|
||||
|
||||
fn type_of_or_i8(ccx: @crate_ctxt, typ: ty::t) -> TypeRef {
|
||||
if check type_has_static_size(ccx, typ) {
|
||||
type_of(ccx, typ)
|
||||
|
Loading…
x
Reference in New Issue
Block a user