@@ -604,7 +604,8 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
604
604
}
605
605
ast:: expr_tup( ref args) => {
606
606
let repr = adt:: represent_type ( bcx. ccx ( ) , expr_ty ( bcx, expr) ) ;
607
- return trans_adt ( bcx, & repr, 0 , * args, dest) ;
607
+ return trans_adt ( bcx, & repr, 0 , args. mapi ( |i, arg| ( i, * arg) ) ,
608
+ None , dest) ;
608
609
}
609
610
ast:: expr_lit( @codemap:: spanned { node : ast:: lit_str( s) , _} ) => {
610
611
return tvec:: trans_lit_str ( bcx, expr, s, dest) ;
@@ -885,7 +886,7 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
885
886
let _icx = bcx. insn_ctxt ( "trans_rec_field" ) ;
886
887
887
888
let base_datum = unpack_datum ! ( bcx, trans_to_datum( bcx, base) ) ;
888
- do with_field_tys ( bcx. tcx ( ) , base_datum. ty , None ) |_dtor , field_tys| {
889
+ do with_field_tys ( bcx. tcx ( ) , base_datum. ty , None ) |_disr , field_tys| {
889
890
let ix = ty:: field_idx_strict ( bcx. tcx ( ) , field, field_tys) ;
890
891
DatumBlock {
891
892
datum : base_datum. GEPi ( bcx,
@@ -1098,15 +1099,14 @@ pub fn trans_local_var(bcx: block, def: ast::def) -> Datum {
1098
1099
pub fn with_field_tys < R > ( tcx : ty:: ctxt ,
1099
1100
ty : ty:: t ,
1100
1101
node_id_opt : Option < ast:: node_id > ,
1101
- op : fn ( bool , ( & [ ty:: field ] ) ) -> R ) -> R {
1102
+ op : fn ( int , ( & [ ty:: field ] ) ) -> R ) -> R {
1102
1103
match ty:: get ( ty) . sty {
1103
1104
ty:: ty_rec( ref fields) => {
1104
- op ( false , * fields)
1105
+ op ( 0 , * fields)
1105
1106
}
1106
1107
1107
1108
ty:: ty_struct( did, ref substs) => {
1108
- let has_dtor = ty:: ty_dtor ( tcx, did) . is_present ( ) ;
1109
- op ( has_dtor, struct_mutable_fields ( tcx, did, substs) )
1109
+ op ( 0 , struct_mutable_fields ( tcx, did, substs) )
1110
1110
}
1111
1111
1112
1112
ty:: ty_enum( _, ref substs) => {
@@ -1120,8 +1120,10 @@ pub fn with_field_tys<R>(tcx: ty::ctxt,
1120
1120
}
1121
1121
Some ( node_id) => {
1122
1122
match tcx. def_map . get ( & node_id) {
1123
- ast:: def_variant( _, variant_id) => {
1124
- op ( false , struct_mutable_fields (
1123
+ ast:: def_variant( enum_id, variant_id) => {
1124
+ let variant_info = ty:: enum_variant_with_id (
1125
+ tcx, enum_id, variant_id) ;
1126
+ op ( variant_info. disr_val , struct_mutable_fields (
1125
1127
tcx, variant_id, substs) )
1126
1128
}
1127
1129
_ => {
@@ -1150,135 +1152,100 @@ fn trans_rec_or_struct(bcx: block,
1150
1152
let _icx = bcx. insn_ctxt ( "trans_rec" ) ;
1151
1153
let mut bcx = bcx;
1152
1154
1153
- // Handle the case where the result is ignored.
1154
- let addr;
1155
- match dest {
1156
- SaveIn ( p) => {
1157
- addr = p;
1158
- }
1159
- Ignore => {
1160
- // just evaluate the values for each field and drop them
1161
- // on the floor
1162
- for vec:: each( fields) |fld| {
1163
- bcx = trans_into ( bcx, fld. node . expr , Ignore ) ;
1164
- }
1165
- return bcx;
1166
- }
1167
- }
1168
-
1169
- // If this is a struct-like variant, write in the discriminant if
1170
- // necessary, position the address at the right location, and cast the
1171
- // address.
1172
1155
let ty = node_id_type ( bcx, id) ;
1173
1156
let tcx = bcx. tcx ( ) ;
1174
- let addr = match ty:: get ( ty) . sty {
1175
- ty:: ty_enum( _, ref substs) => {
1176
- match tcx. def_map . get ( & id) {
1177
- ast:: def_variant( enum_id, variant_id) => {
1178
- let variant_info = ty:: enum_variant_with_id (
1179
- tcx, enum_id, variant_id) ;
1180
- let addr = if ty:: enum_is_univariant ( tcx, enum_id) {
1181
- addr
1182
- } else {
1183
- Store ( bcx,
1184
- C_int ( bcx. ccx ( ) , variant_info. disr_val ) ,
1185
- GEPi ( bcx, addr, [ 0 , 0 ] ) ) ;
1186
- GEPi ( bcx, addr, [ 0 , 1 ] )
1187
- } ;
1188
- let fields = ty:: struct_mutable_fields (
1189
- tcx, variant_id, substs) ;
1190
- let field_lltys = do fields. map |field| {
1191
- type_of:: type_of ( bcx. ccx ( ) ,
1192
- ty:: subst_tps (
1193
- tcx, substs. tps , None , field. mt . ty ) )
1194
- } ;
1195
- PointerCast ( bcx, addr,
1196
- T_ptr ( T_struct ( ~[ T_struct ( field_lltys) ] ) ) )
1157
+ do with_field_tys ( tcx, ty, Some ( id) ) |discr, field_tys| {
1158
+ let mut need_base = vec:: from_elem ( field_tys. len ( ) , true ) ;
1159
+
1160
+ let numbered_fields = do fields. map |field| {
1161
+ match do vec:: position ( field_tys) |field_ty| {
1162
+ field_ty. ident == field. node . ident
1163
+ } {
1164
+ Some ( i) => {
1165
+ need_base[ i] = false ;
1166
+ ( i, field. node . expr )
1197
1167
}
1198
- _ => {
1199
- tcx. sess . bug ( ~"resolve didn ' t write the right def in for \
1200
- this struct-like variant ")
1168
+ None => {
1169
+ tcx. sess . span_bug ( field . span ,
1170
+ ~" Couldn ' t find field in struct type ")
1201
1171
}
1202
1172
}
1203
- }
1204
- _ => addr
1205
- } ;
1206
-
1207
- do with_field_tys( tcx, ty, Some ( id) ) |has_dtor, field_tys| {
1208
- // evaluate each of the fields and store them into their
1209
- // correct locations
1210
- let mut temp_cleanups = ~[ ] ;
1211
- for fields. each |field| {
1212
- let ix = ty:: field_idx_strict ( tcx, field. node . ident , field_tys) ;
1213
- let dest = GEPi ( bcx, addr, struct_field ( ix) ) ;
1214
- bcx = trans_into ( bcx, field. node . expr , SaveIn ( dest) ) ;
1215
- add_clean_temp_mem ( bcx, dest, field_tys[ ix] . mt . ty ) ;
1216
- temp_cleanups. push ( dest) ;
1217
- }
1218
-
1219
- // copy over any remaining fields from the base (for
1220
- // functional record update)
1221
- for base. each |base_expr| {
1222
- let base_datum = unpack_datum ! (
1223
- bcx, trans_to_datum( bcx, * base_expr) ) ;
1224
-
1225
- // Copy/move over inherited fields
1226
- for field_tys. eachi |i, field_ty| {
1227
- if !fields. any ( |f| f. node . ident == field_ty. ident ) {
1228
- let dest = GEPi ( bcx, addr, struct_field ( i) ) ;
1229
- let base_field =
1230
- base_datum. GEPi ( bcx,
1231
- struct_field ( i) ,
1232
- field_ty. mt . ty ,
1233
- ZeroMem ) ;
1234
- bcx = base_field. store_to ( bcx, base_expr. id , INIT , dest) ;
1173
+ } ;
1174
+ let optbase = match base {
1175
+ Some ( base_expr) => {
1176
+ let mut leftovers = ~[ ] ;
1177
+ for need_base. eachi |i, b| {
1178
+ if * b {
1179
+ leftovers. push ( ( i, field_tys[ i] . mt . ty ) )
1180
+ }
1235
1181
}
1182
+ Some ( StructBaseInfo { expr : base_expr,
1183
+ fields : leftovers } )
1236
1184
}
1237
- }
1238
-
1239
- // Add the drop flag if necessary.
1240
- if has_dtor {
1241
- let dest = GEPi ( bcx, addr, struct_dtor ( ) ) ;
1242
- Store ( bcx, C_u8 ( 1 ) , dest) ;
1243
- }
1185
+ None => {
1186
+ if need_base. any ( |b| * b) {
1187
+ // XXX should be span bug
1188
+ tcx. sess . bug ( ~"missing fields and no base expr")
1189
+ }
1190
+ None
1191
+ }
1192
+ } ;
1244
1193
1245
- // Now revoke the cleanups as we pass responsibility for the data
1246
- // structure on to the caller
1247
- for temp_cleanups. each |cleanup| {
1248
- revoke_clean( bcx, * cleanup) ;
1249
- }
1250
- bcx
1194
+ let repr = adt:: represent_type ( bcx. ccx ( ) , ty) ;
1195
+ trans_adt ( bcx, & repr, discr, numbered_fields, optbase, dest)
1251
1196
}
1252
1197
}
1253
1198
1254
- fn trans_adt ( bcx : block , repr : & adt:: Repr , discr : int , elts : & [ @ast:: expr ] ,
1199
+ struct StructBaseInfo {
1200
+ expr : @ast:: expr ,
1201
+ fields : ~[ ( uint , ty:: t ) ]
1202
+ }
1203
+
1204
+ fn trans_adt ( bcx : block , repr : & adt:: Repr , discr : int ,
1205
+ fields : & [ ( uint , @ast:: expr ) ] ,
1206
+ optbase : Option < StructBaseInfo > ,
1255
1207
dest : Dest ) -> block {
1256
- let _icx = bcx. insn_ctxt ( "trans_tup " ) ;
1208
+ let _icx = bcx. insn_ctxt ( "trans_adt " ) ;
1257
1209
let mut bcx = bcx;
1258
1210
let addr = match dest {
1259
1211
Ignore => {
1260
- for vec:: each( elts) |ex| {
1261
- bcx = trans_into ( bcx, * ex, Ignore ) ;
1212
+ for fields. each |& ( _i, e) | {
1213
+ bcx = trans_into ( bcx, e, Ignore ) ;
1214
+ }
1215
+ for optbase. each |sbi| {
1216
+ bcx = trans_into ( bcx, sbi. expr , Ignore ) ;
1262
1217
}
1263
1218
return bcx;
1264
1219
}
1265
- SaveIn ( pos) => pos,
1220
+ SaveIn ( pos) => pos
1266
1221
} ;
1267
1222
let mut temp_cleanups = ~[ ] ;
1268
1223
adt:: trans_set_discr ( bcx, repr, addr, discr) ;
1269
- for vec :: eachi ( elts ) | i, e| {
1224
+ for fields . each | & ( i, e) | {
1270
1225
let dest = adt:: trans_GEP ( bcx, repr, addr, discr, i) ;
1271
- let e_ty = expr_ty ( bcx, * e) ;
1272
- bcx = trans_into ( bcx, * e, SaveIn ( dest) ) ;
1226
+ let e_ty = expr_ty ( bcx, e) ;
1227
+ bcx = trans_into ( bcx, e, SaveIn ( dest) ) ;
1273
1228
add_clean_temp_mem ( bcx, dest, e_ty) ;
1274
1229
temp_cleanups. push ( dest) ;
1275
1230
}
1231
+ for optbase. each |base| {
1232
+ let base_datum = unpack_datum ! ( bcx, trans_to_datum( bcx, base. expr) ) ;
1233
+ for base. fields. each |& ( i, t) | {
1234
+ let datum =
1235
+ // XXX convert this to adt
1236
+ base_datum. GEPi ( bcx, struct_field ( i) , t, ZeroMem ) ;
1237
+ let dest = adt:: trans_GEP ( bcx, repr, addr, discr, i) ;
1238
+ bcx = datum. store_to ( bcx, base. expr . id , INIT , dest) ;
1239
+ }
1240
+ }
1241
+
1276
1242
for vec:: each( temp_cleanups) |cleanup| {
1277
1243
revoke_clean( bcx, * cleanup) ;
1278
1244
}
1279
1245
return bcx;
1280
1246
}
1281
1247
1248
+
1282
1249
fn trans_immediate_lit ( bcx : block , expr : @ast:: expr ,
1283
1250
lit : ast:: lit ) -> DatumBlock {
1284
1251
// must not be a string constant, that is a RvalueDpsExpr
0 commit comments