@@ -1102,11 +1102,6 @@ pub fn trans_trace(bcx: block, sp_opt: Option<span>, trace_str: @str) {
11021102 Call ( bcx, ccx. upcalls. trace, args) ;
11031103}
11041104
1105- pub fn build_return( bcx: block) {
1106- let _icx = push_ctxt( "build_return" ) ;
1107- Br ( bcx, bcx. fcx. llreturn) ;
1108- }
1109-
11101105pub fn ignore_lhs( _bcx: block, local: & ast:: local) -> bool {
11111106 match local. node. pat. node {
11121107 ast:: pat_wild => true , _ => false
@@ -1364,6 +1359,42 @@ pub fn cleanup_and_leave(bcx: block,
13641359 }
13651360}
13661361
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+
13671398pub fn cleanup_and_Br( bcx: block, upto: block, target: BasicBlockRef ) {
13681399 let _icx = push_ctxt( "cleanup_and_Br" ) ;
13691400 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
15261557 return llvm:: LLVMGetUndef ( ty. to_ref( ) ) ;
15271558 }
15281559 }
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 ( ) ) ;
15301561 let p = Alloca ( initcx, ty, name) ;
15311562 if zero { memzero( initcx, p, ty) ; }
15321563 p
@@ -1539,24 +1570,26 @@ pub fn arrayalloca(cx: block, ty: Type, v: ValueRef) -> ValueRef {
15391570 return llvm:: LLVMGetUndef ( ty. to_ref( ) ) ;
15401571 }
15411572 }
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) ;
15431574}
15441575
15451576pub struct BasicBlocks {
15461577 sa: BasicBlockRef ,
1547- rt: BasicBlockRef
15481578}
15491579
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 {
15521581 unsafe {
15531582 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) )
15601593 }
15611594}
15621595
@@ -1568,7 +1601,7 @@ pub fn make_return_pointer(fcx: fn_ctxt, output_type: ty::t) -> ValueRef {
15681601 llvm:: LLVMGetParam ( fcx. llfn, 0 )
15691602 } else {
15701603 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,
15721605 "__make_return_pointer" )
15731606 }
15741607 }
@@ -1596,8 +1629,6 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
15961629 id,
15971630 param_substs. repr( ccx. tcx) ) ;
15981631
1599- let llbbs = mk_standard_basic_blocks( llfndecl) ;
1600-
16011632 let substd_output_type = match param_substs {
16021633 None => output_type,
16031634 Some ( substs) => {
@@ -1611,9 +1642,9 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext,
16111642 llvm:: LLVMGetUndef ( Type :: i8p( ) . to_ref( ) )
16121643 } ,
16131644 llretptr: None ,
1614- llstaticallocas: llbbs . sa ,
1645+ llstaticallocas: None ,
16151646 llloadenv: None ,
1616- llreturn: llbbs . rt ,
1647+ llreturn: None ,
16171648 llself: None ,
16181649 personality: None ,
16191650 loop_ret: None ,
@@ -1757,16 +1788,24 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
17571788
17581789// Ties up the llstaticallocas -> llloadenv -> lltop edges,
17591790// 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 ) {
17611792 let _icx = push_ctxt( "finish_fn" ) ;
17621793 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) ;
17641805}
17651806
17661807// 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) {
17701809 // Return the value if this function immediate; otherwise, return void.
17711810 if fcx. llretptr. is_some( ) && fcx. has_immediate_return_value {
17721811 Ret ( ret_cx, Load ( ret_cx, fcx. llretptr. get( ) ) )
@@ -1777,14 +1816,24 @@ pub fn build_return_block(fcx: fn_ctxt) {
17771816
17781817pub fn tie_up_header_blocks( fcx: fn_ctxt, lltop: BasicBlockRef ) {
17791818 let _icx = push_ctxt( "tie_up_header_blocks" ) ;
1780- match fcx. llloadenv {
1819+ let llnext = match fcx. llloadenv {
17811820 Some ( ll) => {
1782- Br ( raw_block( fcx, false , fcx. llstaticallocas) , ll) ;
1821+ unsafe {
1822+ llvm:: LLVMMoveBasicBlockBefore ( ll, lltop) ;
1823+ }
17831824 Br ( raw_block( fcx, false , ll) , lltop) ;
1825+ ll
17841826 }
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) ;
17871835 }
1836+ None => ( )
17881837 }
17891838}
17901839
@@ -1854,16 +1903,21 @@ pub fn trans_closure(ccx: @mut CrateContext,
18541903 }
18551904
18561905 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+ } ;
18581910
18591911 // Put return block after all other blocks.
18601912 // This somewhat improves single-stepping experience in debugger.
18611913 unsafe {
1862- llvm:: LLVMMoveBasicBlockAfter ( fcx. llreturn, bcx. llbb) ;
1914+ for fcx. llreturn. iter( ) . advance |& llreturn| {
1915+ llvm:: LLVMMoveBasicBlockAfter ( llreturn, bcx. llbb) ;
1916+ }
18631917 }
18641918
18651919 // Insert the mandatory first few basic blocks before lltop.
1866- finish_fn( fcx, lltop) ;
1920+ finish_fn( fcx, lltop, bcx ) ;
18671921}
18681922
18691923// 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>(
20462100 let arg_ty = arg_tys[ i] ;
20472101 memcpy_ty( bcx, lldestptr, llarg, arg_ty) ;
20482102 }
2049- build_return( bcx) ;
2050- finish_fn( fcx, lltop) ;
2103+ finish_fn( fcx, lltop, bcx) ;
20512104}
20522105
20532106pub fn trans_enum_def( ccx: @mut CrateContext , enum_definition: & ast:: enum_def,
@@ -2288,8 +2341,7 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext,
22882341 let args = ~[ llenvarg] ;
22892342 Call ( bcx, main_llfn, args) ;
22902343
2291- build_return( bcx) ;
2292- finish_fn( fcx, lltop) ;
2344+ finish_fn( fcx, lltop, bcx) ;
22932345 return llfdecl;
22942346 }
22952347
0 commit comments