@@ -113,13 +113,18 @@ type stats =
113
113
mutable uint n_null_glues ,
114
114
mutable uint n_real_glues ) ;
115
115
116
+ // Crate context. Every crate we compile has one of these.
116
117
type crate_ctxt =
117
118
rec ( session:: session sess,
118
119
ModuleRef llmod,
119
120
target_data td,
120
121
type_names tn,
121
122
hashmap[ str, ValueRef ] externs ,
122
123
hashmap[ str, ValueRef ] intrinsics ,
124
+
125
+ // A mapping from the def_id of each item in this crate to the address
126
+ // of the first instruction of the item's definition in the executable
127
+ // we're generating.
123
128
hashmap[ ast:: def_id, ValueRef ] item_ids ,
124
129
hashmap[ ast:: def_id, @ast:: item] items ,
125
130
hashmap[ ast:: def_id, @ast:: native_item] native_items ,
@@ -5966,24 +5971,26 @@ fn recv_val(&@block_ctxt cx, ValueRef lhs, &@ast::expr rhs, &ty::t unit_ty,
5966
5971
5967
5972
*/
5968
5973
5969
- // trans_anon_obj: create (and return!) an LLVM function that is the object
5970
- // constructor for the anonymous object being translated.
5971
- //
5972
- // This code differs from trans_obj in that, rather than creating an object
5973
- // constructor function and putting it in the generated code as an object
5974
- // item, we are instead "inlining" the construction of the object.
5975
- fn trans_anon_obj( @block_ctxt cx, & span sp, & ast:: anon_obj anon_obj,
5974
+ // trans_anon_obj: create and return a pointer to an object. This code
5975
+ // differs from trans_obj in that, rather than creating an object constructor
5976
+ // function and putting it in the generated code as an object item, we are
5977
+ // instead "inlining" the construction of the object and returning the object
5978
+ // itself.
5979
+ fn trans_anon_obj( @block_ctxt bcx, & span sp, & ast:: anon_obj anon_obj,
5976
5980
& vec[ ast:: ty_param] ty_params, ast:: def_id oid,
5977
5981
& ast:: ann ann) -> result {
5978
- auto ccx = cx. fcx. lcx. ccx;
5979
- // A crate_ctxt has an item_ids hashmap, which has all of the def_ids of
5980
- // everything in the crate. By looking up a def_id, you can get the
5981
- // ValueRef of that item.
5982
5982
5983
- auto llctor_decl = ccx. item_ids. get( oid) ;
5983
+ // Right now, we're assuming that anon objs don't take ty params, even
5984
+ // though the AST supports it. It's nonsensical to write an expression
5985
+ // like "obj[T](){ ... with ... }", since T is never instantiated;
5986
+ // nevertheless, such an expression will parse. FIXME for the future:
5987
+ // support typarams (issue #n).
5988
+ assert vec:: len( ty_params) == 0 u;
5989
+
5990
+ auto ccx = bcx. fcx. lcx. ccx;
5991
+
5984
5992
// If with_obj (the object being extended) exists, translate it, producing
5985
5993
// a result.
5986
-
5987
5994
let option:: t[ result] with_obj_val = none[ result] ;
5988
5995
alt ( anon_obj. with_obj) {
5989
5996
case ( none) { }
@@ -5992,81 +5999,44 @@ fn trans_anon_obj(@block_ctxt cx, &span sp, &ast::anon_obj anon_obj,
5992
5999
// value) wrapped in a result. We want to allocate space for this
5993
6000
// value in our outer object, then copy it into the outer object.
5994
6001
5995
- with_obj_val = some[ result] ( trans_expr( cx , e) ) ;
6002
+ with_obj_val = some[ result] ( trans_expr( bcx , e) ) ;
5996
6003
}
5997
6004
}
5998
- // If the anonymous object we're translating adds any additional fields,
5999
- // they'll become the arguments to the function we're creating.
6000
6005
6001
6006
// FIXME (part of issue #417): all of the following code is copypasta from
6002
6007
// trans_obj for translating the anonymous wrapper object. Eventually we
6003
6008
// should abstract this code out of trans_anon_obj and trans_obj.
6004
6009
6005
- // For the anon obj's additional fields, if any exist, translate object
6006
- // constructor arguments to function arguments.
6007
-
6008
- let vec[ ast:: obj_field] addtl_fields = [ ] ;
6009
- let vec[ ast:: arg] addtl_fn_args = [ ] ;
6010
- alt ( anon_obj. fields) {
6011
- case ( none) { }
6012
- case ( some( ?fields) ) {
6013
- addtl_fields = fields;
6014
- for ( ast:: obj_field f in fields) {
6015
- addtl_fn_args +=
6016
- [ rec( mode=ast:: alias( false) ,
6017
- ty=f. ty,
6018
- ident=f. ident,
6019
- id=f. id) ] ;
6020
- }
6021
- }
6022
- }
6023
- auto fcx = new_fn_ctxt( cx. fcx. lcx, sp, llctor_decl) ;
6024
- // Both regular arguments and type parameters are handled here.
6025
-
6026
- create_llargs_for_fn_args( fcx, ast:: proto_fn, none[ ty_self_pair] ,
6027
- ret_ty_of_fn( ccx, ann) , addtl_fn_args,
6028
- ty_params) ;
6029
- let vec[ ty:: arg] arg_tys = arg_tys_of_fn( ccx, ann) ;
6030
- copy_args_to_allocas( fcx, addtl_fn_args, arg_tys) ;
6031
- // Create the first block context in the function and keep a handle on it
6032
- // to pass to finish_fn later.
6033
-
6034
- auto bcx = new_top_block_ctxt( fcx) ;
6035
- auto lltop = bcx. llbb;
6036
- // Pick up the type of this object by looking at our own output type, that
6037
- // is, the output type of the object constructor we're building.
6038
-
6039
- auto self_ty = ret_ty_of_fn( ccx, ann) ;
6010
+ auto self_ty = ty:: ann_to_type( ccx. tcx, ann) ;
6040
6011
auto llself_ty = type_of( ccx, sp, self_ty) ;
6041
- // Set up the two-word pair that we're going to return from the object
6042
- // constructor we're building. The two elements of this pair will be a
6043
- // vtable pointer and a body pointer. (llretptr already points to the
6044
- // place where this two-word pair should go; it was pre-allocated by the
6045
- // caller of the function.)
6046
6012
6047
- auto pair = bcx. fcx. llretptr;
6013
+ // Allocate the object that we're going to return. It's a two-word pair
6014
+ // containing a vtable pointer and a body pointer.
6015
+ auto pair = alloca( bcx, llself_ty) ;
6016
+
6048
6017
// Grab onto the first and second elements of the pair.
6049
6018
// abi::obj_field_vtbl and abi::obj_field_box simply specify words 0 and 1
6050
6019
// of 'pair'.
6051
-
6052
6020
auto pair_vtbl =
6053
6021
bcx. build. GEP ( pair, [ C_int ( 0 ) , C_int ( abi:: obj_field_vtbl) ] ) ;
6054
6022
auto pair_box =
6055
6023
bcx. build. GEP ( pair, [ C_int ( 0 ) , C_int ( abi:: obj_field_box) ] ) ;
6056
- // Make a vtable for this object: a static array of pointers to functions.
6057
- // It will be located in the read-only memory of the executable we're
6058
- // creating and will contain ValueRefs for all of this object's methods.
6059
- // create_vtbl returns a pointer to the vtable, which we store.
6060
6024
6061
- // create_vtbl() wants an ast::_obj and all we have is an
6062
- // ast::anon_obj, so we need to roll our own.
6025
+ // Make a vtable for the outer object. create_vtbl() wants an ast::_obj
6026
+ // and all we have is an ast::anon_obj, so we need to roll our own.
6027
+ let vec[ ast:: obj_field] addtl_fields = [ ] ;
6028
+ alt ( anon_obj. fields) {
6029
+ case ( none) { }
6030
+ case ( some( ?fields) ) { addtl_fields = fields; }
6031
+ }
6032
+ let ast:: _obj wrapper_obj = rec(
6033
+ fields = addtl_fields,
6034
+ methods = anon_obj. methods,
6035
+ dtor = none[ @ast:: method] ) ;
6036
+
6037
+ auto vtbl = create_vtbl( bcx. fcx. lcx, llself_ty, self_ty, wrapper_obj,
6038
+ ty_params) ;
6063
6039
6064
- let ast:: _obj wrapper_obj =
6065
- rec( fields=addtl_fields,
6066
- methods=anon_obj. methods,
6067
- dtor=none[ @ast:: method] ) ;
6068
- auto vtbl =
6069
- create_vtbl( cx. fcx. lcx, llself_ty, self_ty, wrapper_obj, ty_params) ;
6070
6040
bcx. build. Store ( vtbl, pair_vtbl) ;
6071
6041
// FIXME (part of issue #417): This vtable needs to contain "forwarding
6072
6042
// slots" for the methods that exist in the with_obj, as well. How do we
@@ -6080,127 +6050,29 @@ fn trans_anon_obj(@block_ctxt cx, &span sp, &ast::anon_obj anon_obj,
6080
6050
// also have to fill in the with_obj field of this tuple.
6081
6051
6082
6052
let TypeRef llbox_ty = T_opaque_obj_ptr ( ccx. tn) ;
6083
- // FIXME: we should probably also allocate a box for empty objs that have
6084
- // a dtor, since otherwise they are never dropped, and the dtor never
6085
- // runs.
6086
-
6087
- if ( vec:: len[ ast:: ty_param] ( ty_params) == 0 u &&
6088
- vec:: len[ ty:: arg] ( arg_tys) == 0 u) {
6089
- // If the object we're translating has no fields or type parameters,
6090
- // there's not much to do.
6091
-
6092
- // Store null into pair, if no args or typarams.
6093
-
6094
- bcx. build. Store ( C_null ( llbox_ty) , pair_box) ;
6095
- } else {
6096
- // Otherwise, we have to synthesize a big structural type for the
6097
- // object body.
6098
-
6099
- let vec[ ty:: t] obj_fields = [ ] ;
6100
- for ( ty:: arg a in arg_tys) { vec:: push[ ty:: t] ( obj_fields, a. ty) ; }
6101
- // Tuple type for fields: [field, ...]
6053
+
6054
+ alt ( anon_obj. fields) {
6055
+ case ( none) {
6056
+ // If the object we're translating has no fields or type
6057
+ // parameters, there's not much to do.
6102
6058
6103
- let ty :: t fields_ty = ty :: mk_imm_tup ( ccx . tcx , obj_fields ) ;
6104
- // Tuple type for typarams: [typaram, ...]
6059
+ // Store null into pair, if no args or typarams.
6060
+ bcx . build . Store ( C_null ( llbox_ty ) , pair_box ) ;
6105
6061
6106
- auto tydesc_ty = ty:: mk_type( ccx. tcx) ;
6107
- let vec[ ty:: t] tps = [ ] ;
6108
- for ( ast:: ty_param tp in ty_params) {
6109
- vec:: push[ ty:: t] ( tps, tydesc_ty) ;
6110
6062
}
6111
- let ty:: t typarams_ty = ty:: mk_imm_tup( ccx. tcx, tps) ;
6112
- // Tuple type for body: [tydesc_ty, [typaram, ...], [field, ...]]
6113
-
6114
- let ty:: t body_ty =
6115
- ty:: mk_imm_tup( ccx. tcx, [ tydesc_ty, typarams_ty, fields_ty] ) ;
6116
- // Hand this type we've synthesized off to trans_malloc_boxed, which
6117
- // allocates a box, including space for a refcount.
6118
6063
6119
- auto box = trans_malloc_boxed( bcx, body_ty) ;
6120
- bcx = box. bcx;
6121
- // mk_imm_box throws a refcount into the type we're synthesizing, so
6122
- // that it looks like: [rc, [tydesc_ty, [typaram, ...], [field, ...]]]
6123
-
6124
- let ty:: t boxed_body_ty = ty:: mk_imm_box( ccx. tcx, body_ty) ;
6125
- // Grab onto the refcount and body parts of the box we allocated.
6126
-
6127
- auto rc =
6128
- GEP_tup_like ( bcx, boxed_body_ty, box. val,
6129
- [ 0 , abi:: box_rc_field_refcnt] ) ;
6130
- bcx = rc. bcx;
6131
- auto body =
6132
- GEP_tup_like ( bcx, boxed_body_ty, box. val,
6133
- [ 0 , abi:: box_rc_field_body] ) ;
6134
- bcx = body. bcx;
6135
- bcx. build. Store ( C_int ( 1 ) , rc. val) ;
6136
- // Put together a tydesc for the body, so that the object can later be
6137
- // freed by calling through its tydesc.
6138
-
6139
- // Every object (not just those with type parameters) needs to have a
6140
- // tydesc to describe its body, since all objects have unknown type to
6141
- // the user of the object. So the tydesc is needed to keep track of
6142
- // the types of the object's fields, so that the fields can be freed
6143
- // later.
6144
-
6145
- auto body_tydesc =
6146
- GEP_tup_like ( bcx, body_ty, body. val,
6147
- [ 0 , abi:: obj_body_elt_tydesc] ) ;
6148
- bcx = body_tydesc. bcx;
6149
- auto ti = none[ @tydesc_info] ;
6150
- auto body_td = get_tydesc( bcx, body_ty, true, ti) ;
6151
- lazily_emit_tydesc_glue( bcx, abi:: tydesc_field_drop_glue, ti) ;
6152
- lazily_emit_tydesc_glue( bcx, abi:: tydesc_field_free_glue, ti) ;
6153
- bcx = body_td. bcx;
6154
- bcx. build. Store ( body_td. val, body_tydesc. val) ;
6155
- // Copy the object's type parameters and fields into the space we
6156
- // allocated for the object body. (This is something like saving the
6157
- // lexical environment of a function in its closure: the "captured
6158
- // typarams" are any type parameters that are passed to the object
6159
- // constructor and are then available to the object's methods.
6160
- // Likewise for the object's fields.)
6161
-
6162
- // Copy typarams into captured typarams.
6163
-
6164
- auto body_typarams =
6165
- GEP_tup_like ( bcx, body_ty, body. val,
6166
- [ 0 , abi:: obj_body_elt_typarams] ) ;
6167
- bcx = body_typarams. bcx;
6168
- let int i = 0 ;
6169
- for ( ast:: ty_param tp in ty_params) {
6170
- auto typaram = bcx. fcx. lltydescs. ( i) ;
6171
- auto capture =
6172
- GEP_tup_like ( bcx, typarams_ty, body_typarams. val, [ 0 , i] ) ;
6173
- bcx = capture. bcx;
6174
- bcx = copy_val( bcx, INIT , capture. val, typaram, tydesc_ty) . bcx;
6175
- i += 1 ;
6176
- }
6177
- // Copy args into body fields.
6064
+ case ( some( ?fields) ) {
6065
+ // For the moment let's pretend that there are no additional
6066
+ // fields.
6067
+ bcx. fcx. lcx. ccx. sess. unimpl( "anon objs don' t support "
6068
+ + "adding fields yet") ;
6178
6069
6179
- auto body_fields =
6180
- GEP_tup_like ( bcx, body_ty, body. val,
6181
- [ 0 , abi:: obj_body_elt_fields] ) ;
6182
- bcx = body_fields. bcx;
6183
- i = 0 ;
6184
- for ( ast:: obj_field f in wrapper_obj. fields) {
6185
- auto arg = bcx. fcx. llargs. get( f. id) ;
6186
- arg = load_if_immediate( bcx, arg, arg_tys. ( i) . ty) ;
6187
- auto field =
6188
- GEP_tup_like ( bcx, fields_ty, body_fields. val, [ 0 , i] ) ;
6189
- bcx = field. bcx;
6190
- bcx = copy_val( bcx, INIT , field. val, arg, arg_tys. ( i) . ty) . bcx;
6191
- i += 1 ;
6070
+ // FIXME (issue #417): drop these fields into the newly created
6071
+ // object.
6192
6072
}
6193
- // Store box ptr in outer pair.
6194
-
6195
- auto p = bcx. build. PointerCast ( box. val, llbox_ty) ;
6196
- bcx. build. Store ( p, pair_box) ;
6197
6073
}
6198
- bcx. build. RetVoid ( ) ;
6199
- // Insert the mandatory first few basic blocks before lltop.
6200
6074
6201
- finish_fn( fcx, lltop) ;
6202
6075
// Return the object we built.
6203
-
6204
6076
ret res( bcx, pair) ;
6205
6077
}
6206
6078
@@ -6657,6 +6529,10 @@ fn arg_tys_of_fn(&@crate_ctxt ccx, ast::ann ann) -> vec[ty::arg] {
6657
6529
fn ret_ty_of_fn_ty( & @crate_ctxt ccx, ty:: t t) -> ty:: t {
6658
6530
alt ( ty:: struct ( ccx. tcx, t) ) {
6659
6531
case ( ty:: ty_fn( _, _, ?ret_ty, _, _) ) { ret ret_ty; }
6532
+ case ( _) {
6533
+ ccx. sess. bug( "ret_ty_of_fn_ty( ) called on non-function type : "
6534
+ + ty_to_str( ccx. tcx, t) ) ;
6535
+ }
6660
6536
}
6661
6537
}
6662
6538
@@ -6806,6 +6682,10 @@ fn create_vtbl(@local_ctxt cx, TypeRef llself_ty, ty::t self_ty,
6806
6682
let str s = mangle_internal_name_by_path( mcx. ccx, mcx. path) ;
6807
6683
let ValueRef llfn =
6808
6684
decl_internal_fastcall_fn( cx. ccx. llmod, s, llfnty) ;
6685
+
6686
+ // Every method on an object gets its def_id inserted into the
6687
+ // crate-wide item_ids map, together with the ValueRef that points to
6688
+ // where that method's definition will be in the executable.
6809
6689
cx. ccx. item_ids. insert( m. node. id, llfn) ;
6810
6690
cx. ccx. item_symbols. insert( m. node. id, s) ;
6811
6691
trans_fn( mcx, m. span, m. node. meth, llfn,
@@ -7156,6 +7036,11 @@ fn trans_item(@local_ctxt cx, &ast::item item) {
7156
7036
}
7157
7037
}
7158
7038
7039
+ // Translate a module. Doing this amounts to translating the items in the
7040
+ // module; there ends up being no artifact (aside from linkage names) of
7041
+ // separate modules in the compiled program. That's because modules exist
7042
+ // only as a convenience for humans working with the code, to organize names
7043
+ // and control visibility.
7159
7044
fn trans_mod( @local_ctxt cx, & ast:: _mod m) {
7160
7045
for ( @ast:: item item in m. items) { trans_item( cx, * item) ; }
7161
7046
}
0 commit comments