@@ -63,7 +63,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
63
63
}
64
64
}
65
65
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 > > (
67
69
& self ,
68
70
fx : & mut FunctionCx < ' a , ' tcx , Bx > ,
69
71
target : mir:: BasicBlock ,
@@ -73,32 +75,36 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
73
75
let target_funclet = fx. cleanup_kinds [ target] . funclet_bb ( target) ;
74
76
match ( self . funclet_bb , target_funclet) {
75
77
( 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
- }
79
78
// jump *into* cleanup - need a landing pad if GNU, cleanup pad if MSVC
80
79
( None , Some ( _) ) => ( fx. landing_pad_for ( target) , false ) ,
81
80
( 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
+ }
83
88
}
84
89
}
85
90
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 > > (
88
94
& self ,
89
95
fx : & mut FunctionCx < ' a , ' tcx , Bx > ,
90
96
target : mir:: BasicBlock ,
91
97
) -> Bx :: BasicBlock {
92
- let ( lltarget, is_cleanupret) = self . lltarget ( fx, target) ;
98
+ let ( lltarget, is_cleanupret) = self . llbb_with_landing_pad ( fx, target) ;
93
99
if is_cleanupret {
94
100
// 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) ;
97
103
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 ) ;
100
106
trampoline_bx. cleanup_ret ( self . funclet ( fx) . unwrap ( ) , Some ( lltarget) ) ;
101
- trampoline
107
+ trampoline_llbb
102
108
} else {
103
109
lltarget
104
110
}
@@ -110,10 +116,11 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
110
116
bx : & mut Bx ,
111
117
target : mir:: BasicBlock ,
112
118
) {
113
- let ( lltarget, is_cleanupret) = self . lltarget ( fx, target) ;
119
+ let ( lltarget, is_cleanupret) = self . llbb_with_landing_pad ( fx, target) ;
114
120
if is_cleanupret {
115
- // micro-optimization: generate a `ret` rather than a jump
121
+ // MSVC micro-optimization: generate a `ret` rather than a jump
116
122
// to a trampoline.
123
+ debug_assert ! ( base:: wants_msvc_seh( fx. cx. tcx( ) . sess) ) ;
117
124
bx. cleanup_ret ( self . funclet ( fx) . unwrap ( ) , Some ( lltarget) ) ;
118
125
} else {
119
126
bx. br ( lltarget) ;
@@ -138,7 +145,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
138
145
let fn_ty = bx. fn_decl_backend_type ( & fn_abi) ;
139
146
140
147
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) )
142
149
} else if fx. mir [ self . bb ] . is_cleanup
143
150
&& fn_abi. can_unwind
144
151
&& !base:: wants_msvc_seh ( fx. cx . tcx ( ) . sess )
@@ -231,7 +238,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
231
238
options,
232
239
line_spans,
233
240
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) ) ) ,
235
242
) ;
236
243
} else {
237
244
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> {
281
288
if target_iter. len ( ) == 1 {
282
289
// If there are two targets (one conditional, one fallback), emit br instead of switch
283
290
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 ( ) ) ;
286
293
if switch_ty == bx. tcx ( ) . types . bool {
287
294
// Don't generate trivial icmps when switching on bool
288
295
match test_value {
@@ -299,8 +306,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
299
306
} else {
300
307
bx. switch (
301
308
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) ) ) ,
304
311
) ;
305
312
}
306
313
}
@@ -530,7 +537,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
530
537
let cond = bx. expect ( cond, expected) ;
531
538
532
539
// 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) ;
534
541
let panic_block = bx. append_sibling_block ( "panic" ) ;
535
542
if expected {
536
543
bx. cond_br ( cond, lltarget, panic_block) ;
@@ -1459,20 +1466,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1459
1466
// bar();
1460
1467
// }
1461
1468
Some ( & mir:: TerminatorKind :: Abort ) => {
1462
- let cs_bb =
1469
+ let cs_llbb =
1463
1470
Bx :: append_block ( self . cx , self . llfn , & format ! ( "cs_funclet{:?}" , bb) ) ;
1464
- let cp_bb =
1471
+ let cp_llbb =
1465
1472
Bx :: append_block ( self . cx , self . llfn , & format ! ( "cp_funclet{:?}" , bb) ) ;
1466
- ret_llbb = cs_bb ;
1473
+ ret_llbb = cs_llbb ;
1467
1474
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 ] ) ;
1470
1477
1471
1478
// The "null" here is actually a RTTI type descriptor for the
1472
1479
// C++ personality function, but `catch (...)` has no type so
1473
1480
// it's null. The 64 here is actually a bitfield which
1474
1481
// 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 ) ;
1476
1483
let null = cp_bx. const_null (
1477
1484
cp_bx. type_i8p_ext ( cp_bx. cx ( ) . data_layout ( ) . instruction_address_space ) ,
1478
1485
) ;
@@ -1481,30 +1488,31 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1481
1488
cp_bx. br ( llbb) ;
1482
1489
}
1483
1490
_ => {
1484
- let cleanup_bb =
1491
+ let cleanup_llbb =
1485
1492
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 ) ;
1488
1495
funclet = cleanup_bx. cleanup_pad ( None , & [ ] ) ;
1489
1496
cleanup_bx. br ( llbb) ;
1490
1497
}
1491
1498
}
1492
1499
self . funclets [ bb] = Some ( funclet) ;
1493
1500
ret_llbb
1494
1501
} 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 ) ;
1497
1504
1498
1505
let llpersonality = self . cx . eh_personality ( ) ;
1499
1506
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) ;
1501
1508
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) ;
1505
1513
1506
- bx . br ( llbb) ;
1507
- bx . llbb ( )
1514
+ cleanup_bx . br ( llbb) ;
1515
+ cleanup_llbb
1508
1516
}
1509
1517
}
1510
1518
0 commit comments