11//! Propagates constants for early reporting of statically known
22//! assertion failures
33
4- use std:: cell:: Cell ;
5-
6- use rustc_ast:: Mutability ;
7- use rustc_data_structures:: fx:: FxHashSet ;
4+ use crate :: const_prop:: ConstPropMachine ;
5+ use crate :: const_prop:: ConstPropMode ;
6+ use crate :: MirLint ;
7+ use rustc_const_eval:: const_eval:: ConstEvalErr ;
8+ use rustc_const_eval:: interpret:: {
9+ self , InterpCx , InterpResult , LocalState , LocalValue , MemoryKind , OpTy , Scalar ,
10+ ScalarMaybeUninit , StackPopCleanup ,
11+ } ;
812use rustc_hir:: def:: DefKind ;
913use rustc_hir:: HirId ;
1014use rustc_index:: bit_set:: BitSet ;
1115use rustc_index:: vec:: IndexVec ;
1216use rustc_middle:: mir:: visit:: { MutatingUseContext , NonMutatingUseContext , PlaceContext , Visitor } ;
1317use rustc_middle:: mir:: {
14- AssertKind , BasicBlock , BinOp , Body , Constant , ConstantKind , Local , LocalDecl , LocalKind ,
15- Location , Operand , Place , Rvalue , SourceInfo , SourceScope , SourceScopeData , Statement ,
16- StatementKind , Terminator , TerminatorKind , UnOp , RETURN_PLACE ,
18+ AssertKind , BinOp , Body , Constant , ConstantKind , Local , LocalDecl , LocalKind , Location ,
19+ Operand , Place , Rvalue , SourceInfo , SourceScope , SourceScopeData , Statement , StatementKind ,
20+ Terminator , TerminatorKind , UnOp , RETURN_PLACE ,
1721} ;
1822use rustc_middle:: ty:: layout:: { LayoutError , LayoutOf , LayoutOfHelpers , TyAndLayout } ;
1923use rustc_middle:: ty:: subst:: { InternalSubsts , Subst } ;
@@ -22,42 +26,15 @@ use rustc_middle::ty::{
2226 TypeVisitable ,
2327} ;
2428use rustc_session:: lint;
25- use rustc_span:: { def_id :: DefId , Span } ;
29+ use rustc_span:: Span ;
2630use rustc_target:: abi:: { HasDataLayout , Size , TargetDataLayout } ;
27- use rustc_target:: spec:: abi:: Abi as CallAbi ;
2831use rustc_trait_selection:: traits;
29-
30- use crate :: MirLint ;
31- use rustc_const_eval:: const_eval:: ConstEvalErr ;
32- use rustc_const_eval:: interpret:: {
33- self , compile_time_machine, AllocId , ConstAllocation , Frame , ImmTy , InterpCx , InterpResult ,
34- LocalState , LocalValue , MemoryKind , OpTy , PlaceTy , Pointer , Scalar , ScalarMaybeUninit ,
35- StackPopCleanup , StackPopUnwind ,
36- } ;
32+ use std:: cell:: Cell ;
3733
3834/// The maximum number of bytes that we'll allocate space for a local or the return value.
3935/// Needed for #66397, because otherwise we eval into large places and that can cause OOM or just
4036/// Severely regress performance.
4137const MAX_ALLOC_LIMIT : u64 = 1024 ;
42-
43- /// Macro for machine-specific `InterpError` without allocation.
44- /// (These will never be shown to the user, but they help diagnose ICEs.)
45- macro_rules! throw_machine_stop_str {
46- ( $( $tt: tt) * ) => { {
47- // We make a new local type for it. The type itself does not carry any information,
48- // but its vtable (for the `MachineStopType` trait) does.
49- struct Zst ;
50- // Printing this type shows the desired string.
51- impl std:: fmt:: Display for Zst {
52- fn fmt( & self , f: & mut std:: fmt:: Formatter <' _>) -> std:: fmt:: Result {
53- write!( f, $( $tt) * )
54- }
55- }
56- impl rustc_middle:: mir:: interpret:: MachineStopType for Zst { }
57- throw_machine_stop!( Zst )
58- } } ;
59- }
60-
6138pub struct ConstProp ;
6239
6340impl < ' tcx > MirLint < ' tcx > for ConstProp {
@@ -151,172 +128,6 @@ impl<'tcx> MirLint<'tcx> for ConstProp {
151128 }
152129}
153130
154- struct ConstPropMachine < ' mir , ' tcx > {
155- /// The virtual call stack.
156- stack : Vec < Frame < ' mir , ' tcx > > ,
157- /// `OnlyInsideOwnBlock` locals that were written in the current block get erased at the end.
158- written_only_inside_own_block_locals : FxHashSet < Local > ,
159- /// Locals that need to be cleared after every block terminates.
160- only_propagate_inside_block_locals : BitSet < Local > ,
161- can_const_prop : IndexVec < Local , ConstPropMode > ,
162- }
163-
164- impl ConstPropMachine < ' _ , ' _ > {
165- fn new (
166- only_propagate_inside_block_locals : BitSet < Local > ,
167- can_const_prop : IndexVec < Local , ConstPropMode > ,
168- ) -> Self {
169- Self {
170- stack : Vec :: new ( ) ,
171- written_only_inside_own_block_locals : Default :: default ( ) ,
172- only_propagate_inside_block_locals,
173- can_const_prop,
174- }
175- }
176- }
177-
178- impl < ' mir , ' tcx > interpret:: Machine < ' mir , ' tcx > for ConstPropMachine < ' mir , ' tcx > {
179- compile_time_machine ! ( <' mir, ' tcx>) ;
180- const PANIC_ON_ALLOC_FAIL : bool = true ; // all allocations are small (see `MAX_ALLOC_LIMIT`)
181-
182- type MemoryKind = !;
183-
184- fn load_mir (
185- _ecx : & InterpCx < ' mir , ' tcx , Self > ,
186- _instance : ty:: InstanceDef < ' tcx > ,
187- ) -> InterpResult < ' tcx , & ' tcx Body < ' tcx > > {
188- throw_machine_stop_str ! ( "calling functions isn't supported in ConstProp" )
189- }
190-
191- fn find_mir_or_eval_fn (
192- _ecx : & mut InterpCx < ' mir , ' tcx , Self > ,
193- _instance : ty:: Instance < ' tcx > ,
194- _abi : CallAbi ,
195- _args : & [ OpTy < ' tcx > ] ,
196- _destination : & PlaceTy < ' tcx > ,
197- _target : Option < BasicBlock > ,
198- _unwind : StackPopUnwind ,
199- ) -> InterpResult < ' tcx , Option < ( & ' mir Body < ' tcx > , ty:: Instance < ' tcx > ) > > {
200- Ok ( None )
201- }
202-
203- fn call_intrinsic (
204- _ecx : & mut InterpCx < ' mir , ' tcx , Self > ,
205- _instance : ty:: Instance < ' tcx > ,
206- _args : & [ OpTy < ' tcx > ] ,
207- _destination : & PlaceTy < ' tcx > ,
208- _target : Option < BasicBlock > ,
209- _unwind : StackPopUnwind ,
210- ) -> InterpResult < ' tcx > {
211- throw_machine_stop_str ! ( "calling intrinsics isn't supported in ConstProp" )
212- }
213-
214- fn assert_panic (
215- _ecx : & mut InterpCx < ' mir , ' tcx , Self > ,
216- _msg : & rustc_middle:: mir:: AssertMessage < ' tcx > ,
217- _unwind : Option < rustc_middle:: mir:: BasicBlock > ,
218- ) -> InterpResult < ' tcx > {
219- bug ! ( "panics terminators are not evaluated in ConstProp" )
220- }
221-
222- fn binary_ptr_op (
223- _ecx : & InterpCx < ' mir , ' tcx , Self > ,
224- _bin_op : BinOp ,
225- _left : & ImmTy < ' tcx > ,
226- _right : & ImmTy < ' tcx > ,
227- ) -> InterpResult < ' tcx , ( Scalar , bool , Ty < ' tcx > ) > {
228- // We can't do this because aliasing of memory can differ between const eval and llvm
229- throw_machine_stop_str ! ( "pointer arithmetic or comparisons aren't supported in ConstProp" )
230- }
231-
232- fn access_local < ' a > (
233- frame : & ' a Frame < ' mir , ' tcx , Self :: Provenance , Self :: FrameExtra > ,
234- local : Local ,
235- ) -> InterpResult < ' tcx , & ' a interpret:: Operand < Self :: Provenance > > {
236- let l = & frame. locals [ local] ;
237-
238- if matches ! (
239- l. value,
240- LocalValue :: Live ( interpret:: Operand :: Immediate ( interpret:: Immediate :: Uninit ) )
241- ) {
242- // For us "uninit" means "we don't know its value, might be initiailized or not".
243- // So stop here.
244- throw_machine_stop_str ! ( "tried to access a local with unknown value" )
245- }
246-
247- l. access ( )
248- }
249-
250- fn access_local_mut < ' a > (
251- ecx : & ' a mut InterpCx < ' mir , ' tcx , Self > ,
252- frame : usize ,
253- local : Local ,
254- ) -> InterpResult < ' tcx , & ' a mut interpret:: Operand < Self :: Provenance > > {
255- if ecx. machine . can_const_prop [ local] == ConstPropMode :: NoPropagation {
256- throw_machine_stop_str ! ( "tried to write to a local that is marked as not propagatable" )
257- }
258- if frame == 0 && ecx. machine . only_propagate_inside_block_locals . contains ( local) {
259- trace ! (
260- "mutating local {:?} which is restricted to its block. \
261- Will remove it from const-prop after block is finished.",
262- local
263- ) ;
264- ecx. machine . written_only_inside_own_block_locals . insert ( local) ;
265- }
266- ecx. machine . stack [ frame] . locals [ local] . access_mut ( )
267- }
268-
269- fn before_access_global (
270- _tcx : TyCtxt < ' tcx > ,
271- _machine : & Self ,
272- _alloc_id : AllocId ,
273- alloc : ConstAllocation < ' tcx , Self :: Provenance , Self :: AllocExtra > ,
274- _static_def_id : Option < DefId > ,
275- is_write : bool ,
276- ) -> InterpResult < ' tcx > {
277- if is_write {
278- throw_machine_stop_str ! ( "can't write to global" ) ;
279- }
280- // If the static allocation is mutable, then we can't const prop it as its content
281- // might be different at runtime.
282- if alloc. inner ( ) . mutability == Mutability :: Mut {
283- throw_machine_stop_str ! ( "can't access mutable globals in ConstProp" ) ;
284- }
285-
286- Ok ( ( ) )
287- }
288-
289- #[ inline( always) ]
290- fn expose_ptr (
291- _ecx : & mut InterpCx < ' mir , ' tcx , Self > ,
292- _ptr : Pointer < AllocId > ,
293- ) -> InterpResult < ' tcx > {
294- throw_machine_stop_str ! ( "exposing pointers isn't supported in ConstProp" )
295- }
296-
297- #[ inline( always) ]
298- fn init_frame_extra (
299- _ecx : & mut InterpCx < ' mir , ' tcx , Self > ,
300- frame : Frame < ' mir , ' tcx > ,
301- ) -> InterpResult < ' tcx , Frame < ' mir , ' tcx > > {
302- Ok ( frame)
303- }
304-
305- #[ inline( always) ]
306- fn stack < ' a > (
307- ecx : & ' a InterpCx < ' mir , ' tcx , Self > ,
308- ) -> & ' a [ Frame < ' mir , ' tcx , Self :: Provenance , Self :: FrameExtra > ] {
309- & ecx. machine . stack
310- }
311-
312- #[ inline( always) ]
313- fn stack_mut < ' a > (
314- ecx : & ' a mut InterpCx < ' mir , ' tcx , Self > ,
315- ) -> & ' a mut Vec < Frame < ' mir , ' tcx , Self :: Provenance , Self :: FrameExtra > > {
316- & mut ecx. machine . stack
317- }
318- }
319-
320131/// Finds optimization opportunities on the MIR.
321132struct ConstPropagator < ' mir , ' tcx > {
322133 ecx : InterpCx < ' mir , ' tcx , ConstPropMachine < ' mir , ' tcx > > ,
@@ -711,20 +522,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
711522 }
712523}
713524
714- /// The mode that `ConstProp` is allowed to run in for a given `Local`.
715- #[ derive( Clone , Copy , Debug , PartialEq ) ]
716- enum ConstPropMode {
717- /// The `Local` can be propagated into and reads of this `Local` can also be propagated.
718- FullConstProp ,
719- /// The `Local` can only be propagated into and from its own block.
720- OnlyInsideOwnBlock ,
721- /// The `Local` can be propagated into but reads cannot be propagated.
722- OnlyPropagateInto ,
723- /// The `Local` cannot be part of propagation at all. Any statement
724- /// referencing it either for reading or writing will not get propagated.
725- NoPropagation ,
726- }
727-
728525struct CanConstProp {
729526 can_const_prop : IndexVec < Local , ConstPropMode > ,
730527 // False at the beginning. Once set, no more assignments are allowed to that local.
0 commit comments