@@ -1207,16 +1207,23 @@ pub fn arrayalloca(cx: &Block, ty: Type, v: ValueRef) -> ValueRef {
1207
1207
p
1208
1208
}
1209
1209
1210
- // Creates and returns space for, or returns the argument representing, the
1211
- // slot where the return value of the function must go.
1212
- pub fn make_return_pointer ( fcx : & FunctionContext , output_type : ty:: t )
1213
- -> ValueRef {
1210
+ // Creates the alloca slot which holds the pointer to the slot for the final return value
1211
+ pub fn make_return_slot_pointer ( fcx : & FunctionContext , output_type : ty:: t ) -> ValueRef {
1212
+ let lloutputtype = type_of:: type_of ( fcx. ccx , output_type) ;
1213
+
1214
+ // Let's create the stack slot
1215
+ let slot = AllocaFcx ( fcx, lloutputtype. ptr_to ( ) , "llretslotptr" ) ;
1216
+
1217
+ // and if we're using an out pointer, then store that in our newly made slot
1214
1218
if type_of:: return_uses_outptr ( fcx. ccx , output_type) {
1215
- get_param ( fcx. llfn , 0 )
1216
- } else {
1217
- let lloutputtype = type_of:: type_of ( fcx. ccx , output_type) ;
1218
- AllocaFcx ( fcx, lloutputtype, "__make_return_pointer" )
1219
+ let outptr = get_param ( fcx. llfn , 0 ) ;
1220
+
1221
+ let b = fcx. ccx . builder ( ) ;
1222
+ b. position_before ( fcx. alloca_insert_pt . get ( ) . unwrap ( ) ) ;
1223
+ b. store ( outptr, slot) ;
1219
1224
}
1225
+
1226
+ slot
1220
1227
}
1221
1228
1222
1229
// NB: must keep 4 fns in sync:
@@ -1254,7 +1261,7 @@ pub fn new_fn_ctxt<'a>(ccx: &'a CrateContext,
1254
1261
let mut fcx = FunctionContext {
1255
1262
llfn : llfndecl,
1256
1263
llenv : None ,
1257
- llretptr : Cell :: new ( None ) ,
1264
+ llretslotptr : Cell :: new ( None ) ,
1258
1265
alloca_insert_pt : Cell :: new ( None ) ,
1259
1266
llreturn : Cell :: new ( None ) ,
1260
1267
personality : Cell :: new ( None ) ,
@@ -1298,12 +1305,12 @@ pub fn init_function<'a>(fcx: &'a FunctionContext<'a>,
1298
1305
1299
1306
if !return_type_is_void ( fcx. ccx , substd_output_type) {
1300
1307
// If the function returns nil/bot, there is no real return
1301
- // value, so do not set `llretptr `.
1308
+ // value, so do not set `llretslotptr `.
1302
1309
if !skip_retptr || fcx. caller_expects_out_pointer {
1303
- // Otherwise, we normally allocate the llretptr , unless we
1310
+ // Otherwise, we normally allocate the llretslotptr , unless we
1304
1311
// have been instructed to skip it for immediate return
1305
1312
// values.
1306
- fcx. llretptr . set ( Some ( make_return_pointer ( fcx, substd_output_type) ) ) ;
1313
+ fcx. llretslotptr . set ( Some ( make_return_slot_pointer ( fcx, substd_output_type) ) ) ;
1307
1314
}
1308
1315
}
1309
1316
@@ -1528,12 +1535,12 @@ pub fn finish_fn<'a>(fcx: &'a FunctionContext<'a>,
1528
1535
1529
1536
// Builds the return block for a function.
1530
1537
pub fn build_return_block ( fcx : & FunctionContext , ret_cx : & Block , retty : ty:: t ) {
1531
- // Return the value if this function immediate; otherwise, return void.
1532
- if fcx. llretptr . get ( ) . is_none ( ) || fcx. caller_expects_out_pointer {
1538
+ if fcx. llretslotptr . get ( ) . is_none ( ) {
1533
1539
return RetVoid ( ret_cx) ;
1534
1540
}
1535
1541
1536
- let retptr = Value ( fcx. llretptr . get ( ) . unwrap ( ) ) ;
1542
+ let retslot = Load ( ret_cx, fcx. llretslotptr . get ( ) . unwrap ( ) ) ;
1543
+ let retptr = Value ( retslot) ;
1537
1544
let retval = match retptr. get_dominating_store ( ret_cx) {
1538
1545
// If there's only a single store to the ret slot, we can directly return
1539
1546
// the value that was stored and omit the store and the alloca
@@ -1552,10 +1559,15 @@ pub fn build_return_block(fcx: &FunctionContext, ret_cx: &Block, retty: ty::t) {
1552
1559
}
1553
1560
}
1554
1561
// Otherwise, load the return value from the ret slot
1555
- None => load_ty ( ret_cx, fcx . llretptr . get ( ) . unwrap ( ) , retty)
1562
+ None => load_ty ( ret_cx, retslot , retty)
1556
1563
} ;
1557
1564
1558
- Ret ( ret_cx, retval) ;
1565
+ if fcx. caller_expects_out_pointer {
1566
+ store_ty ( ret_cx, retval, get_param ( fcx. llfn , 0 ) , retty) ;
1567
+ RetVoid ( ret_cx) ;
1568
+ } else {
1569
+ Ret ( ret_cx, retval) ;
1570
+ }
1559
1571
}
1560
1572
1561
1573
#[ deriving( Clone , Eq , PartialEq ) ]
@@ -1651,10 +1663,10 @@ pub fn trans_closure(ccx: &CrateContext,
1651
1663
// emitting should be enabled.
1652
1664
debuginfo:: start_emitting_source_locations( & fcx) ;
1653
1665
1654
- let dest = match fcx. llretptr . get( ) {
1655
- Some ( e ) => { expr:: SaveIn ( e ) }
1666
+ let dest = match fcx. llretslotptr . get( ) {
1667
+ Some ( _ ) => expr:: SaveIn ( alloca ( bcx , type_of :: type_of ( bcx . ccx ( ) , block_ty ) , "iret_slot" ) ) ,
1656
1668
None => {
1657
- assert!( type_is_zero_size( bcx. ccx( ) , block_ty) )
1669
+ assert ! ( type_is_zero_size( bcx. ccx( ) , block_ty) ) ;
1658
1670
expr:: Ignore
1659
1671
}
1660
1672
} ;
@@ -1665,6 +1677,13 @@ pub fn trans_closure(ccx: &CrateContext,
1665
1677
// (trans_block, trans_expr, et cetera).
1666
1678
bcx = controlflow:: trans_block( bcx, body, dest) ;
1667
1679
1680
+ match dest {
1681
+ expr : : SaveIn ( slot) => {
1682
+ Store ( bcx, slot, fcx. llretslotptr. get( ) . unwrap( ) ) ;
1683
+ }
1684
+ _ => { }
1685
+ }
1686
+
1668
1687
match fcx. llreturn. get( ) {
1669
1688
Some ( _) => {
1670
1689
Br ( bcx, fcx. return_exit_block( ) ) ;
@@ -1832,16 +1851,18 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
1832
1851
let arg_datums = create_datums_for_fn_args( & fcx, arg_tys. as_slice( ) ) ;
1833
1852
1834
1853
if !type_is_zero_size( fcx. ccx, result_ty) {
1854
+ let dest = alloca( bcx, type_of:: type_of( bcx. ccx( ) , result_ty) , "eret_slot") ;
1835
1855
let repr = adt:: represent_type( ccx, result_ty) ;
1836
1856
for ( i, arg_datum) in arg_datums. move_iter( ) . enumerate( ) {
1837
1857
let lldestptr = adt:: trans_field_ptr( bcx,
1838
1858
& * repr,
1839
- fcx . llretptr . get ( ) . unwrap ( ) ,
1859
+ dest ,
1840
1860
disr,
1841
1861
i) ;
1842
1862
arg_datum. store_to( bcx, lldestptr) ;
1843
1863
}
1844
- adt:: trans_set_discr( bcx, & * repr, fcx. llretptr. get( ) . unwrap( ) , disr) ;
1864
+ adt:: trans_set_discr( bcx, & * repr, dest, disr) ;
1865
+ Store ( bcx, dest, fcx. llretslotptr. get( ) . unwrap( ) ) ;
1845
1866
}
1846
1867
1847
1868
finish_fn( & fcx, bcx, result_ty) ;
0 commit comments