@@ -3752,7 +3752,8 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
3752
3752
for the call itself is unreachable. */
3753
3753
let retval = C_nil ( ) ;
3754
3754
if !is_terminated ( bcx) {
3755
- bcx = invoke_fastcall ( bcx, faddr, llargs) . bcx ;
3755
+ bcx = invoke_fastcall ( bcx, faddr, llargs,
3756
+ args_res. to_zero , args_res. to_revoke ) . bcx ;
3756
3757
alt lliterbody {
3757
3758
none. {
3758
3759
if !ty:: type_is_nil ( bcx_tcx ( cx) , ret_ty) {
@@ -3775,12 +3776,8 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
3775
3776
}
3776
3777
3777
3778
// Forget about anything we moved out.
3778
- for { v: v, t: t} : { v: ValueRef , t: ty:: t} in args_res. to_zero {
3779
- bcx = zero_alloca ( bcx, v, t) . bcx ;
3780
- }
3781
- for { v: v, t: t} in args_res. to_revoke {
3782
- bcx = revoke_clean ( bcx, v, t) ;
3783
- }
3779
+ bcx = zero_and_revoke ( bcx, args_res. to_zero , args_res. to_revoke ) ;
3780
+
3784
3781
if !by_ref { bcx = trans_block_cleanups ( bcx, cx) ; }
3785
3782
let next_cx = new_sub_block_ctxt ( in_cx, "next" ) ;
3786
3783
Br ( bcx, next_cx. llbb ) ;
@@ -3789,45 +3786,70 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
3789
3786
ret { res : rslt ( bcx, retval) , by_ref : by_ref} ;
3790
3787
}
3791
3788
3789
+ fn zero_and_revoke ( bcx : @block_ctxt ,
3790
+ to_zero : [ { v : ValueRef , t : ty:: t } ] ,
3791
+ to_revoke : [ { v : ValueRef , t : ty:: t } ] ) -> @block_ctxt {
3792
+ let bcx = bcx;
3793
+ for { v, t} in to_zero {
3794
+ bcx = zero_alloca ( bcx, v, t) . bcx ;
3795
+ }
3796
+ for { v, t} in to_revoke {
3797
+ bcx = revoke_clean ( bcx, v, t) ;
3798
+ }
3799
+ ret bcx;
3800
+ }
3801
+
3792
3802
fn invoke ( bcx : @block_ctxt , llfn : ValueRef ,
3793
3803
llargs : [ ValueRef ] ) -> result {
3794
- ret invoke_ ( bcx, llfn, llargs, Invoke ) ;
3804
+ ret invoke_ ( bcx, llfn, llargs, [ ] , [ ] , Invoke ) ;
3795
3805
}
3796
3806
3797
3807
fn invoke_fastcall ( bcx : @block_ctxt , llfn : ValueRef ,
3798
- llargs : [ ValueRef ] ) -> result {
3799
- ret invoke_ ( bcx, llfn, llargs, FastInvoke ) ;
3808
+ llargs : [ ValueRef ] ,
3809
+ to_zero : [ { v : ValueRef , t : ty:: t } ] ,
3810
+ to_revoke : [ { v : ValueRef , t : ty:: t } ] ) -> result {
3811
+ ret invoke_ ( bcx, llfn, llargs,
3812
+ to_zero, to_revoke,
3813
+ FastInvoke ) ;
3800
3814
}
3801
3815
3802
- fn invoke_ ( bcx : @block_ctxt , llfn : ValueRef ,
3803
- llargs : [ ValueRef ] ,
3816
+ fn invoke_ ( bcx : @block_ctxt , llfn : ValueRef , llargs : [ ValueRef ] ,
3817
+ to_zero : [ { v : ValueRef , t : ty:: t } ] ,
3818
+ to_revoke : [ { v : ValueRef , t : ty:: t } ] ,
3804
3819
invoker : fn ( @block_ctxt , ValueRef , [ ValueRef ] ,
3805
3820
BasicBlockRef , BasicBlockRef ) -> ValueRef ) -> result {
3806
3821
// FIXME: May be worth turning this into a plain call when there are no
3807
3822
// cleanups to run
3808
3823
let normal_bcx = new_sub_block_ctxt ( bcx, "normal return" ) ;
3809
3824
let retval = invoker ( bcx, llfn, llargs,
3810
3825
normal_bcx. llbb ,
3811
- get_landing_pad ( bcx) ) ;
3826
+ get_landing_pad ( bcx, to_zero , to_revoke ) ) ;
3812
3827
ret rslt( normal_bcx, retval) ;
3813
3828
}
3814
3829
3815
- fn get_landing_pad ( bcx : @block_ctxt ) -> BasicBlockRef {
3816
- let scope_bcx = find_scope_for_lpad ( bcx) ;
3817
- if scope_bcx. cleanups_dirty {
3830
+ fn get_landing_pad ( bcx : @block_ctxt ,
3831
+ to_zero : [ { v : ValueRef , t : ty:: t } ] ,
3832
+ to_revoke : [ { v : ValueRef , t : ty:: t } ]
3833
+ ) -> BasicBlockRef {
3834
+ let have_zero_or_revoke = vec:: is_not_empty ( to_zero)
3835
+ || vec:: is_not_empty ( to_revoke) ;
3836
+ let scope_bcx = find_scope_for_lpad ( bcx, have_zero_or_revoke) ;
3837
+ if scope_bcx. lpad_dirty || have_zero_or_revoke {
3818
3838
let unwind_bcx = new_sub_block_ctxt ( bcx, "unwind" ) ;
3819
- let lpadbb = trans_landing_pad ( unwind_bcx) ;
3839
+ let lpadbb = trans_landing_pad ( unwind_bcx, to_zero , to_revoke ) ;
3820
3840
scope_bcx. lpad = some ( lpadbb) ;
3821
- scope_bcx. cleanups_dirty = false ;
3841
+ scope_bcx. lpad_dirty = have_zero_or_revoke ;
3822
3842
}
3823
3843
assert option:: is_some ( scope_bcx. lpad ) ;
3824
3844
ret option:: get ( scope_bcx. lpad ) ;
3825
3845
3826
- fn find_scope_for_lpad ( bcx : @block_ctxt ) -> @block_ctxt {
3846
+ fn find_scope_for_lpad ( bcx : @block_ctxt ,
3847
+ have_zero_or_revoke : bool ) -> @block_ctxt {
3827
3848
let scope_bcx = bcx;
3828
3849
while true {
3829
3850
scope_bcx = find_scope_cx ( scope_bcx) ;
3830
- if vec:: is_not_empty ( scope_bcx. cleanups ) {
3851
+ if vec:: is_not_empty ( scope_bcx. cleanups )
3852
+ || have_zero_or_revoke {
3831
3853
ret scope_bcx;
3832
3854
} else {
3833
3855
scope_bcx = alt scope_bcx. parent {
@@ -3842,7 +3864,10 @@ fn get_landing_pad(bcx: @block_ctxt) -> BasicBlockRef {
3842
3864
}
3843
3865
}
3844
3866
3845
- fn trans_landing_pad ( bcx : @block_ctxt ) -> BasicBlockRef {
3867
+ fn trans_landing_pad ( bcx : @block_ctxt ,
3868
+ to_zero : [ { v : ValueRef , t : ty:: t } ] ,
3869
+ to_revoke : [ { v : ValueRef , t : ty:: t } ]
3870
+ ) -> BasicBlockRef {
3846
3871
// The landing pad return type (the type being propagated). Not sure what
3847
3872
// this represents but it's determined by the personality function and
3848
3873
// this is what the EH proposal example uses.
@@ -3863,7 +3888,7 @@ fn trans_landing_pad(bcx: @block_ctxt) -> BasicBlockRef {
3863
3888
// FIXME: This seems like a very naive and redundant way to generate the
3864
3889
// landing pads, as we're re-generating all in-scope cleanups for each
3865
3890
// function call. Probably good optimization opportunities here.
3866
- let bcx = bcx;
3891
+ let bcx = zero_and_revoke ( bcx, to_zero , to_revoke ) ;
3867
3892
let scope_cx = bcx;
3868
3893
while true {
3869
3894
scope_cx = find_scope_cx ( scope_cx) ;
@@ -4372,7 +4397,7 @@ fn trans_put(in_cx: @block_ctxt, e: option::t<@ast::expr>) -> result {
4372
4397
llargs += [ r. val ] ;
4373
4398
}
4374
4399
}
4375
- bcx = invoke_fastcall ( bcx, llcallee, llargs) . bcx ;
4400
+ bcx = invoke_fastcall ( bcx, llcallee, llargs, [ ] , [ ] ) . bcx ;
4376
4401
bcx = trans_block_cleanups ( bcx, cx) ;
4377
4402
let next_cx = new_sub_block_ctxt ( in_cx, "next" ) ;
4378
4403
Br ( bcx, next_cx. llbb ) ;
@@ -4638,7 +4663,7 @@ fn new_block_ctxt(cx: @fn_ctxt, parent: block_parent, kind: block_kind,
4638
4663
parent : parent,
4639
4664
kind : kind,
4640
4665
mutable cleanups : [ ] ,
4641
- mutable cleanups_dirty : true ,
4666
+ mutable lpad_dirty : true ,
4642
4667
mutable lpad: option:: none,
4643
4668
sp : cx. sp ,
4644
4669
fcx : cx} ;
@@ -4674,7 +4699,7 @@ fn new_raw_block_ctxt(fcx: @fn_ctxt, llbb: BasicBlockRef) -> @block_ctxt {
4674
4699
parent : parent_none,
4675
4700
kind : NON_SCOPE_BLOCK ,
4676
4701
mutable cleanups : [ ] ,
4677
- mutable cleanups_dirty : true ,
4702
+ mutable lpad_dirty : true ,
4678
4703
mutable lpad: option:: none,
4679
4704
sp : fcx. sp ,
4680
4705
fcx : fcx} ;
@@ -4741,7 +4766,7 @@ fn llstaticallocas_block_ctxt(fcx: @fn_ctxt) -> @block_ctxt {
4741
4766
parent : parent_none,
4742
4767
kind : SCOPE_BLOCK ,
4743
4768
mutable cleanups : [ ] ,
4744
- mutable cleanups_dirty : true ,
4769
+ mutable lpad_dirty : true ,
4745
4770
mutable lpad: option:: none,
4746
4771
sp : fcx. sp ,
4747
4772
fcx : fcx} ;
@@ -4753,7 +4778,7 @@ fn llderivedtydescs_block_ctxt(fcx: @fn_ctxt) -> @block_ctxt {
4753
4778
parent : parent_none,
4754
4779
kind : SCOPE_BLOCK ,
4755
4780
mutable cleanups : [ ] ,
4756
- mutable cleanups_dirty : true ,
4781
+ mutable lpad_dirty : true ,
4757
4782
mutable lpad: option:: none,
4758
4783
sp : fcx. sp ,
4759
4784
fcx : fcx} ;
0 commit comments