@@ -1210,16 +1210,23 @@ pub fn arrayalloca(cx: &Block, ty: Type, v: ValueRef) -> ValueRef {
12101210 p
12111211}
12121212
1213- // Creates and returns space for, or returns the argument representing, the
1214- // slot where the return value of the function must go.
1215- pub fn make_return_pointer ( fcx : & FunctionContext , output_type : ty:: t )
1216- -> ValueRef {
1213+ // Creates the alloca slot which holds the pointer to the slot for the final return value
1214+ pub fn make_return_slot_pointer ( fcx : & FunctionContext , output_type : ty:: t ) -> ValueRef {
1215+ let lloutputtype = type_of:: type_of ( fcx. ccx , output_type) ;
1216+
1217+ // Let's create the stack slot
1218+ let slot = AllocaFcx ( fcx, lloutputtype. ptr_to ( ) , "llretslotptr" ) ;
1219+
1220+ // and if we're using an out pointer, then store that in our newly made slot
12171221 if type_of:: return_uses_outptr ( fcx. ccx , output_type) {
1218- get_param ( fcx. llfn , 0 )
1219- } else {
1220- let lloutputtype = type_of:: type_of ( fcx. ccx , output_type) ;
1221- AllocaFcx ( fcx, lloutputtype, "__make_return_pointer" )
1222+ let outptr = get_param ( fcx. llfn , 0 ) ;
1223+
1224+ let b = fcx. ccx . builder ( ) ;
1225+ b. position_before ( fcx. alloca_insert_pt . get ( ) . unwrap ( ) ) ;
1226+ b. store ( outptr, slot) ;
12221227 }
1228+
1229+ slot
12231230}
12241231
12251232// NB: must keep 4 fns in sync:
@@ -1258,7 +1265,7 @@ pub fn new_fn_ctxt<'a>(ccx: &'a CrateContext,
12581265 let mut fcx = FunctionContext {
12591266 llfn : llfndecl,
12601267 llenv : None ,
1261- llretptr : Cell :: new ( None ) ,
1268+ llretslotptr : Cell :: new ( None ) ,
12621269 alloca_insert_pt : Cell :: new ( None ) ,
12631270 llreturn : Cell :: new ( None ) ,
12641271 personality : Cell :: new ( None ) ,
@@ -1303,12 +1310,12 @@ pub fn init_function<'a>(fcx: &'a FunctionContext<'a>,
13031310
13041311 if !return_type_is_void ( fcx. ccx , substd_output_type) {
13051312 // If the function returns nil/bot, there is no real return
1306- // value, so do not set `llretptr `.
1313+ // value, so do not set `llretslotptr `.
13071314 if !skip_retptr || fcx. caller_expects_out_pointer {
1308- // Otherwise, we normally allocate the llretptr , unless we
1315+ // Otherwise, we normally allocate the llretslotptr , unless we
13091316 // have been instructed to skip it for immediate return
13101317 // values.
1311- fcx. llretptr . set ( Some ( make_return_pointer ( fcx, substd_output_type) ) ) ;
1318+ fcx. llretslotptr . set ( Some ( make_return_slot_pointer ( fcx, substd_output_type) ) ) ;
13121319 }
13131320 }
13141321
@@ -1533,12 +1540,12 @@ pub fn finish_fn<'a>(fcx: &'a FunctionContext<'a>,
15331540
15341541// Builds the return block for a function.
15351542pub fn build_return_block ( fcx : & FunctionContext , ret_cx : & Block , retty : ty:: t ) {
1536- // Return the value if this function immediate; otherwise, return void.
1537- if fcx. llretptr . get ( ) . is_none ( ) || fcx. caller_expects_out_pointer {
1543+ if fcx. llretslotptr . get ( ) . is_none ( ) {
15381544 return RetVoid ( ret_cx) ;
15391545 }
15401546
1541- let retptr = Value ( fcx. llretptr . get ( ) . unwrap ( ) ) ;
1547+ let retslot = Load ( ret_cx, fcx. llretslotptr . get ( ) . unwrap ( ) ) ;
1548+ let retptr = Value ( retslot) ;
15421549 let retval = match retptr. get_dominating_store ( ret_cx) {
15431550 // If there's only a single store to the ret slot, we can directly return
15441551 // the value that was stored and omit the store and the alloca
@@ -1557,10 +1564,15 @@ pub fn build_return_block(fcx: &FunctionContext, ret_cx: &Block, retty: ty::t) {
15571564 }
15581565 }
15591566 // Otherwise, load the return value from the ret slot
1560- None => load_ty ( ret_cx, fcx . llretptr . get ( ) . unwrap ( ) , retty)
1567+ None => load_ty ( ret_cx, retslot , retty)
15611568 } ;
15621569
1563- Ret ( ret_cx, retval) ;
1570+ if fcx. caller_expects_out_pointer {
1571+ store_ty ( ret_cx, retval, get_param ( fcx. llfn , 0 ) , retty) ;
1572+ RetVoid ( ret_cx) ;
1573+ } else {
1574+ Ret ( ret_cx, retval) ;
1575+ }
15641576}
15651577
15661578#[ deriving( Clone , Eq , PartialEq ) ]
@@ -1658,10 +1670,10 @@ pub fn trans_closure(ccx: &CrateContext,
16581670 // emitting should be enabled.
16591671 debuginfo:: start_emitting_source_locations( & fcx) ;
16601672
1661- let dest = match fcx. llretptr . get( ) {
1662- Some ( e ) => { expr:: SaveIn ( e ) }
1673+ let dest = match fcx. llretslotptr . get( ) {
1674+ Some ( _ ) => expr:: SaveIn ( alloca ( bcx , type_of :: type_of ( bcx . ccx ( ) , block_ty ) , "iret_slot" ) ) ,
16631675 None => {
1664- assert!( type_is_zero_size( bcx. ccx( ) , block_ty) )
1676+ assert ! ( type_is_zero_size( bcx. ccx( ) , block_ty) ) ;
16651677 expr:: Ignore
16661678 }
16671679 } ;
@@ -1672,6 +1684,13 @@ pub fn trans_closure(ccx: &CrateContext,
16721684 // (trans_block, trans_expr, et cetera).
16731685 bcx = controlflow:: trans_block( bcx, body, dest) ;
16741686
1687+ match dest {
1688+ expr : : SaveIn ( slot) => {
1689+ Store ( bcx, slot, fcx. llretslotptr. get( ) . unwrap( ) ) ;
1690+ }
1691+ _ => { }
1692+ }
1693+
16751694 match fcx. llreturn. get( ) {
16761695 Some ( _) => {
16771696 Br ( bcx, fcx. return_exit_block( ) ) ;
@@ -1841,16 +1860,18 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
18411860 let arg_datums = create_datums_for_fn_args( & fcx, arg_tys. as_slice( ) ) ;
18421861
18431862 if !type_is_zero_size( fcx. ccx, result_ty) {
1863+ let dest = alloca( bcx, type_of:: type_of( bcx. ccx( ) , result_ty) , "eret_slot") ;
18441864 let repr = adt:: represent_type( ccx, result_ty) ;
18451865 for ( i, arg_datum) in arg_datums. move_iter( ) . enumerate( ) {
18461866 let lldestptr = adt:: trans_field_ptr( bcx,
18471867 & * repr,
1848- fcx . llretptr . get ( ) . unwrap ( ) ,
1868+ dest ,
18491869 disr,
18501870 i) ;
18511871 arg_datum. store_to( bcx, lldestptr) ;
18521872 }
1853- adt:: trans_set_discr( bcx, & * repr, fcx. llretptr. get( ) . unwrap( ) , disr) ;
1873+ adt:: trans_set_discr( bcx, & * repr, dest, disr) ;
1874+ Store ( bcx, dest, fcx. llretslotptr. get( ) . unwrap( ) ) ;
18541875 }
18551876
18561877 finish_fn( & fcx, bcx, result_ty) ;
0 commit comments