Remove a large part of the tydesc-passing code

This commit is contained in:
Marijn Haverbeke 2012-03-08 19:02:22 +01:00
parent 83c9f58534
commit 8f84d4c8b6
9 changed files with 112 additions and 307 deletions

@ -429,7 +429,9 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_family(ebml_w, 'f');
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, fn_ty);
encode_symbol(ecx, ebml_w, ctor_id);
if tps.len() == 0u {
encode_symbol(ecx, ebml_w, ctor_id);
}
encode_path(ebml_w, path, ast_map::path_name(item.ident));
ebml_w.end_tag();
}
@ -447,7 +449,6 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
}
alt ifce {
some(t) {
encode_symbol(ecx, ebml_w, item.id);
let i_ty = alt check t.node {
ty_path(_, id) { ty::node_id_to_type(tcx, id) }
};

@ -270,7 +270,7 @@ fn dynastack_alloca(cx: block, t: TypeRef, n: ValueRef, ty: ty::t) ->
C_uint(bcx.ccx(), llsize_of_real(bcx.ccx(), t)),
n);
let lltydesc = get_tydesc_simple(cx, ty, false).val;
let lltydesc = get_tydesc_simple(cx, ty).val;
let llresult = Call(dy_cx, dynastack_alloc, [llsz, lltydesc]);
ret PointerCast(dy_cx, llresult, T_ptr(t));
@ -450,7 +450,7 @@ fn trans_malloc_boxed_raw(bcx: block, t: ty::t,
let llty = type_of(ccx, box_ptr);
// Get the tydesc for the body:
let {bcx, val: lltydesc} = get_tydesc(bcx, t, true, static_ti);
let {bcx, val: lltydesc} = get_tydesc(bcx, t, static_ti);
lazily_emit_all_tydesc_glue(ccx, static_ti);
// Allocate space:
@ -470,37 +470,6 @@ fn trans_malloc_boxed(bcx: block, t: ty::t) ->
// Type descriptor and type glue stuff
// Given a type and a field index into its corresponding type descriptor,
// returns an LLVM ValueRef of that field from the tydesc, generating the
// tydesc if necessary.
fn field_of_tydesc(cx: block, t: ty::t, escapes: bool, field: int) ->
result {
let tydesc = get_tydesc_simple(cx, t, escapes);
ret rslt(tydesc.bcx,
GEPi(tydesc.bcx, tydesc.val, [0, field]));
}
// Given a type containing ty params, build a vector containing a ValueRef for
// each of the ty params it uses (from the current frame) and a vector of the
// indices of the ty params present in the type. This is used solely for
// constructing derived tydescs.
fn linearize_ty_params(cx: block, t: ty::t) ->
{params: [uint], descs: [ValueRef]} {
let param_vals = [], param_defs = [];
ty::walk_ty(cx.tcx(), t) {|t|
alt ty::get(t).struct {
ty::ty_param(pid, _) {
if !vec::any(param_defs, {|d| d == pid}) {
param_vals += [cx.fcx.lltyparams[pid].desc];
param_defs += [pid];
}
}
_ { }
}
}
ret {params: param_defs, descs: param_vals};
}
fn trans_stack_local_derived_tydesc(cx: block, llsz: ValueRef,
llalign: ValueRef, llroottydesc: ValueRef,
llfirstparam: ValueRef, n_params: uint)
@ -527,93 +496,16 @@ fn trans_stack_local_derived_tydesc(cx: block, llsz: ValueRef,
ret llmyroottydesc;
}
fn get_derived_tydesc(cx: block, t: ty::t, escapes: bool,
&static_ti: option<@tydesc_info>) -> result {
alt cx.fcx.derived_tydescs.find(t) {
some(info) {
// If the tydesc escapes in this context, the cached derived
// tydesc also has to be one that was marked as escaping.
if !(escapes && !info.escapes) {
ret rslt(cx, info.lltydesc);
}
}
none {/* fall through */ }
}
cx.ccx().stats.n_derived_tydescs += 1u;
let bcx = raw_block(cx.fcx, cx.fcx.llderivedtydescs);
let tys = linearize_ty_params(bcx, t);
let root_ti = get_static_tydesc(bcx.ccx(), t, tys.params);
static_ti = some(root_ti);
lazily_emit_all_tydesc_glue(cx.ccx(), static_ti);
let root = root_ti.tydesc;
let sz = size_of(bcx, t);
bcx = sz.bcx;
let align = align_of(bcx, t);
bcx = align.bcx;
// Store the captured type descriptors in an alloca if the caller isn't
// promising to do so itself.
let n_params = ty::count_ty_params(bcx.tcx(), t);
assert n_params == tys.params.len();
assert n_params == tys.descs.len();
let llparamtydescs =
alloca(bcx, T_array(T_ptr(bcx.ccx().tydesc_type), n_params + 1u));
let i = 0;
// If the type descriptor escapes, we need to add in the root as
// the first parameter, because upcall_get_type_desc() expects it.
if escapes {
Store(bcx, root, GEPi(bcx, llparamtydescs, [0, 0]));
i += 1;
}
for td: ValueRef in tys.descs {
Store(bcx, td, GEPi(bcx, llparamtydescs, [0, i]));
i += 1;
}
let llfirstparam =
PointerCast(bcx, llparamtydescs,
T_ptr(T_ptr(bcx.ccx().tydesc_type)));
let v;
if escapes {
let ccx = bcx.ccx();
let td_val =
Call(bcx, ccx.upcalls.get_type_desc,
[C_null(T_ptr(T_nil())), sz.val,
align.val, C_uint(ccx, 1u + n_params), llfirstparam,
C_uint(ccx, 0u)]);
v = td_val;
} else {
v = trans_stack_local_derived_tydesc(bcx, sz.val, align.val, root,
llfirstparam, n_params);
}
bcx.fcx.derived_tydescs.insert(t, {lltydesc: v, escapes: escapes});
ret rslt(cx, v);
}
fn get_tydesc_simple(bcx: block, t: ty::t, escapes: bool) -> result {
fn get_tydesc_simple(bcx: block, t: ty::t) -> result {
let ti = none;
get_tydesc(bcx, t, escapes, ti)
get_tydesc(bcx, t, ti)
}
fn get_tydesc(cx: block, t: ty::t, escapes: bool,
fn get_tydesc(cx: block, t: ty::t,
&static_ti: option<@tydesc_info>) -> result {
// Is the supplied type a type param? If so, return the passed-in tydesc.
alt ty::type_param(t) {
some(id) { ret rslt(cx, cx.fcx.lltyparams[id].desc); }
none {/* fall through */ }
}
// Does it contain a type param? If so, generate a derived tydesc.
if ty::type_has_params(t) {
ret get_derived_tydesc(cx, t, escapes, static_ti);
}
// FIXME[mono]
assert !ty::type_has_params(t);
// Otherwise, generate a tydesc if necessary, and return it.
let info = get_static_tydesc(cx.ccx(), t, []);
static_ti = some(info);
@ -980,7 +872,7 @@ fn trans_res_drop(bcx: block, rs: ValueRef, did: ast::def_id,
let dtor_addr = common::get_res_dtor(ccx, did, inner_t);
let args = [bcx.fcx.llretptr, null_env_ptr(bcx)];
for tp in tps {
let td = get_tydesc_simple(bcx, tp, false);
let td = get_tydesc_simple(bcx, tp);
args += [td.val];
bcx = td.bcx;
}
@ -1244,13 +1136,6 @@ fn lazily_emit_all_tydesc_glue(ccx: @crate_ctxt,
lazily_emit_tydesc_glue(ccx, abi::tydesc_field_free_glue, static_ti);
}
fn lazily_emit_all_generic_info_tydesc_glues(ccx: @crate_ctxt,
gi: generic_info) {
for ti: option<@tydesc_info> in gi.static_tis {
lazily_emit_all_tydesc_glue(ccx, ti);
}
}
fn lazily_emit_tydesc_glue(ccx: @crate_ctxt, field: int,
static_ti: option<@tydesc_info>) {
alt static_ti {
@ -1349,7 +1234,7 @@ fn call_tydesc_glue_full(cx: block, v: ValueRef, tydesc: ValueRef,
fn call_tydesc_glue(cx: block, v: ValueRef, t: ty::t, field: int) ->
block {
let ti: option<@tydesc_info> = none::<@tydesc_info>;
let {bcx: bcx, val: td} = get_tydesc(cx, t, false, ti);
let {bcx: bcx, val: td} = get_tydesc(cx, t, ti);
call_tydesc_glue_full(bcx, v, td, field, ti);
ret bcx;
}
@ -1370,7 +1255,7 @@ fn call_cmp_glue(cx: block, lhs: ValueRef, rhs: ValueRef, t: ty::t,
let llrawlhsptr = BitCast(bcx, lllhs, T_ptr(T_i8()));
let llrawrhsptr = BitCast(bcx, llrhs, T_ptr(T_i8()));
r = get_tydesc_simple(bcx, t, false);
r = get_tydesc_simple(bcx, t);
let lltydesc = r.val;
bcx = r.bcx;
let lltydescs =
@ -2047,18 +1932,6 @@ fn trans_loop(cx:block, body: ast::blk) -> block {
ret next_cx;
}
type generic_info = {item_type: ty::t,
static_tis: [option<@tydesc_info>],
tydescs: [ValueRef],
param_bounds: @[ty::param_bounds],
origins: option<typeck::vtable_res>};
enum generic_callee {
generic_full(generic_info),
generic_mono(ty::t),
generic_none,
}
enum lval_kind {
temporary, //< Temporary value passed by value if of immediate type
owned, //< Non-temporary value passed by pointer
@ -2075,7 +1948,7 @@ type lval_maybe_callee = {bcx: block,
val: ValueRef,
kind: lval_kind,
env: callee_env,
generic: generic_callee};
tds: option<[ValueRef]>};
fn null_env_ptr(bcx: block) -> ValueRef {
C_null(T_opaque_box_ptr(bcx.ccx()))
@ -2094,8 +1967,7 @@ 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,
generic: generic_none};
ret {bcx: bcx, val: val, kind: kind, env: is_closure, tds: none};
}
fn trans_external_path(cx: block, did: ast::def_id,
@ -2108,7 +1980,7 @@ fn trans_external_path(cx: block, did: ast::def_id,
fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
vtables: option<typeck::vtable_res>)
-> option<{llfn: ValueRef, fty: ty::t}> {
-> option<ValueRef> {
let substs = vec::map(substs, {|t|
alt ty::get(t).struct {
ty::ty_box(mt) { ty::mk_opaque_box(ccx.tcx) }
@ -2126,7 +1998,7 @@ 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 llfty = type_of_fn_from_ty(ccx, mono_ty, 0u);
let map_node = ccx.tcx.items.get(fn_id.node);
// Get the path so that we can create a symbol
@ -2146,7 +2018,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
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});
ccx.monomorphized.insert(hash_id, lldecl);
let psubsts = some({tys: substs, vtables: vtables, bounds: tpt.bounds});
alt check map_node {
@ -2182,10 +2054,9 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
}
}
}
some({llfn: lldecl, fty: mono_ty})
some(lldecl)
}
// FIXME[mono] Only actually translate things that are not generic
fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id)
-> ast::def_id {
alt ccx.external.find(fn_id) {
@ -2266,10 +2137,12 @@ fn lval_static_fn(bcx: block, fn_id: ast::def_id, id: ast::node_id,
}
};
alt mono {
some({llfn, fty}) {
ret {bcx: bcx, val: llfn,
some(llfn) {
let cast = PointerCast(bcx, llfn, T_ptr(type_of_fn_from_ty(
ccx, node_id_type(bcx, id), 0u)));
ret {bcx: bcx, val: cast,
kind: owned, env: null_env,
generic: generic_mono(fty)};
tds: none};
}
none {}
}
@ -2295,23 +2168,22 @@ fn lval_static_fn(bcx: block, fn_id: ast::def_id, id: ast::node_id,
}
}
let gen = generic_none, bcx = bcx;
let tds = none, bcx = bcx;
// FIXME[mono] ensure this is a native function
if tys.len() > 0u {
let tydescs = [], tis = [];
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, true, ti);
tis += [ti];
let td = get_tydesc(bcx, t, ti);
lazily_emit_all_tydesc_glue(ccx, ti);
bcx = td.bcx;
tydescs += [td.val];
}
gen = generic_full({item_type: tpt.ty,
static_tis: tis,
tydescs: tydescs,
param_bounds: tpt.bounds,
origins: ccx.maps.vtable_map.find(id)});
tds = some(tydescs);
}
ret {bcx: bcx, val: val, kind: owned, env: null_env, generic: gen};
ret {bcx: bcx, val: val, kind: owned, env: null_env, tds: tds};
}
fn lookup_discriminant(ccx: @crate_ctxt, vid: ast::def_id) -> ValueRef {
@ -2564,7 +2436,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 = alt c.generic { generic_full(_) { true } _ { false } } ||
let must_bind = option::is_some(c.tds) ||
alt c.env { self_env(_, _) { true } _ { false } };
if must_bind {
let n_args = ty::ty_fn_args(ty).len();
@ -2761,7 +2633,7 @@ fn trans_arg_expr(cx: block, arg: ty::arg, lldestty: TypeRef, e: @ast::expr,
// - new_fn_ctxt
// - trans_args
fn trans_args(cx: block, llenv: ValueRef,
gen: generic_callee, es: [@ast::expr], fn_ty: ty::t,
tds: option<[ValueRef]>, es: [@ast::expr], fn_ty: ty::t,
dest: dest)
-> {bcx: block,
args: [ValueRef],
@ -2770,54 +2642,40 @@ fn trans_args(cx: block, llenv: ValueRef,
let temp_cleanups = [];
let args = ty::ty_fn_args(fn_ty);
let llargs: [ValueRef] = [];
let lltydescs: [ValueRef] = [];
let ccx = cx.ccx();
let bcx = cx;
let retty = ty::ty_fn_ret(fn_ty), full_retty = retty;
alt gen {
generic_full(g) { fail; }
generic_mono(t) {
args = ty::ty_fn_args(t);
retty = ty::ty_fn_ret(t);
}
_ { }
}
let retty = ty::ty_fn_ret(fn_ty);
// Arg 0: Output pointer.
let llretslot = alt dest {
ignore {
if ty::type_is_nil(retty) {
llvm::LLVMGetUndef(T_ptr(T_nil()))
} else {
let {bcx: cx, val} = alloc_ty(bcx, full_retty);
let {bcx: cx, val} = alloc_ty(bcx, retty);
bcx = cx;
val
}
}
save_in(dst) { dst }
by_val(_) {
let {bcx: cx, val} = alloc_ty(bcx, full_retty);
let {bcx: cx, val} = alloc_ty(bcx, retty);
bcx = cx;
val
}
};
if retty != full_retty || ty::type_has_params(retty) {
// It's possible that the callee has some generic-ness somewhere in
// its return value -- say a method signature within an obj or a fn
// type deep in a structure -- which the caller has a concrete view
// of. If so, cast the caller's view of the restlot to the callee's
// view, for the sake of making a type-compatible call.
let llretty = T_ptr(type_of(ccx, retty));
llargs += [PointerCast(cx, llretslot, llretty)];
} else { llargs += [llretslot]; }
llargs += [llretslot];
// Arg 1: Env (closure-bindings / self value)
llargs += [llenv];
// Args >2: ty_params ...
llargs += lltydescs;
alt tds {
some(tds) { llargs += tds; }
none {}
}
// ... then explicit args.
@ -2883,7 +2741,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.generic, args, fn_expr_ty, dest);
trans_args(bcx, llenv, f_res.tds, args, fn_expr_ty, dest);
bcx = args_res.bcx;
let llargs = args_res.args;
let llretslot = args_res.retslot;
@ -3418,7 +3276,7 @@ fn trans_log(lvl: @ast::expr, bcx: block, e: @ast::expr) -> block {
with_scope(bcx, "log") {|bcx|
let {bcx, val, _} = trans_temp_expr(bcx, e);
let e_ty = expr_ty(bcx, e);
let {bcx, val: tydesc} = get_tydesc_simple(bcx, e_ty, false);
let {bcx, val: tydesc} = get_tydesc_simple(bcx, e_ty);
// Call the polymorphic log function.
let {bcx, val} = spill_if_immediate(bcx, val, e_ty);
let val = PointerCast(bcx, val, T_ptr(T_i8()));
@ -4376,6 +4234,15 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
let llfndecl = get_item_val(ccx, item.id);
trans_fn(ccx, *path + [path_name(item.ident)], decl, body,
llfndecl, no_self, none, item.id, none);
} else {
for stmt in body.node.stmts {
alt stmt.node {
ast::stmt_decl(@{node: ast::decl_item(i), _}, _) {
trans_item(ccx, *i);
}
_ {}
}
}
}
}
ast::item_impl(tps, _, _, ms) {
@ -4400,8 +4267,8 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
let vi = ty::enum_variants(ccx.tcx, local_def(item.id));
let i = 0;
for variant: ast::variant in variants {
let llfn = get_item_val(ccx, variant.node.id);
if variant.node.args.len() > 0u {
let llfn = get_item_val(ccx, variant.node.id);
trans_enum_variant(ccx, item.id, variant,
vi[i].disr_val, degen,
none, llfn);
@ -4535,7 +4402,7 @@ 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);
let llfty = type_of_fn_from_ty(ccx, node_type, bnds.len());
register_fn_fuller(ccx, sp, path, flav, node_id, node_type,
lib::llvm::CCallConv, llfty)
}
@ -4582,7 +4449,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, []);
let llfty = type_of_fn(ccx, [vecarg_ty], nt, 0u);
let llfdecl = decl_fn(ccx.llmod, "_rust_main",
lib::llvm::CCallConv, llfty);

@ -131,21 +131,15 @@ 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: [fn_ty_param],
ty_params: option<[ValueRef]>,
bound_values: [environment_value])
-> (ty::t, [ty::t]) {
let bound_tys = [];
let tydesc_ty = mk_tydesc_ty(tcx, ck);
// Compute the closed over tydescs
let param_ptrs = [];
for tp in ty_params {
param_ptrs += [tydesc_ty];
option::may(tp.vtables) {|vtables|
for vtable in vtables { param_ptrs += [tydesc_ty]; }
}
}
let n_param_ptrs = alt ty_params {
some(tds) { tds.len() } none { 0u }
};
// Compute the closed over data
for bv in bound_values {
@ -158,7 +152,8 @@ fn mk_closure_tys(tcx: ty::ctxt,
}
let bound_data_ty = ty::mk_tup(tcx, bound_tys);
let cdata_ty = ty::mk_tup(tcx, [ty::mk_tup(tcx, param_ptrs),
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),
bound_data_ty]);
#debug["cdata_ty=%s", ty_to_str(tcx, cdata_ty)];
ret (cdata_ty, bound_tys);
@ -186,7 +181,7 @@ fn allocate_cbox(bcx: block,
&ti: option<@tydesc_info>) -> block {
let ccx = bcx.ccx();
let bound_tydesc = GEPi(bcx, box, [0, abi::box_field_tydesc]);
let {bcx, val: td} = base::get_tydesc(bcx, cdata_ty, true, ti);
let {bcx, val: td} = base::get_tydesc(bcx, cdata_ty, ti);
let td = Call(bcx, ccx.upcalls.create_shared_type_desc, [td]);
Store(bcx, td, bound_tydesc);
bcx
@ -243,7 +238,7 @@ fn cast_if_we_can(bcx: block, llbox: ValueRef, t: ty::t) -> ValueRef {
// 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: [fn_ty_param],
bcx: block, lltyparams: option<[ValueRef]>,
bound_values: [environment_value],
ck: ty::closure_kind)
-> closure_result {
@ -284,18 +279,11 @@ fn store_environment(
let {bcx:bcx, val:ty_params_slot} =
GEP_tup_like(bcx, cbox_ty, llbox,
[0, abi::box_field_body, abi::closure_body_ty_params]);
let off = 0;
for tp in lltyparams {
let cloned_td = maybe_clone_tydesc(bcx, ck, tp.desc);
Store(bcx, cloned_td, GEPi(bcx, ty_params_slot, [0, off]));
off += 1;
option::may(tp.vtables, {|vtables|
for vtable in vtables {
let cast = PointerCast(bcx, vtable, val_ty(cloned_td));
Store(bcx, cast, GEPi(bcx, ty_params_slot, [0, off]));
off += 1;
}
});
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.
@ -389,14 +377,13 @@ fn build_closure(bcx0: block,
}
}
}
ret store_environment(bcx, copy bcx.fcx.lltyparams, env_vals, ck);
ret store_environment(bcx, none, env_vals, ck);
}
// Given an enclosing block context, a new function context, a closure type,
// and a list of upvars, generate code to load and populate the environment
// with the upvars and type descriptors.
fn load_environment(enclosing_cx: block,
fcx: fn_ctxt,
fn load_environment(fcx: fn_ctxt,
cdata_ty: ty::t,
cap_vars: [capture::capture_var],
ck: ty::closure_kind) {
@ -405,27 +392,6 @@ fn load_environment(enclosing_cx: block,
// Load a pointer to the closure data, skipping over the box header:
let llcdata = base::opaque_box_body(bcx, cdata_ty, fcx.llenv);
// Populate the type parameters from the environment. We need to
// do this first because the tydescs are needed to index into
// the bindings if they are dynamically sized.
let {bcx, val: lltydescs} = GEP_tup_like(bcx, cdata_ty, llcdata,
[0, abi::closure_body_ty_params]);
let off = 0;
for tp in copy enclosing_cx.fcx.lltyparams {
let tydesc = Load(bcx, GEPi(bcx, lltydescs, [0, off]));
off += 1;
let vtables = option::map(tp.vtables, {|vtables|
let rslt = [];
for vtable in vtables {
let vtable = Load(bcx, GEPi(bcx, lltydescs, [0, off]));
rslt += [PointerCast(bcx, vtable, T_ptr(T_vtable()))];
off += 1;
}
rslt
});
fcx.lltyparams += [{desc: tydesc, vtables: vtables}];
}
// Populate the upvars from the environment.
let i = 0u;
vec::iter(cap_vars) { |cap_var|
@ -460,7 +426,7 @@ 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, []);
let llfnty = type_of_fn_from_ty(ccx, fty, 0u);
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);
@ -472,7 +438,7 @@ fn trans_expr_fn(bcx: block,
let {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, ck, id);
trans_closure(ccx, sub_path, decl, body, llfn, no_self,
bcx.fcx.param_substs, id, none, {|fcx|
load_environment(bcx, fcx, cdata_ty, cap_vars, ck);
load_environment(fcx, cdata_ty, cap_vars, ck);
});
llbox
};
@ -513,13 +479,7 @@ fn trans_bind_1(cx: block, outgoing_fty: ty::t,
ret bcx;
}
// Figure out which tydescs we need to pass, if any.
let (outgoing_fty_real, lltydescs, param_bounds) = alt f_res.generic {
generic_full(ginfo) { fail; }
_ { (outgoing_fty, [], @[]) }
};
if bound.len() == 0u && lltydescs.len() == 0u &&
if bound.len() == 0u && option::is_none(f_res.tds) &&
(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);
@ -545,14 +505,15 @@ fn trans_bind_1(cx: block, outgoing_fty: ty::t,
// Actually construct the closure
let {llbox, cdata_ty, bcx} = store_environment(
bcx, vec::map(lltydescs, {|d| {desc: d, vtables: none}}),
bcx, f_res.tds,
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_real, args,
cdata_ty, *param_bounds, target_info);
cx.fcx.ccx, cx.fcx.path, pair_ty, outgoing_fty, args,
cdata_ty, target_info,
alt f_res.tds { some(x) { x.len() } _ { 0u } });
// Fill the function pair
fill_fn_pair(bcx, get_dest_addr(dest), llthunk.val, llbox);
@ -704,16 +665,15 @@ fn trans_bind_thunk(ccx: @crate_ctxt,
outgoing_fty: ty::t,
args: [option<@ast::expr>],
cdata_ty: ty::t,
param_bounds: [ty::param_bounds],
target_info: target_info)
target_info: target_info,
n_tps: uint)
-> {val: ValueRef, ty: TypeRef} {
let tcx = ccx.tcx;
#debug["trans_bind_thunk[incoming_fty=%s,outgoing_fty=%s,\
cdata_ty=%s,param_bounds=%?]",
cdata_ty=%s]",
ty_to_str(tcx, incoming_fty),
ty_to_str(tcx, outgoing_fty),
ty_to_str(tcx, cdata_ty),
param_bounds];
ty_to_str(tcx, cdata_ty)];
// Here we're not necessarily constructing a thunk in the sense of
// "function with no arguments". The result of compiling 'bind f(foo,
@ -813,28 +773,11 @@ fn trans_bind_thunk(ccx: @crate_ctxt,
let {bcx: l_bcx, val: param_record} =
GEP_tup_like(l_bcx, cdata_ty, llcdata,
[0, abi::closure_body_ty_params]);
let off = 0;
for param in param_bounds {
let dsc = Load(l_bcx, GEPi(l_bcx, param_record, [0, off])),
vtables = none;
let i = 0u;
while i < n_tps {
let dsc = Load(l_bcx, GEPi(l_bcx, param_record, [0, i as int]));
llargs += [dsc];
off += 1;
for bound in *param {
alt bound {
ty::bound_iface(_) {
let vtable = Load(l_bcx, GEPi(l_bcx, param_record, [0, off]));
vtable = PointerCast(l_bcx, vtable, T_ptr(T_vtable()));
llargs += [vtable];
off += 1;
vtables = some(alt vtables {
none { [vtable] }
some(ds) { ds + [vtable] }
});
}
_ {}
}
}
fcx.lltyparams += [{desc: dsc, vtables: vtables}];
fcx.lltyparams += [{desc: dsc, vtables: none}];
}
let a: uint = first_tp_arg; // retptr, env come first
@ -895,7 +838,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, param_bounds);
type_of_fn_from_ty(ccx, outgoing_fty, 0u);
lltargetfn = PointerCast(bcx, lltargetfn, T_ptr(lltargetty));
Call(bcx, lltargetfn, llargs);
build_return(bcx);

@ -93,7 +93,7 @@ type crate_ctxt = {
// Track mapping of external ids to local items imported for inlining
external: hashmap<ast::def_id, option<ast::node_id>>,
// Cache instances of monomorphized functions
monomorphized: hashmap<mono_id, {llfn: ValueRef, fty: ty::t}>,
monomorphized: hashmap<mono_id, ValueRef>,
// Cache generated vtables
vtables: hashmap<mono_id, ValueRef>,
module_data: hashmap<str, ValueRef>,
@ -180,6 +180,7 @@ type fn_ctxt = @{
llupvars: hashmap<ast::node_id, ValueRef>,
// A vector of incoming type descriptors and their associated vtables.
// Currently only used by glue functions
mutable lltyparams: [fn_ty_param],
// Derived tydescs are tydescs created at runtime, for types that
@ -307,7 +308,7 @@ fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id, inner_t: ty::t)
let nil_res = ty::mk_nil(ccx.tcx);
let fn_mode = ast::expl(ast::by_ref);
let f_t = type_of::type_of_fn(ccx, [{mode: fn_mode, ty: inner_t}],
nil_res, *param_bounds);
nil_res, (*param_bounds).len());
ret base::get_extern_const(ccx.externs, ccx.llmod,
csearch::get_symbol(ccx.sess.cstore,
did), f_t);
@ -542,9 +543,9 @@ fn set_struct_body(t: TypeRef, elts: [TypeRef]) unsafe {
fn T_empty_struct() -> TypeRef { ret T_struct([]); }
// A vtable is, in reality, a vtable pointer followed by zero or more pointers
// to tydescs and other vtables that it closes over. But the types and number
// of those are rarely known to the code that needs to manipulate them, so
// they are described by this opaque type.
// to tydescs and other vtables that it closes over. But the types and number of
// those are rarely known to the code that needs to manipulate them, so they
// are described by this opaque type.
fn T_vtable() -> TypeRef { T_array(T_ptr(T_i8()), 1u) }
fn T_task(targ_cfg: @session::config) -> TypeRef {

@ -76,7 +76,7 @@ fn trans_static_callee(bcx: block, callee_id: ast::node_id,
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);
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)}
}
@ -86,13 +86,11 @@ fn trans_vtable_callee(bcx: block, env: callee_env, vtable: ValueRef,
-> 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, []);
let llfty = type_of::type_of_fn_from_ty(ccx, fty, 0u);
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,
generic: generic_none}
{bcx: bcx, val: mptr, kind: owned, env: env, tds: none}
}
fn method_with_name(ccx: @crate_ctxt, impl_id: ast::def_id,
@ -243,10 +241,10 @@ 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, []))
C_null(type_of_fn_from_ty(ccx, fty, 0u))
} else {
let m_id = method_with_name(ccx, impl_id, im.ident);
option::get(monomorphic_fn(ccx, m_id, substs, some(vtables))).llfn
option::get(monomorphic_fn(ccx, m_id, substs, some(vtables)))
}
}))
}

@ -269,7 +269,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, []);
let llty = type_of_fn_from_ty(ccx, t, 0u);
let llfndecl = decl_internal_cdecl_fn(ccx.llmod, ps, llty);
trans_fn(ccx, path, decl, body, llfndecl, no_self, none, id,
none);
@ -383,8 +383,7 @@ fn decl_native_fn(ccx: @crate_ctxt, i: @ast::native_item,
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, param_bounds(ccx, tps));
let fn_type = type_of_fn_from_ty(ccx, node_type, tps.len());
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,

@ -701,7 +701,7 @@ fn dynamic_metrics(cx: block, t: ty::t) -> metrics {
alt ty::get(t).struct {
ty::ty_param(p, _) {
let {bcx, val: tydesc} = base::get_tydesc_simple(cx, t, false);
let {bcx, val: tydesc} = base::get_tydesc_simple(cx, t);
let szptr = GEPi(bcx, tydesc, [0, abi::tydesc_field_size]);
let aptr = GEPi(bcx, tydesc, [0, abi::tydesc_field_align]);
{bcx: bcx, sz: Load(bcx, szptr), align: Load(bcx, aptr)}

@ -202,7 +202,7 @@ fn trans_append_literal(bcx: block, vptrptr: ValueRef, vec_ty: ty::t,
let ccx = bcx.ccx();
let elt_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
let ti = none;
let {bcx: bcx, val: td} = get_tydesc(bcx, elt_ty, false, ti);
let {bcx: bcx, val: td} = get_tydesc(bcx, elt_ty, ti);
base::lazily_emit_tydesc_glue(ccx, abi::tydesc_field_take_glue, ti);
let opaque_v = PointerCast(bcx, vptrptr,
T_ptr(T_ptr(ccx.opaque_vec_type)));

@ -19,7 +19,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, params: [ty::param_bounds]) -> TypeRef {
output: ty::t, n_ty_params: uint) -> TypeRef {
let atys: [TypeRef] = [];
// Arg 0: Output pointer.
@ -29,14 +29,10 @@ fn type_of_fn(cx: @crate_ctxt, inputs: [ty::arg],
atys += [T_opaque_box_ptr(cx)];
// Args >2: ty params, if not acquired via capture...
for bounds in params {
let i = 0u;
while i < n_ty_params {
atys += [T_ptr(cx.tydesc_type)];
for bound in *bounds {
alt bound {
ty::bound_iface(_) { atys += [T_ptr(T_vtable())]; }
_ {}
}
}
i += 1u;
}
// ... then explicit args.
atys += type_of_explicit_args(cx, inputs);
@ -44,9 +40,9 @@ fn type_of_fn(cx: @crate_ctxt, inputs: [ty::arg],
}
// 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,
param_bounds: [ty::param_bounds]) -> TypeRef {
type_of_fn(cx, ty::ty_fn_args(fty), ty::ty_fn_ret(fty), param_bounds)
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(cx: @crate_ctxt, t: ty::t) -> TypeRef {
@ -93,7 +89,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, []))
T_fn_pair(cx, type_of_fn_from_ty(cx, t, 0u))
}
ty::ty_iface(_, _) { T_opaque_iface(cx) }
ty::ty_res(_, sub, tps) {
@ -155,7 +151,7 @@ fn type_of_ty_param_bounds_and_ty
let t = tpt.ty;
alt ty::get(t).struct {
ty::ty_fn(_) {
ret type_of_fn_from_ty(ccx, t, *tpt.bounds);
ret type_of_fn_from_ty(ccx, t, (*tpt.bounds).len());
}
_ {
// fall through