11use rustc:: mir:: visit:: { PlaceContext , Visitor } ;
22use rustc:: mir:: visit:: { MutatingUseContext , NonMutatingUseContext , NonUseContext } ;
33use rustc:: mir:: { self , Local , Location , Place , PlaceBase } ;
4+ use rustc:: ty:: { self , TyCtxt , ParamEnv } ;
45use rustc_data_structures:: bit_set:: BitSet ;
56use rustc_data_structures:: fx:: FxHashMap ;
67use rustc_data_structures:: indexed_vec:: { Idx , IndexVec } ;
8+ use rustc_target:: spec:: abi:: Abi ;
9+
710use smallvec:: SmallVec ;
11+ use syntax:: symbol:: sym;
812
913use super :: { BitDenotation , GenKillSet , BottomValue } ;
1014
@@ -74,16 +78,41 @@ pub struct ReachingDefinitions {
7478 at_location : FxHashMap < Location , SmallVec < [ DefIndex ; 4 ] > > ,
7579}
7680
77- fn is_call_with_side_effects ( terminator : & mir:: Terminator < ' tcx > ) -> bool {
78- if let mir:: TerminatorKind :: Call { .. } = terminator. kind {
79- true
80- } else {
81- false
81+ fn has_side_effects (
82+ tcx : TyCtxt < ' tcx > ,
83+ body : & mir:: Body < ' tcx > ,
84+ param_env : ParamEnv < ' tcx > ,
85+ terminator : & mir:: Terminator < ' tcx > ,
86+ ) -> bool {
87+ match & terminator. kind {
88+ mir:: TerminatorKind :: Call { .. } => true ,
89+
90+ // Types with special drop glue may mutate their environment.
91+ | mir:: TerminatorKind :: Drop { location : place, .. }
92+ | mir:: TerminatorKind :: DropAndReplace { location : place, .. }
93+ => place. ty ( body, tcx) . ty . needs_drop ( tcx, param_env) ,
94+
95+ | mir:: TerminatorKind :: Goto { .. }
96+ | mir:: TerminatorKind :: SwitchInt { .. }
97+ | mir:: TerminatorKind :: Resume
98+ | mir:: TerminatorKind :: Abort
99+ | mir:: TerminatorKind :: Return
100+ | mir:: TerminatorKind :: Unreachable
101+ | mir:: TerminatorKind :: Assert { .. }
102+ | mir:: TerminatorKind :: FalseEdges { .. }
103+ | mir:: TerminatorKind :: FalseUnwind { .. }
104+ => false ,
105+
106+ // FIXME: I don't know the semantics around these so assume that they may mutate their
107+ // environment.
108+ | mir:: TerminatorKind :: Yield { .. }
109+ | mir:: TerminatorKind :: GeneratorDrop
110+ => true ,
82111 }
83112}
84113
85114impl ReachingDefinitions {
86- pub fn new ( body : & mir:: Body < ' _ > ) -> Self {
115+ pub fn new < ' tcx > ( tcx : TyCtxt < ' tcx > , body : & mir:: Body < ' tcx > , param_env : ParamEnv < ' tcx > ) -> Self {
87116 let mut ret = ReachingDefinitions {
88117 all : IndexVec :: new ( ) ,
89118 for_local_direct : IndexVec :: from_elem ( Vec :: new ( ) , & body. local_decls ) ,
@@ -102,7 +131,7 @@ impl ReachingDefinitions {
102131 let blocks_with_side_effects = body
103132 . basic_blocks ( )
104133 . iter_enumerated ( )
105- . filter ( |( _, data) | is_call_with_side_effects ( data. terminator ( ) ) ) ;
134+ . filter ( |( _, data) | has_side_effects ( tcx , body , param_env , data. terminator ( ) ) ) ;
106135
107136 for ( block, data) in blocks_with_side_effects {
108137 let term_loc = Location { block, statement_index : data. statements . len ( ) } ;
0 commit comments