Skip to content

Commit d9f452a

Browse files
committed
Some work on supporting forwarding slots in vtables (issue #539).
1 parent 523a088 commit d9f452a

File tree

1 file changed

+70
-42
lines changed

1 file changed

+70
-42
lines changed

src/comp/middle/trans.rs

Lines changed: 70 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6519,17 +6519,20 @@ fn recv_val(&@block_ctxt cx, ValueRef to, &@ast::expr from, &ty::t unit_ty,
65196519
// itself.
65206520
fn trans_anon_obj(@block_ctxt bcx, &span sp, &ast::anon_obj anon_obj,
65216521
&vec[ast::ty_param] ty_params, ast::node_id oid,
6522-
ast::node_id id) -> result {
6522+
ast::node_id type_id) -> result {
65236523

65246524
// Right now, we're assuming that anon objs don't take ty params, even
65256525
// though the AST supports it. It's nonsensical to write an expression
65266526
// like "obj[T](){ ... with ... }", since T is never instantiated;
6527-
// nevertheless, such an expression will parse. FIXME for the future:
6528-
// support typarams (issue #n).
6527+
// nevertheless, such an expression will parse. Idea for the future:
6528+
// support typarams.
65296529

65306530
assert (vec::len(ty_params) == 0u);
65316531
auto ccx = bcx.fcx.lcx.ccx;
65326532

6533+
// Fields.
6534+
// FIXME (part of issue #538): Where do we fill in the field *values* from
6535+
// the outer object?
65336536
let vec[ast::anon_obj_field] additional_fields = [];
65346537
let vec[result] additional_field_vals = [];
65356538
let vec[ty::t] additional_field_tys = [];
@@ -6544,63 +6547,86 @@ fn trans_anon_obj(@block_ctxt bcx, &span sp, &ast::anon_obj anon_obj,
65446547
}
65456548
}
65466549

6547-
// If with_obj (the object being extended) exists, translate it, producing
6548-
// a result.
6549-
let option::t[result] with_obj_val = none;
6550-
let ty::t with_obj_ty = ty::mk_type(ccx.tcx);
6551-
alt (anon_obj.with_obj) {
6552-
case (none) { }
6553-
case (some(?e)) {
6554-
// Translating with_obj returns a ValueRef (pointer to a 2-word
6555-
// value) wrapped in a result.
6556-
with_obj_val = some[result](trans_expr(bcx, e));
6557-
with_obj_ty = ty::expr_ty(ccx.tcx, e);
6558-
}
6559-
}
6560-
// FIXME (part of issue #538): much of the following code is copypasta
6561-
// from trans_obj for translating the anonymous wrapper object.
6562-
// Eventually we might want to abstract this code out of trans_anon_obj
6563-
// and trans_obj.
6550+
// Get the type of the eventual entire anonymous object, possibly with
6551+
// extensions.
6552+
auto outer_obj_ty = ty::node_id_to_type(ccx.tcx, type_id);
6553+
auto llouter_obj_ty = type_of(ccx, sp, outer_obj_ty);
65646554

6565-
auto self_ty = ty::node_id_to_type(ccx.tcx, id);
6566-
auto llself_ty = type_of(ccx, sp, self_ty);
65676555
// Allocate the object that we're going to return. It's a two-word pair
65686556
// containing a vtable pointer and a body pointer.
6557+
auto pair = alloca(bcx, llouter_obj_ty);
65696558

6570-
auto pair = alloca(bcx, llself_ty);
65716559
// Grab onto the first and second elements of the pair.
65726560
// abi::obj_field_vtbl and abi::obj_field_box simply specify words 0 and 1
65736561
// of 'pair'.
6574-
65756562
auto pair_vtbl =
65766563
bcx.build.GEP(pair, [C_int(0), C_int(abi::obj_field_vtbl)]);
65776564
auto pair_box =
65786565
bcx.build.GEP(pair, [C_int(0), C_int(abi::obj_field_box)]);
6579-
// Make a vtable for the outer object. create_vtbl() wants an ast::_obj
6580-
// and all we have is an ast::anon_obj, so we need to roll our own.
65816566

6582-
fn anon_obj_field_to_obj_field(&ast::anon_obj_field f) -> ast::obj_field {
6567+
// Create a vtable for the anonymous object.
6568+
6569+
// create_vtbl() wants an ast::_obj and all we have is an ast::anon_obj,
6570+
// so we need to roll our own.
6571+
fn anon_obj_field_to_obj_field(&ast::anon_obj_field f)
6572+
-> ast::obj_field {
65836573
ret rec(mut=f.mut, ty=f.ty, ident=f.ident, id=f.id);
65846574
}
65856575
let ast::_obj wrapper_obj = rec(
6586-
fields = vec::map(anon_obj_field_to_obj_field, additional_fields),
6576+
fields = vec::map(anon_obj_field_to_obj_field,
6577+
additional_fields),
65876578
methods = anon_obj.methods,
65886579
dtor = none[@ast::method]);
6589-
auto vtbl = create_vtbl(bcx.fcx.lcx, llself_ty, self_ty, wrapper_obj,
6590-
ty_params);
65916580

6592-
bcx.build.Store(vtbl, pair_vtbl);
6593-
// FIXME (part of issue #538): Where do we fill in the field *values* from
6594-
// the outer object?
65956581

6596-
// FIXME (part of issue #539): This vtable needs to contain "forwarding
6597-
// slots" for the methods that exist in the with_obj, as well. How do we
6598-
// do that?
6582+
// If with_obj (the object being extended) exists, translate it, producing
6583+
// a result.
6584+
let option::t[result] with_obj_val = none;
6585+
let ty::t with_obj_ty = ty::mk_type(ccx.tcx);
6586+
let TypeRef llwith_obj_ty;
6587+
auto vtbl;
6588+
alt (anon_obj.with_obj) {
6589+
case (none) {
6590+
// If there's no with_obj -- that is, if we aren't extending our
6591+
// object with any fields -- then we just pass the outer object to
6592+
// create_vtbl(). This vtable won't need to have any forwarding
6593+
// slots.
6594+
vtbl = create_vtbl(bcx.fcx.lcx, llouter_obj_ty, outer_obj_ty,
6595+
wrapper_obj, ty_params, none);
6596+
}
6597+
case (some(?e)) {
6598+
// Translating with_obj returns a ValueRef (pointer to a 2-word
6599+
// value) wrapped in a result.
6600+
with_obj_val = some[result](trans_expr(bcx, e));
6601+
6602+
// TODO: What makes more sense to get the type of an expr --
6603+
// calling ty::expr_ty(ccx.tcx, e) on it or calling
6604+
// ty::node_id_to_type(ccx.tcx, id) on its id?
6605+
with_obj_ty = ty::expr_ty(ccx.tcx, e);
6606+
//with_obj_ty = ty::node_id_to_type(ccx.tcx, e.id);
6607+
6608+
llwith_obj_ty = type_of(ccx, sp, with_obj_ty);
6609+
6610+
// If there's a with_obj, we pass it as the main argument to
6611+
// create_vtbl(), but we're also passing along the additional
6612+
// methods as the last argument. Part of what create_vtbl() will
6613+
// do is take the set difference of methods defined on the
6614+
// original and methods being added. For every method defined on
6615+
// the original that does *not* have one with a matching name and
6616+
// type being added, we'll need to create a forwarding slot. And,
6617+
// of course, we need to create a normal vtable entry for every
6618+
// method being added.
6619+
vtbl = create_vtbl(bcx.fcx.lcx, llwith_obj_ty, with_obj_ty,
6620+
wrapper_obj, ty_params,
6621+
some(anon_obj.methods));
6622+
}
6623+
}
6624+
6625+
bcx.build.Store(vtbl, pair_vtbl);
65996626

66006627
// Next we have to take care of the other half of the pair we're
66016628
// returning: a boxed (reference-counted) tuple containing a tydesc,
66026629
// typarams, fields, and a pointer to our with_obj.
6603-
66046630
let TypeRef llbox_ty = T_opaque_obj_ptr(ccx.tn);
66056631

66066632
if (vec::len[ast::ty_param](ty_params) == 0u &&
@@ -7330,11 +7356,13 @@ fn trans_fn(@local_ctxt cx, &span sp, &ast::_fn f, ValueRef llfndecl,
73307356
finish_fn(fcx, lltop);
73317357
}
73327358

7333-
73347359
// Create a vtable for an object being translated. Returns a pointer into
73357360
// read-only memory.
73367361
fn create_vtbl(@local_ctxt cx, TypeRef llself_ty, ty::t self_ty,
7337-
&ast::_obj ob, &vec[ast::ty_param] ty_params) -> ValueRef {
7362+
&ast::_obj ob, &vec[ast::ty_param] ty_params,
7363+
option::t[vec[@ast::method]] additional_methods) -> ValueRef {
7364+
// FIXME (issue #539): Implement forwarding slots.
7365+
73387366
auto dtor = C_null(T_ptr(T_i8()));
73397367
alt (ob.dtor) {
73407368
case (some(?d)) {
@@ -7364,10 +7392,10 @@ fn create_vtbl(@local_ctxt cx, TypeRef llself_ty, ty::t self_ty,
73647392
let str s = mangle_internal_name_by_path(mcx.ccx, mcx.path);
73657393
let ValueRef llfn =
73667394
decl_internal_fastcall_fn(cx.ccx.llmod, s, llfnty);
7367-
// Every method on an object gets its def_id inserted into the
7395+
7396+
// Every method on an object gets its node_id inserted into the
73687397
// crate-wide item_ids map, together with the ValueRef that points to
73697398
// where that method's definition will be in the executable.
7370-
73717399
cx.ccx.item_ids.insert(m.node.id, llfn);
73727400
cx.ccx.item_symbols.insert(m.node.id, s);
73737401
trans_fn(mcx, m.span, m.node.meth, llfn,
@@ -7459,7 +7487,7 @@ fn trans_obj(@local_ctxt cx, &span sp, &ast::_obj ob, ast::node_id ctor_id,
74597487
// creating and will contain ValueRefs for all of this object's methods.
74607488
// create_vtbl returns a pointer to the vtable, which we store.
74617489

7462-
auto vtbl = create_vtbl(cx, llself_ty, self_ty, ob, ty_params);
7490+
auto vtbl = create_vtbl(cx, llself_ty, self_ty, ob, ty_params, none);
74637491
bcx.build.Store(vtbl, pair_vtbl);
74647492
// Next we have to take care of the other half of the pair we're
74657493
// returning: a boxed (reference-counted) tuple containing a tydesc,

0 commit comments

Comments
 (0)