parent
149d1d4a6e
commit
1dc5e1aa94
@ -10,7 +10,7 @@ type path = [path_elt];
|
||||
enum ast_node {
|
||||
node_item(@item, @path),
|
||||
node_native_item(@native_item, @path),
|
||||
node_method(@method, @path),
|
||||
node_method(@method, node_id, @path),
|
||||
node_variant(variant, def_id, @path),
|
||||
node_expr(@expr),
|
||||
// Locals are numbered, because the alias analysis needs to know in which
|
||||
@ -69,7 +69,7 @@ fn map_item(i: @item, cx: ctx, v: vt) {
|
||||
cx.map.insert(i.id, node_item(i, @cx.path));
|
||||
alt i.node {
|
||||
item_impl(_, _, _, ms) {
|
||||
for m in ms { cx.map.insert(m.id, node_method(m, @cx.path)); }
|
||||
for m in ms { cx.map.insert(m.id, node_method(m, i.id, @cx.path)); }
|
||||
}
|
||||
item_res(_, _, _, dtor_id, ctor_id) {
|
||||
cx.map.insert(ctor_id, node_res_ctor(i));
|
||||
|
@ -802,7 +802,7 @@ fn create_function(fcx: @fn_ctxt) -> @metadata<subprogram_md> {
|
||||
bound to non-function"); }
|
||||
}
|
||||
}
|
||||
ast_map::node_method(method, _) {
|
||||
ast_map::node_method(method, _, _) {
|
||||
(method.ident, method.decl.output, method.id)
|
||||
}
|
||||
ast_map::node_res_ctor(item) {
|
||||
|
@ -2450,10 +2450,12 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
|
||||
some(val) { ret some(val); }
|
||||
none {}
|
||||
}
|
||||
|
||||
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 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)];
|
||||
@ -2462,10 +2464,10 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
|
||||
alt item.node {
|
||||
ast::item_fn(decl, _, body) {
|
||||
trans_fn(ccx, pt, decl, body, lldecl, no_self, [],
|
||||
some(substs), fn_id.node);
|
||||
psubsts, fn_id.node);
|
||||
}
|
||||
ast::item_res(decl, _, _, _, ctor_id) {
|
||||
trans_res_ctor(ccx, pt, decl, ctor_id, [], some(substs), lldecl);
|
||||
trans_res_ctor(ccx, pt, decl, ctor_id, [], psubsts, lldecl);
|
||||
}
|
||||
_ { fail "Unexpected item type"; }
|
||||
}
|
||||
@ -2478,7 +2480,16 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
|
||||
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, [], some(substs), lldecl);
|
||||
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);
|
||||
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;
|
||||
@ -2490,19 +2501,35 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
|
||||
some(val)
|
||||
}
|
||||
|
||||
fn lval_static_fn(bcx: @block_ctxt, fn_id: ast::def_id, id: ast::node_id)
|
||||
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 tpt = ty::lookup_item_type(ccx.tcx, fn_id);
|
||||
if ccx.sess.opts.monomorphize && vec::len(tys) > 0u &&
|
||||
if ccx.sess.opts.monomorphize &&
|
||||
(option::is_some(substs) || vec::len(tys) > 0u) &&
|
||||
fn_id.crate == ast::local_crate &&
|
||||
!vec::any(tys, {|t| ty::type_has_params(t)}) &&
|
||||
vec::all(*tpt.bounds, {|bs| vec::all(*bs, {|b|
|
||||
alt b { ty::bound_iface(_) { false } _ { true } }
|
||||
})}) {
|
||||
let dicts = ccx.dict_map.find(id);
|
||||
alt monomorphic_fn(ccx, fn_id, tys, dicts) {
|
||||
!vec::any(tys, {|t| ty::type_has_params(t)}) {
|
||||
let mono = alt substs {
|
||||
some((stys, dicts)) {
|
||||
if (vec::len(stys) + vec::len(stys)) > 0u {
|
||||
monomorphic_fn(ccx, fn_id, stys + tys, some(dicts))
|
||||
} else { none }
|
||||
}
|
||||
none {
|
||||
alt ccx.dict_map.find(id) {
|
||||
some(dicts) {
|
||||
alt impl::resolve_dicts_in_fn_ctxt(bcx.fcx, dicts) {
|
||||
some(dicts) { monomorphic_fn(ccx, fn_id, tys, some(dicts)) }
|
||||
none { none }
|
||||
}
|
||||
}
|
||||
none { monomorphic_fn(ccx, fn_id, tys, none) }
|
||||
}
|
||||
}
|
||||
};
|
||||
alt mono {
|
||||
some({llfn, fty}) {
|
||||
ret {bcx: bcx, val: llfn,
|
||||
kind: owned, env: null_env,
|
||||
@ -2601,12 +2628,12 @@ fn trans_var(cx: @block_ctxt, def: ast::def, id: ast::node_id)
|
||||
let ccx = bcx_ccx(cx);
|
||||
alt def {
|
||||
ast::def_fn(did, _) {
|
||||
ret lval_static_fn(cx, did, id);
|
||||
ret lval_static_fn(cx, did, id, none);
|
||||
}
|
||||
ast::def_variant(tid, vid) {
|
||||
if vec::len(ty::enum_variant_with_id(ccx.tcx, tid, vid).args) > 0u {
|
||||
// N-ary variant.
|
||||
ret lval_static_fn(cx, vid, id);
|
||||
ret lval_static_fn(cx, vid, id, none);
|
||||
} else {
|
||||
// Nullary variant.
|
||||
let enum_ty = ty::node_id_to_type(ccx.tcx, id);
|
||||
@ -4259,7 +4286,7 @@ fn mk_standard_basic_blocks(llfn: ValueRef) ->
|
||||
// - trans_args
|
||||
fn new_fn_ctxt_w_id(ccx: @crate_ctxt, path: path,
|
||||
llfndecl: ValueRef, id: ast::node_id,
|
||||
param_substs: option<[ty::t]>,
|
||||
param_substs: option<param_substs>,
|
||||
sp: option<span>) -> @fn_ctxt {
|
||||
let llbbs = mk_standard_basic_blocks(llfndecl);
|
||||
ret @{llfn: llfndecl,
|
||||
@ -4405,7 +4432,7 @@ enum self_arg { impl_self(ty::t), no_self, }
|
||||
fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
|
||||
body: ast::blk, llfndecl: ValueRef,
|
||||
ty_self: self_arg, ty_params: [ast::ty_param],
|
||||
param_substs: option<[ty::t]>,
|
||||
param_substs: option<param_substs>,
|
||||
id: ast::node_id, maybe_load_env: fn(@fn_ctxt)) {
|
||||
set_uwtable(llfndecl);
|
||||
|
||||
@ -4421,14 +4448,6 @@ fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
|
||||
let block_ty = node_id_type(bcx, body.node.id);
|
||||
|
||||
let arg_tys = ty::ty_fn_args(node_id_type(bcx, id));
|
||||
alt param_substs {
|
||||
some(ts) {
|
||||
arg_tys = vec::map(arg_tys, {|a|
|
||||
{mode: a.mode,
|
||||
ty: ty::substitute_type_params(fcx.ccx.tcx, ts, a.ty)}})
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
bcx = copy_args_to_allocas(fcx, bcx, decl.inputs, arg_tys);
|
||||
|
||||
maybe_load_env(fcx);
|
||||
@ -4454,7 +4473,7 @@ fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
|
||||
// function.
|
||||
fn trans_fn(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
|
||||
body: ast::blk, llfndecl: ValueRef, ty_self: self_arg,
|
||||
ty_params: [ast::ty_param], param_substs: option<[ty::t]>,
|
||||
ty_params: [ast::ty_param], param_substs: option<param_substs>,
|
||||
id: ast::node_id) {
|
||||
let do_time = ccx.sess.opts.stats;
|
||||
let start = if do_time { time::get_time() }
|
||||
@ -4473,7 +4492,7 @@ fn trans_fn(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
|
||||
|
||||
fn trans_res_ctor(ccx: @crate_ctxt, path: path, dtor: ast::fn_decl,
|
||||
ctor_id: ast::node_id, ty_params: [ast::ty_param],
|
||||
param_substs: option<[ty::t]>, llfndecl: ValueRef) {
|
||||
param_substs: option<param_substs>, llfndecl: ValueRef) {
|
||||
// Create a function for the constructor
|
||||
let fcx = new_fn_ctxt_w_id(ccx, path, llfndecl, ctor_id,
|
||||
param_substs, none);
|
||||
@ -4505,11 +4524,11 @@ fn trans_res_ctor(ccx: @crate_ctxt, path: path, dtor: ast::fn_decl,
|
||||
}
|
||||
|
||||
|
||||
fn trans_enum_variant(ccx: @crate_ctxt,
|
||||
enum_id: ast::node_id,
|
||||
fn trans_enum_variant(ccx: @crate_ctxt, enum_id: ast::node_id,
|
||||
variant: ast::variant, disr: int, is_degen: bool,
|
||||
ty_params: [ast::ty_param],
|
||||
param_substs: option<[ty::t]>, llfndecl: ValueRef) {
|
||||
param_substs: option<param_substs>,
|
||||
llfndecl: ValueRef) {
|
||||
// Translate variant arguments to function arguments.
|
||||
let fn_args = [], i = 0u;
|
||||
for varg in variant.node.args {
|
||||
@ -4522,7 +4541,7 @@ fn trans_enum_variant(ccx: @crate_ctxt,
|
||||
param_substs, none);
|
||||
create_llargs_for_fn_args(fcx, no_self, fn_args, ty_params);
|
||||
let ty_param_substs = alt param_substs {
|
||||
some(ts) { ts }
|
||||
some(substs) { substs.tys }
|
||||
none {
|
||||
let i = 0u;
|
||||
vec::map(ty_params, {|tp|
|
||||
|
@ -132,6 +132,10 @@ enum local_val { local_mem(ValueRef), local_imm(ValueRef), }
|
||||
|
||||
type fn_ty_param = {desc: ValueRef, dicts: option<[ValueRef]>};
|
||||
|
||||
type param_substs = {tys: [ty::t],
|
||||
dicts: option<typeck::dict_res>,
|
||||
bounds: @[ty::param_bounds]};
|
||||
|
||||
// Function context. Every LLVM function we create will have one of
|
||||
// these.
|
||||
type fn_ctxt = {
|
||||
@ -200,7 +204,7 @@ type fn_ctxt = {
|
||||
|
||||
// If this function is being monomorphized, this contains the type
|
||||
// substitutions used.
|
||||
param_substs: option<[ty::t]>,
|
||||
param_substs: option<param_substs>,
|
||||
|
||||
// The source span and nesting context where this function comes from, for
|
||||
// error reporting and symbol generation.
|
||||
@ -901,7 +905,7 @@ fn node_id_type(bcx: @block_ctxt, id: ast::node_id) -> ty::t {
|
||||
let tcx = bcx_tcx(bcx);
|
||||
let t = ty::node_id_to_type(tcx, id);
|
||||
alt bcx.fcx.param_substs {
|
||||
some(s) { ty::substitute_type_params(tcx, s, t) }
|
||||
some(substs) { ty::substitute_type_params(tcx, substs.tys, t) }
|
||||
_ { t }
|
||||
}
|
||||
}
|
||||
|
@ -76,10 +76,18 @@ fn trans_method_callee(bcx: @block_ctxt, callee_id: ast::node_id,
|
||||
-> lval_maybe_callee {
|
||||
alt origin {
|
||||
typeck::method_static(did) {
|
||||
trans_static_callee(bcx, callee_id, self, did)
|
||||
trans_static_callee(bcx, callee_id, self, did, none)
|
||||
}
|
||||
typeck::method_param(iid, off, p, b) {
|
||||
trans_param_callee(bcx, callee_id, self, iid, off, p, b)
|
||||
alt bcx.fcx.param_substs {
|
||||
some(substs) {
|
||||
trans_monomorphized_callee(bcx, callee_id, self,
|
||||
iid, off, p, b, substs)
|
||||
}
|
||||
none {
|
||||
trans_param_callee(bcx, callee_id, self, iid, off, p, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
typeck::method_iface(off) {
|
||||
trans_iface_callee(bcx, callee_id, self, off)
|
||||
@ -89,10 +97,11 @@ fn trans_method_callee(bcx: @block_ctxt, callee_id: ast::node_id,
|
||||
|
||||
// Method callee where the method is statically known
|
||||
fn trans_static_callee(bcx: @block_ctxt, callee_id: ast::node_id,
|
||||
base: @ast::expr, did: ast::def_id)
|
||||
base: @ast::expr, did: ast::def_id,
|
||||
substs: option<([ty::t], typeck::dict_res)>)
|
||||
-> lval_maybe_callee {
|
||||
let {bcx, val} = trans_self_arg(bcx, base);
|
||||
{env: self_env(val) with lval_static_fn(bcx, did, callee_id)}
|
||||
{env: self_env(val) with lval_static_fn(bcx, did, callee_id, substs)}
|
||||
}
|
||||
|
||||
fn wrapper_fn_ty(ccx: @crate_ctxt, dict_ty: TypeRef, fty: ty::t,
|
||||
@ -135,6 +144,38 @@ fn trans_vtable_callee(bcx: @block_ctxt, self: ValueRef, dict: ValueRef,
|
||||
generic: generic}
|
||||
}
|
||||
|
||||
fn trans_monomorphized_callee(bcx: @block_ctxt, callee_id: ast::node_id,
|
||||
base: @ast::expr, iface_id: ast::def_id,
|
||||
n_method: uint, n_param: uint, n_bound: uint,
|
||||
substs: param_substs) -> lval_maybe_callee {
|
||||
alt find_dict_in_fn_ctxt(substs, n_param, n_bound) {
|
||||
typeck::dict_static(impl_did, tys, sub_origins) {
|
||||
let tcx = bcx_tcx(bcx);
|
||||
if impl_did.crate != ast::local_crate {
|
||||
ret trans_param_callee(bcx, callee_id, base, iface_id,
|
||||
n_method, n_param, n_bound);
|
||||
}
|
||||
let mname = ty::iface_methods(tcx, iface_id)[n_method].ident;
|
||||
let mth = alt tcx.items.get(impl_did.node) {
|
||||
ast_map::node_item(@{node: ast::item_impl(_, _, _, ms), _}, _) {
|
||||
option::get(vec::find(ms, {|m| m.ident == mname}))
|
||||
}
|
||||
_ { fail; }
|
||||
};
|
||||
ret trans_static_callee(bcx, callee_id, base,
|
||||
ast_util::local_def(mth.id),
|
||||
some((tys, sub_origins)));
|
||||
}
|
||||
typeck::dict_iface(_) {
|
||||
ret trans_iface_callee(bcx, callee_id, base, n_method);
|
||||
}
|
||||
typeck::dict_param(n_param, n_bound) {
|
||||
fail "dict_param left in monomorphized function's dict substs";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Method callee where the dict comes from a type param
|
||||
fn trans_param_callee(bcx: @block_ctxt, callee_id: ast::node_id,
|
||||
base: @ast::expr, iface_id: ast::def_id, n_method: uint,
|
||||
@ -184,6 +225,46 @@ fn trans_vtable(ccx: @crate_ctxt, id: ast::node_id, name: str,
|
||||
ccx.item_symbols.insert(id, name);
|
||||
}
|
||||
|
||||
fn find_dict_in_fn_ctxt(ps: param_substs, n_param: uint, n_bound: uint)
|
||||
-> typeck::dict_origin {
|
||||
let dict_off = n_bound, i = 0u;
|
||||
// Dicts are stored in a flat array, finding the right one is
|
||||
// somewhat awkward
|
||||
for bounds in *ps.bounds {
|
||||
i += 1u;
|
||||
if i >= n_param { break; }
|
||||
for bound in *bounds {
|
||||
alt bound { ty::bound_iface(_) { dict_off += 1u; } _ {} }
|
||||
}
|
||||
}
|
||||
option::get(ps.dicts)[dict_off]
|
||||
}
|
||||
|
||||
fn resolve_dicts_in_fn_ctxt(fcx: @fn_ctxt, dicts: typeck::dict_res)
|
||||
-> option<typeck::dict_res> {
|
||||
let result = [];
|
||||
for dict in *dicts {
|
||||
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) }
|
||||
none { ret none; }
|
||||
}
|
||||
}
|
||||
typeck::dict_param(n_param, n_bound) {
|
||||
alt fcx.param_substs {
|
||||
some(substs) {
|
||||
find_dict_in_fn_ctxt(substs, n_param, n_bound)
|
||||
}
|
||||
none { ret none; }
|
||||
}
|
||||
}
|
||||
_ { dict }
|
||||
}];
|
||||
}
|
||||
some(@result)
|
||||
}
|
||||
|
||||
fn trans_wrapper(ccx: @crate_ctxt, pt: path, llfty: TypeRef,
|
||||
fill: fn(ValueRef, @block_ctxt) -> @block_ctxt)
|
||||
-> ValueRef {
|
||||
|
@ -1663,7 +1663,7 @@ fn lookup_method_inner(fcx: @fn_ctxt, expr: @ast::expr,
|
||||
fn ty_from_did(tcx: ty::ctxt, did: ast::def_id) -> ty::t {
|
||||
if did.crate == ast::local_crate {
|
||||
alt tcx.items.get(did.node) {
|
||||
ast_map::node_method(m, _) {
|
||||
ast_map::node_method(m, _, _) {
|
||||
let mt = ty_of_method(tcx, m_check, m);
|
||||
ty::mk_fn(tcx, mt.fty)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user