@@ -33,8 +33,8 @@ use crate::mir::interpret::{AllocRange, Scalar};
3333use crate :: ty:: codec:: { TyDecoder , TyEncoder } ;
3434use crate :: ty:: print:: { FmtPrinter , Printer , pretty_print_const, with_no_trimmed_paths} ;
3535use crate :: ty:: {
36- self , GenericArg , GenericArgsRef , Instance , InstanceKind , List , Ty , TyCtxt , TypeVisitableExt ,
37- TypingEnv , UserTypeAnnotationIndex ,
36+ self , GenericArg , GenericArgsRef , InstanceKind , List , Ty , TyCtxt , TypeVisitableExt , TypingEnv ,
37+ UserTypeAnnotationIndex ,
3838} ;
3939
4040mod basic_blocks;
@@ -375,6 +375,8 @@ pub struct Body<'tcx> {
375375 #[ type_foldable( identity) ]
376376 #[ type_visitable( ignore) ]
377377 pub function_coverage_info : Option < Box < coverage:: FunctionCoverageInfo > > ,
378+
379+ pub is_codegen_mir : bool ,
378380}
379381
380382impl < ' tcx > Body < ' tcx > {
@@ -418,6 +420,7 @@ impl<'tcx> Body<'tcx> {
418420 tainted_by_errors,
419421 coverage_info_hi : None ,
420422 function_coverage_info : None ,
423+ is_codegen_mir : false ,
421424 } ;
422425 body. is_polymorphic = body. has_non_region_param ( ) ;
423426 body
@@ -449,6 +452,7 @@ impl<'tcx> Body<'tcx> {
449452 tainted_by_errors : None ,
450453 coverage_info_hi : None ,
451454 function_coverage_info : None ,
455+ is_codegen_mir : false ,
452456 } ;
453457 body. is_polymorphic = body. has_non_region_param ( ) ;
454458 body
@@ -633,74 +637,6 @@ impl<'tcx> Body<'tcx> {
633637 self . injection_phase . is_some ( )
634638 }
635639
636- /// If this basic block ends with a [`TerminatorKind::SwitchInt`] for which we can evaluate the
637- /// discriminant in monomorphization, we return the discriminant bits and the
638- /// [`SwitchTargets`], just so the caller doesn't also have to match on the terminator.
639- fn try_const_mono_switchint < ' a > (
640- tcx : TyCtxt < ' tcx > ,
641- instance : Instance < ' tcx > ,
642- block : & ' a BasicBlockData < ' tcx > ,
643- ) -> Option < ( u128 , & ' a SwitchTargets ) > {
644- // There are two places here we need to evaluate a constant.
645- let eval_mono_const = |constant : & ConstOperand < ' tcx > | {
646- // FIXME(#132279): what is this, why are we using an empty environment here.
647- let typing_env = ty:: TypingEnv :: fully_monomorphized ( ) ;
648- let mono_literal = instance. instantiate_mir_and_normalize_erasing_regions (
649- tcx,
650- typing_env,
651- crate :: ty:: EarlyBinder :: bind ( constant. const_ ) ,
652- ) ;
653- mono_literal. try_eval_bits ( tcx, typing_env)
654- } ;
655-
656- let TerminatorKind :: SwitchInt { discr, targets } = & block. terminator ( ) . kind else {
657- return None ;
658- } ;
659-
660- // If this is a SwitchInt(const _), then we can just evaluate the constant and return.
661- let discr = match discr {
662- Operand :: Constant ( constant) => {
663- let bits = eval_mono_const ( constant) ?;
664- return Some ( ( bits, targets) ) ;
665- }
666- Operand :: Move ( place) | Operand :: Copy ( place) => place,
667- } ;
668-
669- // MIR for `if false` actually looks like this:
670- // _1 = const _
671- // SwitchInt(_1)
672- //
673- // And MIR for if intrinsics::ub_checks() looks like this:
674- // _1 = UbChecks()
675- // SwitchInt(_1)
676- //
677- // So we're going to try to recognize this pattern.
678- //
679- // If we have a SwitchInt on a non-const place, we find the most recent statement that
680- // isn't a storage marker. If that statement is an assignment of a const to our
681- // discriminant place, we evaluate and return the const, as if we've const-propagated it
682- // into the SwitchInt.
683-
684- let last_stmt = block. statements . iter ( ) . rev ( ) . find ( |stmt| {
685- !matches ! ( stmt. kind, StatementKind :: StorageDead ( _) | StatementKind :: StorageLive ( _) )
686- } ) ?;
687-
688- let ( place, rvalue) = last_stmt. kind . as_assign ( ) ?;
689-
690- if discr != place {
691- return None ;
692- }
693-
694- match rvalue {
695- Rvalue :: NullaryOp ( NullOp :: UbChecks , _) => Some ( ( tcx. sess . ub_checks ( ) as u128 , targets) ) ,
696- Rvalue :: Use ( Operand :: Constant ( constant) ) => {
697- let bits = eval_mono_const ( constant) ?;
698- Some ( ( bits, targets) )
699- }
700- _ => None ,
701- }
702- }
703-
704640 /// For a `Location` in this scope, determine what the "caller location" at that point is. This
705641 /// is interesting because of inlining: the `#[track_caller]` attribute of inlined functions
706642 /// must be honored. Falls back to the `tracked_caller` value for `#[track_caller]` functions,
@@ -1391,19 +1327,6 @@ impl<'tcx> BasicBlockData<'tcx> {
13911327 pub fn is_empty_unreachable ( & self ) -> bool {
13921328 self . statements . is_empty ( ) && matches ! ( self . terminator( ) . kind, TerminatorKind :: Unreachable )
13931329 }
1394-
1395- /// Like [`Terminator::successors`] but tries to use information available from the [`Instance`]
1396- /// to skip successors like the `false` side of an `if const {`.
1397- ///
1398- /// This is used to implement [`traversal::mono_reachable`] and
1399- /// [`traversal::mono_reachable_reverse_postorder`].
1400- pub fn mono_successors ( & self , tcx : TyCtxt < ' tcx > , instance : Instance < ' tcx > ) -> Successors < ' _ > {
1401- if let Some ( ( bits, targets) ) = Body :: try_const_mono_switchint ( tcx, instance, self ) {
1402- targets. successors_for_value ( bits)
1403- } else {
1404- self . terminator ( ) . successors ( )
1405- }
1406- }
14071330}
14081331
14091332///////////////////////////////////////////////////////////////////////////
0 commit comments