@@ -4029,30 +4029,56 @@ fn trans_landing_pad(bcx: @block_ctxt,
4029
4029
fn trans_tup ( bcx : @block_ctxt , elts : [ @ast:: expr ] , id : ast:: node_id ,
4030
4030
dest : dest ) -> @block_ctxt {
4031
4031
let t = node_id_type ( bcx. fcx . lcx . ccx , id) ;
4032
+ let ( addr, overwrite) = alt dest {
4033
+ ignore. {
4034
+ for ex in elts { bcx = trans_expr_dps ( bcx, ex, ignore) ; }
4035
+ ret bcx;
4036
+ }
4037
+ save_in ( pos) { ( pos, none) }
4038
+ overwrite ( pos, _) {
4039
+ let scratch = alloca ( bcx, val_ty ( pos) ) ;
4040
+ ( scratch, some ( pos) )
4041
+ }
4042
+ } ;
4032
4043
let temp_cleanups = [ ] , i = 0 ;
4033
4044
for e in elts {
4034
- alt dest {
4035
- save_in( addr) {
4036
- let dst = GEP_tup_like_1 ( bcx, t, addr, [ 0 , i] ) ;
4037
- let e_ty = ty:: expr_ty ( bcx_tcx ( bcx) , e) ;
4038
- bcx = trans_expr_save_in ( dst. bcx , e, dst. val ) ;
4039
- add_clean_temp_mem ( bcx, dst. val , e_ty) ;
4040
- temp_cleanups += [ dst. val ] ;
4041
- }
4042
- ignore. {
4043
- bcx = trans_expr_dps ( bcx, e, ignore) ;
4044
- }
4045
- }
4045
+ let dst = GEP_tup_like_1 ( bcx, t, addr, [ 0 , i] ) ;
4046
+ let e_ty = ty:: expr_ty ( bcx_tcx ( bcx) , e) ;
4047
+ bcx = trans_expr_save_in ( dst. bcx , e, dst. val ) ;
4048
+ add_clean_temp_mem ( bcx, dst. val , e_ty) ;
4049
+ temp_cleanups += [ dst. val ] ;
4046
4050
i += 1 ;
4047
4051
}
4048
4052
for cleanup in temp_cleanups { revoke_clean ( bcx, cleanup) ; }
4053
+ alt overwrite {
4054
+ some( pos) {
4055
+ bcx = drop_ty ( bcx, pos, t) ;
4056
+ bcx = memmove_ty ( bcx, pos, addr, t) ;
4057
+ }
4058
+ none. { }
4059
+ }
4049
4060
ret bcx ;
4050
4061
}
4051
4062
4052
4063
fn trans_rec ( bcx : @block_ctxt , fields : [ ast:: field ] ,
4053
4064
base : option:: t < @ast:: expr > , id : ast:: node_id ,
4054
4065
dest : dest ) -> @block_ctxt {
4055
4066
let t = node_id_type ( bcx_ccx ( bcx) , id) ;
4067
+ let ( addr, overwrite) = alt dest {
4068
+ ignore. {
4069
+ for fld in fields {
4070
+ bcx = trans_expr_dps ( bcx, fld. node . expr , ignore) ;
4071
+ }
4072
+ ret bcx;
4073
+ }
4074
+ save_in ( pos) { ( pos, none) }
4075
+ // The expressions that populate the fields might still use the old
4076
+ // record, so we build the new on in a scratch area
4077
+ overwrite ( pos, _) {
4078
+ let scratch = alloca ( bcx, val_ty ( pos) ) ;
4079
+ ( scratch, some ( pos) )
4080
+ }
4081
+ } ;
4056
4082
4057
4083
let base_val = alt base {
4058
4084
some( bexp) {
@@ -4063,55 +4089,38 @@ fn trans_rec(bcx: @block_ctxt, fields: [ast::field],
4063
4089
none. { C_nil ( ) }
4064
4090
} ;
4065
4091
4066
- let ty_fields = alt ty:: struct ( bcx_tcx ( bcx) , t) {
4067
- ty:: ty_rec ( f) { f }
4068
- ty:: ty_bot. {
4069
- bcx_ccx ( bcx) . sess . bug ( "https://github.com/graydon/rust/issues/924" )
4070
- }
4071
- } ;
4092
+ let ty_fields = alt ty:: struct ( bcx_tcx ( bcx) , t) { ty:: ty_rec ( f) { f } } ;
4072
4093
let temp_cleanups = [ ] , i = 0 ;
4073
4094
for tf in ty_fields {
4074
- let fdest = alt dest {
4075
- save_in( addr) {
4076
- let gep = GEP_tup_like_1 ( bcx, t, addr, [ 0 , i] ) ;
4077
- bcx = gep. bcx ;
4078
- some ( gep. val )
4079
- }
4080
- ignore. { none }
4081
- } ;
4095
+ let gep = GEP_tup_like_1 ( bcx, t, addr, [ 0 , i] ) ;
4096
+ bcx = gep. bcx ;
4082
4097
// FIXME make this {|f| str::eq(f.node.ident, tf.ident)} again when
4083
4098
// bug #913 is fixed
4084
4099
fn test ( n : str , f : ast:: field ) -> bool { str:: eq ( f. node . ident , n) }
4085
4100
alt vec:: find ( bind test ( tf. ident , _) , fields) {
4086
4101
some ( f) {
4087
- alt fdest {
4088
- some( x) { bcx = trans_expr_save_in ( bcx, f. node . expr , x) ; }
4089
- none. { bcx = trans_expr_dps ( bcx, f. node . expr , ignore) ; }
4090
- }
4102
+ bcx = trans_expr_save_in ( bcx, f. node . expr , gep. val ) ;
4091
4103
}
4092
4104
none. {
4093
- alt fdest {
4094
- some( addr) {
4095
- let gep = GEP_tup_like_1 ( bcx, t, base_val, [ 0 , i] ) ;
4096
- let val = load_if_immediate ( gep. bcx , gep. val , tf. mt . ty ) ;
4097
- bcx = copy_val ( gep. bcx , INIT , addr, val, tf. mt . ty ) ;
4098
- }
4099
- none. { }
4100
- }
4101
- }
4102
- }
4103
- alt fdest {
4104
- some( addr) {
4105
- add_clean_temp_mem ( bcx, addr, tf. mt . ty ) ;
4106
- temp_cleanups += [ addr] ;
4105
+ let base = GEP_tup_like_1 ( bcx, t, base_val, [ 0 , i] ) ;
4106
+ let val = load_if_immediate ( base. bcx , base. val , tf. mt . ty ) ;
4107
+ bcx = copy_val ( base. bcx , INIT , gep. val , val, tf. mt . ty ) ;
4107
4108
}
4108
- none. { }
4109
4109
}
4110
+ add_clean_temp_mem ( bcx, addr, tf. mt . ty ) ;
4111
+ temp_cleanups += [ addr] ;
4110
4112
i += 1 ;
4111
4113
}
4112
4114
// Now revoke the cleanups as we pass responsibility for the data
4113
4115
// structure on to the caller
4114
4116
for cleanup in temp_cleanups { revoke_clean ( bcx, cleanup) ; }
4117
+ alt overwrite {
4118
+ some( pos) {
4119
+ bcx = drop_ty ( bcx, pos, t) ;
4120
+ bcx = memmove_ty ( bcx, pos, addr, t) ;
4121
+ }
4122
+ none. { }
4123
+ }
4115
4124
ret bcx ;
4116
4125
}
4117
4126
0 commit comments