@@ -9,7 +9,7 @@ use rustc_hir::def::DefKind;
99use rustc_middle:: mir:: visit:: { MutVisitor , Visitor } ;
1010use rustc_middle:: mir:: * ;
1111use rustc_middle:: ty:: layout:: TyAndLayout ;
12- use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
12+ use rustc_middle:: ty:: { self , ScalarInt , Ty , TyCtxt } ;
1313use rustc_mir_dataflow:: value_analysis:: {
1414 Map , State , TrackElem , ValueAnalysis , ValueAnalysisWrapper , ValueOrPlace ,
1515} ;
@@ -58,9 +58,13 @@ impl<'tcx> MirPass<'tcx> for DataflowConstProp {
5858 . in_scope ( || analysis. wrap ( ) . into_engine ( tcx, body) . iterate_to_fixpoint ( ) ) ;
5959
6060 // Collect results and patch the body afterwards.
61- let mut visitor = CollectAndPatch :: new ( tcx) ;
61+ let mut visitor = CollectAndPatch :: new ( tcx, & body . local_decls ) ;
6262 debug_span ! ( "collect" ) . in_scope ( || results. visit_reachable_with ( body, & mut visitor) ) ;
63- debug_span ! ( "patch" ) . in_scope ( || visitor. visit_body ( body) ) ;
63+ debug_span ! ( "patch" ) . in_scope ( || {
64+ for ( block, bbdata) in body. basic_blocks . as_mut_preserves_cfg ( ) . iter_enumerated_mut ( ) {
65+ visitor. visit_basic_block_data ( block, bbdata) ;
66+ }
67+ } )
6468 }
6569}
6670
@@ -73,7 +77,7 @@ struct ConstAnalysis<'a, 'tcx> {
7377}
7478
7579impl < ' tcx > ValueAnalysis < ' tcx > for ConstAnalysis < ' _ , ' tcx > {
76- type Value = FlatSet < ScalarTy < ' tcx > > ;
80+ type Value = FlatSet < ScalarInt > ;
7781
7882 const NAME : & ' static str = "ConstAnalysis" ;
7983
@@ -172,9 +176,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
172176 if let Some ( overflow_target) = overflow_target {
173177 let overflow = match overflow {
174178 FlatSet :: Top => FlatSet :: Top ,
175- FlatSet :: Elem ( overflow) => {
176- self . wrap_scalar ( Scalar :: from_bool ( overflow) , self . tcx . types . bool )
177- }
179+ FlatSet :: Elem ( overflow) => FlatSet :: Elem ( overflow. into ( ) ) ,
178180 FlatSet :: Bottom => FlatSet :: Bottom ,
179181 } ;
180182 // We have flooded `target` earlier.
@@ -209,7 +211,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
209211 }
210212 _ => unreachable ! ( ) ,
211213 }
212- . map ( |result| ValueOrPlace :: Value ( self . wrap_immediate ( result, * ty ) ) )
214+ . map ( |result| ValueOrPlace :: Value ( self . wrap_immediate ( result) ) )
213215 . unwrap_or ( ValueOrPlace :: TOP ) ,
214216 _ => ValueOrPlace :: TOP ,
215217 } ,
@@ -242,9 +244,8 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
242244 constant
243245 . literal
244246 . eval ( self . tcx , self . param_env )
245- . try_to_scalar ( )
246- . map ( |value| FlatSet :: Elem ( ScalarTy ( value, constant. ty ( ) ) ) )
247- . unwrap_or ( FlatSet :: Top )
247+ . try_to_scalar_int ( )
248+ . map_or ( FlatSet :: Top , FlatSet :: Elem )
248249 }
249250
250251 fn handle_switch_int < ' mir > (
@@ -261,26 +262,15 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
261262 // We are branching on uninitialized data, this is UB, treat it as unreachable.
262263 // This allows the set of visited edges to grow monotonically with the lattice.
263264 FlatSet :: Bottom => TerminatorEdges :: None ,
264- FlatSet :: Elem ( ScalarTy ( scalar, _) ) => {
265- let int = scalar. assert_int ( ) ;
266- let choice = int. assert_bits ( int. size ( ) ) ;
265+ FlatSet :: Elem ( scalar) => {
266+ let choice = scalar. assert_bits ( scalar. size ( ) ) ;
267267 TerminatorEdges :: Single ( targets. target_for_value ( choice) )
268268 }
269269 FlatSet :: Top => TerminatorEdges :: SwitchInt { discr, targets } ,
270270 }
271271 }
272272}
273273
274- #[ derive( Clone , PartialEq , Eq ) ]
275- struct ScalarTy < ' tcx > ( Scalar , Ty < ' tcx > ) ;
276-
277- impl < ' tcx > std:: fmt:: Debug for ScalarTy < ' tcx > {
278- fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
279- // This is used for dataflow visualization, so we return something more concise.
280- std:: fmt:: Display :: fmt ( & ConstantKind :: Val ( ConstValue :: Scalar ( self . 0 ) , self . 1 ) , f)
281- }
282- }
283-
284274impl < ' a , ' tcx > ConstAnalysis < ' a , ' tcx > {
285275 pub fn new ( tcx : TyCtxt < ' tcx > , body : & ' a Body < ' tcx > , map : Map ) -> Self {
286276 let param_env = tcx. param_env_reveal_all_normalized ( body. source . def_id ( ) ) ;
@@ -295,17 +285,19 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
295285
296286 fn binary_op (
297287 & self ,
298- state : & mut State < FlatSet < ScalarTy < ' tcx > > > ,
288+ state : & mut State < FlatSet < ScalarInt > > ,
299289 op : BinOp ,
300290 left : & Operand < ' tcx > ,
301291 right : & Operand < ' tcx > ,
302- ) -> ( FlatSet < ScalarTy < ' tcx > > , FlatSet < bool > ) {
292+ ) -> ( FlatSet < ScalarInt > , FlatSet < bool > ) {
303293 let left = self . eval_operand ( left, state) ;
304294 let right = self . eval_operand ( right, state) ;
305295 match ( left, right) {
306296 ( FlatSet :: Elem ( left) , FlatSet :: Elem ( right) ) => {
307297 match self . ecx . overflowing_binary_op ( op, & left, & right) {
308- Ok ( ( val, overflow, ty) ) => ( self . wrap_scalar ( val, ty) , FlatSet :: Elem ( overflow) ) ,
298+ Ok ( ( Scalar :: Int ( val) , overflow, _) ) => {
299+ ( FlatSet :: Elem ( val) , FlatSet :: Elem ( overflow) )
300+ }
309301 _ => ( FlatSet :: Top , FlatSet :: Top ) ,
310302 }
311303 }
@@ -320,84 +312,84 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
320312 fn eval_operand (
321313 & self ,
322314 op : & Operand < ' tcx > ,
323- state : & mut State < FlatSet < ScalarTy < ' tcx > > > ,
315+ state : & mut State < FlatSet < ScalarInt > > ,
324316 ) -> FlatSet < ImmTy < ' tcx > > {
325317 let value = match self . handle_operand ( op, state) {
326318 ValueOrPlace :: Value ( value) => value,
327319 ValueOrPlace :: Place ( place) => state. get_idx ( place, & self . map ) ,
328320 } ;
329321 match value {
330322 FlatSet :: Top => FlatSet :: Top ,
331- FlatSet :: Elem ( ScalarTy ( scalar, ty) ) => self
332- . tcx
333- . layout_of ( self . param_env . and ( ty) )
334- . map ( |layout| FlatSet :: Elem ( ImmTy :: from_scalar ( scalar, layout) ) )
335- . unwrap_or ( FlatSet :: Top ) ,
323+ FlatSet :: Elem ( scalar) => {
324+ let ty = op. ty ( self . local_decls , self . tcx ) ;
325+ self . tcx
326+ . layout_of ( self . param_env . and ( ty) )
327+ . map ( |layout| FlatSet :: Elem ( ImmTy :: from_scalar ( scalar. into ( ) , layout) ) )
328+ . unwrap_or ( FlatSet :: Top )
329+ }
336330 FlatSet :: Bottom => FlatSet :: Bottom ,
337331 }
338332 }
339333
340- fn eval_discriminant (
341- & self ,
342- enum_ty : Ty < ' tcx > ,
343- variant_index : VariantIdx ,
344- ) -> Option < ScalarTy < ' tcx > > {
334+ fn eval_discriminant ( & self , enum_ty : Ty < ' tcx > , variant_index : VariantIdx ) -> Option < ScalarInt > {
345335 if !enum_ty. is_enum ( ) {
346336 return None ;
347337 }
348338 let discr = enum_ty. discriminant_for_variant ( self . tcx , variant_index) ?;
349339 let discr_layout = self . tcx . layout_of ( self . param_env . and ( discr. ty ) ) . ok ( ) ?;
350- let discr_value = Scalar :: try_from_uint ( discr. val , discr_layout. size ) ?;
351- Some ( ScalarTy ( discr_value, discr. ty ) )
352- }
353-
354- fn wrap_scalar ( & self , scalar : Scalar , ty : Ty < ' tcx > ) -> FlatSet < ScalarTy < ' tcx > > {
355- FlatSet :: Elem ( ScalarTy ( scalar, ty) )
340+ let discr_value = ScalarInt :: try_from_uint ( discr. val , discr_layout. size ) ?;
341+ Some ( discr_value)
356342 }
357343
358- fn wrap_immediate ( & self , imm : Immediate , ty : Ty < ' tcx > ) -> FlatSet < ScalarTy < ' tcx > > {
344+ fn wrap_immediate ( & self , imm : Immediate ) -> FlatSet < ScalarInt > {
359345 match imm {
360- Immediate :: Scalar ( scalar) => self . wrap_scalar ( scalar, ty ) ,
346+ Immediate :: Scalar ( Scalar :: Int ( scalar) ) => FlatSet :: Elem ( scalar) ,
361347 _ => FlatSet :: Top ,
362348 }
363349 }
364350
365- fn wrap_immty ( & self , val : ImmTy < ' tcx > ) -> FlatSet < ScalarTy < ' tcx > > {
366- self . wrap_immediate ( * val, val . layout . ty )
351+ fn wrap_immty ( & self , val : ImmTy < ' tcx > ) -> FlatSet < ScalarInt > {
352+ self . wrap_immediate ( * val)
367353 }
368354}
369355
370- struct CollectAndPatch < ' tcx > {
356+ struct CollectAndPatch < ' tcx , ' locals > {
371357 tcx : TyCtxt < ' tcx > ,
358+ local_decls : & ' locals LocalDecls < ' tcx > ,
372359
373360 /// For a given MIR location, this stores the values of the operands used by that location. In
374361 /// particular, this is before the effect, such that the operands of `_1 = _1 + _2` are
375362 /// properly captured. (This may become UB soon, but it is currently emitted even by safe code.)
376- before_effect : FxHashMap < ( Location , Place < ' tcx > ) , ScalarTy < ' tcx > > ,
363+ before_effect : FxHashMap < ( Location , Place < ' tcx > ) , ScalarInt > ,
377364
378365 /// Stores the assigned values for assignments where the Rvalue is constant.
379- assignments : FxHashMap < Location , ScalarTy < ' tcx > > ,
366+ assignments : FxHashMap < Location , ScalarInt > ,
380367}
381368
382- impl < ' tcx > CollectAndPatch < ' tcx > {
383- fn new ( tcx : TyCtxt < ' tcx > ) -> Self {
384- Self { tcx, before_effect : FxHashMap :: default ( ) , assignments : FxHashMap :: default ( ) }
369+ impl < ' tcx , ' locals > CollectAndPatch < ' tcx , ' locals > {
370+ fn new ( tcx : TyCtxt < ' tcx > , local_decls : & ' locals LocalDecls < ' tcx > ) -> Self {
371+ Self {
372+ tcx,
373+ local_decls,
374+ before_effect : FxHashMap :: default ( ) ,
375+ assignments : FxHashMap :: default ( ) ,
376+ }
385377 }
386378
387- fn make_operand ( & self , scalar : ScalarTy < ' tcx > ) -> Operand < ' tcx > {
379+ fn make_operand ( & self , scalar : ScalarInt , ty : Ty < ' tcx > ) -> Operand < ' tcx > {
388380 Operand :: Constant ( Box :: new ( Constant {
389381 span : DUMMY_SP ,
390382 user_ty : None ,
391- literal : ConstantKind :: Val ( ConstValue :: Scalar ( scalar. 0 ) , scalar . 1 ) ,
383+ literal : ConstantKind :: Val ( ConstValue :: Scalar ( scalar. into ( ) ) , ty ) ,
392384 } ) )
393385 }
394386}
395387
396388impl < ' mir , ' tcx >
397389 ResultsVisitor < ' mir , ' tcx , Results < ' tcx , ValueAnalysisWrapper < ConstAnalysis < ' _ , ' tcx > > > >
398- for CollectAndPatch < ' tcx >
390+ for CollectAndPatch < ' tcx , ' _ >
399391{
400- type FlowState = State < FlatSet < ScalarTy < ' tcx > > > ;
392+ type FlowState = State < FlatSet < ScalarInt > > ;
401393
402394 fn visit_statement_before_primary_effect (
403395 & mut self ,
@@ -453,16 +445,17 @@ impl<'mir, 'tcx>
453445 }
454446}
455447
456- impl < ' tcx > MutVisitor < ' tcx > for CollectAndPatch < ' tcx > {
457- fn tcx < ' a > ( & ' a self ) -> TyCtxt < ' tcx > {
448+ impl < ' tcx > MutVisitor < ' tcx > for CollectAndPatch < ' tcx , ' _ > {
449+ fn tcx ( & self ) -> TyCtxt < ' tcx > {
458450 self . tcx
459451 }
460452
461453 fn visit_statement ( & mut self , statement : & mut Statement < ' tcx > , location : Location ) {
462454 if let Some ( value) = self . assignments . get ( & location) {
463455 match & mut statement. kind {
464456 StatementKind :: Assign ( box ( _, rvalue) ) => {
465- * rvalue = Rvalue :: Use ( self . make_operand ( value. clone ( ) ) ) ;
457+ let ty = rvalue. ty ( self . local_decls , self . tcx ) ;
458+ * rvalue = Rvalue :: Use ( self . make_operand ( * value, ty) ) ;
466459 }
467460 _ => bug ! ( "found assignment info for non-assign statement" ) ,
468461 }
@@ -475,21 +468,22 @@ impl<'tcx> MutVisitor<'tcx> for CollectAndPatch<'tcx> {
475468 match operand {
476469 Operand :: Copy ( place) | Operand :: Move ( place) => {
477470 if let Some ( value) = self . before_effect . get ( & ( location, * place) ) {
478- * operand = self . make_operand ( value. clone ( ) ) ;
471+ let ty = place. ty ( self . local_decls , self . tcx ) . ty ;
472+ * operand = self . make_operand ( * value, ty) ;
479473 }
480474 }
481- _ => ( ) ,
475+ Operand :: Constant ( _ ) => { }
482476 }
483477 }
484478}
485479
486- struct OperandCollector < ' tcx , ' map , ' a > {
487- state : & ' a State < FlatSet < ScalarTy < ' tcx > > > ,
488- visitor : & ' a mut CollectAndPatch < ' tcx > ,
480+ struct OperandCollector < ' tcx , ' map , ' locals , ' a > {
481+ state : & ' a State < FlatSet < ScalarInt > > ,
482+ visitor : & ' a mut CollectAndPatch < ' tcx , ' locals > ,
489483 map : & ' map Map ,
490484}
491485
492- impl < ' tcx , ' map , ' a > Visitor < ' tcx > for OperandCollector < ' tcx , ' map , ' a > {
486+ impl < ' tcx > Visitor < ' tcx > for OperandCollector < ' tcx , ' _ , ' _ , ' _ > {
493487 fn visit_operand ( & mut self , operand : & Operand < ' tcx > , location : Location ) {
494488 match operand {
495489 Operand :: Copy ( place) | Operand :: Move ( place) => {
@@ -572,7 +566,7 @@ impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for Dumm
572566 _bin_op : BinOp ,
573567 _left : & rustc_const_eval:: interpret:: ImmTy < ' tcx , Self :: Provenance > ,
574568 _right : & rustc_const_eval:: interpret:: ImmTy < ' tcx , Self :: Provenance > ,
575- ) -> interpret:: InterpResult < ' tcx , ( interpret :: Scalar < Self :: Provenance > , bool , Ty < ' tcx > ) > {
569+ ) -> interpret:: InterpResult < ' tcx , ( Scalar < Self :: Provenance > , bool , Ty < ' tcx > ) > {
576570 throw_unsup ! ( Unsupported ( "" . into( ) ) )
577571 }
578572
0 commit comments