@@ -1122,7 +1122,7 @@ pub fn memcpy_ty(bcx: &Block, dst: ValueRef, src: ValueRef, t: ty::t) {
1122
1122
let llalign = llalign_of_min ( ccx, llty) ;
1123
1123
call_memcpy ( bcx, dst, src, llsz, llalign as u32 ) ;
1124
1124
} else {
1125
- store_ty ( bcx, Load ( bcx, src) , dst, t ) ;
1125
+ Store ( bcx, Load ( bcx, src) , dst) ;
1126
1126
}
1127
1127
}
1128
1128
@@ -1210,120 +1210,15 @@ pub fn arrayalloca(cx: &Block, ty: Type, v: ValueRef) -> ValueRef {
1210
1210
p
1211
1211
}
1212
1212
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
- // We create an alloca to hold a pointer of type `output_type`
1218
- // which will hold the pointer to the right alloca which has the
1219
- // final ret value
1220
- if fcx. needs_ret_allocas {
1221
- // Let's create the stack slot
1222
- let slot = AllocaFcx ( fcx, lloutputtype. ptr_to ( ) , "llretslotptr" ) ;
1223
-
1224
- // and if we're using an out pointer, then store that in our newly made slot
1225
- if type_of:: return_uses_outptr ( fcx. ccx , output_type) {
1226
- let outptr = get_param ( fcx. llfn , 0 ) ;
1227
-
1228
- let b = fcx. ccx . builder ( ) ;
1229
- b. position_before ( fcx. alloca_insert_pt . get ( ) . unwrap ( ) ) ;
1230
- b. store ( outptr, slot) ;
1231
- }
1232
-
1233
- slot
1234
-
1235
- // But if there are no nested returns, we skip the indirection and have a single
1236
- // retslot
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 {
1217
+ if type_of:: return_uses_outptr ( fcx. ccx , output_type) {
1218
+ get_param ( fcx. llfn , 0 )
1237
1219
} else {
1238
- if type_of:: return_uses_outptr ( fcx. ccx , output_type) {
1239
- get_param ( fcx. llfn , 0 )
1240
- } else {
1241
- AllocaFcx ( fcx, lloutputtype, "sret_slot" )
1242
- }
1243
- }
1244
- }
1245
-
1246
- struct CheckForNestedReturnsVisitor {
1247
- found : bool
1248
- }
1249
-
1250
- impl Visitor < bool > for CheckForNestedReturnsVisitor {
1251
- fn visit_expr ( & mut self , e : & ast:: Expr , in_return : bool ) {
1252
- match e. node {
1253
- ast:: ExprRet ( ..) if in_return => {
1254
- self . found = true ;
1255
- return ;
1256
- }
1257
- ast:: ExprRet ( ..) => visit:: walk_expr ( self , e, true ) ,
1258
- _ => visit:: walk_expr ( self , e, in_return)
1259
- }
1260
- }
1261
- }
1262
-
1263
- fn has_nested_returns ( tcx : & ty:: ctxt , id : ast:: NodeId ) -> bool {
1264
- match tcx. map . find ( id) {
1265
- Some ( ast_map:: NodeItem ( i) ) => {
1266
- match i. node {
1267
- ast:: ItemFn ( _, _, _, _, blk) => {
1268
- let mut explicit = CheckForNestedReturnsVisitor { found : false } ;
1269
- let mut implicit = CheckForNestedReturnsVisitor { found : false } ;
1270
- visit:: walk_item ( & mut explicit, & * i, false ) ;
1271
- visit:: walk_expr_opt ( & mut implicit, blk. expr , true ) ;
1272
- explicit. found || implicit. found
1273
- }
1274
- _ => tcx. sess . bug ( "unexpected item variant in has_nested_returns" )
1275
- }
1276
- }
1277
- Some ( ast_map:: NodeTraitMethod ( trait_method) ) => {
1278
- match * trait_method {
1279
- ast:: Provided ( m) => {
1280
- match m. node {
1281
- ast:: MethDecl ( _, _, _, _, _, _, blk, _) => {
1282
- let mut explicit = CheckForNestedReturnsVisitor { found : false } ;
1283
- let mut implicit = CheckForNestedReturnsVisitor { found : false } ;
1284
- visit:: walk_method_helper ( & mut explicit, & * m, false ) ;
1285
- visit:: walk_expr_opt ( & mut implicit, blk. expr , true ) ;
1286
- explicit. found || implicit. found
1287
- }
1288
- ast:: MethMac ( _) => tcx. sess . bug ( "unexpanded macro" )
1289
- }
1290
- }
1291
- ast:: Required ( _) => tcx. sess . bug ( "unexpected variant: required trait method in \
1292
- has_nested_returns")
1293
- }
1294
- }
1295
- Some ( ast_map:: NodeMethod ( m) ) => {
1296
- match m. node {
1297
- ast:: MethDecl ( _, _, _, _, _, _, blk, _) => {
1298
- let mut explicit = CheckForNestedReturnsVisitor { found : false } ;
1299
- let mut implicit = CheckForNestedReturnsVisitor { found : false } ;
1300
- visit:: walk_method_helper ( & mut explicit, & * m, false ) ;
1301
- visit:: walk_expr_opt ( & mut implicit, blk. expr , true ) ;
1302
- explicit. found || implicit. found
1303
- }
1304
- ast:: MethMac ( _) => tcx. sess . bug ( "unexpanded macro" )
1305
- }
1306
- }
1307
- Some ( ast_map:: NodeExpr ( e) ) => {
1308
- match e. node {
1309
- ast:: ExprFnBlock ( _, blk) | ast:: ExprProc ( _, blk) | ast:: ExprUnboxedFn ( _, blk) => {
1310
- let mut explicit = CheckForNestedReturnsVisitor { found : false } ;
1311
- let mut implicit = CheckForNestedReturnsVisitor { found : false } ;
1312
- visit:: walk_expr ( & mut explicit, & * e, false ) ;
1313
- visit:: walk_expr_opt ( & mut implicit, blk. expr , true ) ;
1314
- explicit. found || implicit. found
1315
- }
1316
- _ => tcx. sess . bug ( "unexpected expr variant in has_nested_returns" )
1317
- }
1318
- }
1319
-
1320
- Some ( ast_map:: NodeVariant ( ..) ) | Some ( ast_map:: NodeStructCtor ( ..) ) => false ,
1321
-
1322
- // glue, shims, etc
1323
- None if id == ast:: DUMMY_NODE_ID => false ,
1324
-
1325
- _ => tcx. sess . bug ( format ! ( "unexpected variant in has_nested_returns: {}" ,
1326
- tcx. map. path_to_string( id) ) . as_slice ( ) )
1220
+ let lloutputtype = type_of:: type_of ( fcx. ccx , output_type) ;
1221
+ AllocaFcx ( fcx, lloutputtype, "__make_return_pointer" )
1327
1222
}
1328
1223
}
1329
1224
@@ -1359,15 +1254,13 @@ pub fn new_fn_ctxt<'a>(ccx: &'a CrateContext,
1359
1254
let substd_output_type = output_type. substp ( ccx. tcx ( ) , param_substs) ;
1360
1255
let uses_outptr = type_of:: return_uses_outptr ( ccx, substd_output_type) ;
1361
1256
let debug_context = debuginfo:: create_function_debug_context ( ccx, id, param_substs, llfndecl) ;
1362
- let nested_returns = has_nested_returns ( ccx. tcx ( ) , id) ;
1363
1257
1364
1258
let mut fcx = FunctionContext {
1365
1259
llfn : llfndecl,
1366
1260
llenv : None ,
1367
- llretslotptr : Cell :: new ( None ) ,
1261
+ llretptr : Cell :: new ( None ) ,
1368
1262
alloca_insert_pt : Cell :: new ( None ) ,
1369
1263
llreturn : Cell :: new ( None ) ,
1370
- needs_ret_allocas : nested_returns,
1371
1264
personality : Cell :: new ( None ) ,
1372
1265
caller_expects_out_pointer : uses_outptr,
1373
1266
llargs : RefCell :: new ( NodeMap :: new ( ) ) ,
@@ -1410,12 +1303,12 @@ pub fn init_function<'a>(fcx: &'a FunctionContext<'a>,
1410
1303
1411
1304
if !return_type_is_void ( fcx. ccx , substd_output_type) {
1412
1305
// If the function returns nil/bot, there is no real return
1413
- // value, so do not set `llretslotptr `.
1306
+ // value, so do not set `llretptr `.
1414
1307
if !skip_retptr || fcx. caller_expects_out_pointer {
1415
- // Otherwise, we normally allocate the llretslotptr , unless we
1308
+ // Otherwise, we normally allocate the llretptr , unless we
1416
1309
// have been instructed to skip it for immediate return
1417
1310
// values.
1418
- fcx. llretslotptr . set ( Some ( make_return_slot_pointer ( fcx, substd_output_type) ) ) ;
1311
+ fcx. llretptr . set ( Some ( make_return_pointer ( fcx, substd_output_type) ) ) ;
1419
1312
}
1420
1313
}
1421
1314
@@ -1640,18 +1533,13 @@ pub fn finish_fn<'a>(fcx: &'a FunctionContext<'a>,
1640
1533
1641
1534
// Builds the return block for a function.
1642
1535
pub fn build_return_block ( fcx : & FunctionContext , ret_cx : & Block , retty : ty:: t ) {
1643
- if fcx . llretslotptr . get ( ) . is_none ( ) ||
1644
- ( ! fcx. needs_ret_allocas && fcx. caller_expects_out_pointer ) {
1536
+ // Return the value if this function immediate; otherwise, return void.
1537
+ if fcx. llretptr . get ( ) . is_none ( ) || fcx. caller_expects_out_pointer {
1645
1538
return RetVoid ( ret_cx) ;
1646
1539
}
1647
1540
1648
- let retslot = if fcx. needs_ret_allocas {
1649
- Load ( ret_cx, fcx. llretslotptr . get ( ) . unwrap ( ) )
1650
- } else {
1651
- fcx. llretslotptr . get ( ) . unwrap ( )
1652
- } ;
1653
- let retptr = Value ( retslot) ;
1654
- match retptr. get_dominating_store ( ret_cx) {
1541
+ let retptr = Value ( fcx. llretptr . get ( ) . unwrap ( ) ) ;
1542
+ let retval = match retptr. get_dominating_store ( ret_cx) {
1655
1543
// If there's only a single store to the ret slot, we can directly return
1656
1544
// the value that was stored and omit the store and the alloca
1657
1545
Some ( s) => {
@@ -1662,29 +1550,17 @@ pub fn build_return_block(fcx: &FunctionContext, ret_cx: &Block, retty: ty::t) {
1662
1550
retptr. erase_from_parent ( ) ;
1663
1551
}
1664
1552
1665
- let retval = if ty:: type_is_bool ( retty) {
1553
+ if ty:: type_is_bool ( retty) {
1666
1554
Trunc ( ret_cx, retval, Type :: i1 ( fcx. ccx ) )
1667
1555
} else {
1668
1556
retval
1669
- } ;
1670
-
1671
- if fcx. caller_expects_out_pointer {
1672
- store_ty ( ret_cx, retval, get_param ( fcx. llfn , 0 ) , retty) ;
1673
- return RetVoid ( ret_cx) ;
1674
- } else {
1675
- return Ret ( ret_cx, retval) ;
1676
1557
}
1677
1558
}
1678
- // Otherwise, copy the return value to the ret slot
1679
- None => {
1680
- if fcx. caller_expects_out_pointer {
1681
- memcpy_ty ( ret_cx, get_param ( fcx. llfn , 0 ) , retslot, retty) ;
1682
- return RetVoid ( ret_cx) ;
1683
- } else {
1684
- return Ret ( ret_cx, load_ty ( ret_cx, retslot, retty) ) ;
1685
- }
1686
- }
1687
- }
1559
+ // Otherwise, load the return value from the ret slot
1560
+ None => load_ty ( ret_cx, fcx. llretptr . get ( ) . unwrap ( ) , retty)
1561
+ } ;
1562
+
1563
+ Ret ( ret_cx, retval) ;
1688
1564
}
1689
1565
1690
1566
#[ deriving( Clone , Eq , PartialEq ) ]
@@ -1782,10 +1658,10 @@ pub fn trans_closure(ccx: &CrateContext,
1782
1658
// emitting should be enabled.
1783
1659
debuginfo:: start_emitting_source_locations( & fcx) ;
1784
1660
1785
- let dest = match fcx. llretslotptr . get( ) {
1786
- Some ( _ ) => expr:: SaveIn ( fcx . get_ret_slot ( bcx , block_ty , "iret_slot" ) ) ,
1661
+ let dest = match fcx. llretptr . get( ) {
1662
+ Some ( e ) => { expr:: SaveIn ( e ) }
1787
1663
None => {
1788
- assert ! ( type_is_zero_size( bcx. ccx( ) , block_ty) ) ;
1664
+ assert!( type_is_zero_size( bcx. ccx( ) , block_ty) )
1789
1665
expr:: Ignore
1790
1666
}
1791
1667
} ;
@@ -1796,13 +1672,6 @@ pub fn trans_closure(ccx: &CrateContext,
1796
1672
// (trans_block, trans_expr, et cetera).
1797
1673
bcx = controlflow:: trans_block( bcx, body, dest) ;
1798
1674
1799
- match dest {
1800
- expr : : SaveIn ( slot) if fcx. needs_ret_allocas => {
1801
- Store ( bcx, slot, fcx. llretslotptr. get( ) . unwrap( ) ) ;
1802
- }
1803
- _ => { }
1804
- }
1805
-
1806
1675
match fcx. llreturn. get( ) {
1807
1676
Some ( _) => {
1808
1677
Br ( bcx, fcx. return_exit_block( ) ) ;
@@ -1967,24 +1836,21 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
1967
1836
param_substs, None , & arena, TranslateItems ) ;
1968
1837
let bcx = init_function( & fcx, false , result_ty) ;
1969
1838
1970
- assert!( !fcx. needs_ret_allocas) ;
1971
-
1972
1839
let arg_tys = ty:: ty_fn_args( ctor_ty) ;
1973
1840
1974
1841
let arg_datums = create_datums_for_fn_args( & fcx, arg_tys. as_slice( ) ) ;
1975
1842
1976
1843
if !type_is_zero_size( fcx. ccx, result_ty) {
1977
- let dest = fcx. get_ret_slot( bcx, result_ty, "eret_slot") ;
1978
1844
let repr = adt:: represent_type( ccx, result_ty) ;
1979
1845
for ( i, arg_datum) in arg_datums. move_iter( ) . enumerate( ) {
1980
1846
let lldestptr = adt:: trans_field_ptr( bcx,
1981
1847
& * repr,
1982
- dest ,
1848
+ fcx . llretptr . get ( ) . unwrap ( ) ,
1983
1849
disr,
1984
1850
i) ;
1985
1851
arg_datum. store_to( bcx, lldestptr) ;
1986
1852
}
1987
- adt:: trans_set_discr( bcx, & * repr, dest , disr) ;
1853
+ adt:: trans_set_discr( bcx, & * repr, fcx . llretptr . get ( ) . unwrap ( ) , disr) ;
1988
1854
}
1989
1855
1990
1856
finish_fn( & fcx, bcx, result_ty) ;
0 commit comments