Skip to content

Commit e1dc40b

Browse files
committed
More work on translating dictionary-passing
Reached a point where simple uses of interfaces without bounds work. Issue #1227
1 parent 45b153a commit e1dc40b

File tree

8 files changed

+387
-162
lines changed

8 files changed

+387
-162
lines changed

src/comp/driver/driver.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,9 @@ fn compile_input(sess: session::session, cfg: ast::crate_cfg, input: str,
173173
time(time_passes, "const checking",
174174
bind middle::check_const::check_crate(sess, crate));
175175
let ty_cx = ty::mk_ctxt(sess, def_map, ast_map, freevars);
176-
let method_map = time(time_passes, "typechecking",
177-
bind typeck::check_crate(ty_cx, impl_map, crate));
176+
let (method_map, dict_map) =
177+
time(time_passes, "typechecking",
178+
bind typeck::check_crate(ty_cx, impl_map, crate));
178179
time(time_passes, "block-use checking",
179180
bind middle::block_use::check_crate(ty_cx, crate));
180181
time(time_passes, "function usage",
@@ -202,7 +203,7 @@ fn compile_input(sess: session::session, cfg: ast::crate_cfg, input: str,
202203
bind trans::trans_crate(sess, crate, ty_cx,
203204
outputs.obj_filename, exp_map, ast_map,
204205
mut_map, copy_map, last_uses,
205-
method_map));
206+
method_map, dict_map));
206207
time(time_passes, "LLVM passes",
207208
bind link::write::run_passes(sess, llmod, outputs.obj_filename));
208209

src/comp/lib/llvm.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -993,7 +993,8 @@ fn type_to_str_inner(names: type_names, outer0: [TypeRef], ty: TypeRef) ->
993993
}
994994
10 {
995995
let el_ty = llvm::LLVMGetElementType(ty);
996-
ret "[" + type_to_str_inner(names, outer, el_ty) + "]";
996+
ret "[" + type_to_str_inner(names, outer, el_ty) + " x " +
997+
uint::str(llvm::LLVMGetArrayLength(ty)) + "]";
997998
}
998999
11 {
9991000
let i: uint = 0u;

src/comp/middle/trans.rs

Lines changed: 76 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,14 @@ fn type_of_fn(cx: @crate_ctxt, sp: span, is_method: bool, inputs: [ty::arg],
9898

9999
// Args >2: ty params, if not acquired via capture...
100100
if !is_method {
101-
// FIXME[impl] Also add args for the dicts
102-
for _param in params {
101+
for bounds in params {
103102
atys += [T_ptr(cx.tydesc_type)];
103+
for bound in *bounds {
104+
alt bound {
105+
ty::bound_iface(_) { atys += [T_ptr(T_dict())]; }
106+
_ {}
107+
}
108+
}
104109
}
105110
}
106111
// ... then explicit args.
@@ -905,7 +910,10 @@ fn linearize_ty_params(cx: @block_ctxt, t: ty::t) ->
905910
ty::ty_param(pid, _) {
906911
let seen: bool = false;
907912
for d: uint in r.defs { if d == pid { seen = true; } }
908-
if !seen { r.vals += [r.cx.fcx.lltydescs[pid]]; r.defs += [pid]; }
913+
if !seen {
914+
r.vals += [r.cx.fcx.lltyparams[pid].desc];
915+
r.defs += [pid];
916+
}
909917
}
910918
_ { }
911919
}
@@ -1041,8 +1049,9 @@ fn get_tydesc(cx: @block_ctxt, t: ty::t, escapes: bool,
10411049
// Is the supplied type a type param? If so, return the passed-in tydesc.
10421050
alt ty::type_param(bcx_tcx(cx), t) {
10431051
some(id) {
1044-
if id < vec::len(cx.fcx.lltydescs) {
1045-
ret {kind: tk_param, result: rslt(cx, cx.fcx.lltydescs[id])};
1052+
if id < vec::len(cx.fcx.lltyparams) {
1053+
ret {kind: tk_param,
1054+
result: rslt(cx, cx.fcx.lltyparams[id].desc)};
10461055
} else {
10471056
bcx_tcx(cx).sess.span_bug(cx.sp,
10481057
"Unbound typaram in get_tydesc: " +
@@ -1205,10 +1214,7 @@ fn make_generic_glue_inner(cx: @local_ctxt, sp: span, t: ty::t,
12051214
p += 1u;
12061215
}
12071216

1208-
// FIXME: Implement some kind of freeze operation in the standard library.
1209-
let lltydescs_frozen = [];
1210-
for lltydesc: ValueRef in lltydescs { lltydescs_frozen += [lltydesc]; }
1211-
fcx.lltydescs = lltydescs_frozen;
1217+
fcx.lltyparams = vec::map_mut(lltydescs, {|d| {desc: d, dicts: none}});
12121218

12131219
let bcx = new_top_block_ctxt(fcx);
12141220
let lltop = bcx.llbb;
@@ -2558,11 +2564,13 @@ fn trans_do_while(cx: @block_ctxt, body: ast::blk, cond: @ast::expr) ->
25582564
ret next_cx;
25592565
}
25602566

2561-
type generic_info =
2562-
{item_type: ty::t,
2563-
static_tis: [option::t<@tydesc_info>],
2564-
tydescs: [ValueRef],
2565-
param_bounds: @[ty::param_bounds]};
2567+
type generic_info = {
2568+
item_type: ty::t,
2569+
static_tis: [option::t<@tydesc_info>],
2570+
tydescs: [ValueRef],
2571+
param_bounds: @[ty::param_bounds],
2572+
origins: option::t<typeck::dict_res>
2573+
};
25662574

25672575
tag lval_kind {
25682576
temporary; //< Temporary value passed by value if of immediate type
@@ -2571,7 +2579,12 @@ tag lval_kind {
25712579
}
25722580
type local_var_result = {val: ValueRef, kind: lval_kind};
25732581
type lval_result = {bcx: @block_ctxt, val: ValueRef, kind: lval_kind};
2574-
tag callee_env { obj_env(ValueRef); null_env; is_closure; }
2582+
tag callee_env {
2583+
null_env;
2584+
is_closure;
2585+
obj_env(ValueRef);
2586+
dict_env(ValueRef, ValueRef);
2587+
}
25752588
type lval_maybe_callee = {bcx: @block_ctxt,
25762589
val: ValueRef,
25772590
kind: lval_kind,
@@ -2630,11 +2643,11 @@ fn lval_static_fn(bcx: @block_ctxt, fn_id: ast::def_id, id: ast::node_id)
26302643
bcx = td.bcx;
26312644
tydescs += [td.val];
26322645
}
2633-
let bounds = ty::lookup_item_type(ccx.tcx, fn_id).bounds;
26342646
gen = some({item_type: tpt.ty,
26352647
static_tis: tis,
26362648
tydescs: tydescs,
2637-
param_bounds: bounds});
2649+
param_bounds: tpt.bounds,
2650+
origins: ccx.dict_map.find(id)});
26382651
}
26392652
ret {bcx: bcx, val: val, kind: owned, env: null_env, generic: gen};
26402653
}
@@ -2843,17 +2856,6 @@ fn expr_is_lval(bcx: @block_ctxt, e: @ast::expr) -> bool {
28432856
ty::expr_is_lval(ccx.method_map, ccx.tcx, e)
28442857
}
28452858

2846-
// This is for impl methods, not obj methods.
2847-
fn trans_method_callee(bcx: @block_ctxt, e: @ast::expr, base: @ast::expr,
2848-
did: ast::def_id) -> lval_maybe_callee {
2849-
let tz = [], tr = [];
2850-
let basety = ty::expr_ty(bcx_tcx(bcx), base);
2851-
let {bcx, val} = trans_arg_expr(bcx, {mode: ast::by_ref, ty: basety},
2852-
type_of_or_i8(bcx, basety), tz, tr, base);
2853-
let val = PointerCast(bcx, val, T_opaque_boxed_closure_ptr(bcx_ccx(bcx)));
2854-
{env: obj_env(val) with lval_static_fn(bcx, did, e.id)}
2855-
}
2856-
28572859
fn trans_callee(bcx: @block_ctxt, e: @ast::expr) -> lval_maybe_callee {
28582860
alt e.node {
28592861
ast::expr_path(p) { ret trans_path(bcx, p, e.id); }
@@ -2862,10 +2864,11 @@ fn trans_callee(bcx: @block_ctxt, e: @ast::expr) -> lval_maybe_callee {
28622864
if !expr_is_lval(bcx, e) {
28632865
alt bcx_ccx(bcx).method_map.find(e.id) {
28642866
some(typeck::method_static(did)) { // An impl method
2865-
ret trans_method_callee(bcx, e, base, did);
2867+
ret trans_impl::trans_static_callee(bcx, e, base, did);
28662868
}
2867-
some(typeck::method_param(_)) {
2868-
fail "not implemented"; // FIXME[impl]
2869+
some(typeck::method_param(iid, off, p, b)) {
2870+
ret trans_impl::trans_dict_callee(
2871+
bcx, e, base, iid, off, p, b);
28692872
}
28702873
none. { // An object method
28712874
let of = trans_object_field(bcx, base, ident);
@@ -2936,7 +2939,7 @@ fn maybe_add_env(bcx: @block_ctxt, c: lval_maybe_callee)
29362939
-> (lval_kind, ValueRef) {
29372940
alt c.env {
29382941
is_closure. { (c.kind, c.val) }
2939-
obj_env(_) {
2942+
obj_env(_) | dict_env(_, _) {
29402943
fail "Taking the value of a method does not work yet (issue #435)";
29412944
}
29422945
null_env. {
@@ -3149,7 +3152,23 @@ fn trans_args(cx: @block_ctxt, llenv: ValueRef,
31493152
alt gen {
31503153
some(g) {
31513154
lazily_emit_all_generic_info_tydesc_glues(cx, g);
3152-
lltydescs = g.tydescs;
3155+
let i = 0u, n_orig = 0u;
3156+
for param in *g.param_bounds {
3157+
lltydescs += [g.tydescs[i]];
3158+
for bound in *param {
3159+
alt bound {
3160+
ty::bound_iface(_) {
3161+
let res = trans_impl::get_dict(
3162+
bcx, option::get(g.origins)[n_orig]);
3163+
lltydescs += [res.val];
3164+
bcx = res.bcx;
3165+
n_orig += 1u;
3166+
}
3167+
_ {}
3168+
}
3169+
}
3170+
i += 1u;
3171+
}
31533172
args = ty::ty_fn_args(tcx, g.item_type);
31543173
retty = ty::ty_fn_ret(tcx, g.item_type);
31553174
}
@@ -3220,12 +3239,13 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
32203239
let bcx = f_res.bcx;
32213240

32223241
let faddr = f_res.val;
3223-
let llenv;
3242+
let llenv, dict_param = none;
32243243
alt f_res.env {
32253244
null_env. {
32263245
llenv = llvm::LLVMGetUndef(T_opaque_boxed_closure_ptr(bcx_ccx(cx)));
32273246
}
32283247
obj_env(e) { llenv = e; }
3248+
dict_env(dict, e) { llenv = e; dict_param = some(dict); }
32293249
is_closure. {
32303250
// It's a closure. Have to fetch the elements
32313251
if f_res.kind == owned {
@@ -3244,6 +3264,7 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
32443264
trans_args(bcx, llenv, f_res.generic, args, fn_expr_ty, dest);
32453265
bcx = args_res.bcx;
32463266
let llargs = args_res.args;
3267+
option::may(dict_param) {|dict| llargs = [dict] + llargs}
32473268
let llretslot = args_res.retslot;
32483269

32493270
/* If the block is terminated,
@@ -3306,8 +3327,7 @@ fn invoke_(bcx: @block_ctxt, llfn: ValueRef, llargs: [ValueRef],
33063327
// cleanups to run
33073328
if bcx.unreachable { ret bcx; }
33083329
let normal_bcx = new_sub_block_ctxt(bcx, "normal return");
3309-
invoker(bcx, llfn, llargs,
3310-
normal_bcx.llbb,
3330+
invoker(bcx, llfn, llargs, normal_bcx.llbb,
33113331
get_landing_pad(bcx, to_zero, to_revoke));
33123332
ret normal_bcx;
33133333
}
@@ -4351,7 +4371,7 @@ fn new_fn_ctxt_w_id(cx: @local_ctxt, sp: span, llfndecl: ValueRef,
43514371
llobjfields: new_int_hash::<ValueRef>(),
43524372
lllocals: new_int_hash::<local_val>(),
43534373
llupvars: new_int_hash::<ValueRef>(),
4354-
mutable lltydescs: [],
4374+
mutable lltyparams: [],
43554375
derived_tydescs: ty::new_ty_hash(),
43564376
id: id,
43574377
ret_style: rstyle,
@@ -4393,10 +4413,22 @@ fn create_llargs_for_fn_args(cx: @fn_ctxt, ty_self: self_arg,
43934413
obj_self(_) {}
43944414
_ {
43954415
for tp in ty_params {
4396-
let llarg = llvm::LLVMGetParam(cx.llfn, arg_n);
4397-
assert (llarg as int != 0);
4398-
cx.lltydescs += [llarg];
4416+
let lltydesc = llvm::LLVMGetParam(cx.llfn, arg_n), dicts = none;
43994417
arg_n += 1u;
4418+
for bound in *fcx_tcx(cx).ty_param_bounds.get(tp.id) {
4419+
alt bound {
4420+
ty::bound_iface(_) {
4421+
let dict = llvm::LLVMGetParam(cx.llfn, arg_n);
4422+
arg_n += 1u;
4423+
dicts = some(alt dicts {
4424+
none. { [dict] }
4425+
some(ds) { ds + [dict] }
4426+
});
4427+
}
4428+
_ {}
4429+
}
4430+
}
4431+
cx.lltyparams += [{desc: lltydesc, dicts: dicts}];
44004432
}
44014433
}
44024434
}
@@ -4485,7 +4517,7 @@ fn populate_fn_ctxt_from_llself(fcx: @fn_ctxt, llself: val_self_pair) {
44854517
let lltyparam: ValueRef =
44864518
GEPi(bcx, obj_typarams, [0, i]);
44874519
lltyparam = Load(bcx, lltyparam);
4488-
fcx.lltydescs += [lltyparam];
4520+
fcx.lltyparams += [{desc: lltyparam, dicts: none}];
44894521
i += 1;
44904522
}
44914523
i = 0;
@@ -5582,7 +5614,8 @@ fn write_abi_version(ccx: @crate_ctxt) {
55825614
fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
55835615
output: str, emap: resolve::exp_map, amap: ast_map::map,
55845616
mut_map: mut::mut_map, copy_map: alias::copy_map,
5585-
last_uses: last_use::last_uses, method_map: typeck::method_map)
5617+
last_uses: last_use::last_uses, method_map: typeck::method_map,
5618+
dict_map: typeck::dict_map)
55865619
-> (ModuleRef, link::link_meta) {
55875620
let sha = std::sha1::mk_sha1();
55885621
let link_meta = link::build_link_meta(sess, *crate, output, sha);
@@ -5659,6 +5692,7 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
56595692
copy_map: copy_map,
56605693
last_uses: last_uses,
56615694
method_map: method_map,
5695+
dict_map: dict_map,
56625696
stats:
56635697
{mutable n_static_tydescs: 0u,
56645698
mutable n_derived_tydescs: 0u,

0 commit comments

Comments
 (0)