11//! Propagates constants for early reporting of statically known
22//! assertion failures
33
4+ use std:: borrow:: Cow ;
45use std:: cell:: Cell ;
56
67use rustc:: hir:: def:: DefKind ;
8+ use rustc:: hir:: def_id:: DefId ;
79use rustc:: mir:: {
810 AggregateKind , Constant , Location , Place , PlaceBase , Body , Operand , Rvalue ,
9- Local , NullOp , UnOp , StatementKind , Statement , LocalKind ,
11+ Local , NullOp , UnOp , StatementKind , Statement , LocalKind , Static ,
1012 TerminatorKind , Terminator , ClearCrossCrate , SourceInfo , BinOp ,
11- SourceScope , SourceScopeLocalData , LocalDecl ,
13+ SourceScope , SourceScopeLocalData , LocalDecl , BasicBlock ,
1214} ;
1315use rustc:: mir:: visit:: {
1416 Visitor , PlaceContext , MutatingUseContext , MutVisitor , NonMutatingUseContext ,
@@ -17,18 +19,19 @@ use rustc::mir::interpret::{Scalar, InterpResult, PanicInfo};
1719use rustc:: ty:: { self , Instance , ParamEnv , Ty , TyCtxt } ;
1820use syntax_pos:: { Span , DUMMY_SP } ;
1921use rustc:: ty:: subst:: InternalSubsts ;
22+ use rustc_data_structures:: fx:: FxHashMap ;
2023use rustc_data_structures:: indexed_vec:: IndexVec ;
2124use rustc:: ty:: layout:: {
2225 LayoutOf , TyLayout , LayoutError , HasTyCtxt , TargetDataLayout , HasDataLayout ,
2326} ;
2427
2528use crate :: interpret:: {
2629 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 ,
3133} ;
34+ use crate :: const_eval:: error_to_const_error;
3235use crate :: transform:: { MirPass , MirSource } ;
3336
3437pub struct ConstProp ;
@@ -111,11 +114,149 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
111114 }
112115}
113116
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+
114255type Const < ' tcx > = OpTy < ' tcx > ;
115256
116257/// Finds optimization opportunities on the MIR.
117258struct ConstPropagator < ' mir , ' tcx > {
118- ecx : InterpCx < ' mir , ' tcx , CompileTimeInterpreter < ' mir , ' tcx > > ,
259+ ecx : InterpCx < ' mir , ' tcx , ConstPropMachine > ,
119260 tcx : TyCtxt < ' tcx > ,
120261 source : MirSource < ' tcx > ,
121262 can_const_prop : IndexVec < Local , bool > ,
@@ -158,7 +299,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
158299 let def_id = source. def_id ( ) ;
159300 let param_env = tcx. param_env ( def_id) ;
160301 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 , ( ) ) ;
162303 let can_const_prop = CanConstProp :: check ( body) ;
163304
164305 ecx. push_stack_frame (
0 commit comments