@@ -63,7 +63,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
6363 }
6464 }
6565
66- fn lltarget < Bx : BuilderMethods < ' a , ' tcx > > (
66+ /// Get a basic block (creating it if necessary), possibly with a landing
67+ /// pad next to it.
68+ fn llbb_with_landing_pad < Bx : BuilderMethods < ' a , ' tcx > > (
6769 & self ,
6870 fx : & mut FunctionCx < ' a , ' tcx , Bx > ,
6971 target : mir:: BasicBlock ,
@@ -73,32 +75,36 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
7375 let target_funclet = fx. cleanup_kinds [ target] . funclet_bb ( target) ;
7476 match ( self . funclet_bb , target_funclet) {
7577 ( None , None ) => ( lltarget, false ) ,
76- ( Some ( f) , Some ( t_f) ) if f == t_f || !base:: wants_msvc_seh ( fx. cx . tcx ( ) . sess ) => {
77- ( lltarget, false )
78- }
7978 // jump *into* cleanup - need a landing pad if GNU, cleanup pad if MSVC
8079 ( None , Some ( _) ) => ( fx. landing_pad_for ( target) , false ) ,
8180 ( Some ( _) , None ) => span_bug ! ( span, "{:?} - jump out of cleanup?" , self . terminator) ,
82- ( Some ( _) , Some ( _) ) => ( fx. landing_pad_for ( target) , true ) ,
81+ ( Some ( f) , Some ( t_f) ) => {
82+ if f == t_f || !base:: wants_msvc_seh ( fx. cx . tcx ( ) . sess ) {
83+ ( lltarget, false )
84+ } else {
85+ ( fx. landing_pad_for ( target) , true )
86+ }
87+ }
8388 }
8489 }
8590
86- /// Create a basic block.
87- fn llblock < Bx : BuilderMethods < ' a , ' tcx > > (
91+ /// Get a basic block (creating it if necessary), possibly with cleanup
92+ /// stuff in it or next to it.
93+ fn llbb_with_cleanup < Bx : BuilderMethods < ' a , ' tcx > > (
8894 & self ,
8995 fx : & mut FunctionCx < ' a , ' tcx , Bx > ,
9096 target : mir:: BasicBlock ,
9197 ) -> Bx :: BasicBlock {
92- let ( lltarget, is_cleanupret) = self . lltarget ( fx, target) ;
98+ let ( lltarget, is_cleanupret) = self . llbb_with_landing_pad ( fx, target) ;
9399 if is_cleanupret {
94100 // MSVC cross-funclet jump - need a trampoline
95-
96- debug ! ( "llblock : creating cleanup trampoline for {:?}" , target) ;
101+ debug_assert ! ( base :: wants_msvc_seh ( fx . cx . tcx ( ) . sess ) ) ;
102+ debug ! ( "llbb_with_cleanup : creating cleanup trampoline for {:?}" , target) ;
97103 let name = & format ! ( "{:?}_cleanup_trampoline_{:?}" , self . bb, target) ;
98- let trampoline = Bx :: append_block ( fx. cx , fx. llfn , name) ;
99- let mut trampoline_bx = Bx :: build ( fx. cx , trampoline ) ;
104+ let trampoline_llbb = Bx :: append_block ( fx. cx , fx. llfn , name) ;
105+ let mut trampoline_bx = Bx :: build ( fx. cx , trampoline_llbb ) ;
100106 trampoline_bx. cleanup_ret ( self . funclet ( fx) . unwrap ( ) , Some ( lltarget) ) ;
101- trampoline
107+ trampoline_llbb
102108 } else {
103109 lltarget
104110 }
@@ -110,10 +116,11 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
110116 bx : & mut Bx ,
111117 target : mir:: BasicBlock ,
112118 ) {
113- let ( lltarget, is_cleanupret) = self . lltarget ( fx, target) ;
119+ let ( lltarget, is_cleanupret) = self . llbb_with_landing_pad ( fx, target) ;
114120 if is_cleanupret {
115- // micro-optimization: generate a `ret` rather than a jump
121+ // MSVC micro-optimization: generate a `ret` rather than a jump
116122 // to a trampoline.
123+ debug_assert ! ( base:: wants_msvc_seh( fx. cx. tcx( ) . sess) ) ;
117124 bx. cleanup_ret ( self . funclet ( fx) . unwrap ( ) , Some ( lltarget) ) ;
118125 } else {
119126 bx. br ( lltarget) ;
@@ -138,7 +145,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
138145 let fn_ty = bx. fn_decl_backend_type ( & fn_abi) ;
139146
140147 let unwind_block = if let Some ( cleanup) = cleanup. filter ( |_| fn_abi. can_unwind ) {
141- Some ( self . llblock ( fx, cleanup) )
148+ Some ( self . llbb_with_cleanup ( fx, cleanup) )
142149 } else if fx. mir [ self . bb ] . is_cleanup
143150 && fn_abi. can_unwind
144151 && !base:: wants_msvc_seh ( fx. cx . tcx ( ) . sess )
@@ -231,7 +238,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
231238 options,
232239 line_spans,
233240 instance,
234- Some ( ( ret_llbb, self . llblock ( fx, cleanup) , self . funclet ( fx) ) ) ,
241+ Some ( ( ret_llbb, self . llbb_with_cleanup ( fx, cleanup) , self . funclet ( fx) ) ) ,
235242 ) ;
236243 } else {
237244 bx. codegen_inline_asm ( template, & operands, options, line_spans, instance, None ) ;
@@ -281,8 +288,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
281288 if target_iter. len ( ) == 1 {
282289 // If there are two targets (one conditional, one fallback), emit br instead of switch
283290 let ( test_value, target) = target_iter. next ( ) . unwrap ( ) ;
284- let lltrue = helper. llblock ( self , target) ;
285- let llfalse = helper. llblock ( self , targets. otherwise ( ) ) ;
291+ let lltrue = helper. llbb_with_cleanup ( self , target) ;
292+ let llfalse = helper. llbb_with_cleanup ( self , targets. otherwise ( ) ) ;
286293 if switch_ty == bx. tcx ( ) . types . bool {
287294 // Don't generate trivial icmps when switching on bool
288295 match test_value {
@@ -299,8 +306,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
299306 } else {
300307 bx. switch (
301308 discr. immediate ( ) ,
302- helper. llblock ( self , targets. otherwise ( ) ) ,
303- target_iter. map ( |( value, target) | ( value, helper. llblock ( self , target) ) ) ,
309+ helper. llbb_with_cleanup ( self , targets. otherwise ( ) ) ,
310+ target_iter. map ( |( value, target) | ( value, helper. llbb_with_cleanup ( self , target) ) ) ,
304311 ) ;
305312 }
306313 }
@@ -530,7 +537,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
530537 let cond = bx. expect ( cond, expected) ;
531538
532539 // Create the failure block and the conditional branch to it.
533- let lltarget = helper. llblock ( self , target) ;
540+ let lltarget = helper. llbb_with_cleanup ( self , target) ;
534541 let panic_block = bx. append_sibling_block ( "panic" ) ;
535542 if expected {
536543 bx. cond_br ( cond, lltarget, panic_block) ;
@@ -1459,20 +1466,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
14591466 // bar();
14601467 // }
14611468 Some ( & mir:: TerminatorKind :: Abort ) => {
1462- let cs_bb =
1469+ let cs_llbb =
14631470 Bx :: append_block ( self . cx , self . llfn , & format ! ( "cs_funclet{:?}" , bb) ) ;
1464- let cp_bb =
1471+ let cp_llbb =
14651472 Bx :: append_block ( self . cx , self . llfn , & format ! ( "cp_funclet{:?}" , bb) ) ;
1466- ret_llbb = cs_bb ;
1473+ ret_llbb = cs_llbb ;
14671474
1468- let mut cs_bx = Bx :: build ( self . cx , cs_bb ) ;
1469- let cs = cs_bx. catch_switch ( None , None , & [ cp_bb ] ) ;
1475+ let mut cs_bx = Bx :: build ( self . cx , cs_llbb ) ;
1476+ let cs = cs_bx. catch_switch ( None , None , & [ cp_llbb ] ) ;
14701477
14711478 // The "null" here is actually a RTTI type descriptor for the
14721479 // C++ personality function, but `catch (...)` has no type so
14731480 // it's null. The 64 here is actually a bitfield which
14741481 // represents that this is a catch-all block.
1475- let mut cp_bx = Bx :: build ( self . cx , cp_bb ) ;
1482+ let mut cp_bx = Bx :: build ( self . cx , cp_llbb ) ;
14761483 let null = cp_bx. const_null (
14771484 cp_bx. type_i8p_ext ( cp_bx. cx ( ) . data_layout ( ) . instruction_address_space ) ,
14781485 ) ;
@@ -1481,30 +1488,31 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
14811488 cp_bx. br ( llbb) ;
14821489 }
14831490 _ => {
1484- let cleanup_bb =
1491+ let cleanup_llbb =
14851492 Bx :: append_block ( self . cx , self . llfn , & format ! ( "funclet_{:?}" , bb) ) ;
1486- ret_llbb = cleanup_bb ;
1487- let mut cleanup_bx = Bx :: build ( self . cx , cleanup_bb ) ;
1493+ ret_llbb = cleanup_llbb ;
1494+ let mut cleanup_bx = Bx :: build ( self . cx , cleanup_llbb ) ;
14881495 funclet = cleanup_bx. cleanup_pad ( None , & [ ] ) ;
14891496 cleanup_bx. br ( llbb) ;
14901497 }
14911498 }
14921499 self . funclets [ bb] = Some ( funclet) ;
14931500 ret_llbb
14941501 } else {
1495- let bb = Bx :: append_block ( self . cx , self . llfn , "cleanup" ) ;
1496- let mut bx = Bx :: build ( self . cx , bb ) ;
1502+ let cleanup_llbb = Bx :: append_block ( self . cx , self . llfn , "cleanup" ) ;
1503+ let mut cleanup_bx = Bx :: build ( self . cx , cleanup_llbb ) ;
14971504
14981505 let llpersonality = self . cx . eh_personality ( ) ;
14991506 let llretty = self . landing_pad_type ( ) ;
1500- let lp = bx . cleanup_landing_pad ( llretty, llpersonality) ;
1507+ let lp = cleanup_bx . cleanup_landing_pad ( llretty, llpersonality) ;
15011508
1502- let slot = self . get_personality_slot ( & mut bx) ;
1503- slot. storage_live ( & mut bx) ;
1504- Pair ( bx. extract_value ( lp, 0 ) , bx. extract_value ( lp, 1 ) ) . store ( & mut bx, slot) ;
1509+ let slot = self . get_personality_slot ( & mut cleanup_bx) ;
1510+ slot. storage_live ( & mut cleanup_bx) ;
1511+ Pair ( cleanup_bx. extract_value ( lp, 0 ) , cleanup_bx. extract_value ( lp, 1 ) )
1512+ . store ( & mut cleanup_bx, slot) ;
15051513
1506- bx . br ( llbb) ;
1507- bx . llbb ( )
1514+ cleanup_bx . br ( llbb) ;
1515+ cleanup_llbb
15081516 }
15091517 }
15101518
0 commit comments