Skip to content

Commit 7d3f892

Browse files
committed
First barely-working version of casting to iface
Issue #1437
1 parent a161371 commit 7d3f892

File tree

6 files changed

+99
-33
lines changed

6 files changed

+99
-33
lines changed

src/comp/middle/shape.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ const shape_res: u8 = 20u8;
5252
const shape_var: u8 = 21u8;
5353
const shape_uniq: u8 = 22u8;
5454
const shape_opaque_closure_ptr: u8 = 23u8; // the closure itself.
55+
const shape_iface: u8 = 24u8;
5556

5657
// FIXME: This is a bad API in trans_common.
5758
fn C_u8(n: u8) -> ValueRef { ret trans_common::C_u8(n as uint); }
@@ -387,6 +388,7 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint],
387388
}
388389
ty::ty_native_fn(_, _) { s += [shape_u32]; }
389390
ty::ty_obj(_) { s += [shape_obj]; }
391+
ty::ty_iface(_, _) { s += [shape_iface]; }
390392
ty::ty_res(did, raw_subt, tps) {
391393
let subt = ty::substitute_type_params(ccx.tcx, tps, raw_subt);
392394
let ri = {did: did, t: subt};

src/comp/middle/trans.rs

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,8 @@ fn type_of_inner(cx: @crate_ctxt, sp: span, t: ty::t)
178178
let nft = native_fn_wrapper_type(cx, sp, [], t);
179179
T_fn_pair(cx, nft)
180180
}
181-
ty::ty_obj(meths) { cx.rust_object_type }
181+
ty::ty_obj(_) { cx.rust_object_type }
182+
ty::ty_iface(_, _) { T_opaque_iface_ptr(cx) }
182183
ty::ty_res(_, sub, tps) {
183184
let sub1 = ty::substitute_type_params(cx.tcx, tps, sub);
184185
check non_ty_var(cx, sub1);
@@ -483,7 +484,9 @@ fn mk_obstack_token(ccx: @crate_ctxt, fcx: @fn_ctxt) ->
483484
fn simplify_type(ccx: @crate_ctxt, typ: ty::t) -> ty::t {
484485
fn simplifier(ccx: @crate_ctxt, typ: ty::t) -> ty::t {
485486
alt ty::struct(ccx.tcx, typ) {
486-
ty::ty_box(_) { ret ty::mk_imm_box(ccx.tcx, ty::mk_nil(ccx.tcx)); }
487+
ty::ty_box(_) | ty::ty_iface(_, _) {
488+
ret ty::mk_imm_box(ccx.tcx, ty::mk_nil(ccx.tcx));
489+
}
487490
ty::ty_uniq(_) {
488491
ret ty::mk_imm_uniq(ccx.tcx, ty::mk_nil(ccx.tcx));
489492
}
@@ -1386,9 +1389,10 @@ fn make_free_glue(bcx: @block_ctxt, v: ValueRef, t: ty::t) {
13861389
ty::ty_vec(_) | ty::ty_str. {
13871390
tvec::make_free_glue(bcx, PointerCast(bcx, v, type_of_1(bcx, t)), t)
13881391
}
1389-
ty::ty_obj(_) {
1392+
ty::ty_obj(_) | ty::ty_iface(_, _) {
13901393
// Call through the obj's own fields-drop glue first.
13911394
// Then free the body.
1395+
// (Same code of ifaces, whose layout is similar)
13921396
let ccx = bcx_ccx(bcx);
13931397
let llbox_ty = T_opaque_obj_ptr(ccx);
13941398
let b = PointerCast(bcx, v, llbox_ty);
@@ -1425,13 +1429,14 @@ fn make_drop_glue(bcx: @block_ctxt, v0: ValueRef, t: ty::t) {
14251429
let ccx = bcx_ccx(bcx);
14261430
let bcx =
14271431
alt ty::struct(ccx.tcx, t) {
1428-
ty::ty_box(_) { decr_refcnt_maybe_free(bcx, Load(bcx, v0), t) }
1432+
ty::ty_box(_) | ty::ty_iface(_, _) {
1433+
decr_refcnt_maybe_free(bcx, Load(bcx, v0), t)
1434+
}
14291435
ty::ty_uniq(_) | ty::ty_vec(_) | ty::ty_str. | ty::ty_send_type. {
14301436
free_ty(bcx, Load(bcx, v0), t)
14311437
}
14321438
ty::ty_obj(_) {
1433-
let box_cell =
1434-
GEPi(bcx, v0, [0, abi::obj_field_box]);
1439+
let box_cell = GEPi(bcx, v0, [0, abi::obj_field_box]);
14351440
decr_refcnt_maybe_free(bcx, Load(bcx, box_cell), t)
14361441
}
14371442
ty::ty_res(did, inner, tps) {
@@ -1935,22 +1940,22 @@ fn drop_ty(cx: @block_ctxt, v: ValueRef, t: ty::t) -> @block_ctxt {
19351940

19361941
fn drop_ty_immediate(bcx: @block_ctxt, v: ValueRef, t: ty::t) -> @block_ctxt {
19371942
alt ty::struct(bcx_tcx(bcx), t) {
1938-
ty::ty_uniq(_) | ty::ty_vec(_) | ty::ty_str. {
1939-
ret free_ty(bcx, v, t);
1940-
}
1941-
ty::ty_box(_) { ret decr_refcnt_maybe_free(bcx, v, t); }
1943+
ty::ty_uniq(_) | ty::ty_vec(_) | ty::ty_str. { free_ty(bcx, v, t) }
1944+
ty::ty_box(_) | ty::ty_iface(_, _) { decr_refcnt_maybe_free(bcx, v, t) }
19421945
}
19431946
}
19441947

19451948
fn take_ty_immediate(bcx: @block_ctxt, v: ValueRef, t: ty::t) -> result {
19461949
alt ty::struct(bcx_tcx(bcx), t) {
1947-
ty::ty_box(_) { ret rslt(incr_refcnt_of_boxed(bcx, v), v); }
1950+
ty::ty_box(_) | ty::ty_iface(_, _) {
1951+
rslt(incr_refcnt_of_boxed(bcx, v), v)
1952+
}
19481953
ty::ty_uniq(_) {
19491954
check trans_uniq::type_is_unique_box(bcx, t);
1950-
ret trans_uniq::duplicate(bcx, v, t);
1955+
trans_uniq::duplicate(bcx, v, t)
19511956
}
1952-
ty::ty_str. | ty::ty_vec(_) { ret tvec::duplicate(bcx, v, t); }
1953-
_ { ret rslt(bcx, v); }
1957+
ty::ty_str. | ty::ty_vec(_) { tvec::duplicate(bcx, v, t) }
1958+
_ { rslt(bcx, v) }
19541959
}
19551960
}
19561961

@@ -2873,9 +2878,12 @@ fn trans_callee(bcx: @block_ctxt, e: @ast::expr) -> lval_maybe_callee {
28732878
ret trans_impl::trans_static_callee(bcx, e, base, did);
28742879
}
28752880
some(typeck::method_param(iid, off, p, b)) {
2876-
ret trans_impl::trans_dict_callee(
2881+
ret trans_impl::trans_param_callee(
28772882
bcx, e, base, iid, off, p, b);
28782883
}
2884+
some(typeck::method_iface(off)) {
2885+
ret trans_impl::trans_iface_callee(bcx, e, base, off);
2886+
}
28792887
none. { // An object method
28802888
let of = trans_object_field(bcx, base, ident);
28812889
ret {bcx: of.bcx, val: of.mthptr, kind: owned,
@@ -3001,10 +3009,14 @@ fn float_cast(bcx: @block_ctxt, lldsttype: TypeRef, llsrctype: TypeRef,
30013009
fn trans_cast(cx: @block_ctxt, e: @ast::expr, id: ast::node_id,
30023010
dest: dest) -> @block_ctxt {
30033011
let ccx = bcx_ccx(cx);
3012+
let t_out = node_id_type(ccx, id);
3013+
alt ty::struct(ccx.tcx, t_out) {
3014+
ty::ty_iface(_, _) { ret trans_impl::trans_cast(cx, e, id, dest); }
3015+
_ {}
3016+
}
30043017
let e_res = trans_temp_expr(cx, e);
30053018
let ll_t_in = val_ty(e_res.val);
30063019
let t_in = ty::expr_ty(ccx.tcx, e);
3007-
let t_out = node_id_type(ccx, id);
30083020
// Check should be avoidable because it's a cast.
30093021
// FIXME: Constrain types so as to avoid this check.
30103022
check (type_has_static_size(ccx, t_out));

src/comp/middle/trans_common.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,11 @@ fn T_obj_ptr(cx: @crate_ctxt, n_captured_tydescs: uint) -> TypeRef {
754754

755755
fn T_opaque_obj_ptr(cx: @crate_ctxt) -> TypeRef { ret T_obj_ptr(cx, 0u); }
756756

757+
fn T_opaque_iface_ptr(cx: @crate_ctxt) -> TypeRef {
758+
let tdptr = T_ptr(cx.tydesc_type);
759+
T_ptr(T_box(cx, T_struct([tdptr, tdptr, T_i8()])))
760+
}
761+
757762
fn T_opaque_port_ptr() -> TypeRef { ret T_ptr(T_i8()); }
758763

759764
fn T_opaque_chan_ptr() -> TypeRef { ret T_ptr(T_i8()); }

src/comp/middle/trans_impl.rs

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import trans_build::*;
44
import option::{some, none};
55
import syntax::{ast, ast_util};
66
import metadata::csearch;
7-
import back::link;
7+
import back::{link, abi};
88
import lib::llvm::llvm;
99
import llvm::{ValueRef, TypeRef, LLVMGetParam};
1010

@@ -61,21 +61,20 @@ fn trans_self_arg(bcx: @block_ctxt, base: @ast::expr) -> result {
6161
rslt(bcx, PointerCast(bcx, val, T_opaque_cbox_ptr(bcx_ccx(bcx))))
6262
}
6363

64+
// Method callee where the method is statically known
6465
fn trans_static_callee(bcx: @block_ctxt, e: @ast::expr, base: @ast::expr,
6566
did: ast::def_id) -> lval_maybe_callee {
6667
let {bcx, val} = trans_self_arg(bcx, base);
6768
{env: obj_env(val) with lval_static_fn(bcx, did, e.id)}
6869
}
6970

70-
fn trans_dict_callee(bcx: @block_ctxt, e: @ast::expr, base: @ast::expr,
71-
iface_id: ast::def_id, n_method: uint,
72-
n_param: uint, n_bound: uint) -> lval_maybe_callee {
73-
let tcx = bcx_tcx(bcx);
74-
let {bcx, val} = trans_self_arg(bcx, base);
75-
let dict = option::get(bcx.fcx.lltyparams[n_param].dicts)[n_bound];
71+
fn trans_vtable_callee(bcx: @block_ctxt, self: ValueRef, dict: ValueRef,
72+
fld_expr: @ast::expr, iface_id: ast::def_id,
73+
n_method: uint) -> lval_maybe_callee {
74+
let bcx = bcx, ccx = bcx_ccx(bcx), tcx = ccx.tcx;
7675
let method = ty::iface_methods(tcx, iface_id)[n_method];
77-
let fty = ty::expr_ty(tcx, e);
78-
let bare_fn_ty = type_of_fn_from_ty(bcx_ccx(bcx), ast_util::dummy_sp(),
76+
let fty = ty::expr_ty(tcx, fld_expr);
77+
let bare_fn_ty = type_of_fn_from_ty(ccx, ast_util::dummy_sp(),
7978
fty, *method.tps);
8079
let {inputs: bare_inputs, output} = llfn_arg_tys(bare_fn_ty);
8180
let fn_ty = T_fn([val_ty(dict)] + bare_inputs, output);
@@ -85,9 +84,8 @@ fn trans_dict_callee(bcx: @block_ctxt, e: @ast::expr, base: @ast::expr,
8584
let generic = none;
8685
if vec::len(*method.tps) > 0u {
8786
let tydescs = [], tis = [];
88-
let tptys = ty::node_id_to_type_params(tcx, e.id);
87+
let tptys = ty::node_id_to_type_params(tcx, fld_expr.id);
8988
for t in vec::tail_n(tptys, vec::len(tptys) - vec::len(*method.tps)) {
90-
// TODO: Doesn't always escape.
9189
let ti = none;
9290
let td = get_tydesc(bcx, t, true, tps_normal, ti).result;
9391
tis += [ti];
@@ -98,13 +96,40 @@ fn trans_dict_callee(bcx: @block_ctxt, e: @ast::expr, base: @ast::expr,
9896
static_tis: tis,
9997
tydescs: tydescs,
10098
param_bounds: method.tps,
101-
origins: bcx_ccx(bcx).dict_map.find(e.id)});
99+
origins: bcx_ccx(bcx).dict_map.find(fld_expr.id)});
102100
}
103101
{bcx: bcx, val: mptr, kind: owned,
104-
env: dict_env(dict, val),
102+
env: dict_env(dict, self),
105103
generic: generic}
106104
}
107105

106+
// Method callee where the dict comes from a type param
107+
fn trans_param_callee(bcx: @block_ctxt, fld_expr: @ast::expr,
108+
base: @ast::expr, iface_id: ast::def_id, n_method: uint,
109+
n_param: uint, n_bound: uint) -> lval_maybe_callee {
110+
let {bcx, val} = trans_self_arg(bcx, base);
111+
let dict = option::get(bcx.fcx.lltyparams[n_param].dicts)[n_bound];
112+
trans_vtable_callee(bcx, val, dict, fld_expr, iface_id, n_method)
113+
}
114+
115+
// Method callee where the dict comes from a boxed iface
116+
fn trans_iface_callee(bcx: @block_ctxt, fld_expr: @ast::expr, base: @ast::expr,
117+
n_method: uint)
118+
-> lval_maybe_callee {
119+
let tcx = bcx_tcx(bcx);
120+
let {bcx, val} = trans_temp_expr(bcx, base);
121+
let box_body = GEPi(bcx, val, [0, abi::box_rc_field_body]);
122+
let dict = Load(bcx, PointerCast(bcx, GEPi(bcx, box_body, [0, 1]),
123+
T_ptr(T_ptr(T_dict()))));
124+
// FIXME[impl] I doubt this is alignment-safe
125+
let self = PointerCast(bcx, GEPi(bcx, box_body, [0, 2]),
126+
T_opaque_cbox_ptr(bcx_ccx(bcx)));
127+
let iface_id = alt ty::struct(tcx, ty::expr_ty(tcx, base)) {
128+
ty::ty_iface(did, _) { did }
129+
};
130+
trans_vtable_callee(bcx, self, dict, fld_expr, iface_id, n_method)
131+
}
132+
108133
fn llfn_arg_tys(ft: TypeRef) -> {inputs: [TypeRef], output: TypeRef} {
109134
let out_ty = llvm::LLVMGetReturnType(ft);
110135
let n_args = llvm::LLVMCountParamTypes(ft);
@@ -274,3 +299,22 @@ fn get_dict_ptrs(bcx: @block_ctxt, origin: typeck::dict_origin)
274299
}
275300
}
276301
}
302+
303+
fn trans_cast(bcx: @block_ctxt, val: @ast::expr, id: ast::node_id, dest: dest)
304+
-> @block_ctxt {
305+
let ccx = bcx_ccx(bcx), tcx = ccx.tcx;
306+
let val_ty = ty::expr_ty(tcx, val);
307+
let {bcx, val: dict} = get_dict(bcx, ccx.dict_map.get(id)[0]);
308+
let body_ty = ty::mk_tup(tcx, [ty::mk_type(tcx), ty::mk_type(tcx),
309+
val_ty]);
310+
let ti = none;
311+
let {bcx, val: tydesc} = get_tydesc(bcx, body_ty, true,
312+
tps_normal, ti).result;
313+
lazily_emit_all_tydesc_glue(bcx, ti);
314+
let {bcx, box, body: box_body} = trans_malloc_boxed(bcx, body_ty);
315+
Store(bcx, tydesc, GEPi(bcx, box_body, [0, 0]));
316+
Store(bcx, PointerCast(bcx, dict, T_ptr(ccx.tydesc_type)),
317+
GEPi(bcx, box_body, [0, 1]));
318+
bcx = trans_expr_save_in(bcx, val, GEPi(bcx, box_body, [0, 2]));
319+
store_in_dest(bcx, PointerCast(bcx, box, T_opaque_iface_ptr(ccx)), dest)
320+
}

src/comp/middle/ty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -909,7 +909,7 @@ pure fn type_is_box(cx: ctxt, ty: t) -> bool {
909909

910910
pure fn type_is_boxed(cx: ctxt, ty: t) -> bool {
911911
alt struct(cx, ty) {
912-
ty_box(_) { ret true; }
912+
ty_box(_) | ty_iface(_, _) { ret true; }
913913
_ { ret false; }
914914
}
915915
}

src/comp/middle/typeck.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@ import std::map::{hashmap, new_int_hash};
1818
import option::{none, some};
1919
import syntax::print::pprust::*;
2020

21-
export check_crate, method_map, method_origin, method_static, method_param;
21+
export check_crate;
22+
export method_map, method_origin, method_static, method_param, method_iface;
2223
export dict_map, dict_res, dict_origin, dict_static, dict_param;
2324

2425
tag method_origin {
2526
method_static(ast::def_id);
2627
// iface id, method num, param num, bound num
2728
method_param(ast::def_id, uint, uint, uint);
28-
method_iface;
29+
method_iface(uint);
2930
}
3031
type method_map = hashmap<ast::node_id, method_origin>;
3132

@@ -1575,13 +1576,15 @@ fn lookup_method(fcx: @fn_ctxt, isc: resolve::iscopes,
15751576
ret none;
15761577
}
15771578
ty::ty_iface(did, tps) {
1579+
let i = 0u;
15781580
for m in *ty::iface_methods(tcx, did) {
15791581
if m.ident == name {
15801582
ret some({method_ty: ty::mk_fn(tcx, m.fty),
15811583
n_tps: vec::len(*m.tps),
15821584
substs: tps,
1583-
origin: method_iface});
1585+
origin: method_iface(i)});
15841586
}
1587+
i += 1u;
15851588
}
15861589
}
15871590
_ {}

0 commit comments

Comments
 (0)