Skip to content

Commit 9c08e14

Browse files
committed
---
yaml --- r: 2928 b: refs/heads/master c: dcf7fbf h: refs/heads/master v: v3
1 parent 7906da7 commit 9c08e14

File tree

2 files changed

+65
-32
lines changed

2 files changed

+65
-32
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: cb4c969ba6ec61007ac1bbdaeed7eb5f21859949
2+
refs/heads/master: dcf7fbf833130a046c41d58a26567e39a6c001ce

trunk/src/comp/middle/trans.rs

Lines changed: 64 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,8 @@ state type fn_ctxt = rec(
160160
// The three implicit arguments that arrive in the function we're
161161
// creating. For instance, foo(int, int) is really foo(ret*, task*, env*,
162162
// int, int). These are also available via llvm::LLVMGetParam(llfn, uint)
163-
// where uint = 2, 0, 1 respectively, but we unpack them here for
164-
// convenience.
163+
// where uint = 1, 2, 0 respectively, but we unpack them into these fields
164+
// for convenience.
165165
ValueRef lltaskptr,
166166
ValueRef llenv,
167167
ValueRef llretptr,
@@ -7000,6 +7000,7 @@ fn trans_fn(@local_ctxt cx, &span sp, &ast::_fn f, ast::def_id fid,
70007000
&vec[ast::ty_param] ty_params, &ast::ann ann) {
70017001
auto llfndecl = cx.ccx.item_ids.get(fid);
70027002

7003+
// Set up arguments to the function.
70037004
auto fcx = new_fn_ctxt(cx, sp, llfndecl);
70047005
create_llargs_for_fn_args(fcx, f.proto,
70057006
ty_self, ret_ty_of_fn(cx.ccx, ann),
@@ -7018,9 +7019,10 @@ fn trans_fn(@local_ctxt cx, &span sp, &ast::_fn f, ast::def_id fid,
70187019
auto arg_tys = arg_tys_of_fn(fcx.lcx.ccx, ann);
70197020
copy_args_to_allocas(fcx, f.decl.inputs, arg_tys);
70207021

7022+
// Create the first basic block in the function and keep a handle on it to
7023+
// pass to finish_fn later.
70217024
auto bcx = new_top_block_ctxt(fcx);
70227025
add_cleanups_for_args(bcx, f.decl.inputs, arg_tys);
7023-
70247026
auto lltop = bcx.llbb;
70257027

70267028
auto block_ty = node_ann_type(cx.ccx, f.body.node.a);
@@ -7041,9 +7043,12 @@ fn trans_fn(@local_ctxt cx, &span sp, &ast::_fn f, ast::def_id fid,
70417043
res.bcx.build.RetVoid();
70427044
}
70437045

7046+
// Insert the mandatory first few basic blocks before lltop.
70447047
finish_fn(fcx, lltop);
70457048
}
70467049

7050+
// Create a vtable for an object being translated. Returns a pointer into
7051+
// read-only memory.
70477052
fn create_vtbl(@local_ctxt cx,
70487053
TypeRef llself_ty,
70497054
ty::t self_ty,
@@ -7136,13 +7141,15 @@ fn trans_obj(@local_ctxt cx, &span sp, &ast::_obj ob, ast::def_id oid,
71367141
// starting with an ast::_obj rather than an ast::_fn, we have some setup
71377142
// work to do.
71387143

7139-
// Translate obj ctor args to function arguments.
7144+
// The fields of our object will become the arguments to the function
7145+
// we're creating.
71407146
let vec[ast::arg] fn_args = [];
71417147
for (ast::obj_field f in ob.fields) {
71427148
fn_args += [rec(mode=ast::alias, ty=f.ty, ident=f.ident, id=f.id)];
71437149
}
7144-
71457150
auto fcx = new_fn_ctxt(cx, sp, llctor_decl);
7151+
7152+
// Both regular arguments and type parameters are handled here.
71467153
create_llargs_for_fn_args(fcx, ast::proto_fn,
71477154
none[ty_self_pair],
71487155
ret_ty_of_fn(ccx, ann),
@@ -7151,78 +7158,103 @@ fn trans_obj(@local_ctxt cx, &span sp, &ast::_obj ob, ast::def_id oid,
71517158
let vec[ty::arg] arg_tys = arg_tys_of_fn(ccx, ann);
71527159
copy_args_to_allocas(fcx, fn_args, arg_tys);
71537160

7154-
// Make the first block context in the function and keep a handle on it
7161+
// Create the first block context in the function and keep a handle on it
71557162
// to pass to finish_fn later.
71567163
auto bcx = new_top_block_ctxt(fcx);
71577164
auto lltop = bcx.llbb;
71587165

7166+
// Pick up the type of this object by looking at our own output type, that
7167+
// is, the output type of the object constructor we're building.
71597168
auto self_ty = ret_ty_of_fn(ccx, ann);
71607169
auto llself_ty = type_of(ccx, sp, self_ty);
7161-
auto pair = bcx.fcx.llretptr;
71627170

7163-
auto vtbl = create_vtbl(cx, llself_ty, self_ty, ob, ty_params);
7171+
// Set up the two-word pair that we're going to return from the object
7172+
// constructor we're building. The two elements of this pair will be a
7173+
// vtable pointer and a body pointer. (llretptr already points to the
7174+
// place where this two-word pair should go; it was pre-allocated by the
7175+
// caller of the function.)
7176+
auto pair = bcx.fcx.llretptr;
71647177

7178+
// Grab onto the first and second elements of the pair.
7179+
// abi::obj_field_vtbl and abi::obj_field_box simply specify words 0 and 1
7180+
// of 'pair'.
71657181
auto pair_vtbl = bcx.build.GEP(pair,
71667182
[C_int(0),
7167-
C_int(abi::obj_field_vtbl)]);
7183+
C_int(abi::obj_field_vtbl)]);
71687184
auto pair_box = bcx.build.GEP(pair,
71697185
[C_int(0),
7170-
C_int(abi::obj_field_box)]);
7186+
C_int(abi::obj_field_box)]);
7187+
7188+
// Make a vtable for this object: a static array of pointers to functions.
7189+
// It will be located in the read-only memory of the executable we're
7190+
// creating and will contain ValueRefs for all of this object's methods.
7191+
// create_vtbl returns a pointer to the vtable, which we store.
7192+
auto vtbl = create_vtbl(cx, llself_ty, self_ty, ob, ty_params);
71717193
bcx.build.Store(vtbl, pair_vtbl);
71727194

7173-
let TypeRef llbox_ty = T_opaque_obj_ptr(ccx.tn);
7195+
// Next we have to take care of the other half of the pair we're
7196+
// returning: a boxed (reference-counted) tuple containing a tydesc,
7197+
// typarams, and fields.
71747198

7175-
// FIXME we should probably also allocate a box for empty objs that have a
7176-
// dtor, since otherwise they are never dropped, and the dtor never runs
7199+
// FIXME: What about with_obj? Do we have to think about it here?
7200+
// (Pertains to issue #417.)
7201+
7202+
let TypeRef llbox_ty = T_opaque_obj_ptr(ccx.tn);
7203+
7204+
// FIXME: we should probably also allocate a box for empty objs that have
7205+
// a dtor, since otherwise they are never dropped, and the dtor never
7206+
// runs.
71777207
if (vec::len[ast::ty_param](ty_params) == 0u &&
71787208
vec::len[ty::arg](arg_tys) == 0u) {
7209+
// If the object we're translating has no fields or type parameters,
7210+
// there's not much to do.
7211+
71797212
// Store null into pair, if no args or typarams.
71807213
bcx.build.Store(C_null(llbox_ty), pair_box);
71817214
} else {
7182-
// Malloc a box for the body and copy args in.
7215+
// Otherwise, we have to synthesize a big structural type for the
7216+
// object body.
71837217

71847218
let vec[ty::t] obj_fields = [];
71857219
for (ty::arg a in arg_tys) {
71867220
vec::push[ty::t](obj_fields, a.ty);
71877221
}
71887222

7189-
// Synthesize an obj body type.
7223+
// Tuple type for fields: [field, ...]
7224+
let ty::t fields_ty = ty::mk_imm_tup(ccx.tcx, obj_fields);
7225+
7226+
// Tuple type for typarams: [typaram, ...]
71907227
auto tydesc_ty = ty::mk_type(ccx.tcx);
71917228
let vec[ty::t] tps = [];
71927229
for (ast::ty_param tp in ty_params) {
71937230
vec::push[ty::t](tps, tydesc_ty);
71947231
}
7195-
7196-
// typarams_ty = [typaram_ty, ...]
71977232
let ty::t typarams_ty = ty::mk_imm_tup(ccx.tcx, tps);
7198-
7199-
// fields_ty = [field_ty, ...]
7200-
let ty::t fields_ty = ty::mk_imm_tup(ccx.tcx, obj_fields);
7201-
7202-
// body_ty = [tydesc_ty, [typaram_ty, ...], [field_ty, ...]]
7233+
7234+
// Tuple type for body: [tydesc_ty, [typaram, ...], [field, ...]]
72037235
let ty::t body_ty = ty::mk_imm_tup(ccx.tcx,
72047236
[tydesc_ty,
72057237
typarams_ty,
72067238
fields_ty]);
72077239

7208-
// boxed_body_ty = [[tydesc_ty, [typaram_ty, ...], [field_ty, ...]]]
7209-
let ty::t boxed_body_ty = ty::mk_imm_box(ccx.tcx, body_ty);
7210-
7211-
// Malloc a box for the body.
7240+
// Hand this thing we've constructed off to trans_malloc_boxed, which
7241+
// makes space for the refcount.
72127242
auto box = trans_malloc_boxed(bcx, body_ty);
72137243
bcx = box.bcx;
7244+
7245+
// And mk_imm_box throws a refcount into the type we're synthesizing:
7246+
// [rc, [tydesc_ty, [typaram, ...], [field, ...]]]
7247+
let ty::t boxed_body_ty = ty::mk_imm_box(ccx.tcx, body_ty);
7248+
72147249
auto rc = GEP_tup_like(bcx, boxed_body_ty, box.val,
7215-
[0, abi::box_rc_field_refcnt]);
7250+
[0,
7251+
abi::box_rc_field_refcnt]);
72167252
bcx = rc.bcx;
72177253

7218-
// We've now created a structure that looks like:
7219-
// [refcount, [tydesc_ty, [typaram_ty, ...], [field_ty, ...]]]
7220-
72217254
auto body = GEP_tup_like(bcx, boxed_body_ty, box.val,
72227255
[0, abi::box_rc_field_body]);
72237256
bcx = body.bcx;
72247257

7225-
72267258
bcx.build.Store(C_int(1), rc.val);
72277259

72287260
// Put together a tydesc for the body, so that the object can later be
@@ -7285,6 +7317,7 @@ fn trans_obj(@local_ctxt cx, &span sp, &ast::_obj ob, ast::def_id oid,
72857317
}
72867318
bcx.build.RetVoid();
72877319

7320+
// Insert the mandatory first few basic blocks before lltop.
72887321
finish_fn(fcx, lltop);
72897322
}
72907323

0 commit comments

Comments
 (0)