@@ -2112,7 +2112,6 @@ fn move_val(cx: @block_ctxt, action: copy_action, dst: ValueRef,
2112
2112
ty_to_str ( tcx, t) ) ;
2113
2113
}
2114
2114
2115
- // FIXME[DPS] rename to store_temp_expr
2116
2115
fn move_val_if_temp ( cx : @block_ctxt , action : copy_action , dst : ValueRef ,
2117
2116
src : lval_result , t : ty:: t ) -> @block_ctxt {
2118
2117
// Lvals in memory are not temporaries. Copy them.
@@ -2214,7 +2213,7 @@ fn trans_unary(bcx: @block_ctxt, op: ast::unop, e: @ast::expr,
2214
2213
let llety = T_ptr ( type_of ( ccx, e_sp, e_ty) ) ;
2215
2214
body = PointerCast ( bcx, body, llety) ;
2216
2215
}
2217
- bcx = trans_expr_save_in ( bcx, e, body) ;
2216
+ bcx = trans_expr_save_in ( bcx, e, body, INIT ) ;
2218
2217
revoke_clean ( bcx, box) ;
2219
2218
ret store_in_dest ( bcx, box, dest) ;
2220
2219
}
@@ -2256,7 +2255,8 @@ fn trans_expr_fn(bcx: @block_ctxt, f: ast::_fn, sp: span,
2256
2255
trans_closure ( sub_cx, sp, f, llfn, none, [ ] , id, { |_fcx|} ) ;
2257
2256
}
2258
2257
} ;
2259
- fill_fn_pair ( bcx, get_dest_addr ( dest) , llfn, env) ;
2258
+ let { bcx, val: addr } = get_dest_addr ( bcx, dest) ;
2259
+ fill_fn_pair ( bcx, addr, llfn, env) ;
2260
2260
ret bcx;
2261
2261
}
2262
2262
@@ -2357,18 +2357,19 @@ fn trans_assign_op(bcx: @block_ctxt, op: ast::binop, dst: @ast::expr,
2357
2357
}
2358
2358
_ { }
2359
2359
}
2360
- let { bcx , val : rhs_val } = trans_expr ( lhs_res. bcx , src) ;
2360
+ let rhs_res = trans_expr ( lhs_res. bcx , src) ;
2361
2361
if ty:: type_is_sequence ( tcx, t) {
2362
2362
alt op {
2363
2363
ast : : add. {
2364
- ret tvec:: trans_append ( bcx, t, lhs_res. val , rhs_val) ;
2364
+ ret tvec:: trans_append ( rhs_res. bcx , t, lhs_res. val ,
2365
+ rhs_res. val ) ;
2365
2366
}
2366
2367
_ { }
2367
2368
}
2368
2369
}
2369
-
2370
- ret trans_eager_binop( bcx, op, Load ( bcx , lhs_res . val ) , t, rhs_val , t,
2371
- save_in ( lhs_res. val ) ) ;
2370
+ let lhs_val = load_if_immediate ( rhs_res . bcx , lhs_res . val , t ) ;
2371
+ ret trans_eager_binop ( rhs_res . bcx , op, lhs_val , t, rhs_res . val , t,
2372
+ overwrite ( lhs_res. val , t ) ) ;
2372
2373
}
2373
2374
2374
2375
fn autoderef ( cx : @block_ctxt , v : ValueRef , t : ty:: t ) -> result_t {
@@ -2484,6 +2485,7 @@ tag dest {
2484
2485
by_val( @mutable ValueRef ) ;
2485
2486
by_ref ( @mutable ValueRef ) ;
2486
2487
save_in ( ValueRef ) ;
2488
+ overwrite ( ValueRef , ty:: t) ;
2487
2489
ignore;
2488
2490
}
2489
2491
@@ -2536,12 +2538,19 @@ fn store_in_dest(bcx: @block_ctxt, val: ValueRef, dest: dest) -> @block_ctxt {
2536
2538
ignore. { }
2537
2539
by_val ( cell) { * cell = val; }
2538
2540
save_in ( addr) { Store ( bcx, val, addr) ; }
2541
+ overwrite ( addr, tp) {
2542
+ bcx = drop_ty ( bcx, addr, tp) ;
2543
+ Store ( bcx, val, addr) ;
2544
+ }
2539
2545
}
2540
2546
ret bcx;
2541
2547
}
2542
2548
2543
- fn get_dest_addr ( dest : dest ) -> ValueRef {
2544
- alt dest { save_in( a) { a } }
2549
+ fn get_dest_addr ( bcx : @block_ctxt , dest : dest ) -> result {
2550
+ alt dest {
2551
+ save_in( a) { rslt ( bcx, a) }
2552
+ overwrite ( a, t) { rslt ( drop_ty ( bcx, a, t) , a) }
2553
+ }
2545
2554
}
2546
2555
2547
2556
// Wrapper through which legacy non-DPS code can use DPS functions
@@ -2724,7 +2733,7 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
2724
2733
bcx = bound. bcx ;
2725
2734
alt bv {
2726
2735
env_expr( e) {
2727
- bcx = trans_expr_save_in ( bcx, e, bound. val ) ;
2736
+ bcx = trans_expr_save_in ( bcx, e, bound. val , INIT ) ;
2728
2737
add_clean_temp_mem ( bcx, bound. val , bound_tys[ i] ) ;
2729
2738
temp_cleanups += [ bound. val ] ;
2730
2739
}
@@ -3689,7 +3698,8 @@ fn trans_bind_1(cx: @block_ctxt, outgoing_fty: ty::t,
3689
3698
let lv = lval_maybe_callee_to_lval ( f_res, pair_ty) ;
3690
3699
bcx = lv. bcx ;
3691
3700
// FIXME[DPS] factor this out
3692
- ret memmove_ty( bcx, get_dest_addr ( dest) , lv. val , pair_ty) ;
3701
+ let { bcx, val: addr } = get_dest_addr ( bcx, dest) ;
3702
+ ret memmove_ty( bcx, addr, lv. val , pair_ty) ;
3693
3703
}
3694
3704
let closure = alt f_res. env {
3695
3705
null_env. { none }
@@ -3726,7 +3736,8 @@ fn trans_bind_1(cx: @block_ctxt, outgoing_fty: ty::t,
3726
3736
closure. ptrty , ty_param_count, target_res) ;
3727
3737
3728
3738
// Fill the function pair
3729
- fill_fn_pair ( bcx, get_dest_addr ( dest) , llthunk. val , closure. ptr ) ;
3739
+ let { bcx, val: addr } = get_dest_addr ( bcx, dest) ;
3740
+ fill_fn_pair ( bcx, addr, llthunk. val , closure. ptr ) ;
3730
3741
ret bcx;
3731
3742
}
3732
3743
@@ -3834,7 +3845,7 @@ fn trans_args(cx: @block_ctxt, outer_cx: @block_ctxt, llenv: ValueRef,
3834
3845
} else { alloca ( cx, llretty) }
3835
3846
}
3836
3847
save_in ( dst) { dst }
3837
- by_val ( _) { alloca ( cx, llretty) }
3848
+ overwrite ( _ , _ ) | by_val ( _) { alloca ( cx, llretty) }
3838
3849
by_ref ( _) { dest_ref = true ; alloca ( cx, T_ptr ( llretty) ) }
3839
3850
} ;
3840
3851
// FIXME[DSP] does this always hold?
@@ -3959,6 +3970,10 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
3959
3970
}
3960
3971
}
3961
3972
save_in ( _) { } // Already saved by callee
3973
+ overwrite ( a, t) {
3974
+ bcx = drop_ty ( bcx, a, t) ;
3975
+ bcx = memmove_ty ( bcx, a, llretslot, ret_ty) ;
3976
+ }
3962
3977
by_ref ( cell) | by_val ( cell) {
3963
3978
* cell = Load ( bcx, llretslot) ;
3964
3979
}
@@ -4152,38 +4167,55 @@ fn trans_landing_pad(bcx: @block_ctxt,
4152
4167
fn trans_tup ( bcx : @block_ctxt , elts : [ @ast:: expr ] , id : ast:: node_id ,
4153
4168
dest : dest ) -> @block_ctxt {
4154
4169
let t = node_id_type ( bcx. fcx . lcx . ccx , id) ;
4155
- let addr = alt dest {
4170
+ let ( addr, overwrite ) = alt dest {
4156
4171
ignore. {
4157
4172
for ex in elts { bcx = trans_expr_dps ( bcx, ex, ignore) ; }
4158
4173
ret bcx;
4159
4174
}
4160
- save_in ( pos) { pos }
4175
+ save_in ( pos) { ( pos, none) }
4176
+ overwrite ( pos, _) {
4177
+ let scratch = alloca ( bcx, llvm:: LLVMGetElementType ( val_ty ( pos) ) ) ;
4178
+ ( scratch, some ( pos) )
4179
+ }
4161
4180
} ;
4162
4181
let temp_cleanups = [ ] , i = 0 ;
4163
4182
for e in elts {
4164
4183
let dst = GEP_tup_like_1 ( bcx, t, addr, [ 0 , i] ) ;
4165
4184
let e_ty = ty:: expr_ty ( bcx_tcx ( bcx) , e) ;
4166
- bcx = trans_expr_save_in ( dst. bcx , e, dst. val ) ;
4185
+ bcx = trans_expr_save_in ( dst. bcx , e, dst. val , INIT ) ;
4167
4186
add_clean_temp_mem ( bcx, dst. val , e_ty) ;
4168
4187
temp_cleanups += [ dst. val ] ;
4169
4188
i += 1 ;
4170
4189
}
4171
4190
for cleanup in temp_cleanups { revoke_clean ( bcx, cleanup) ; }
4191
+ alt overwrite {
4192
+ some( pos) {
4193
+ bcx = drop_ty ( bcx, pos, t) ;
4194
+ bcx = memmove_ty ( bcx, pos, addr, t) ;
4195
+ }
4196
+ none. { }
4197
+ }
4172
4198
ret bcx ;
4173
4199
}
4174
4200
4175
4201
fn trans_rec ( bcx : @block_ctxt , fields : [ ast:: field ] ,
4176
4202
base : option:: t < @ast:: expr > , id : ast:: node_id ,
4177
4203
dest : dest ) -> @block_ctxt {
4178
4204
let t = node_id_type ( bcx_ccx ( bcx) , id) ;
4179
- let addr = alt dest {
4205
+ let ( addr, overwrite ) = alt dest {
4180
4206
ignore. {
4181
4207
for fld in fields {
4182
4208
bcx = trans_expr_dps ( bcx, fld. node . expr , ignore) ;
4183
4209
}
4184
4210
ret bcx;
4185
4211
}
4186
- save_in ( pos) { pos }
4212
+ save_in ( pos) { ( pos, none) }
4213
+ // The expressions that populate the fields might still use the old
4214
+ // record, so we build the new on in a scratch area
4215
+ overwrite ( pos, _) {
4216
+ let scratch = alloca ( bcx, llvm:: LLVMGetElementType ( val_ty ( pos) ) ) ;
4217
+ ( scratch, some ( pos) )
4218
+ }
4187
4219
} ;
4188
4220
4189
4221
let base_val = alt base {
@@ -4202,7 +4234,7 @@ fn trans_rec(bcx: @block_ctxt, fields: [ast::field],
4202
4234
bcx = dst. bcx ;
4203
4235
alt vec:: find ( { |f| str:: eq ( f. node . ident , tf. ident ) } , fields) {
4204
4236
some ( f) {
4205
- bcx = trans_expr_save_in ( bcx, f. node . expr , dst. val ) ;
4237
+ bcx = trans_expr_save_in ( bcx, f. node . expr , dst. val , INIT ) ;
4206
4238
}
4207
4239
none. {
4208
4240
let base = GEP_tup_like_1 ( bcx, t, base_val, [ 0 , i] ) ;
@@ -4217,6 +4249,13 @@ fn trans_rec(bcx: @block_ctxt, fields: [ast::field],
4217
4249
// Now revoke the cleanups as we pass responsibility for the data
4218
4250
// structure on to the caller
4219
4251
for cleanup in temp_cleanups { revoke_clean ( bcx, cleanup) ; }
4252
+ alt overwrite {
4253
+ some( pos) {
4254
+ bcx = drop_ty ( bcx, pos, t) ;
4255
+ bcx = memmove_ty ( bcx, pos, addr, t) ;
4256
+ }
4257
+ none. { }
4258
+ }
4220
4259
ret bcx ;
4221
4260
}
4222
4261
@@ -4235,37 +4274,19 @@ fn trans_expr(cx: @block_ctxt, e: @ast::expr) -> result {
4235
4274
}
4236
4275
}
4237
4276
4238
- fn trans_expr_save_in ( bcx : @block_ctxt , e : @ast:: expr , dest : ValueRef )
4239
- -> @block_ctxt {
4277
+ fn trans_expr_save_in ( bcx : @block_ctxt , e : @ast:: expr , dest : ValueRef ,
4278
+ kind : copy_action ) -> @block_ctxt {
4240
4279
let tcx = bcx_tcx ( bcx) , t = ty:: expr_ty ( tcx, e) ;
4241
4280
let dst = if ty:: type_is_bot ( tcx, t) || ty:: type_is_nil ( tcx, t) {
4242
4281
ignore
4243
- } else { save_in ( dest) } ;
4244
- ret trans_expr_dps ( bcx, e, dst) ;
4245
- }
4246
-
4247
- fn trans_temp_expr ( bcx : @block_ctxt , e : @ast:: expr ) -> lval_result {
4248
- if expr_is_lval ( bcx_tcx ( bcx) , e) {
4249
- ret trans_lval ( bcx, e) ;
4282
+ } else if kind == INIT {
4283
+ save_in ( dest)
4250
4284
} else {
4251
- let tcx = bcx_tcx ( bcx) ;
4252
- let ty = ty:: expr_ty ( tcx, e) ;
4253
- if ty:: type_is_nil ( tcx, ty) || ty:: type_is_bot ( tcx, ty) {
4254
- bcx = trans_expr_dps ( bcx, e, ignore) ;
4255
- ret { bcx : bcx, val : C_nil ( ) , is_mem : false } ;
4256
- } else if type_is_immediate ( bcx_ccx ( bcx) , ty) {
4257
- let cell = empty_dest_cell ( ) ;
4258
- bcx = trans_expr_dps ( bcx, e, by_val ( cell) ) ;
4259
- ret { bcx : bcx, val : * cell, is_mem : false } ;
4260
- } else {
4261
- let { bcx, val: scratch } = alloc_ty ( bcx, ty) ;
4262
- bcx = trans_expr_dps ( bcx, e, save_in ( scratch) ) ;
4263
- ret { bcx : bcx, val : scratch, is_mem : false } ;
4264
- }
4265
- }
4285
+ overwrite ( dest, t)
4286
+ } ;
4287
+ ret trans_expr_dps ( bcx, e, dst) ;
4266
4288
}
4267
4289
4268
- // FIXME[DPS] supersede by trans_temp_expr, get rid of by_ref dests
4269
4290
fn trans_expr_by_ref ( bcx : @block_ctxt , e : @ast:: expr ) -> result {
4270
4291
let cell = empty_dest_cell ( ) ;
4271
4292
bcx = trans_expr_dps ( bcx, e, by_ref ( cell) ) ;
@@ -4409,20 +4430,22 @@ fn trans_expr_dps(bcx: @block_ctxt, e: @ast::expr, dest: dest)
4409
4430
}
4410
4431
ast:: expr_assign ( dst, src) {
4411
4432
assert dest == ignore;
4412
- let src_r = trans_temp_expr ( bcx, src) ;
4413
- let { bcx, val: addr , is_mem } = trans_lval ( src_r. bcx , dst) ;
4433
+ let { bcx, val: lhs_addr , is_mem} = trans_lval ( bcx, dst) ;
4414
4434
assert is_mem;
4415
- ret move_val_if_temp ( bcx, DROP_EXISTING , addr, src_r,
4416
- ty:: expr_ty ( bcx_tcx ( bcx) , src) ) ;
4435
+ ret trans_expr_save_in ( bcx, src, lhs_addr, DROP_EXISTING ) ;
4417
4436
}
4418
4437
ast:: expr_move ( dst, src) {
4419
- // FIXME: calculate copy init-ness in typestate.
4420
4438
assert dest == ignore;
4421
- let src_r = trans_temp_expr ( bcx, src) ;
4422
- let { bcx, val: addr , is_mem } = trans_lval ( src_r. bcx , dst) ;
4439
+ let { bcx, val: addr , is_mem } = trans_lval ( bcx, dst) ;
4423
4440
assert is_mem;
4424
- ret move_val( bcx, DROP_EXISTING , addr, src_r,
4425
- ty:: expr_ty ( bcx_tcx ( bcx) , src) ) ;
4441
+ // FIXME: calculate copy init-ness in typestate.
4442
+ if expr_is_lval ( tcx, src) {
4443
+ ret trans_expr_save_in ( bcx, src, addr, DROP_EXISTING ) ;
4444
+ } else {
4445
+ let srclv = trans_lval ( bcx, src) ;
4446
+ let t = ty:: expr_ty ( tcx, src) ;
4447
+ ret move_val( srclv. bcx , DROP_EXISTING , addr, srclv, t) ;
4448
+ }
4426
4449
}
4427
4450
ast:: expr_swap ( dst, src) {
4428
4451
assert dest == ignore;
@@ -4469,6 +4492,9 @@ fn lval_to_dps(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
4469
4492
* cell = val;
4470
4493
}
4471
4494
save_in ( loc) { bcx = move_val_if_temp ( bcx, INIT , loc, lv, ty) ; }
4495
+ overwrite ( loc, _) {
4496
+ bcx = move_val_if_temp ( bcx, DROP_EXISTING , loc, lv, ty) ;
4497
+ }
4472
4498
ignore. { }
4473
4499
}
4474
4500
ret bcx;
@@ -4720,7 +4746,7 @@ fn trans_ret(bcx: @block_ctxt, e: option::t<@ast::expr>) -> @block_ctxt {
4720
4746
Store ( cx, val, bcx. fcx . llretptr ) ;
4721
4747
bcx = cx;
4722
4748
} else {
4723
- bcx = trans_expr_save_in ( bcx, x, bcx. fcx . llretptr ) ;
4749
+ bcx = trans_expr_save_in ( bcx, x, bcx. fcx . llretptr , INIT ) ;
4724
4750
}
4725
4751
}
4726
4752
_ { }
@@ -4758,7 +4784,7 @@ fn init_local(bcx: @block_ctxt, local: @ast::local) -> @block_ctxt {
4758
4784
some ( init) {
4759
4785
if init. op == ast:: init_assign ||
4760
4786
!expr_is_lval ( bcx_tcx ( bcx) , init. expr ) {
4761
- bcx = trans_expr_save_in ( bcx, init. expr , llptr) ;
4787
+ bcx = trans_expr_save_in ( bcx, init. expr , llptr, INIT ) ;
4762
4788
} else { // This is a move from an lval, must perform an actual move
4763
4789
let sub = trans_lval ( bcx, init. expr ) ;
4764
4790
bcx = move_val ( sub. bcx , INIT , llptr, sub, ty) ;
0 commit comments