From: Marijn Haverbeke Date: Sat, 7 Jan 2012 21:44:14 +0000 (+0100) Subject: First barely-working version of casting to iface X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=7d3f892f3568d6641a39a9fabb8a44b7d0d85a25;p=rust.git First barely-working version of casting to iface Issue #1437 --- diff --git a/src/comp/middle/shape.rs b/src/comp/middle/shape.rs index 43afb88361b..ff760230d93 100644 --- a/src/comp/middle/shape.rs +++ b/src/comp/middle/shape.rs @@ -52,6 +52,7 @@ const shape_var: u8 = 21u8; const shape_uniq: u8 = 22u8; const shape_opaque_closure_ptr: u8 = 23u8; // the closure itself. +const shape_iface: u8 = 24u8; // FIXME: This is a bad API in trans_common. 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], } ty::ty_native_fn(_, _) { s += [shape_u32]; } ty::ty_obj(_) { s += [shape_obj]; } + ty::ty_iface(_, _) { s += [shape_iface]; } ty::ty_res(did, raw_subt, tps) { let subt = ty::substitute_type_params(ccx.tcx, tps, raw_subt); let ri = {did: did, t: subt}; diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index f6539e4f0f3..108f2c5b1c5 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -178,7 +178,8 @@ fn type_of_inner(cx: @crate_ctxt, sp: span, t: ty::t) let nft = native_fn_wrapper_type(cx, sp, [], t); T_fn_pair(cx, nft) } - ty::ty_obj(meths) { cx.rust_object_type } + ty::ty_obj(_) { cx.rust_object_type } + ty::ty_iface(_, _) { T_opaque_iface_ptr(cx) } ty::ty_res(_, sub, tps) { let sub1 = ty::substitute_type_params(cx.tcx, tps, sub); check non_ty_var(cx, sub1); @@ -483,7 +484,9 @@ fn mk_obstack_token(ccx: @crate_ctxt, fcx: @fn_ctxt) -> fn simplify_type(ccx: @crate_ctxt, typ: ty::t) -> ty::t { fn simplifier(ccx: @crate_ctxt, typ: ty::t) -> ty::t { alt ty::struct(ccx.tcx, typ) { - ty::ty_box(_) { ret ty::mk_imm_box(ccx.tcx, ty::mk_nil(ccx.tcx)); } + ty::ty_box(_) | ty::ty_iface(_, _) { + ret ty::mk_imm_box(ccx.tcx, ty::mk_nil(ccx.tcx)); + } ty::ty_uniq(_) { ret ty::mk_imm_uniq(ccx.tcx, ty::mk_nil(ccx.tcx)); } @@ -1386,9 +1389,10 @@ fn make_free_glue(bcx: @block_ctxt, v: ValueRef, t: ty::t) { ty::ty_vec(_) | ty::ty_str. { tvec::make_free_glue(bcx, PointerCast(bcx, v, type_of_1(bcx, t)), t) } - ty::ty_obj(_) { + ty::ty_obj(_) | ty::ty_iface(_, _) { // Call through the obj's own fields-drop glue first. // Then free the body. + // (Same code of ifaces, whose layout is similar) let ccx = bcx_ccx(bcx); let llbox_ty = T_opaque_obj_ptr(ccx); let b = PointerCast(bcx, v, llbox_ty); @@ -1425,13 +1429,14 @@ fn make_drop_glue(bcx: @block_ctxt, v0: ValueRef, t: ty::t) { let ccx = bcx_ccx(bcx); let bcx = alt ty::struct(ccx.tcx, t) { - ty::ty_box(_) { decr_refcnt_maybe_free(bcx, Load(bcx, v0), t) } + ty::ty_box(_) | ty::ty_iface(_, _) { + decr_refcnt_maybe_free(bcx, Load(bcx, v0), t) + } ty::ty_uniq(_) | ty::ty_vec(_) | ty::ty_str. | ty::ty_send_type. { free_ty(bcx, Load(bcx, v0), t) } ty::ty_obj(_) { - let box_cell = - GEPi(bcx, v0, [0, abi::obj_field_box]); + let box_cell = GEPi(bcx, v0, [0, abi::obj_field_box]); decr_refcnt_maybe_free(bcx, Load(bcx, box_cell), t) } ty::ty_res(did, inner, tps) { @@ -1935,22 +1940,22 @@ fn drop_ty(cx: @block_ctxt, v: ValueRef, t: ty::t) -> @block_ctxt { fn drop_ty_immediate(bcx: @block_ctxt, v: ValueRef, t: ty::t) -> @block_ctxt { alt ty::struct(bcx_tcx(bcx), t) { - ty::ty_uniq(_) | ty::ty_vec(_) | ty::ty_str. { - ret free_ty(bcx, v, t); - } - ty::ty_box(_) { ret decr_refcnt_maybe_free(bcx, v, t); } + ty::ty_uniq(_) | ty::ty_vec(_) | ty::ty_str. { free_ty(bcx, v, t) } + ty::ty_box(_) | ty::ty_iface(_, _) { decr_refcnt_maybe_free(bcx, v, t) } } } fn take_ty_immediate(bcx: @block_ctxt, v: ValueRef, t: ty::t) -> result { alt ty::struct(bcx_tcx(bcx), t) { - ty::ty_box(_) { ret rslt(incr_refcnt_of_boxed(bcx, v), v); } + ty::ty_box(_) | ty::ty_iface(_, _) { + rslt(incr_refcnt_of_boxed(bcx, v), v) + } ty::ty_uniq(_) { check trans_uniq::type_is_unique_box(bcx, t); - ret trans_uniq::duplicate(bcx, v, t); + trans_uniq::duplicate(bcx, v, t) } - ty::ty_str. | ty::ty_vec(_) { ret tvec::duplicate(bcx, v, t); } - _ { ret rslt(bcx, v); } + ty::ty_str. | ty::ty_vec(_) { tvec::duplicate(bcx, v, t) } + _ { rslt(bcx, v) } } } @@ -2873,9 +2878,12 @@ fn trans_callee(bcx: @block_ctxt, e: @ast::expr) -> lval_maybe_callee { ret trans_impl::trans_static_callee(bcx, e, base, did); } some(typeck::method_param(iid, off, p, b)) { - ret trans_impl::trans_dict_callee( + ret trans_impl::trans_param_callee( bcx, e, base, iid, off, p, b); } + some(typeck::method_iface(off)) { + ret trans_impl::trans_iface_callee(bcx, e, base, off); + } none. { // An object method let of = trans_object_field(bcx, base, ident); ret {bcx: of.bcx, val: of.mthptr, kind: owned, @@ -3001,10 +3009,14 @@ fn float_cast(bcx: @block_ctxt, lldsttype: TypeRef, llsrctype: TypeRef, fn trans_cast(cx: @block_ctxt, e: @ast::expr, id: ast::node_id, dest: dest) -> @block_ctxt { let ccx = bcx_ccx(cx); + let t_out = node_id_type(ccx, id); + alt ty::struct(ccx.tcx, t_out) { + ty::ty_iface(_, _) { ret trans_impl::trans_cast(cx, e, id, dest); } + _ {} + } let e_res = trans_temp_expr(cx, e); let ll_t_in = val_ty(e_res.val); let t_in = ty::expr_ty(ccx.tcx, e); - let t_out = node_id_type(ccx, id); // Check should be avoidable because it's a cast. // FIXME: Constrain types so as to avoid this check. check (type_has_static_size(ccx, t_out)); diff --git a/src/comp/middle/trans_common.rs b/src/comp/middle/trans_common.rs index 8b99efc337b..72803fd309a 100644 --- a/src/comp/middle/trans_common.rs +++ b/src/comp/middle/trans_common.rs @@ -754,6 +754,11 @@ fn T_obj(cx: @crate_ctxt, n_captured_tydescs: uint) -> TypeRef { fn T_opaque_obj_ptr(cx: @crate_ctxt) -> TypeRef { ret T_obj_ptr(cx, 0u); } +fn T_opaque_iface_ptr(cx: @crate_ctxt) -> TypeRef { + let tdptr = T_ptr(cx.tydesc_type); + T_ptr(T_box(cx, T_struct([tdptr, tdptr, T_i8()]))) +} + fn T_opaque_port_ptr() -> TypeRef { ret T_ptr(T_i8()); } fn T_opaque_chan_ptr() -> TypeRef { ret T_ptr(T_i8()); } diff --git a/src/comp/middle/trans_impl.rs b/src/comp/middle/trans_impl.rs index 284cef0f289..f4d9e58e427 100644 --- a/src/comp/middle/trans_impl.rs +++ b/src/comp/middle/trans_impl.rs @@ -4,7 +4,7 @@ import option::{some, none}; import syntax::{ast, ast_util}; import metadata::csearch; -import back::link; +import back::{link, abi}; import lib::llvm::llvm; import llvm::{ValueRef, TypeRef, LLVMGetParam}; @@ -61,21 +61,20 @@ fn trans_self_arg(bcx: @block_ctxt, base: @ast::expr) -> result { rslt(bcx, PointerCast(bcx, val, T_opaque_cbox_ptr(bcx_ccx(bcx)))) } +// Method callee where the method is statically known fn trans_static_callee(bcx: @block_ctxt, e: @ast::expr, base: @ast::expr, did: ast::def_id) -> lval_maybe_callee { let {bcx, val} = trans_self_arg(bcx, base); {env: obj_env(val) with lval_static_fn(bcx, did, e.id)} } -fn trans_dict_callee(bcx: @block_ctxt, e: @ast::expr, base: @ast::expr, - iface_id: ast::def_id, n_method: uint, - n_param: uint, n_bound: uint) -> lval_maybe_callee { - let tcx = bcx_tcx(bcx); - let {bcx, val} = trans_self_arg(bcx, base); - let dict = option::get(bcx.fcx.lltyparams[n_param].dicts)[n_bound]; +fn trans_vtable_callee(bcx: @block_ctxt, self: ValueRef, dict: ValueRef, + fld_expr: @ast::expr, iface_id: ast::def_id, + n_method: uint) -> lval_maybe_callee { + let bcx = bcx, ccx = bcx_ccx(bcx), tcx = ccx.tcx; let method = ty::iface_methods(tcx, iface_id)[n_method]; - let fty = ty::expr_ty(tcx, e); - let bare_fn_ty = type_of_fn_from_ty(bcx_ccx(bcx), ast_util::dummy_sp(), + let fty = ty::expr_ty(tcx, fld_expr); + let bare_fn_ty = type_of_fn_from_ty(ccx, ast_util::dummy_sp(), fty, *method.tps); let {inputs: bare_inputs, output} = llfn_arg_tys(bare_fn_ty); 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, let generic = none; if vec::len(*method.tps) > 0u { let tydescs = [], tis = []; - let tptys = ty::node_id_to_type_params(tcx, e.id); + let tptys = ty::node_id_to_type_params(tcx, fld_expr.id); for t in vec::tail_n(tptys, vec::len(tptys) - vec::len(*method.tps)) { - // TODO: Doesn't always escape. let ti = none; let td = get_tydesc(bcx, t, true, tps_normal, ti).result; tis += [ti]; @@ -98,13 +96,40 @@ fn trans_dict_callee(bcx: @block_ctxt, e: @ast::expr, base: @ast::expr, static_tis: tis, tydescs: tydescs, param_bounds: method.tps, - origins: bcx_ccx(bcx).dict_map.find(e.id)}); + origins: bcx_ccx(bcx).dict_map.find(fld_expr.id)}); } {bcx: bcx, val: mptr, kind: owned, - env: dict_env(dict, val), + env: dict_env(dict, self), generic: generic} } +// Method callee where the dict comes from a type param +fn trans_param_callee(bcx: @block_ctxt, fld_expr: @ast::expr, + base: @ast::expr, iface_id: ast::def_id, n_method: uint, + n_param: uint, n_bound: uint) -> lval_maybe_callee { + let {bcx, val} = trans_self_arg(bcx, base); + let dict = option::get(bcx.fcx.lltyparams[n_param].dicts)[n_bound]; + trans_vtable_callee(bcx, val, dict, fld_expr, iface_id, n_method) +} + +// Method callee where the dict comes from a boxed iface +fn trans_iface_callee(bcx: @block_ctxt, fld_expr: @ast::expr, base: @ast::expr, + n_method: uint) + -> lval_maybe_callee { + let tcx = bcx_tcx(bcx); + let {bcx, val} = trans_temp_expr(bcx, base); + let box_body = GEPi(bcx, val, [0, abi::box_rc_field_body]); + let dict = Load(bcx, PointerCast(bcx, GEPi(bcx, box_body, [0, 1]), + T_ptr(T_ptr(T_dict())))); + // FIXME[impl] I doubt this is alignment-safe + let self = PointerCast(bcx, GEPi(bcx, box_body, [0, 2]), + T_opaque_cbox_ptr(bcx_ccx(bcx))); + let iface_id = alt ty::struct(tcx, ty::expr_ty(tcx, base)) { + ty::ty_iface(did, _) { did } + }; + trans_vtable_callee(bcx, self, dict, fld_expr, iface_id, n_method) +} + fn llfn_arg_tys(ft: TypeRef) -> {inputs: [TypeRef], output: TypeRef} { let out_ty = llvm::LLVMGetReturnType(ft); let n_args = llvm::LLVMCountParamTypes(ft); @@ -274,3 +299,22 @@ fn get_dict_ptrs(bcx: @block_ctxt, origin: typeck::dict_origin) } } } + +fn trans_cast(bcx: @block_ctxt, val: @ast::expr, id: ast::node_id, dest: dest) + -> @block_ctxt { + let ccx = bcx_ccx(bcx), tcx = ccx.tcx; + let val_ty = ty::expr_ty(tcx, val); + let {bcx, val: dict} = get_dict(bcx, ccx.dict_map.get(id)[0]); + let body_ty = ty::mk_tup(tcx, [ty::mk_type(tcx), ty::mk_type(tcx), + val_ty]); + let ti = none; + let {bcx, val: tydesc} = get_tydesc(bcx, body_ty, true, + tps_normal, ti).result; + lazily_emit_all_tydesc_glue(bcx, ti); + let {bcx, box, body: box_body} = trans_malloc_boxed(bcx, body_ty); + Store(bcx, tydesc, GEPi(bcx, box_body, [0, 0])); + Store(bcx, PointerCast(bcx, dict, T_ptr(ccx.tydesc_type)), + GEPi(bcx, box_body, [0, 1])); + bcx = trans_expr_save_in(bcx, val, GEPi(bcx, box_body, [0, 2])); + store_in_dest(bcx, PointerCast(bcx, box, T_opaque_iface_ptr(ccx)), dest) +} diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 4c7c8942f28..42225aa2aca 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -909,7 +909,7 @@ fn get_element_type(cx: ctxt, ty: t, i: uint) -> t { pure fn type_is_boxed(cx: ctxt, ty: t) -> bool { alt struct(cx, ty) { - ty_box(_) { ret true; } + ty_box(_) | ty_iface(_, _) { ret true; } _ { ret false; } } } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 075c0dbe2a8..540bae5b32b 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -18,14 +18,15 @@ import option::{none, some}; import syntax::print::pprust::*; -export check_crate, method_map, method_origin, method_static, method_param; +export check_crate; +export method_map, method_origin, method_static, method_param, method_iface; export dict_map, dict_res, dict_origin, dict_static, dict_param; tag method_origin { method_static(ast::def_id); // iface id, method num, param num, bound num method_param(ast::def_id, uint, uint, uint); - method_iface; + method_iface(uint); } type method_map = hashmap; @@ -1575,13 +1576,15 @@ fn lookup_method(fcx: @fn_ctxt, isc: resolve::iscopes, ret none; } ty::ty_iface(did, tps) { + let i = 0u; for m in *ty::iface_methods(tcx, did) { if m.ident == name { ret some({method_ty: ty::mk_fn(tcx, m.fty), n_tps: vec::len(*m.tps), substs: tps, - origin: method_iface}); + origin: method_iface(i)}); } + i += 1u; } } _ {}