@@ -3410,6 +3410,90 @@ fn trans_rec(bcx: block, fields: ~[ast::field],
3410
3410
ret bcx;
3411
3411
}
3412
3412
3413
+ fn trans_struct ( block_context : block , span : span , fields : ~[ ast:: field ] ,
3414
+ id : ast:: node_id , dest : dest ) -> block {
3415
+
3416
+ let _instruction_context = block_context. insn_ctxt ( ~"trans_struct") ;
3417
+ let mut block_context = block_context;
3418
+ let type_context = block_context. ccx ( ) . tcx ;
3419
+
3420
+ let struct_type = node_id_type ( block_context, id) ;
3421
+
3422
+ // Get the address to store the structure into. If there is no address,
3423
+ // just translate each field and be done with it.
3424
+ let dest_address;
3425
+ alt dest {
3426
+ ignore => {
3427
+ for fields. each |field| {
3428
+ block_context = trans_expr ( block_context,
3429
+ field. node . expr ,
3430
+ ignore) ;
3431
+ }
3432
+ ret block_context;
3433
+ }
3434
+ save_in ( destination_address) => {
3435
+ dest_address = destination_address;
3436
+ }
3437
+ by_val ( _) => {
3438
+ type_context. sess . span_bug ( span, ~"didn' t expect by_val") ;
3439
+ }
3440
+ }
3441
+
3442
+ // Get the class ID and its fields.
3443
+ let class_fields, class_id, substitutions;
3444
+ alt ty:: get ( struct_type) . struct {
3445
+ ty:: ty_class ( existing_class_id, existing_substitutions) => {
3446
+ class_id = existing_class_id;
3447
+ substitutions = existing_substitutions;
3448
+ class_fields = ty:: lookup_class_fields ( type_context, class_id) ;
3449
+ }
3450
+ _ => {
3451
+ type_context. sess . span_bug ( span, ~"didn' t resolve to a struct ") ;
3452
+ }
3453
+ }
3454
+
3455
+ // Now translate each field.
3456
+ let mut temp_cleanups = ~[ ] ;
3457
+ for fields. each |field| {
3458
+ let mut found = none;
3459
+ for class_fields. eachi |i, class_field| {
3460
+ if str:: eq ( * class_field. ident , * field. node . ident ) {
3461
+ found = some ( ( i, class_field. id ) ) ;
3462
+ break ;
3463
+ }
3464
+ }
3465
+
3466
+ let index, field_id;
3467
+ alt found {
3468
+ some( ( found_index, found_field_id) ) => {
3469
+ index = found_index;
3470
+ field_id = found_field_id;
3471
+ }
3472
+ none => {
3473
+ type_context. sess . span_bug ( span, ~"unknown field") ;
3474
+ }
3475
+ }
3476
+
3477
+ let dest = GEPi ( block_context, dest_address, ~[ 0 , index] ) ;
3478
+ block_context = trans_expr_save_in ( block_context,
3479
+ field. node . expr ,
3480
+ dest) ;
3481
+
3482
+ let field_type = ty:: lookup_field_type ( type_context, class_id,
3483
+ field_id, substitutions) ;
3484
+ add_clean_temp_mem ( block_context, dest, field_type) ;
3485
+ vec:: push ( temp_cleanups, dest) ;
3486
+ }
3487
+
3488
+ // Now revoke the cleanups, as we pass responsibility for the data
3489
+ // structure onto the caller.
3490
+ for temp_cleanups. each |temp_cleanup| {
3491
+ revoke_clean ( block_context, temp_cleanup) ;
3492
+ }
3493
+
3494
+ block_context
3495
+ }
3496
+
3413
3497
// Store the result of an expression in the given memory location, ensuring
3414
3498
// that nil or bot expressions get ignore rather than save_in as destination.
3415
3499
fn trans_expr_save_in( bcx: block, e: @ast:: expr, dest: ValueRef )
@@ -3558,6 +3642,9 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
3558
3642
ast:: expr_rec ( args, base) {
3559
3643
ret trans_rec ( bcx, args, base, e. id , dest) ;
3560
3644
}
3645
+ ast:: expr_struct ( _, fields) {
3646
+ ret trans_struct ( bcx, e. span , fields, e. id , dest) ;
3647
+ }
3561
3648
ast:: expr_tup ( args) { ret trans_tup ( bcx, args, dest) ; }
3562
3649
ast:: expr_vstore ( e, v) { ret tvec:: trans_vstore ( bcx, e, v, dest) ; }
3563
3650
ast:: expr_lit ( lit) { ret trans_lit ( bcx, e, * lit, dest) ; }
0 commit comments