@@ -4002,32 +4002,30 @@ fn trans_landing_pad(bcx: @block_ctxt,
4002
4002
fn trans_tup ( bcx : @block_ctxt , elts : [ @ast:: expr ] , id : ast:: node_id ,
4003
4003
dest : dest ) -> @block_ctxt {
4004
4004
let t = node_id_type ( bcx. fcx . lcx . ccx , id) ;
4005
- let dst = alt dest { save_in( addr) { addr } } ;
4006
-
4007
- // Like trans_rec, we'll collect the fields of the tuple then build it, so
4008
- // that if we fail in between we don't have to deal with cleaning up a
4009
- // partial tuple
4010
- let tupfields = [ ] , i = 0 ;
4005
+ let temp_cleanups = [ ] , i = 0 ;
4011
4006
for e in elts {
4012
- let e_ty = ty:: expr_ty ( bcx_tcx ( bcx) , e) ;
4013
- let src = trans_lval ( bcx, e) ;
4014
- let dst_res = GEP_tup_like_1 ( src. bcx , t, dst, [ 0 , i] ) ;
4015
- bcx = dst_res. bcx ;
4016
- tupfields += [ ( dst_res. val , src, e_ty) ] ;
4007
+ alt dest {
4008
+ save_in( addr) {
4009
+ let dst = GEP_tup_like_1 ( bcx, t, addr, [ 0 , i] ) ;
4010
+ let e_ty = ty:: expr_ty ( bcx_tcx ( bcx) , e) ;
4011
+ bcx = trans_expr_save_in ( dst. bcx , e, dst. val ) ;
4012
+ add_clean_temp_mem ( bcx, dst. val , e_ty) ;
4013
+ temp_cleanups += [ dst. val ] ;
4014
+ }
4015
+ ignore. {
4016
+ bcx = trans_expr_dps ( bcx, e, ignore) ;
4017
+ }
4018
+ }
4017
4019
i += 1 ;
4018
4020
}
4019
- // Fill in the tuple fields
4020
- for ( dst, src, t) in tupfields {
4021
- bcx = move_val_if_temp ( bcx, INIT , dst, src, t) ;
4022
- }
4021
+ for cleanup in temp_cleanups { revoke_clean ( bcx, cleanup) ; }
4023
4022
ret bcx;
4024
4023
}
4025
4024
4026
4025
fn trans_rec ( bcx : @block_ctxt , fields : [ ast:: field ] ,
4027
4026
base : option:: t < @ast:: expr > , id : ast:: node_id ,
4028
4027
dest : dest ) -> @block_ctxt {
4029
4028
let t = node_id_type ( bcx_ccx ( bcx) , id) ;
4030
- let dst = alt dest { save_in( addr) { addr } } ;
4031
4029
4032
4030
let base_val = alt base {
4033
4031
some( bexp) {
@@ -4038,58 +4036,50 @@ fn trans_rec(bcx: @block_ctxt, fields: [ast::field],
4038
4036
none. { C_nil ( ) }
4039
4037
} ;
4040
4038
4041
- tag fieldsrc {
4042
- provided( lval_result) ;
4043
- inherited ( ValueRef ) ;
4044
- }
4045
- type fieldval = {
4046
- dst : ValueRef ,
4047
- src : fieldsrc ,
4048
- ty: ty:: t
4049
- } ;
4050
-
4051
4039
let ty_fields = alt ty:: struct ( bcx_tcx ( bcx) , t) { ty:: ty_rec ( f) { f } } ;
4052
- let fieldvals = [ ] , i = 0 ;
4053
- // We build the record in two stages so that we don't have to clean up a
4054
- // partial record if we fail: first collect all the values, then construct
4055
- // the record.
4040
+ let temp_cleanups = [ ] , i = 0 ;
4056
4041
for tf in ty_fields {
4057
- let { bcx: a_bcx , val: addr} = GEP_tup_like_1 ( bcx, t, dst, [ 0 , i] ) ;
4058
- bcx = a_bcx;
4059
- // FIXME make this happen in a single pass, again, somehow make the
4060
- // dps helpers tie the cleanups together in the right way (we do not
4061
- // want to create intermediates for these and then move them again)
4062
- fn test ( n : str , f : ast:: field ) -> bool { str:: eq ( f. node . ident , n) }
4042
+ let fdest = alt dest {
4043
+ save_in( addr) {
4044
+ let gep = GEP_tup_like_1 ( bcx, t, addr, [ 0 , i] ) ;
4045
+ bcx = gep. bcx ;
4046
+ some ( gep. val )
4047
+ }
4048
+ ignore. { none }
4049
+ } ;
4063
4050
// FIXME make this {|f| str::eq(f.node.ident, tf.ident)} again when
4064
4051
// bug #913 is fixed
4065
- let s = alt vec:: find ( bind test ( tf. ident , _) , fields) {
4066
- some ( f) {
4067
- let lv = trans_lval ( bcx, f. node . expr ) ;
4068
- bcx = lv. bcx ;
4069
- provided ( lv)
4052
+ fn test ( n : str , f : ast:: field ) -> bool { str:: eq ( f. node . ident , n) }
4053
+ alt vec:: find ( bind test ( tf. ident , _) , fields) {
4054
+ some ( f) {
4055
+ alt fdest {
4056
+ some( x) { bcx = trans_expr_save_in ( bcx, f. node . expr , x) ; }
4057
+ none. { bcx = trans_expr_dps ( bcx, f. node . expr , ignore) ; }
4070
4058
}
4071
- none. {
4072
- let src_res = GEP_tup_like_1 ( bcx, t, base_val, [ 0 , i] ) ;
4073
- bcx = src_res. bcx ;
4074
- inherited ( src_res. val )
4059
+ }
4060
+ none. {
4061
+ alt fdest {
4062
+ some( addr) {
4063
+ let gep = GEP_tup_like_1 ( bcx, t, base_val, [ 0 , i] ) ;
4064
+ let val = load_if_immediate ( gep. bcx , gep. val , tf. mt . ty ) ;
4065
+ bcx = copy_val ( gep. bcx , INIT , addr, val, tf. mt . ty ) ;
4066
+ }
4067
+ none. { }
4075
4068
}
4076
- } ;
4077
- fieldvals += [ { dst: addr, src: s, ty: tf. mt . ty } ] ;
4078
- i += 1 ;
4079
- }
4080
- // Now build the record
4081
- for fieldval in fieldvals {
4082
- alt fieldval. src {
4083
- provided ( lv) {
4084
- bcx = move_val_if_temp ( bcx, INIT , fieldval. dst ,
4085
- lv, fieldval. ty ) ;
4086
4069
}
4087
- inherited ( val) {
4088
- let val = load_if_immediate ( bcx, val, fieldval. ty ) ;
4089
- bcx = copy_val ( bcx, INIT , fieldval. dst , val, fieldval. ty ) ;
4070
+ }
4071
+ alt fdest {
4072
+ some( addr) {
4073
+ add_clean_temp_mem ( bcx, addr, tf. mt . ty ) ;
4074
+ temp_cleanups += [ addr] ;
4090
4075
}
4076
+ none. { }
4091
4077
}
4078
+ i += 1 ;
4092
4079
}
4080
+ // Now revoke the cleanups as we pass responsibility for the data
4081
+ // structure on to the caller
4082
+ for cleanup in temp_cleanups { revoke_clean ( bcx, cleanup) ; }
4093
4083
ret bcx;
4094
4084
}
4095
4085
0 commit comments