1
1
use rustc:: mir:: visit:: { PlaceContext , Visitor } ;
2
2
use rustc:: mir:: visit:: { MutatingUseContext , NonMutatingUseContext , NonUseContext } ;
3
3
use rustc:: mir:: { self , Local , Location , Place , PlaceBase } ;
4
+ use rustc:: ty:: { self , TyCtxt , ParamEnv } ;
4
5
use rustc_data_structures:: bit_set:: BitSet ;
5
6
use rustc_data_structures:: fx:: FxHashMap ;
6
7
use rustc_data_structures:: indexed_vec:: { Idx , IndexVec } ;
8
+ use rustc_target:: spec:: abi:: Abi ;
9
+
7
10
use smallvec:: SmallVec ;
11
+ use syntax:: symbol:: sym;
8
12
9
13
use super :: { BitDenotation , GenKillSet , BottomValue } ;
10
14
@@ -74,16 +78,41 @@ pub struct ReachingDefinitions {
74
78
at_location : FxHashMap < Location , SmallVec < [ DefIndex ; 4 ] > > ,
75
79
}
76
80
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 ,
82
111
}
83
112
}
84
113
85
114
impl 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 {
87
116
let mut ret = ReachingDefinitions {
88
117
all : IndexVec :: new ( ) ,
89
118
for_local_direct : IndexVec :: from_elem ( Vec :: new ( ) , & body. local_decls ) ,
@@ -102,7 +131,7 @@ impl ReachingDefinitions {
102
131
let blocks_with_side_effects = body
103
132
. basic_blocks ( )
104
133
. iter_enumerated ( )
105
- . filter ( |( _, data) | is_call_with_side_effects ( data. terminator ( ) ) ) ;
134
+ . filter ( |( _, data) | has_side_effects ( tcx , body , param_env , data. terminator ( ) ) ) ;
106
135
107
136
for ( block, data) in blocks_with_side_effects {
108
137
let term_loc = Location { block, statement_index : data. statements . len ( ) } ;
0 commit comments