1
1
//! Propagates constants for early reporting of statically known
2
2
//! assertion failures
3
3
4
+ use std:: borrow:: Cow ;
4
5
use std:: cell:: Cell ;
5
6
6
7
use rustc:: hir:: def:: DefKind ;
8
+ use rustc:: hir:: def_id:: DefId ;
7
9
use rustc:: mir:: {
8
10
AggregateKind , Constant , Location , Place , PlaceBase , Body , Operand , Rvalue ,
9
- Local , NullOp , UnOp , StatementKind , Statement , LocalKind ,
11
+ Local , NullOp , UnOp , StatementKind , Statement , LocalKind , Static ,
10
12
TerminatorKind , Terminator , ClearCrossCrate , SourceInfo , BinOp ,
11
- SourceScope , SourceScopeLocalData , LocalDecl ,
13
+ SourceScope , SourceScopeLocalData , LocalDecl , BasicBlock ,
12
14
} ;
13
15
use rustc:: mir:: visit:: {
14
16
Visitor , PlaceContext , MutatingUseContext , MutVisitor , NonMutatingUseContext ,
@@ -17,18 +19,19 @@ use rustc::mir::interpret::{Scalar, InterpResult, PanicInfo};
17
19
use rustc:: ty:: { self , Instance , ParamEnv , Ty , TyCtxt } ;
18
20
use syntax_pos:: { Span , DUMMY_SP } ;
19
21
use rustc:: ty:: subst:: InternalSubsts ;
22
+ use rustc_data_structures:: fx:: FxHashMap ;
20
23
use rustc_data_structures:: indexed_vec:: IndexVec ;
21
24
use rustc:: ty:: layout:: {
22
25
LayoutOf , TyLayout , LayoutError , HasTyCtxt , TargetDataLayout , HasDataLayout ,
23
26
} ;
24
27
25
28
use crate :: interpret:: {
26
29
self , InterpCx , ScalarMaybeUndef , Immediate , OpTy ,
27
- StackPopCleanup , LocalValue , LocalState ,
28
- } ;
29
- use crate :: const_eval:: {
30
- CompileTimeInterpreter , error_to_const_error, mk_eval_cx,
30
+ StackPopCleanup , LocalValue , LocalState , AllocId , Frame ,
31
+ Allocation , MemoryKind , ImmTy , Pointer , Memory , PlaceTy ,
32
+ Operand as InterpOperand ,
31
33
} ;
34
+ use crate :: const_eval:: error_to_const_error;
32
35
use crate :: transform:: { MirPass , MirSource } ;
33
36
34
37
pub struct ConstProp ;
@@ -111,11 +114,149 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
111
114
}
112
115
}
113
116
117
+ struct ConstPropMachine ;
118
+
119
+ impl < ' mir , ' tcx > interpret:: Machine < ' mir , ' tcx > for ConstPropMachine {
120
+ type MemoryKinds = !;
121
+ type PointerTag = ( ) ;
122
+ type ExtraFnVal = !;
123
+
124
+ type FrameExtra = ( ) ;
125
+ type MemoryExtra = ( ) ;
126
+ type AllocExtra = ( ) ;
127
+
128
+ type MemoryMap = FxHashMap < AllocId , ( MemoryKind < !> , Allocation ) > ;
129
+
130
+ const STATIC_KIND : Option < !> = None ;
131
+
132
+ const CHECK_ALIGN : bool = false ;
133
+
134
+ #[ inline( always) ]
135
+ fn enforce_validity ( _ecx : & InterpCx < ' mir , ' tcx , Self > ) -> bool {
136
+ false
137
+ }
138
+
139
+ fn find_fn (
140
+ _ecx : & mut InterpCx < ' mir , ' tcx , Self > ,
141
+ _instance : ty:: Instance < ' tcx > ,
142
+ _args : & [ OpTy < ' tcx > ] ,
143
+ _dest : Option < PlaceTy < ' tcx > > ,
144
+ _ret : Option < BasicBlock > ,
145
+ ) -> InterpResult < ' tcx , Option < & ' mir Body < ' tcx > > > {
146
+ Ok ( None )
147
+ }
148
+
149
+ fn call_extra_fn (
150
+ _ecx : & mut InterpCx < ' mir , ' tcx , Self > ,
151
+ fn_val : !,
152
+ _args : & [ OpTy < ' tcx > ] ,
153
+ _dest : Option < PlaceTy < ' tcx > > ,
154
+ _ret : Option < BasicBlock > ,
155
+ ) -> InterpResult < ' tcx > {
156
+ match fn_val { }
157
+ }
158
+
159
+ fn call_intrinsic (
160
+ _ecx : & mut InterpCx < ' mir , ' tcx , Self > ,
161
+ _instance : ty:: Instance < ' tcx > ,
162
+ _args : & [ OpTy < ' tcx > ] ,
163
+ _dest : PlaceTy < ' tcx > ,
164
+ ) -> InterpResult < ' tcx > {
165
+ throw_unsup_format ! ( "calling intrinsics isn't supported in ConstProp" ) ;
166
+ }
167
+
168
+ fn ptr_to_int (
169
+ _mem : & Memory < ' mir , ' tcx , Self > ,
170
+ _ptr : Pointer ,
171
+ ) -> InterpResult < ' tcx , u64 > {
172
+ throw_unsup_format ! ( "ptr-to-int casts aren't supported in ConstProp" ) ;
173
+ }
174
+
175
+ fn binary_ptr_op (
176
+ _ecx : & InterpCx < ' mir , ' tcx , Self > ,
177
+ _bin_op : BinOp ,
178
+ _left : ImmTy < ' tcx > ,
179
+ _right : ImmTy < ' tcx > ,
180
+ ) -> InterpResult < ' tcx , ( Scalar , bool , Ty < ' tcx > ) > {
181
+ // We can't do this because aliasing of memory can differ between const eval and llvm
182
+ throw_unsup_format ! ( "pointer arithmetic or comparisons aren't supported in ConstProp" ) ;
183
+ }
184
+
185
+ fn find_foreign_static (
186
+ _tcx : TyCtxt < ' tcx > ,
187
+ _def_id : DefId ,
188
+ ) -> InterpResult < ' tcx , Cow < ' tcx , Allocation < Self :: PointerTag > > > {
189
+ throw_unsup ! ( ReadForeignStatic )
190
+ }
191
+
192
+ #[ inline( always) ]
193
+ fn tag_allocation < ' b > (
194
+ _memory_extra : & ( ) ,
195
+ _id : AllocId ,
196
+ alloc : Cow < ' b , Allocation > ,
197
+ _kind : Option < MemoryKind < !> > ,
198
+ ) -> ( Cow < ' b , Allocation < Self :: PointerTag > > , Self :: PointerTag ) {
199
+ // We do not use a tag so we can just cheaply forward the allocation
200
+ ( alloc, ( ) )
201
+ }
202
+
203
+ #[ inline( always) ]
204
+ fn tag_static_base_pointer (
205
+ _memory_extra : & ( ) ,
206
+ _id : AllocId ,
207
+ ) -> Self :: PointerTag {
208
+ ( )
209
+ }
210
+
211
+ fn box_alloc (
212
+ _ecx : & mut InterpCx < ' mir , ' tcx , Self > ,
213
+ _dest : PlaceTy < ' tcx > ,
214
+ ) -> InterpResult < ' tcx > {
215
+ throw_unsup_format ! ( "can't const prop `box` keyword" ) ;
216
+ }
217
+
218
+ fn access_local (
219
+ _ecx : & InterpCx < ' mir , ' tcx , Self > ,
220
+ frame : & Frame < ' mir , ' tcx , Self :: PointerTag , Self :: FrameExtra > ,
221
+ local : Local ,
222
+ ) -> InterpResult < ' tcx , InterpOperand < Self :: PointerTag > > {
223
+ let l = & frame. locals [ local] ;
224
+
225
+ if l. value == LocalValue :: Uninitialized {
226
+ throw_unsup_format ! ( "tried to access an uninitialized local" ) ;
227
+ }
228
+
229
+ l. access ( )
230
+ }
231
+
232
+ fn before_eval_static (
233
+ _ecx : & InterpCx < ' mir , ' tcx , Self > ,
234
+ _place_static : & Static < ' tcx > ,
235
+ ) -> InterpResult < ' tcx > {
236
+ throw_unsup_format ! ( "can't eval statics in ConstProp" ) ;
237
+ }
238
+
239
+ fn before_terminator ( _ecx : & mut InterpCx < ' mir , ' tcx , Self > ) -> InterpResult < ' tcx > {
240
+ Ok ( ( ) )
241
+ }
242
+
243
+ #[ inline( always) ]
244
+ fn stack_push ( _ecx : & mut InterpCx < ' mir , ' tcx , Self > ) -> InterpResult < ' tcx > {
245
+ Ok ( ( ) )
246
+ }
247
+
248
+ /// Called immediately before a stack frame gets popped.
249
+ #[ inline( always) ]
250
+ fn stack_pop ( _ecx : & mut InterpCx < ' mir , ' tcx , Self > , _extra : ( ) ) -> InterpResult < ' tcx > {
251
+ Ok ( ( ) )
252
+ }
253
+ }
254
+
114
255
type Const < ' tcx > = OpTy < ' tcx > ;
115
256
116
257
/// Finds optimization opportunities on the MIR.
117
258
struct ConstPropagator < ' mir , ' tcx > {
118
- ecx : InterpCx < ' mir , ' tcx , CompileTimeInterpreter < ' mir , ' tcx > > ,
259
+ ecx : InterpCx < ' mir , ' tcx , ConstPropMachine > ,
119
260
tcx : TyCtxt < ' tcx > ,
120
261
source : MirSource < ' tcx > ,
121
262
can_const_prop : IndexVec < Local , bool > ,
@@ -158,7 +299,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
158
299
let def_id = source. def_id ( ) ;
159
300
let param_env = tcx. param_env ( def_id) ;
160
301
let span = tcx. def_span ( def_id) ;
161
- let mut ecx = mk_eval_cx ( tcx, span, param_env) ;
302
+ let mut ecx = InterpCx :: new ( tcx. at ( span) , param_env, ConstPropMachine , ( ) ) ;
162
303
let can_const_prop = CanConstProp :: check ( body) ;
163
304
164
305
ecx. push_stack_frame (
0 commit comments