@@ -5,7 +5,8 @@ use rustc_ast as ast;
5
5
use rustc_ast:: { InlineAsmOptions , InlineAsmTemplatePiece } ;
6
6
use rustc_hir:: lang_items:: LangItem ;
7
7
use rustc_middle:: mir:: {
8
- self , AssertKind , BasicBlock , InlineAsmMacro , SwitchTargets , UnwindTerminateReason ,
8
+ self , AssertKind , BasicBlock , InlineAsmMacro , SwitchAction , SwitchTargets ,
9
+ UnwindTerminateReason ,
9
10
} ;
10
11
use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf , ValidityRequirement } ;
11
12
use rustc_middle:: ty:: print:: { with_no_trimmed_paths, with_no_visible_paths} ;
@@ -96,6 +97,17 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
96
97
}
97
98
}
98
99
100
+ fn llbb_with_cleanup_from_switch_action < Bx : BuilderMethods < ' a , ' tcx > > (
101
+ & self ,
102
+ fx : & mut FunctionCx < ' a , ' tcx , Bx > ,
103
+ target : mir:: SwitchAction ,
104
+ ) -> Bx :: BasicBlock {
105
+ match target {
106
+ mir:: SwitchAction :: Unreachable => fx. unreachable_block ( ) ,
107
+ mir:: SwitchAction :: Goto ( bb) => self . llbb_with_cleanup ( fx, bb) ,
108
+ }
109
+ }
110
+
99
111
fn llbb_characteristics < Bx : BuilderMethods < ' a , ' tcx > > (
100
112
& self ,
101
113
fx : & mut FunctionCx < ' a , ' tcx , Bx > ,
@@ -368,7 +380,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
368
380
// If our discriminant is a constant we can branch directly
369
381
if let Some ( const_discr) = bx. const_to_opt_u128 ( discr_value, false ) {
370
382
let target = targets. target_for_value ( const_discr) ;
371
- bx. br ( helper. llbb_with_cleanup ( self , target) ) ;
383
+ bx. br ( helper. llbb_with_cleanup_from_switch_action ( self , target) ) ;
372
384
return ;
373
385
} ;
374
386
@@ -379,9 +391,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
379
391
let ( test_value, target) = target_iter. next ( ) . unwrap ( ) ;
380
392
let otherwise = targets. otherwise ( ) ;
381
393
let lltarget = helper. llbb_with_cleanup ( self , target) ;
382
- let llotherwise = helper. llbb_with_cleanup ( self , otherwise) ;
394
+ let llotherwise = helper. llbb_with_cleanup_from_switch_action ( self , otherwise) ;
383
395
let target_cold = self . cold_blocks [ target] ;
384
- let otherwise_cold = self . cold_blocks [ otherwise] ;
396
+ let otherwise_cold = match otherwise {
397
+ SwitchAction :: Goto ( otherwise) => self . cold_blocks [ otherwise] ,
398
+ SwitchAction :: Unreachable => true ,
399
+ } ;
385
400
// If `target_cold == otherwise_cold`, the branches have the same weight
386
401
// so there is no expectation. If they differ, the `target` branch is expected
387
402
// when the `otherwise` branch is cold.
@@ -406,7 +421,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
406
421
}
407
422
} else if self . cx . sess ( ) . opts . optimize == OptLevel :: No
408
423
&& target_iter. len ( ) == 2
409
- && self . mir [ targets. otherwise ( ) ] . is_empty_unreachable ( )
424
+ && self . mir . basic_blocks . is_empty_unreachable ( targets. otherwise ( ) )
410
425
{
411
426
// In unoptimized builds, if there are two normal targets and the `otherwise` target is
412
427
// an unreachable BB, emit `br` instead of `switch`. This leaves behind the unreachable
@@ -431,7 +446,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
431
446
} else {
432
447
bx. switch (
433
448
discr_value,
434
- helper. llbb_with_cleanup ( self , targets. otherwise ( ) ) ,
449
+ helper. llbb_with_cleanup_from_switch_action ( self , targets. otherwise ( ) ) ,
435
450
target_iter. map ( |( value, target) | ( value, helper. llbb_with_cleanup ( self , target) ) ) ,
436
451
) ;
437
452
}
@@ -1648,11 +1663,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1648
1663
}
1649
1664
1650
1665
fn unreachable_block ( & mut self ) -> Bx :: BasicBlock {
1651
- self . unreachable_block . unwrap_or_else ( || {
1666
+ * self . unreachable_block . get_or_insert_with ( || {
1652
1667
let llbb = Bx :: append_block ( self . cx , self . llfn , "unreachable" ) ;
1653
1668
let mut bx = Bx :: build ( self . cx , llbb) ;
1654
1669
bx. unreachable ( ) ;
1655
- self . unreachable_block = Some ( llbb) ;
1656
1670
llbb
1657
1671
} )
1658
1672
}
0 commit comments