@@ -160,8 +160,8 @@ state type fn_ctxt = rec(
160
160
// The three implicit arguments that arrive in the function we're
161
161
// creating. For instance, foo(int, int) is really foo(ret*, task*, env*,
162
162
// 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.
165
165
ValueRef lltaskptr ,
166
166
ValueRef llenv,
167
167
ValueRef llretptr,
@@ -7000,6 +7000,7 @@ fn trans_fn(@local_ctxt cx, &span sp, &ast::_fn f, ast::def_id fid,
7000
7000
& vec[ ast:: ty_param] ty_params, & ast:: ann ann) {
7001
7001
auto llfndecl = cx. ccx. item_ids. get( fid) ;
7002
7002
7003
+ // Set up arguments to the function.
7003
7004
auto fcx = new_fn_ctxt( cx, sp, llfndecl) ;
7004
7005
create_llargs_for_fn_args( fcx, f. proto,
7005
7006
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,
7018
7019
auto arg_tys = arg_tys_of_fn( fcx. lcx. ccx, ann) ;
7019
7020
copy_args_to_allocas( fcx, f. decl. inputs, arg_tys) ;
7020
7021
7022
+ // Create the first basic block in the function and keep a handle on it to
7023
+ // pass to finish_fn later.
7021
7024
auto bcx = new_top_block_ctxt( fcx) ;
7022
7025
add_cleanups_for_args( bcx, f. decl. inputs, arg_tys) ;
7023
-
7024
7026
auto lltop = bcx. llbb;
7025
7027
7026
7028
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,
7041
7043
res. bcx. build. RetVoid ( ) ;
7042
7044
}
7043
7045
7046
+ // Insert the mandatory first few basic blocks before lltop.
7044
7047
finish_fn( fcx, lltop) ;
7045
7048
}
7046
7049
7050
+ // Create a vtable for an object being translated. Returns a pointer into
7051
+ // read-only memory.
7047
7052
fn create_vtbl( @local_ctxt cx,
7048
7053
TypeRef llself_ty,
7049
7054
ty:: t self_ty,
@@ -7136,13 +7141,15 @@ fn trans_obj(@local_ctxt cx, &span sp, &ast::_obj ob, ast::def_id oid,
7136
7141
// starting with an ast::_obj rather than an ast::_fn, we have some setup
7137
7142
// work to do.
7138
7143
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.
7140
7146
let vec[ ast:: arg] fn_args = [ ] ;
7141
7147
for ( ast:: obj_field f in ob. fields) {
7142
7148
fn_args += [ rec( mode=ast:: alias, ty=f. ty, ident=f. ident, id=f. id) ] ;
7143
7149
}
7144
-
7145
7150
auto fcx = new_fn_ctxt( cx, sp, llctor_decl) ;
7151
+
7152
+ // Both regular arguments and type parameters are handled here.
7146
7153
create_llargs_for_fn_args( fcx, ast:: proto_fn,
7147
7154
none[ ty_self_pair] ,
7148
7155
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,
7151
7158
let vec[ ty:: arg] arg_tys = arg_tys_of_fn( ccx, ann) ;
7152
7159
copy_args_to_allocas( fcx, fn_args, arg_tys) ;
7153
7160
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
7155
7162
// to pass to finish_fn later.
7156
7163
auto bcx = new_top_block_ctxt( fcx) ;
7157
7164
auto lltop = bcx. llbb;
7158
7165
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.
7159
7168
auto self_ty = ret_ty_of_fn( ccx, ann) ;
7160
7169
auto llself_ty = type_of( ccx, sp, self_ty) ;
7161
- auto pair = bcx. fcx. llretptr;
7162
7170
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;
7164
7177
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'.
7165
7181
auto pair_vtbl = bcx. build. GEP ( pair,
7166
7182
[ C_int ( 0 ) ,
7167
- C_int ( abi:: obj_field_vtbl) ] ) ;
7183
+ C_int ( abi:: obj_field_vtbl) ] ) ;
7168
7184
auto pair_box = bcx. build. GEP ( pair,
7169
7185
[ 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) ;
7171
7193
bcx. build. Store ( vtbl, pair_vtbl) ;
7172
7194
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.
7174
7198
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.
7177
7207
if ( vec:: len[ ast:: ty_param] ( ty_params) == 0 u &&
7178
7208
vec:: len[ ty:: arg] ( arg_tys) == 0 u) {
7209
+ // If the object we're translating has no fields or type parameters,
7210
+ // there's not much to do.
7211
+
7179
7212
// Store null into pair, if no args or typarams.
7180
7213
bcx. build. Store ( C_null ( llbox_ty) , pair_box) ;
7181
7214
} 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.
7183
7217
7184
7218
let vec[ ty:: t] obj_fields = [ ] ;
7185
7219
for ( ty:: arg a in arg_tys) {
7186
7220
vec:: push[ ty:: t] ( obj_fields, a. ty) ;
7187
7221
}
7188
7222
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, ...]
7190
7227
auto tydesc_ty = ty:: mk_type( ccx. tcx) ;
7191
7228
let vec[ ty:: t] tps = [ ] ;
7192
7229
for ( ast:: ty_param tp in ty_params) {
7193
7230
vec:: push[ ty:: t] ( tps, tydesc_ty) ;
7194
7231
}
7195
-
7196
- // typarams_ty = [typaram_ty, ...]
7197
7232
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, ...]]
7203
7235
let ty:: t body_ty = ty:: mk_imm_tup( ccx. tcx,
7204
7236
[ tydesc_ty,
7205
7237
typarams_ty,
7206
7238
fields_ty] ) ;
7207
7239
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.
7212
7242
auto box = trans_malloc_boxed( bcx, body_ty) ;
7213
7243
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
+
7214
7249
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] ) ;
7216
7252
bcx = rc. bcx;
7217
7253
7218
- // We've now created a structure that looks like:
7219
- // [refcount, [tydesc_ty, [typaram_ty, ...], [field_ty, ...]]]
7220
-
7221
7254
auto body = GEP_tup_like ( bcx, boxed_body_ty, box. val,
7222
7255
[ 0 , abi:: box_rc_field_body] ) ;
7223
7256
bcx = body. bcx;
7224
7257
7225
-
7226
7258
bcx. build. Store ( C_int ( 1 ) , rc. val) ;
7227
7259
7228
7260
// 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,
7285
7317
}
7286
7318
bcx. build. RetVoid ( ) ;
7287
7319
7320
+ // Insert the mandatory first few basic blocks before lltop.
7288
7321
finish_fn( fcx, lltop) ;
7289
7322
}
7290
7323
0 commit comments