@@ -1210,16 +1210,23 @@ pub fn arrayalloca(cx: &Block, ty: Type, v: ValueRef) -> ValueRef {
1210
1210
p
1211
1211
}
1212
1212
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
1217
1221
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) ;
1222
1227
}
1228
+
1229
+ slot
1223
1230
}
1224
1231
1225
1232
// NB: must keep 4 fns in sync:
@@ -1258,7 +1265,7 @@ pub fn new_fn_ctxt<'a>(ccx: &'a CrateContext,
1258
1265
let mut fcx = FunctionContext {
1259
1266
llfn : llfndecl,
1260
1267
llenv : None ,
1261
- llretptr : Cell :: new ( None ) ,
1268
+ llretslotptr : Cell :: new ( None ) ,
1262
1269
alloca_insert_pt : Cell :: new ( None ) ,
1263
1270
llreturn : Cell :: new ( None ) ,
1264
1271
personality : Cell :: new ( None ) ,
@@ -1303,12 +1310,12 @@ pub fn init_function<'a>(fcx: &'a FunctionContext<'a>,
1303
1310
1304
1311
if !return_type_is_void ( fcx. ccx , substd_output_type) {
1305
1312
// 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 `.
1307
1314
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
1309
1316
// have been instructed to skip it for immediate return
1310
1317
// 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) ) ) ;
1312
1319
}
1313
1320
}
1314
1321
@@ -1533,12 +1540,12 @@ pub fn finish_fn<'a>(fcx: &'a FunctionContext<'a>,
1533
1540
1534
1541
// Builds the return block for a function.
1535
1542
pub 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 ( ) {
1538
1544
return RetVoid ( ret_cx) ;
1539
1545
}
1540
1546
1541
- let retptr = Value ( fcx. llretptr . get ( ) . unwrap ( ) ) ;
1547
+ let retslot = Load ( ret_cx, fcx. llretslotptr . get ( ) . unwrap ( ) ) ;
1548
+ let retptr = Value ( retslot) ;
1542
1549
let retval = match retptr. get_dominating_store ( ret_cx) {
1543
1550
// If there's only a single store to the ret slot, we can directly return
1544
1551
// 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) {
1557
1564
}
1558
1565
}
1559
1566
// 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)
1561
1568
} ;
1562
1569
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
+ }
1564
1576
}
1565
1577
1566
1578
#[ deriving( Clone , Eq , PartialEq ) ]
@@ -1658,10 +1670,10 @@ pub fn trans_closure(ccx: &CrateContext,
1658
1670
// emitting should be enabled.
1659
1671
debuginfo:: start_emitting_source_locations( & fcx) ;
1660
1672
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" ) ) ,
1663
1675
None => {
1664
- assert!( type_is_zero_size( bcx. ccx( ) , block_ty) )
1676
+ assert ! ( type_is_zero_size( bcx. ccx( ) , block_ty) ) ;
1665
1677
expr:: Ignore
1666
1678
}
1667
1679
} ;
@@ -1672,6 +1684,13 @@ pub fn trans_closure(ccx: &CrateContext,
1672
1684
// (trans_block, trans_expr, et cetera).
1673
1685
bcx = controlflow:: trans_block( bcx, body, dest) ;
1674
1686
1687
+ match dest {
1688
+ expr : : SaveIn ( slot) => {
1689
+ Store ( bcx, slot, fcx. llretslotptr. get( ) . unwrap( ) ) ;
1690
+ }
1691
+ _ => { }
1692
+ }
1693
+
1675
1694
match fcx. llreturn. get( ) {
1676
1695
Some ( _) => {
1677
1696
Br ( bcx, fcx. return_exit_block( ) ) ;
@@ -1841,16 +1860,18 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
1841
1860
let arg_datums = create_datums_for_fn_args( & fcx, arg_tys. as_slice( ) ) ;
1842
1861
1843
1862
if !type_is_zero_size( fcx. ccx, result_ty) {
1863
+ let dest = alloca( bcx, type_of:: type_of( bcx. ccx( ) , result_ty) , "eret_slot") ;
1844
1864
let repr = adt:: represent_type( ccx, result_ty) ;
1845
1865
for ( i, arg_datum) in arg_datums. move_iter( ) . enumerate( ) {
1846
1866
let lldestptr = adt:: trans_field_ptr( bcx,
1847
1867
& * repr,
1848
- fcx . llretptr . get ( ) . unwrap ( ) ,
1868
+ dest ,
1849
1869
disr,
1850
1870
i) ;
1851
1871
arg_datum. store_to( bcx, lldestptr) ;
1852
1872
}
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( ) ) ;
1854
1875
}
1855
1876
1856
1877
finish_fn( & fcx, bcx, result_ty) ;
0 commit comments