@@ -2158,10 +2158,7 @@ fn trans_lit(cx: @block_ctxt, lit: ast::lit, dest: dest) -> @block_ctxt {
2158
2158
alt lit. node {
2159
2159
ast:: lit_str ( s) { ret tvec:: trans_str ( cx, s, dest) ; }
2160
2160
_ {
2161
- let cell = alt dest { by_val( c) { c }
2162
- _ { bcx_ccx( cx) . sess . span_note ( lit. span , "here" ) ; fail; } } ;
2163
- * cell = trans_crate_lit ( bcx_ccx ( cx) , lit) ;
2164
- ret cx;
2161
+ ret store_in_dest( cx, trans_crate_lit ( bcx_ccx ( cx) , lit) , dest) ;
2165
2162
}
2166
2163
}
2167
2164
}
@@ -2253,8 +2250,9 @@ fn trans_compare(cx: @block_ctxt, op: ast::binop, lhs: ValueRef,
2253
2250
// Important to get types for both lhs and rhs, because one might be _|_
2254
2251
// and the other not.
2255
2252
fn trans_eager_binop ( cx : @block_ctxt , op : ast:: binop , lhs : ValueRef ,
2256
- lhs_t : ty:: t , rhs : ValueRef , rhs_t : ty:: t ) -> result {
2257
-
2253
+ lhs_t : ty:: t , rhs : ValueRef , rhs_t : ty:: t , dest : dest )
2254
+ -> @block_ctxt {
2255
+ if dest == ignore { ret cx; }
2258
2256
let is_float = false ;
2259
2257
let intype = lhs_t;
2260
2258
if ty:: type_is_bot ( bcx_tcx ( cx) , intype) { intype = rhs_t; }
@@ -2263,45 +2261,47 @@ fn trans_eager_binop(cx: @block_ctxt, op: ast::binop, lhs: ValueRef,
2263
2261
ty:: ty_float. { is_float = true ; }
2264
2262
_ { is_float = false ; }
2265
2263
}
2266
- alt op {
2264
+ if op == ast:: add && ty:: type_is_sequence ( bcx_tcx ( cx) , intype) {
2265
+ ret tvec:: trans_add ( cx, intype, lhs, rhs, dest) ;
2266
+ }
2267
+ let val = alt op {
2267
2268
ast : : add. {
2268
- if ty:: type_is_sequence ( bcx_tcx ( cx) , intype) {
2269
- ret tvec:: trans_add ( cx, intype, lhs, rhs) ;
2270
- }
2271
- if is_float {
2272
- ret rslt ( cx, FAdd ( cx, lhs, rhs) ) ;
2273
- } else { ret rslt ( cx, Add ( cx, lhs, rhs) ) ; }
2269
+ if is_float { FAdd ( cx, lhs, rhs) }
2270
+ else { Add ( cx, lhs, rhs) }
2274
2271
}
2275
2272
ast:: sub. {
2276
- if is_float {
2277
- ret rslt ( cx, FSub ( cx, lhs, rhs) ) ;
2278
- } else { ret rslt ( cx, Sub ( cx, lhs, rhs) ) ; }
2273
+ if is_float { FSub ( cx, lhs, rhs) }
2274
+ else { Sub ( cx, lhs, rhs) }
2279
2275
}
2280
2276
ast:: mul. {
2281
- if is_float {
2282
- ret rslt ( cx, FMul ( cx, lhs, rhs) ) ;
2283
- } else { ret rslt ( cx, Mul ( cx, lhs, rhs) ) ; }
2277
+ if is_float { FMul ( cx, lhs, rhs) }
2278
+ else { Mul ( cx, lhs, rhs) }
2284
2279
}
2285
2280
ast:: div. {
2286
- if is_float { ret rslt ( cx , FDiv ( cx, lhs, rhs) ) ; }
2287
- if ty:: type_is_signed ( bcx_tcx ( cx) , intype) {
2288
- ret rslt ( cx , SDiv ( cx, lhs, rhs) ) ;
2289
- } else { ret rslt ( cx , UDiv ( cx, lhs, rhs) ) ; }
2281
+ if is_float { FDiv ( cx, lhs, rhs) }
2282
+ else if ty:: type_is_signed ( bcx_tcx ( cx) , intype) {
2283
+ SDiv ( cx, lhs, rhs)
2284
+ } else { UDiv ( cx, lhs, rhs) }
2290
2285
}
2291
2286
ast:: rem. {
2292
- if is_float { ret rslt ( cx, FRem ( cx, lhs, rhs) ) ; }
2293
- if ty:: type_is_signed ( bcx_tcx ( cx) , intype) {
2294
- ret rslt ( cx, SRem ( cx, lhs, rhs) ) ;
2295
- } else { ret rslt ( cx, URem ( cx, lhs, rhs) ) ; }
2287
+ if is_float { FRem ( cx, lhs, rhs) }
2288
+ else if ty:: type_is_signed ( bcx_tcx ( cx) , intype) {
2289
+ SRem ( cx, lhs, rhs)
2290
+ } else { URem ( cx, lhs, rhs) }
2291
+ }
2292
+ ast:: bitor. { Or ( cx, lhs, rhs) }
2293
+ ast:: bitand. { And ( cx, lhs, rhs) }
2294
+ ast:: bitxor. { Xor ( cx, lhs, rhs) }
2295
+ ast:: lsl. { Shl ( cx, lhs, rhs) }
2296
+ ast:: lsr. { LShr ( cx, lhs, rhs) }
2297
+ ast:: asr. { AShr ( cx, lhs, rhs) }
2298
+ _ {
2299
+ let cmpr = trans_compare ( cx, op, lhs, lhs_t, rhs, rhs_t) ;
2300
+ cx = cmpr. bcx ;
2301
+ cmpr. val
2296
2302
}
2297
- ast:: bitor. { ret rslt ( cx, Or ( cx, lhs, rhs) ) ; }
2298
- ast:: bitand. { ret rslt ( cx, And ( cx, lhs, rhs) ) ; }
2299
- ast:: bitxor. { ret rslt ( cx, Xor ( cx, lhs, rhs) ) ; }
2300
- ast:: lsl. { ret rslt ( cx, Shl ( cx, lhs, rhs) ) ; }
2301
- ast:: lsr. { ret rslt ( cx, LShr ( cx, lhs, rhs) ) ; }
2302
- ast:: asr. { ret rslt ( cx, AShr ( cx, lhs, rhs) ) ; }
2303
- _ { ret trans_compare( cx, op, lhs, lhs_t, rhs, rhs_t) ; }
2304
- }
2303
+ } ;
2304
+ ret store_in_dest ( cx, val, dest) ;
2305
2305
}
2306
2306
2307
2307
fn trans_assign_op ( bcx : @block_ctxt , op : ast:: binop , dst : @ast:: expr ,
@@ -2334,11 +2334,8 @@ fn trans_assign_op(bcx: @block_ctxt, op: ast::binop, dst: @ast::expr,
2334
2334
}
2335
2335
}
2336
2336
let lhs_val = load_if_immediate ( rhs_res. bcx , lhs_res. val , t) ;
2337
- let v = trans_eager_binop ( rhs_res. bcx , op, lhs_val, t, rhs_res. val , t) ;
2338
- // FIXME: calculate copy init-ness in typestate.
2339
- // This is always a temporary, so can always be safely moved
2340
- ret move_val( v. bcx , DROP_EXISTING , lhs_res. val ,
2341
- lval_val ( v. bcx , v. val ) , t) ;
2337
+ ret trans_eager_binop ( rhs_res. bcx , op, lhs_val, t, rhs_res. val , t,
2338
+ overwrite ( lhs_res. val , t) ) ;
2342
2339
}
2343
2340
2344
2341
fn autoderef ( cx : @block_ctxt , v : ValueRef , t : ty:: t ) -> result_t {
@@ -2390,84 +2387,55 @@ fn autoderef(cx: @block_ctxt, v: ValueRef, t: ty::t) -> result_t {
2390
2387
ret { bcx : cx, val : v1, ty : t1} ;
2391
2388
}
2392
2389
2393
- fn trans_binary ( cx : @block_ctxt , op : ast:: binop , a : @ast:: expr , b : @ast:: expr )
2394
- -> result {
2390
+ fn trans_lazy_binop ( bcx : @block_ctxt , op : ast:: binop , a : @ast:: expr ,
2391
+ b : @ast:: expr , dest : dest ) -> @block_ctxt {
2392
+ let is_and = alt op { ast : : and. { true } ast:: or. { false } } ;
2393
+ let lhs_res = trans_expr ( bcx, a) ;
2394
+ if lhs_res. bcx . unreachable { ret lhs_res. bcx ; }
2395
+ let rhs_cx = new_scope_block_ctxt ( lhs_res. bcx , "rhs" ) ;
2396
+ let rhs_res = trans_expr ( rhs_cx, b) ;
2397
+
2398
+ let lhs_past_cx = new_scope_block_ctxt ( lhs_res. bcx , "lhs" ) ;
2399
+ // The following line ensures that any cleanups for rhs
2400
+ // are done within the block for rhs. This is necessary
2401
+ // because and/or are lazy. So the rhs may never execute,
2402
+ // and the cleanups can't be pushed into later code.
2403
+ let rhs_bcx = trans_block_cleanups ( rhs_res. bcx , rhs_cx) ;
2404
+ if is_and {
2405
+ CondBr ( lhs_res. bcx , lhs_res. val , rhs_cx. llbb , lhs_past_cx. llbb ) ;
2406
+ } else {
2407
+ CondBr ( lhs_res. bcx , lhs_res. val , lhs_past_cx. llbb , rhs_cx. llbb ) ;
2408
+ }
2395
2409
2410
+ let join_cx = new_sub_block_ctxt ( bcx, "join" ) ;
2411
+ Br ( lhs_past_cx, join_cx. llbb ) ;
2412
+ if rhs_bcx. unreachable {
2413
+ ret store_in_dest ( join_cx, C_bool ( !is_and) , dest) ;
2414
+ }
2415
+ Br ( rhs_bcx, join_cx. llbb ) ;
2416
+ let phi = Phi ( join_cx, T_bool ( ) , [ C_bool ( !is_and) , rhs_res. val ] ,
2417
+ [ lhs_past_cx. llbb , rhs_bcx. llbb ] ) ;
2418
+ ret store_in_dest ( join_cx, phi, dest) ;
2419
+ }
2420
+
2421
+ fn trans_binary ( cx : @block_ctxt , op : ast:: binop , a : @ast:: expr , b : @ast:: expr ,
2422
+ dest : dest ) -> @block_ctxt {
2396
2423
// First couple cases are lazy:
2397
2424
alt op {
2398
- ast : : and. {
2399
- // Lazy-eval and
2400
- let lhs_res = trans_expr ( cx, a) ;
2401
- let rhs_cx = new_scope_block_ctxt ( lhs_res. bcx , "rhs" ) ;
2402
- let rhs_res = trans_expr ( rhs_cx, b) ;
2403
-
2404
- let lhs_false_cx = new_scope_block_ctxt ( lhs_res. bcx , "lhs false" ) ;
2405
- let lhs_false_res = rslt ( lhs_false_cx, C_bool ( false ) ) ;
2406
-
2407
- // The following line ensures that any cleanups for rhs
2408
- // are done within the block for rhs. This is necessary
2409
- // because and/or are lazy. So the rhs may never execute,
2410
- // and the cleanups can't be pushed into later code.
2411
- let rhs_bcx = trans_block_cleanups ( rhs_res. bcx , rhs_cx) ;
2412
- CondBr ( lhs_res. bcx , lhs_res. val , rhs_cx. llbb , lhs_false_cx. llbb ) ;
2413
- ret join_results ( cx, T_bool ( ) ,
2414
- [ lhs_false_res, { bcx: rhs_bcx, val: rhs_res. val } ] ) ;
2415
- }
2416
- ast:: or. {
2417
- // Lazy-eval or
2418
- let lhs_res = trans_expr ( cx, a) ;
2419
- let rhs_cx = new_scope_block_ctxt ( lhs_res. bcx , "rhs" ) ;
2420
- let rhs_res = trans_expr ( rhs_cx, b) ;
2421
- let lhs_true_cx = new_scope_block_ctxt ( lhs_res. bcx , "lhs true" ) ;
2422
- let lhs_true_res = rslt ( lhs_true_cx, C_bool ( true ) ) ;
2423
-
2424
- // see the and case for an explanation
2425
- let rhs_bcx = trans_block_cleanups ( rhs_res. bcx , rhs_cx) ;
2426
- CondBr ( lhs_res. bcx , lhs_res. val , lhs_true_cx. llbb , rhs_cx. llbb ) ;
2427
- ret join_results ( cx, T_bool ( ) ,
2428
- [ lhs_true_res, { bcx: rhs_bcx, val: rhs_res. val } ] ) ;
2425
+ ast : : and. | ast:: or . {
2426
+ ret trans_lazy_binop( cx, op, a, b, dest) ;
2429
2427
}
2430
2428
_ {
2431
2429
// Remaining cases are eager:
2432
2430
let lhs = trans_expr ( cx, a) ;
2433
2431
let rhs = trans_expr ( lhs. bcx , b) ;
2434
-
2435
2432
ret trans_eager_binop ( rhs. bcx , op, lhs. val ,
2436
2433
ty:: expr_ty ( bcx_tcx ( cx) , a) , rhs. val ,
2437
- ty:: expr_ty ( bcx_tcx ( cx) , b) ) ;
2434
+ ty:: expr_ty ( bcx_tcx ( cx) , b) , dest ) ;
2438
2435
}
2439
2436
}
2440
2437
}
2441
2438
2442
- fn join_results ( parent_cx : @block_ctxt , t : TypeRef , ins : [ result ] ) -> result {
2443
- let live: [ result ] = [ ] ;
2444
- let vals: [ ValueRef ] = [ ] ;
2445
- let bbs: [ BasicBlockRef ] = [ ] ;
2446
- for r: result in ins {
2447
- if !r. bcx . unreachable {
2448
- live += [ r] ;
2449
- vals += [ r. val ] ;
2450
- bbs += [ r. bcx . llbb ] ;
2451
- }
2452
- }
2453
- alt std:: vec:: len :: < result > ( live) {
2454
- 0 u {
2455
- // No incoming edges are live, so we're in dead-code-land.
2456
- // Arbitrarily pick the first dead edge, since the caller
2457
- // is just going to propagate it outward.
2458
- assert ( std:: vec:: len :: < result > ( ins) >= 1 u) ;
2459
- ret ins[ 0 ] ;
2460
- }
2461
- _ { /* fall through */ }
2462
- }
2463
- // We have >1 incoming edges. Make a join block and br+phi them into it.
2464
-
2465
- let join_cx = new_sub_block_ctxt ( parent_cx, "join" ) ;
2466
- for r: result in live { Br ( r. bcx , join_cx. llbb ) ; }
2467
- let phi = Phi ( join_cx, t, vals, bbs) ;
2468
- ret rslt( join_cx, phi) ;
2469
- }
2470
-
2471
2439
// FIXME remove once all uses have been converted to join_returns
2472
2440
fn join_branches ( parent_cx : @block_ctxt , ins : [ result ] ) -> @block_ctxt {
2473
2441
let out = new_sub_block_ctxt ( parent_cx, "join" ) ;
@@ -2483,6 +2451,7 @@ tag dest {
2483
2451
by_val( @mutable ValueRef ) ;
2484
2452
by_ref ( @mutable ValueRef ) ;
2485
2453
save_in ( ValueRef ) ;
2454
+ overwrite ( ValueRef , ty:: t) ;
2486
2455
ignore;
2487
2456
}
2488
2457
@@ -2529,6 +2498,20 @@ fn join_returns(parent_cx: @block_ctxt, in_cxs: [@block_ctxt],
2529
2498
ret out;
2530
2499
}
2531
2500
2501
+ // Used to put an immediate value in a dest
2502
+ fn store_in_dest ( bcx : @block_ctxt , val : ValueRef , dest : dest ) -> @block_ctxt {
2503
+ alt dest {
2504
+ ignore. { }
2505
+ by_val ( cell) { * cell = val; }
2506
+ save_in ( addr) { Store ( bcx, val, addr) ; }
2507
+ overwrite ( addr, tp) {
2508
+ bcx = drop_ty ( bcx, addr, tp) ;
2509
+ Store ( bcx, val, addr) ;
2510
+ }
2511
+ }
2512
+ ret bcx;
2513
+ }
2514
+
2532
2515
// Wrapper through which legacy non-DPS code can use DPS functions
2533
2516
fn dps_to_result ( bcx : @block_ctxt ,
2534
2517
work : block ( @block_ctxt , dest ) -> @block_ctxt ,
@@ -4135,7 +4118,6 @@ fn trans_rec(bcx: @block_ctxt, fields: [ast::field],
4135
4118
fn trans_expr ( cx : @block_ctxt , e : @ast:: expr ) -> result {
4136
4119
// Fixme Fill in cx.sp
4137
4120
alt e. node {
4138
- ast:: expr_binary ( op, x, y) { ret trans_binary ( cx, op, x, y) ; }
4139
4121
ast:: expr_fn ( f) {
4140
4122
let ccx = bcx_ccx ( cx) ;
4141
4123
let fty = node_id_type ( ccx, e. id ) ;
@@ -4267,6 +4249,7 @@ fn trans_expr_dps(bcx: @block_ctxt, e: @ast::expr, dest: dest)
4267
4249
ast:: expr_tup ( args) { ret trans_tup ( bcx, args, e. id , dest) ; }
4268
4250
ast:: expr_lit ( lit) { ret trans_lit ( bcx, * lit, dest) ; }
4269
4251
ast:: expr_vec ( args, _) { ret tvec:: trans_vec ( bcx, args, e. id , dest) ; }
4252
+ ast:: expr_binary ( op, x, y) { ret trans_binary ( bcx, op, x, y, dest) ; }
4270
4253
4271
4254
ast:: expr_break. {
4272
4255
assert dest == ignore;
@@ -4399,6 +4382,9 @@ fn trans_expr_dps(bcx: @block_ctxt, e: @ast::expr, dest: dest)
4399
4382
* cell = val;
4400
4383
}
4401
4384
save_in ( loc) { bcx = move_val_if_temp ( bcx, INIT , loc, lv, ty) ; }
4385
+ overwrite ( loc, _) {
4386
+ bcx = move_val_if_temp ( bcx, DROP_EXISTING , loc, lv, ty) ;
4387
+ }
4402
4388
ignore. { }
4403
4389
}
4404
4390
ret bcx ;
0 commit comments