@@ -3521,8 +3521,7 @@ fn trans_args(cx: @block_ctxt, llenv: ValueRef, gen: option::t<generic_info>,
3521
3521
args : [ ValueRef ] ,
3522
3522
retslot : ValueRef ,
3523
3523
to_zero : [ { v : ValueRef , t : ty:: t } ] ,
3524
- to_revoke : [ { v : ValueRef , t : ty:: t } ] ,
3525
- by_ref : bool } {
3524
+ to_revoke : [ { v : ValueRef , t : ty:: t } ] } {
3526
3525
3527
3526
let args: [ ty:: arg ] = ty:: ty_fn_args ( bcx_tcx ( cx) , fn_ty) ;
3528
3527
let llargs: [ ValueRef ] = [ ] ;
@@ -3545,8 +3544,7 @@ fn trans_args(cx: @block_ctxt, llenv: ValueRef, gen: option::t<generic_info>,
3545
3544
args : [ ] ,
3546
3545
retslot : C_nil ( ) ,
3547
3546
to_zero : to_zero,
3548
- to_revoke : to_revoke,
3549
- by_ref : by_ref} ;
3547
+ to_revoke : to_revoke} ;
3550
3548
}
3551
3549
let retty = ty:: ty_fn_ret ( tcx, fn_ty) ;
3552
3550
let llretslot_res = if by_ref {
@@ -3620,8 +3618,7 @@ fn trans_args(cx: @block_ctxt, llenv: ValueRef, gen: option::t<generic_info>,
3620
3618
args : llargs,
3621
3619
retslot : llretslot,
3622
3620
to_zero : to_zero,
3623
- to_revoke : to_revoke,
3624
- by_ref : by_ref} ;
3621
+ to_revoke : to_revoke} ;
3625
3622
}
3626
3623
3627
3624
fn trans_call ( in_cx : @block_ctxt , f : @ast:: expr ,
@@ -3630,10 +3627,18 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
3630
3627
// NB: 'f' isn't necessarily a function; it might be an entire self-call
3631
3628
// expression because of the hack that allows us to process self-calls
3632
3629
// with trans_call.
3633
- let cx = new_scope_block_ctxt ( in_cx, "call" ) ;
3634
- Br ( in_cx, cx. llbb ) ;
3630
+ let fn_expr_ty = ty:: expr_ty ( bcx_tcx ( in_cx) , f) ;
3631
+ let fn_ty = ty:: type_autoderef ( bcx_tcx ( in_cx) , fn_expr_ty) ;
3632
+ let by_ref = ty:: ty_fn_ret_style ( bcx_tcx ( in_cx) , fn_ty) == ast:: return_ref;
3633
+ // Things that return by reference must put their arguments (FIXME only
3634
+ // the referenced arguments) into the outer scope, so that they are still
3635
+ // alive when the return value is used.
3636
+ let cx = if by_ref { in_cx } else {
3637
+ let cx = new_scope_block_ctxt ( in_cx, "call" ) ;
3638
+ Br ( in_cx, cx. llbb ) ;
3639
+ cx
3640
+ } ;
3635
3641
let f_res = trans_lval_gen ( cx, f) ;
3636
- let fn_ty = ty:: expr_ty ( bcx_tcx ( cx) , f) ;
3637
3642
let bcx = f_res. res . bcx ;
3638
3643
3639
3644
let faddr = f_res. res . val ;
@@ -3646,10 +3651,9 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
3646
3651
}
3647
3652
none. {
3648
3653
// It's a closure. We have to autoderef.
3649
- if f_res. is_mem { faddr = load_if_immediate ( bcx, faddr, fn_ty ) ; }
3650
- let res = autoderef ( bcx, faddr, fn_ty ) ;
3654
+ if f_res. is_mem { faddr = load_if_immediate ( bcx, faddr, fn_expr_ty ) ; }
3655
+ let res = autoderef ( bcx, faddr, fn_expr_ty ) ;
3651
3656
bcx = res. bcx ;
3652
- fn_ty = res. ty ;
3653
3657
3654
3658
let pair = res. val ;
3655
3659
faddr = GEP ( bcx, pair, [ C_int ( 0 ) , C_int ( abi:: fn_field_code) ] ) ;
@@ -3684,7 +3688,7 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
3684
3688
alt lliterbody {
3685
3689
none. {
3686
3690
if !ty:: type_is_nil ( bcx_tcx ( cx) , ret_ty) {
3687
- if args_res . by_ref {
3691
+ if by_ref {
3688
3692
let retptr = Load ( bcx, llretslot) ;
3689
3693
retval = load_if_immediate ( bcx, retptr, ret_ty) ;
3690
3694
} else {
@@ -3710,7 +3714,7 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
3710
3714
for { v: v, t: t} in args_res. to_revoke {
3711
3715
bcx = revoke_clean ( bcx, v, t) ;
3712
3716
}
3713
- bcx = trans_block_cleanups ( bcx, cx) ;
3717
+ if !by_ref { bcx = trans_block_cleanups ( bcx, cx) ; }
3714
3718
let next_cx = new_sub_block_ctxt ( in_cx, "next" ) ;
3715
3719
Br ( bcx, next_cx. llbb ) ;
3716
3720
bcx = next_cx;
0 commit comments