@@ -1102,11 +1102,6 @@ pub fn trans_trace(bcx: block, sp_opt: Option<span>, trace_str: @str) {
1102
1102
Call ( bcx, ccx. upcalls. trace, args) ;
1103
1103
}
1104
1104
1105
- pub fn build_return( bcx: block) {
1106
- let _icx = push_ctxt( "build_return" ) ;
1107
- Br ( bcx, bcx. fcx. llreturn) ;
1108
- }
1109
-
1110
1105
pub fn ignore_lhs( _bcx: block, local: & ast:: local) -> bool {
1111
1106
match local. node. pat. node {
1112
1107
ast:: pat_wild => true , _ => false
@@ -1364,6 +1359,42 @@ pub fn cleanup_and_leave(bcx: block,
1364
1359
}
1365
1360
}
1366
1361
1362
+ pub fn cleanup_block( bcx: block, upto: Option <BasicBlockRef >) -> block{
1363
+ let _icx = push_ctxt( "cleanup_block" ) ;
1364
+ let mut cur = bcx;
1365
+ let mut bcx = bcx;
1366
+ loop {
1367
+ debug!( "cleanup_block: %s" , cur. to_str( ) ) ;
1368
+
1369
+ if bcx. sess( ) . trace( ) {
1370
+ trans_trace(
1371
+ bcx, None ,
1372
+ ( fmt!( "cleanup_block(%s)" , cur. to_str( ) ) ) . to_managed( ) ) ;
1373
+ }
1374
+
1375
+ let mut cur_scope = cur. scope;
1376
+ loop {
1377
+ cur_scope = match cur_scope {
1378
+ Some ( inf) => {
1379
+ bcx = trans_block_cleanups_( bcx, inf. cleanups. to_owned( ) , false ) ;
1380
+ inf. parent
1381
+ }
1382
+ None => break
1383
+ }
1384
+ }
1385
+
1386
+ match upto {
1387
+ Some ( bb) => { if cur. llbb == bb { break ; } }
1388
+ _ => ( )
1389
+ }
1390
+ cur = match cur. parent {
1391
+ Some ( next) => next,
1392
+ None => { assert!( upto. is_none( ) ) ; break ; }
1393
+ } ;
1394
+ }
1395
+ bcx
1396
+ }
1397
+
1367
1398
pub fn cleanup_and_Br( bcx: block, upto: block, target: BasicBlockRef ) {
1368
1399
let _icx = push_ctxt( "cleanup_and_Br" ) ;
1369
1400
cleanup_and_leave( bcx, Some ( upto. llbb) , Some ( target) ) ;
@@ -1526,7 +1557,7 @@ pub fn alloca_maybe_zeroed(cx: block, ty: Type, name: &str, zero: bool) -> Value
1526
1557
return llvm:: LLVMGetUndef ( ty. to_ref( ) ) ;
1527
1558
}
1528
1559
}
1529
- let initcx = base:: raw_block( cx. fcx, false , cx. fcx. llstaticallocas ) ;
1560
+ let initcx = base:: raw_block( cx. fcx, false , cx. fcx. get_llstaticallocas ( ) ) ;
1530
1561
let p = Alloca ( initcx, ty, name) ;
1531
1562
if zero { memzero( initcx, p, ty) ; }
1532
1563
p
@@ -1539,24 +1570,26 @@ pub fn arrayalloca(cx: block, ty: Type, v: ValueRef) -> ValueRef {
1539
1570
return llvm:: LLVMGetUndef ( ty. to_ref( ) ) ;
1540
1571
}
1541
1572
}
1542
- return ArrayAlloca ( base:: raw_block( cx. fcx, false , cx. fcx. llstaticallocas ) , ty, v) ;
1573
+ return ArrayAlloca ( base:: raw_block( cx. fcx, false , cx. fcx. get_llstaticallocas ( ) ) , ty, v) ;
1543
1574
}
1544
1575
1545
1576
pub struct BasicBlocks {
1546
1577
sa: BasicBlockRef ,
1547
- rt: BasicBlockRef
1548
1578
}
1549
1579
1550
- // Creates the standard set of basic blocks for a function
1551
- pub fn mk_standard_basic_blocks( llfn: ValueRef ) -> BasicBlocks {
1580
+ pub fn mk_staticallocas_basic_block( llfn: ValueRef ) -> BasicBlockRef {
1552
1581
unsafe {
1553
1582
let cx = task_llcx( ) ;
1554
- BasicBlocks {
1555
- sa: str :: as_c_str( "static_allocas" ,
1556
- |buf| llvm:: LLVMAppendBasicBlockInContext ( cx, llfn, buf) ) ,
1557
- rt: str :: as_c_str( "return" ,
1558
- |buf| llvm:: LLVMAppendBasicBlockInContext ( cx, llfn, buf) )
1559
- }
1583
+ str :: as_c_str( "static_allocas" ,
1584
+ |buf| llvm:: LLVMAppendBasicBlockInContext ( cx, llfn, buf) )
1585
+ }
1586
+ }
1587
+
1588
+ pub fn mk_return_basic_block( llfn: ValueRef ) -> BasicBlockRef {
1589
+ unsafe {
1590
+ let cx = task_llcx( ) ;
1591
+ str :: as_c_str( "return" ,
1592
+ |buf| llvm:: LLVMAppendBasicBlockInContext ( cx, llfn, buf) )
1560
1593
}
1561
1594
}
1562
1595
@@ -1568,7 +1601,7 @@ pub fn make_return_pointer(fcx: fn_ctxt, output_type: ty::t) -> ValueRef {
1568
1601
llvm:: LLVMGetParam ( fcx. llfn, 0 )
1569
1602
} else {
1570
1603
let lloutputtype = type_of:: type_of( fcx. ccx, output_type) ;
1571
- alloca( raw_block( fcx, false , fcx. llstaticallocas ) , lloutputtype,
1604
+ alloca( raw_block( fcx, false , fcx. get_llstaticallocas ( ) ) , lloutputtype,
1572
1605
"__make_return_pointer" )
1573
1606
}
1574
1607
}
@@ -1596,8 +1629,6 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
1596
1629
id,
1597
1630
param_substs. repr( ccx. tcx) ) ;
1598
1631
1599
- let llbbs = mk_standard_basic_blocks( llfndecl) ;
1600
-
1601
1632
let substd_output_type = match param_substs {
1602
1633
None => output_type,
1603
1634
Some ( substs) => {
@@ -1611,9 +1642,9 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
1611
1642
llvm:: LLVMGetUndef ( Type :: i8p( ) . to_ref( ) )
1612
1643
} ,
1613
1644
llretptr: None ,
1614
- llstaticallocas: llbbs . sa ,
1645
+ llstaticallocas: None ,
1615
1646
llloadenv: None ,
1616
- llreturn: llbbs . rt ,
1647
+ llreturn: None ,
1617
1648
llself: None ,
1618
1649
personality: None ,
1619
1650
loop_ret: None ,
@@ -1757,16 +1788,24 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
1757
1788
1758
1789
// Ties up the llstaticallocas -> llloadenv -> lltop edges,
1759
1790
// and builds the return block.
1760
- pub fn finish_fn( fcx: fn_ctxt, lltop: BasicBlockRef ) {
1791
+ pub fn finish_fn( fcx: fn_ctxt, lltop: BasicBlockRef , last_bcx : block ) {
1761
1792
let _icx = push_ctxt( "finish_fn" ) ;
1762
1793
tie_up_header_blocks( fcx, lltop) ;
1763
- build_return_block( fcx) ;
1794
+
1795
+ let ret_cx = match fcx. llreturn {
1796
+ Some ( llreturn) => {
1797
+ if !last_bcx. terminated {
1798
+ Br ( last_bcx, llreturn) ;
1799
+ }
1800
+ raw_block( fcx, false , llreturn)
1801
+ }
1802
+ None => last_bcx
1803
+ } ;
1804
+ build_return_block( fcx, ret_cx) ;
1764
1805
}
1765
1806
1766
1807
// Builds the return block for a function.
1767
- pub fn build_return_block( fcx: fn_ctxt) {
1768
- let ret_cx = raw_block( fcx, false , fcx. llreturn) ;
1769
-
1808
+ pub fn build_return_block( fcx: fn_ctxt, ret_cx: block) {
1770
1809
// Return the value if this function immediate; otherwise, return void.
1771
1810
if fcx. llretptr. is_some( ) && fcx. has_immediate_return_value {
1772
1811
Ret ( ret_cx, Load ( ret_cx, fcx. llretptr. get( ) ) )
@@ -1777,14 +1816,24 @@ pub fn build_return_block(fcx: fn_ctxt) {
1777
1816
1778
1817
pub fn tie_up_header_blocks( fcx: fn_ctxt, lltop: BasicBlockRef ) {
1779
1818
let _icx = push_ctxt( "tie_up_header_blocks" ) ;
1780
- match fcx. llloadenv {
1819
+ let llnext = match fcx. llloadenv {
1781
1820
Some ( ll) => {
1782
- Br ( raw_block( fcx, false , fcx. llstaticallocas) , ll) ;
1821
+ unsafe {
1822
+ llvm:: LLVMMoveBasicBlockBefore ( ll, lltop) ;
1823
+ }
1783
1824
Br ( raw_block( fcx, false , ll) , lltop) ;
1825
+ ll
1784
1826
}
1785
- None => {
1786
- Br ( raw_block( fcx, false , fcx. llstaticallocas) , lltop) ;
1827
+ None => lltop
1828
+ } ;
1829
+ match fcx. llstaticallocas {
1830
+ Some ( ll) => {
1831
+ unsafe {
1832
+ llvm:: LLVMMoveBasicBlockBefore ( ll, llnext) ;
1833
+ }
1834
+ Br ( raw_block( fcx, false , ll) , llnext) ;
1787
1835
}
1836
+ None => ( )
1788
1837
}
1789
1838
}
1790
1839
@@ -1854,16 +1903,21 @@ pub fn trans_closure(ccx: @mut CrateContext,
1854
1903
}
1855
1904
1856
1905
finish( bcx) ;
1857
- cleanup_and_Br( bcx, bcx_top, fcx. llreturn) ;
1906
+ match fcx. llreturn {
1907
+ Some ( llreturn) => cleanup_and_Br( bcx, bcx_top, llreturn) ,
1908
+ None => bcx = cleanup_block( bcx, Some ( bcx_top. llbb) )
1909
+ } ;
1858
1910
1859
1911
// Put return block after all other blocks.
1860
1912
// This somewhat improves single-stepping experience in debugger.
1861
1913
unsafe {
1862
- llvm:: LLVMMoveBasicBlockAfter ( fcx. llreturn, bcx. llbb) ;
1914
+ for fcx. llreturn. iter( ) . advance |& llreturn| {
1915
+ llvm:: LLVMMoveBasicBlockAfter ( llreturn, bcx. llbb) ;
1916
+ }
1863
1917
}
1864
1918
1865
1919
// Insert the mandatory first few basic blocks before lltop.
1866
- finish_fn( fcx, lltop) ;
1920
+ finish_fn( fcx, lltop, bcx ) ;
1867
1921
}
1868
1922
1869
1923
// trans_fn: creates an LLVM function corresponding to a source language
@@ -2046,8 +2100,7 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
2046
2100
let arg_ty = arg_tys[ i] ;
2047
2101
memcpy_ty( bcx, lldestptr, llarg, arg_ty) ;
2048
2102
}
2049
- build_return( bcx) ;
2050
- finish_fn( fcx, lltop) ;
2103
+ finish_fn( fcx, lltop, bcx) ;
2051
2104
}
2052
2105
2053
2106
pub fn trans_enum_def( ccx: @mut CrateContext , enum_definition: & ast:: enum_def,
@@ -2288,8 +2341,7 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext,
2288
2341
let args = ~[ llenvarg] ;
2289
2342
Call ( bcx, main_llfn, args) ;
2290
2343
2291
- build_return( bcx) ;
2292
- finish_fn( fcx, lltop) ;
2344
+ finish_fn( fcx, lltop, bcx) ;
2293
2345
return llfdecl;
2294
2346
}
2295
2347
0 commit comments