11//! Propagates constants for early reporting of statically known
22//! assertion failures
33
4+ use std:: cell:: Cell ;
5+
46use rustc:: hir:: def:: DefKind ;
57use rustc:: mir:: {
68 AggregateKind , Constant , Location , Place , PlaceBase , Body , Operand , Rvalue ,
@@ -21,7 +23,8 @@ use rustc::ty::layout::{
2123} ;
2224
2325use crate :: interpret:: {
24- self , InterpretCx , ScalarMaybeUndef , Immediate , OpTy , ImmTy , MemoryKind ,
26+ self , InterpretCx , ScalarMaybeUndef , Immediate , OpTy ,
27+ ImmTy , MemoryKind , StackPopCleanup , LocalValue , LocalState ,
2528} ;
2629use crate :: const_eval:: {
2730 CompileTimeInterpreter , error_to_const_error, eval_promoted, mk_eval_cx,
@@ -56,21 +59,54 @@ impl MirPass for ConstProp {
5659
5760 trace ! ( "ConstProp starting for {:?}" , source. def_id( ) ) ;
5861
62+ // steal some data we need from `body`
63+ let source_scope_local_data = std:: mem:: replace (
64+ & mut body. source_scope_local_data ,
65+ ClearCrossCrate :: Clear
66+ ) ;
67+ let promoted = std:: mem:: replace (
68+ & mut body. promoted ,
69+ IndexVec :: new ( )
70+ ) ;
71+
72+ let dummy_body =
73+ & Body :: new (
74+ body. basic_blocks ( ) . clone ( ) ,
75+ Default :: default ( ) ,
76+ ClearCrossCrate :: Clear ,
77+ Default :: default ( ) ,
78+ None ,
79+ body. local_decls . clone ( ) ,
80+ Default :: default ( ) ,
81+ body. arg_count ,
82+ Default :: default ( ) ,
83+ tcx. def_span ( source. def_id ( ) ) ,
84+ Default :: default ( ) ,
85+ ) ;
86+
5987 // FIXME(oli-obk, eddyb) Optimize locals (or even local paths) to hold
6088 // constants, instead of just checking for const-folding succeeding.
6189 // That would require an uniform one-def no-mutation analysis
6290 // and RPO (or recursing when needing the value of a local).
63- let mut optimization_finder = ConstPropagator :: new ( body, tcx, source) ;
91+ let mut optimization_finder = ConstPropagator :: new (
92+ body,
93+ dummy_body,
94+ source_scope_local_data,
95+ promoted,
96+ tcx,
97+ source
98+ ) ;
6499 optimization_finder. visit_body ( body) ;
65100
66101 // put back the data we stole from `mir`
102+ let ( source_scope_local_data, promoted) = optimization_finder. release_stolen_data ( ) ;
67103 std:: mem:: replace (
68104 & mut body. source_scope_local_data ,
69- optimization_finder . source_scope_local_data
105+ source_scope_local_data
70106 ) ;
71107 std:: mem:: replace (
72108 & mut body. promoted ,
73- optimization_finder . promoted
109+ promoted
74110 ) ;
75111
76112 trace ! ( "ConstProp done for {:?}" , source. def_id( ) ) ;
@@ -84,7 +120,6 @@ struct ConstPropagator<'mir, 'tcx> {
84120 ecx : InterpretCx < ' mir , ' tcx , CompileTimeInterpreter < ' mir , ' tcx > > ,
85121 tcx : TyCtxt < ' tcx > ,
86122 source : MirSource < ' tcx > ,
87- places : IndexVec < Local , Option < Const < ' tcx > > > ,
88123 can_const_prop : IndexVec < Local , bool > ,
89124 param_env : ParamEnv < ' tcx > ,
90125 source_scope_local_data : ClearCrossCrate < IndexVec < SourceScope , SourceScopeLocalData > > ,
@@ -117,42 +152,67 @@ impl<'mir, 'tcx> HasTyCtxt<'tcx> for ConstPropagator<'mir, 'tcx> {
117152
118153impl < ' mir , ' tcx > ConstPropagator < ' mir , ' tcx > {
119154 fn new (
120- body : & mut Body < ' tcx > ,
155+ body : & Body < ' tcx > ,
156+ dummy_body : & ' mir Body < ' tcx > ,
157+ source_scope_local_data : ClearCrossCrate < IndexVec < SourceScope , SourceScopeLocalData > > ,
158+ promoted : IndexVec < Promoted , Body < ' tcx > > ,
121159 tcx : TyCtxt < ' tcx > ,
122160 source : MirSource < ' tcx > ,
123161 ) -> ConstPropagator < ' mir , ' tcx > {
124- let param_env = tcx. param_env ( source. def_id ( ) ) ;
125- let ecx = mk_eval_cx ( tcx, tcx. def_span ( source. def_id ( ) ) , param_env) ;
162+ let def_id = source. def_id ( ) ;
163+ let param_env = tcx. param_env ( def_id) ;
164+ let span = tcx. def_span ( def_id) ;
165+ let mut ecx = mk_eval_cx ( tcx, span, param_env) ;
126166 let can_const_prop = CanConstProp :: check ( body) ;
127- let source_scope_local_data = std:: mem:: replace (
128- & mut body. source_scope_local_data ,
129- ClearCrossCrate :: Clear
130- ) ;
131- let promoted = std:: mem:: replace (
132- & mut body. promoted ,
133- IndexVec :: new ( )
134- ) ;
167+
168+ ecx. push_stack_frame (
169+ Instance :: new ( def_id, & InternalSubsts :: identity_for_item ( tcx, def_id) ) ,
170+ span,
171+ dummy_body,
172+ None ,
173+ StackPopCleanup :: None {
174+ cleanup : false ,
175+ } ,
176+ ) . expect ( "failed to push initial stack frame" ) ;
135177
136178 ConstPropagator {
137179 ecx,
138180 tcx,
139181 source,
140182 param_env,
141183 can_const_prop,
142- places : IndexVec :: from_elem ( None , & body. local_decls ) ,
143184 source_scope_local_data,
144185 //FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it
145186 local_decls : body. local_decls . clone ( ) ,
146187 promoted,
147188 }
148189 }
149190
191+ fn release_stolen_data ( self ) ->
192+ ( ClearCrossCrate < IndexVec < SourceScope , SourceScopeLocalData > > ,
193+ IndexVec < Promoted , Body < ' tcx > > )
194+ {
195+ ( self . source_scope_local_data , self . promoted )
196+ }
197+
150198 fn get_const ( & self , local : Local ) -> Option < Const < ' tcx > > {
151- self . places [ local]
199+ let l = & self . ecx . frame ( ) . locals [ local] ;
200+ if l. value == LocalValue :: Uninitialized || l. value == LocalValue :: Dead {
201+ return None ;
202+ }
203+
204+ self . ecx . access_local ( self . ecx . frame ( ) , local, None ) . ok ( )
152205 }
153206
154207 fn set_const ( & mut self , local : Local , c : Option < Const < ' tcx > > ) {
155- self . places [ local] = c;
208+ self . ecx . frame_mut ( ) . locals [ local] =
209+ match c {
210+ Some ( op_ty) => LocalState {
211+ value : LocalValue :: Live ( * op_ty) ,
212+ layout : Cell :: new ( Some ( op_ty. layout ) ) ,
213+ } ,
214+ None => LocalState { value : LocalValue :: Uninitialized , layout : Cell :: new ( None ) } ,
215+ } ;
156216 }
157217
158218 fn use_ecx < F , T > (
0 commit comments