@@ -2470,7 +2470,7 @@ fn trans_binary(cx: @block_ctxt, op: ast::binop, a: @ast::expr, b: @ast::expr,
2470
2470
}
2471
2471
}
2472
2472
2473
- // FIXME remove once all uses have been converted to join_returns
2473
+ // FIXME[DPS] remove once all uses have been converted to join_returns
2474
2474
fn join_branches ( parent_cx : @block_ctxt , ins : [ result ] ) -> @block_ctxt {
2475
2475
let out = new_sub_block_ctxt ( parent_cx, "join" ) ;
2476
2476
let branched = false ;
@@ -2952,8 +2952,7 @@ fn trans_for_each(cx: @block_ctxt, local: @ast::local, seq: @ast::expr,
2952
2952
ast:: expr_call ( f, args) {
2953
2953
let pair =
2954
2954
create_real_fn_pair ( cx, iter_body_llty, lliterbody, llenv. ptr ) ;
2955
- let r = trans_call ( cx, f, some ( pair) , args, seq. id ) ;
2956
- ret r. res . bcx ;
2955
+ ret trans_call( cx, f, some ( pair) , args, seq. id , ignore) ;
2957
2956
}
2958
2957
}
2959
2958
}
@@ -3300,6 +3299,7 @@ fn expr_is_lval(tcx: ty::ctxt, e: @ast::expr) -> bool {
3300
3299
// The additional bool returned indicates whether it's mem (that is
3301
3300
// represented as an alloca or heap, hence needs a 'load' to be used as an
3302
3301
// immediate).
3302
+ // FIXME[DPS] only allow this to be called on actual lvals
3303
3303
fn trans_lval ( cx : @block_ctxt , e : @ast:: expr ) -> lval_result {
3304
3304
alt e. node {
3305
3305
ast:: expr_path ( p) {
@@ -3340,10 +3340,17 @@ fn trans_lval(cx: @block_ctxt, e: @ast::expr) -> lval_result {
3340
3340
ret lval_mem( sub. bcx , val) ;
3341
3341
}
3342
3342
ast:: expr_call ( f, args) {
3343
- let { res: { bcx , val } , by_ref } =
3344
- trans_call ( cx, f, none, args, e. id ) ;
3345
- if by_ref { ret lval_mem ( bcx, val) ; }
3346
- else { ret lval_val ( bcx, val) ; }
3343
+ // A by-ref returning function
3344
+ if expr_is_lval ( bcx_tcx ( cx) , e) {
3345
+ let cell = empty_dest_cell ( ) ;
3346
+ let bcx = trans_call ( cx, f, none, args, e. id , by_ref ( cell) ) ;
3347
+ ret lval_mem( bcx, * cell) ;
3348
+ } else { // By-value return
3349
+ let { bcx, val} = dps_to_result ( cx, { |bcx, dest|
3350
+ trans_call ( bcx, f, none, args, e. id , dest) } ,
3351
+ ty:: expr_ty ( bcx_tcx ( cx) , e) ) ;
3352
+ ret lval_val( bcx, val) ;
3353
+ }
3347
3354
}
3348
3355
_ {
3349
3356
let res = trans_expr ( cx, e) ;
@@ -3797,7 +3804,8 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty0: TypeRef,
3797
3804
// - trans_args
3798
3805
fn trans_args ( cx : @block_ctxt , outer_cx : @block_ctxt , llenv : ValueRef ,
3799
3806
gen : option:: t < generic_info > ,
3800
- lliterbody : option:: t < ValueRef > , es : [ @ast:: expr ] , fn_ty : ty:: t )
3807
+ lliterbody : option:: t < ValueRef > , es : [ @ast:: expr ] , fn_ty : ty:: t ,
3808
+ dest : dest )
3801
3809
-> { bcx : @block_ctxt ,
3802
3810
outer_cx : @block_ctxt ,
3803
3811
args : [ ValueRef ] ,
@@ -3813,9 +3821,9 @@ fn trans_args(cx: @block_ctxt, outer_cx: @block_ctxt, llenv: ValueRef,
3813
3821
3814
3822
let ccx = bcx_ccx ( cx) ;
3815
3823
let tcx = ccx. tcx ;
3816
- let bcx: @ block_ctxt = cx;
3824
+ let bcx = cx;
3817
3825
let ret_style = ty:: ty_fn_ret_style ( tcx, fn_ty) ;
3818
- let by_ref = ast_util:: ret_by_ref ( ret_style) ;
3826
+ let ret_ref = ast_util:: ret_by_ref ( ret_style) ;
3819
3827
3820
3828
let retty = ty:: ty_fn_ret ( tcx, fn_ty) , full_retty = retty;
3821
3829
alt gen {
@@ -3828,13 +3836,21 @@ fn trans_args(cx: @block_ctxt, outer_cx: @block_ctxt, llenv: ValueRef,
3828
3836
_ { }
3829
3837
}
3830
3838
// Arg 0: Output pointer.
3831
- let llretslot_res = if ty:: type_is_nil ( tcx, retty) {
3832
- rslt ( cx, llvm:: LLVMGetUndef ( T_ptr ( T_nil ( ) ) ) )
3833
- } else if by_ref {
3834
- rslt ( cx, alloca ( cx, T_ptr ( type_of_or_i8 ( bcx, full_retty) ) ) )
3835
- } else { alloc_ty ( bcx, full_retty) } ;
3836
- bcx = llretslot_res. bcx ;
3837
- let llretslot = llretslot_res. val ;
3839
+ let llretty = type_of_or_i8 ( bcx, full_retty) ;
3840
+ let dest_ref = false ;
3841
+ let llretslot = alt dest {
3842
+ ignore. {
3843
+ if ty:: type_is_nil ( tcx, full_retty) || !option:: is_none ( lliterbody) {
3844
+ llvm:: LLVMGetUndef ( T_ptr ( llretty) )
3845
+ } else { alloca ( cx, llretty) }
3846
+ }
3847
+ save_in ( dst) { dst }
3848
+ overwrite ( _, _) | by_val ( _) { alloca ( cx, llretty) }
3849
+ by_ref ( _) { dest_ref = true ; alloca ( cx, T_ptr ( llretty) ) }
3850
+ } ;
3851
+ // FIXME[DSP] does this always hold?
3852
+ assert dest_ref == ret_ref;
3853
+
3838
3854
if ty:: type_contains_params ( tcx, retty) {
3839
3855
// It's possible that the callee has some generic-ness somewhere in
3840
3856
// its return value -- say a method signature within an obj or a fn
@@ -3843,7 +3859,7 @@ fn trans_args(cx: @block_ctxt, outer_cx: @block_ctxt, llenv: ValueRef,
3843
3859
// view, for the sake of making a type-compatible call.
3844
3860
check non_ty_var ( ccx, retty) ;
3845
3861
let llretty = T_ptr ( type_of_inner ( ccx, bcx. sp , retty) ) ;
3846
- if by_ref { llretty = T_ptr ( llretty) ; }
3862
+ if ret_ref { llretty = T_ptr ( llretty) ; }
3847
3863
llargs += [ PointerCast ( cx, llretslot, llretty) ] ;
3848
3864
} else { llargs += [ llretslot] ; }
3849
3865
@@ -3899,18 +3915,17 @@ fn trans_args(cx: @block_ctxt, outer_cx: @block_ctxt, llenv: ValueRef,
3899
3915
3900
3916
fn trans_call ( in_cx : @block_ctxt , f : @ast:: expr ,
3901
3917
lliterbody : option:: t < ValueRef > , args : [ @ast:: expr ] ,
3902
- id : ast:: node_id ) -> { res : result , by_ref : bool } {
3918
+ id : ast:: node_id , dest : dest ) -> @ block_ctxt {
3903
3919
// NB: 'f' isn't necessarily a function; it might be an entire self-call
3904
3920
// expression because of the hack that allows us to process self-calls
3905
3921
// with trans_call.
3906
3922
let tcx = bcx_tcx ( in_cx) ;
3907
3923
let fn_expr_ty = ty:: expr_ty ( tcx, f) ;
3908
3924
3909
3925
if check type_is_native_fn_on_c_stack ( tcx, fn_expr_ty) {
3910
- ret trans_c_stack_native_call ( in_cx, f, args) ;
3926
+ ret trans_c_stack_native_call ( in_cx, f, args, dest ) ;
3911
3927
}
3912
3928
3913
- let by_ref = ast_util:: ret_by_ref ( ty:: ty_fn_ret_style ( tcx, fn_expr_ty) ) ;
3914
3929
let cx = new_scope_block_ctxt ( in_cx, "call" ) ;
3915
3930
let f_res = trans_callee ( cx, f) ;
3916
3931
let bcx = f_res. bcx ;
@@ -3936,65 +3951,49 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
3936
3951
let ret_ty = ty:: node_id_to_type ( tcx, id) ;
3937
3952
let args_res =
3938
3953
trans_args ( bcx, in_cx, llenv, f_res. generic , lliterbody, args,
3939
- fn_expr_ty) ;
3954
+ fn_expr_ty, dest ) ;
3940
3955
Br ( args_res. outer_cx , cx. llbb ) ;
3941
3956
bcx = args_res. bcx ;
3942
3957
let llargs = args_res. args ;
3943
3958
let llretslot = args_res. retslot ;
3944
3959
3945
- /*
3946
- log_err "calling: " + val_str(bcx_ccx(cx).tn, faddr);
3947
-
3948
- for arg: ValueRef in llargs {
3949
- log_err "arg: " + val_str(bcx_ccx(cx).tn, arg);
3950
- }
3951
- */
3952
-
3953
3960
/* If the block is terminated,
3954
3961
then one or more of the args has
3955
3962
type _|_. Since that means it diverges, the code
3956
3963
for the call itself is unreachable. */
3957
- let retval = C_nil ( ) ;
3958
3964
bcx = invoke_full ( bcx, faddr, llargs, args_res. to_zero ,
3959
3965
args_res. to_revoke ) ;
3960
- alt lliterbody {
3961
- none. {
3962
- if !ty:: type_is_nil ( tcx, ret_ty) {
3963
- if by_ref {
3964
- retval = Load ( bcx, llretslot) ;
3965
- } else {
3966
- retval = load_if_immediate ( bcx, llretslot, ret_ty) ;
3967
- // Retval doesn't correspond to anything really tangible
3968
- // in the frame, but it's a ref all the same, so we put a
3969
- // note here to drop it when we're done in this scope.
3970
- add_clean_temp ( in_cx, retval, ret_ty) ;
3971
- }
3966
+ alt dest {
3967
+ ignore. {
3968
+ if llvm:: LLVMIsUndef ( llretslot) != lib:: llvm:: True {
3969
+ bcx = drop_ty ( bcx, llretslot, ret_ty) ;
3972
3970
}
3973
3971
}
3974
- some ( _) {
3975
- // If there was an lliterbody, it means we were calling an
3976
- // iter, and we are *not* the party using its 'output' value,
3977
- // we should ignore llretslot.
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
+ }
3977
+ by_ref ( cell) | by_val ( cell) {
3978
+ * cell = Load ( bcx, llretslot) ;
3978
3979
}
3979
3980
}
3980
3981
// Forget about anything we moved out.
3981
3982
bcx = zero_and_revoke ( bcx, args_res. to_zero , args_res. to_revoke ) ;
3982
3983
3983
- if !by_ref { bcx = trans_block_cleanups ( bcx, cx) ; }
3984
+ bcx = trans_block_cleanups ( bcx, cx) ;
3984
3985
let next_cx = new_sub_block_ctxt ( in_cx, "next" ) ;
3985
3986
if bcx. unreachable || ty:: type_is_bot ( tcx, ret_ty) {
3986
3987
Unreachable ( next_cx) ;
3987
3988
}
3988
3989
Br ( bcx, next_cx. llbb ) ;
3989
- bcx = next_cx;
3990
- ret { res : rslt ( bcx, retval) , by_ref : by_ref} ;
3990
+ ret next_cx;
3991
3991
}
3992
3992
3993
3993
// Translates a native call on the C stack. Calls into the runtime to perform
3994
3994
// the stack switching operation.
3995
3995
fn trans_c_stack_native_call ( bcx : @block_ctxt , f : @ast:: expr ,
3996
- args : [ @ast:: expr ] )
3997
- -> { res : result , by_ref : bool } {
3996
+ args : [ @ast:: expr ] , dest : dest ) -> @block_ctxt {
3998
3997
let ccx = bcx_ccx ( bcx) ;
3999
3998
let f_res = trans_callee ( bcx, f) ;
4000
3999
let llfn = f_res. val ; bcx = f_res. bcx ;
@@ -4047,8 +4046,7 @@ fn trans_c_stack_native_call(bcx: @block_ctxt, f: @ast::expr,
4047
4046
4048
4047
// Forget about anything we moved out.
4049
4048
bcx = zero_and_revoke ( bcx, to_zero, to_revoke) ;
4050
-
4051
- ret { res : rslt ( bcx, llretval) , by_ref : false } ;
4049
+ ret store_in_dest ( bcx, llretval, dest) ;
4052
4050
}
4053
4051
4054
4052
fn zero_and_revoke ( bcx : @block_ctxt ,
@@ -4345,8 +4343,11 @@ fn trans_expr_dps(bcx: @block_ctxt, e: @ast::expr, dest: dest)
4345
4343
ast:: expr_anon_obj ( anon_obj) {
4346
4344
ret trans_anon_obj ( bcx, e. span , anon_obj, e. id , dest) ;
4347
4345
}
4348
- // FIXME[DPS] untangle non-lval calls and fields from trans_lval
4349
- ast:: expr_call ( _, _) | ast:: expr_field ( _, _) {
4346
+ ast:: expr_call ( f, args) {
4347
+ ret trans_call ( bcx, f, none, args, e. id , dest) ;
4348
+ }
4349
+ // FIXME[DPS] untangle non-lval fields from trans_lval
4350
+ ast:: expr_field ( _, _) {
4350
4351
ret lval_to_dps ( bcx, e, dest) ;
4351
4352
}
4352
4353
0 commit comments