33//! Currently, this pass only propagates scalar values.
44
55use std:: assert_matches:: assert_matches;
6+ use std:: cell:: RefCell ;
67use std:: fmt:: Formatter ;
78
89use rustc_abi:: { BackendRepr , FIRST_VARIANT , FieldIdx , Size , VariantIdx } ;
@@ -85,7 +86,7 @@ struct ConstAnalysis<'a, 'tcx> {
8586 map : Map < ' tcx > ,
8687 tcx : TyCtxt < ' tcx > ,
8788 local_decls : & ' a LocalDecls < ' tcx > ,
88- ecx : InterpCx < ' tcx , DummyMachine > ,
89+ ecx : RefCell < InterpCx < ' tcx , DummyMachine > > ,
8990 typing_env : ty:: TypingEnv < ' tcx > ,
9091}
9192
@@ -153,7 +154,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
153154 map,
154155 tcx,
155156 local_decls : & body. local_decls ,
156- ecx : InterpCx :: new ( tcx, DUMMY_SP , typing_env, DummyMachine ) ,
157+ ecx : RefCell :: new ( InterpCx :: new ( tcx, DUMMY_SP , typing_env, DummyMachine ) ) ,
157158 typing_env,
158159 }
159160 }
@@ -410,6 +411,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
410411 match self . eval_operand ( operand, state) {
411412 FlatSet :: Elem ( op) => self
412413 . ecx
414+ . borrow ( )
413415 . int_to_int_or_float ( & op, layout)
414416 . discard_err ( )
415417 . map_or ( FlatSet :: Top , |result| self . wrap_immediate ( * result) ) ,
@@ -424,6 +426,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
424426 match self . eval_operand ( operand, state) {
425427 FlatSet :: Elem ( op) => self
426428 . ecx
429+ . borrow ( )
427430 . float_to_float_or_int ( & op, layout)
428431 . discard_err ( )
429432 . map_or ( FlatSet :: Top , |result| self . wrap_immediate ( * result) ) ,
@@ -454,6 +457,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
454457 match self . eval_operand ( operand, state) {
455458 FlatSet :: Elem ( value) => self
456459 . ecx
460+ . borrow ( )
457461 . unary_op ( * op, & value)
458462 . discard_err ( )
459463 . map_or ( FlatSet :: Top , |val| self . wrap_immediate ( * val) ) ,
@@ -468,6 +472,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
468472 let val = match null_op {
469473 NullOp :: OffsetOf ( fields) => self
470474 . ecx
475+ . borrow ( )
471476 . tcx
472477 . offset_of_subfield ( self . typing_env , layout, fields. iter ( ) )
473478 . bytes ( ) ,
@@ -556,8 +561,11 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
556561 }
557562 }
558563 Operand :: Constant ( box constant) => {
559- if let Some ( constant) =
560- self . ecx . eval_mir_constant ( & constant. const_ , constant. span , None ) . discard_err ( )
564+ if let Some ( constant) = self
565+ . ecx
566+ . borrow ( )
567+ . eval_mir_constant ( & constant. const_ , constant. span , None )
568+ . discard_err ( )
561569 {
562570 self . assign_constant ( state, place, constant, & [ ] ) ;
563571 }
@@ -587,7 +595,9 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
587595 return ;
588596 }
589597 }
590- operand = if let Some ( operand) = self . ecx . project ( & operand, proj_elem) . discard_err ( ) {
598+ operand = if let Some ( operand) =
599+ self . ecx . borrow ( ) . project ( & operand, proj_elem) . discard_err ( )
600+ {
591601 operand
592602 } else {
593603 return ;
@@ -598,17 +608,22 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
598608 place,
599609 operand,
600610 & mut |elem, op| match elem {
601- TrackElem :: Field ( idx) => self . ecx . project_field ( op, idx) . discard_err ( ) ,
602- TrackElem :: Variant ( idx) => self . ecx . project_downcast ( op, idx) . discard_err ( ) ,
611+ TrackElem :: Field ( idx) => self . ecx . borrow ( ) . project_field ( op, idx) . discard_err ( ) ,
612+ TrackElem :: Variant ( idx) => {
613+ self . ecx . borrow ( ) . project_downcast ( op, idx) . discard_err ( )
614+ }
603615 TrackElem :: Discriminant => {
604- let variant = self . ecx . read_discriminant ( op) . discard_err ( ) ?;
605- let discr_value =
606- self . ecx . discriminant_for_variant ( op. layout . ty , variant) . discard_err ( ) ?;
616+ let variant = self . ecx . borrow ( ) . read_discriminant ( op) . discard_err ( ) ?;
617+ let discr_value = self
618+ . ecx
619+ . borrow ( )
620+ . discriminant_for_variant ( op. layout . ty , variant)
621+ . discard_err ( ) ?;
607622 Some ( discr_value. into ( ) )
608623 }
609624 TrackElem :: DerefLen => {
610- let op: OpTy < ' _ > = self . ecx . deref_pointer ( op) . discard_err ( ) ?. into ( ) ;
611- let len_usize = op. len ( & self . ecx ) . discard_err ( ) ?;
625+ let op: OpTy < ' _ > = self . ecx . borrow ( ) . deref_pointer ( op) . discard_err ( ) ?. into ( ) ;
626+ let len_usize = op. len ( & self . ecx . borrow ( ) ) . discard_err ( ) ?;
612627 let layout = self
613628 . tcx
614629 . layout_of ( self . typing_env . as_query_input ( self . tcx . types . usize ) )
@@ -617,7 +632,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
617632 }
618633 } ,
619634 & mut |place, op| {
620- if let Some ( imm) = self . ecx . read_immediate_raw ( op) . discard_err ( )
635+ if let Some ( imm) = self . ecx . borrow ( ) . read_immediate_raw ( op) . discard_err ( )
621636 && let Some ( imm) = imm. right ( )
622637 {
623638 let elem = self . wrap_immediate ( * imm) ;
@@ -641,7 +656,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
641656 ( FlatSet :: Bottom , _) | ( _, FlatSet :: Bottom ) => ( FlatSet :: Bottom , FlatSet :: Bottom ) ,
642657 // Both sides are known, do the actual computation.
643658 ( FlatSet :: Elem ( left) , FlatSet :: Elem ( right) ) => {
644- match self . ecx . binary_op ( op, & left, & right) . discard_err ( ) {
659+ match self . ecx . borrow ( ) . binary_op ( op, & left, & right) . discard_err ( ) {
645660 // Ideally this would return an Immediate, since it's sometimes
646661 // a pair and sometimes not. But as a hack we always return a pair
647662 // and just make the 2nd component `Bottom` when it does not exist.
@@ -714,8 +729,11 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
714729 return None ;
715730 }
716731 let enum_ty_layout = self . tcx . layout_of ( self . typing_env . as_query_input ( enum_ty) ) . ok ( ) ?;
717- let discr_value =
718- self . ecx . discriminant_for_variant ( enum_ty_layout. ty , variant_index) . discard_err ( ) ?;
732+ let discr_value = self
733+ . ecx
734+ . borrow ( )
735+ . discriminant_for_variant ( enum_ty_layout. ty , variant_index)
736+ . discard_err ( ) ?;
719737 Some ( discr_value. to_scalar ( ) )
720738 }
721739
@@ -956,7 +974,7 @@ impl<'tcx> ResultsVisitor<'tcx, ConstAnalysis<'_, 'tcx>> for Collector<'_, 'tcx>
956974 OperandCollector {
957975 state,
958976 visitor : self ,
959- ecx : & mut analysis. ecx ,
977+ ecx : & mut analysis. ecx . borrow_mut ( ) ,
960978 map : & analysis. map ,
961979 }
962980 . visit_rvalue ( rvalue, location) ;
@@ -978,9 +996,12 @@ impl<'tcx> ResultsVisitor<'tcx, ConstAnalysis<'_, 'tcx>> for Collector<'_, 'tcx>
978996 // Don't overwrite the assignment if it already uses a constant (to keep the span).
979997 }
980998 StatementKind :: Assign ( box ( place, _) ) => {
981- if let Some ( value) =
982- self . try_make_constant ( & mut analysis. ecx , place, state, & analysis. map )
983- {
999+ if let Some ( value) = self . try_make_constant (
1000+ & mut analysis. ecx . borrow_mut ( ) ,
1001+ place,
1002+ state,
1003+ & analysis. map ,
1004+ ) {
9841005 self . patch . assignments . insert ( location, value) ;
9851006 }
9861007 }
@@ -995,8 +1016,13 @@ impl<'tcx> ResultsVisitor<'tcx, ConstAnalysis<'_, 'tcx>> for Collector<'_, 'tcx>
9951016 terminator : & Terminator < ' tcx > ,
9961017 location : Location ,
9971018 ) {
998- OperandCollector { state, visitor : self , ecx : & mut analysis. ecx , map : & analysis. map }
999- . visit_terminator ( terminator, location) ;
1019+ OperandCollector {
1020+ state,
1021+ visitor : self ,
1022+ ecx : & mut analysis. ecx . borrow_mut ( ) ,
1023+ map : & analysis. map ,
1024+ }
1025+ . visit_terminator ( terminator, location) ;
10001026 }
10011027}
10021028
0 commit comments