@@ -22,7 +22,6 @@ use std::borrow::Cow;
2222use std:: rc:: Rc ;
2323use syntax:: ast;
2424use syntax_pos:: Span ;
25- use transform;
2625
2726pub mod add_validation;
2827pub mod clean_end_regions;
@@ -109,41 +108,6 @@ fn mir_built<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Stea
109108 tcx. alloc_steal_mir ( mir)
110109}
111110
112- fn mir_const < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , def_id : DefId ) -> & ' tcx Steal < Mir < ' tcx > > {
113- // Unsafety check uses the raw mir, so make sure it is run
114- let _ = tcx. unsafety_check_result ( def_id) ;
115-
116- let source = MirSource :: from_local_def_id ( tcx, def_id) ;
117- let mut mir = tcx. mir_built ( def_id) . steal ( ) ;
118- transform:: run_suite ( tcx, source, MIR_CONST , & mut mir) ;
119- tcx. alloc_steal_mir ( mir)
120- }
121-
122- fn mir_validated < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , def_id : DefId ) -> & ' tcx Steal < Mir < ' tcx > > {
123- let source = MirSource :: from_local_def_id ( tcx, def_id) ;
124- if let MirSource :: Const ( _) = source {
125- // Ensure that we compute the `mir_const_qualif` for constants at
126- // this point, before we steal the mir-const result.
127- let _ = tcx. mir_const_qualif ( def_id) ;
128- }
129-
130- let mut mir = tcx. mir_const ( def_id) . steal ( ) ;
131- transform:: run_suite ( tcx, source, MIR_VALIDATED , & mut mir) ;
132- tcx. alloc_steal_mir ( mir)
133- }
134-
135- fn optimized_mir < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , def_id : DefId ) -> & ' tcx Mir < ' tcx > {
136- // (Mir-)Borrowck uses `mir_validated`, so we have to force it to
137- // execute before we can steal.
138- let _ = tcx. mir_borrowck ( def_id) ;
139- let _ = tcx. borrowck ( def_id) ;
140-
141- let mut mir = tcx. mir_validated ( def_id) . steal ( ) ;
142- let source = MirSource :: from_local_def_id ( tcx, def_id) ;
143- transform:: run_suite ( tcx, source, MIR_OPTIMIZED , & mut mir) ;
144- tcx. alloc_mir ( mir)
145- }
146-
147111/// Generates a default name for the pass based on the name of the
148112/// type `T`.
149113pub fn default_name < T : ?Sized > ( ) -> Cow < ' static , str > {
@@ -155,38 +119,6 @@ pub fn default_name<T: ?Sized>() -> Cow<'static, str> {
155119 }
156120}
157121
158- #[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash , PartialOrd , Ord ) ]
159- pub struct MirSuite ( pub usize ) ;
160-
161- #[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash , PartialOrd , Ord ) ]
162- pub struct MirPassIndex ( pub usize ) ;
163-
164- /// A pass hook is invoked both before and after each pass executes.
165- /// This is primarily used to dump MIR for debugging.
166- ///
167- /// You can tell whether this is before or after by inspecting the
168- /// `mir` parameter -- before the pass executes, it will be `None` (in
169- /// which case you can inspect the MIR from previous pass by executing
170- /// `mir_cx.read_previous_mir()`); after the pass executes, it will be
171- /// `Some()` with the result of the pass (in which case the output
172- /// from the previous pass is most likely stolen, so you would not
173- /// want to try and access it). If the pass is interprocedural, then
174- /// the hook will be invoked once per output.
175- pub trait PassHook {
176- fn on_mir_pass < ' a , ' tcx : ' a > ( & self ,
177- tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
178- suite : MirSuite ,
179- pass_num : MirPassIndex ,
180- pass_name : & str ,
181- source : MirSource ,
182- mir : & Mir < ' tcx > ,
183- is_after : bool ) ;
184- }
185-
186- /// The full suite of types that identifies a particular
187- /// application of a pass to a def-id.
188- pub type PassId = ( MirSuite , MirPassIndex , DefId ) ;
189-
190122/// A streamlined trait that you can implement to create a pass; the
191123/// pass will be named after the type, and it will consist of a main
192124/// loop that goes over each available MIR and applies `run_pass`.
@@ -201,132 +133,104 @@ pub trait MirPass {
201133 mir : & mut Mir < ' tcx > ) ;
202134}
203135
204- /// A manager for MIR passes.
205- ///
206- /// FIXME(#41712) -- it is unclear whether we should have this struct.
207- #[ derive( Clone ) ]
208- pub struct Passes {
209- pass_hooks : Vec < Rc < PassHook > > ,
210- suites : Vec < Vec < Rc < MirPass > > > ,
211- }
212-
213- /// The number of "pass suites" that we have:
214- ///
215- /// - ready for constant evaluation
216- /// - unopt
217- /// - optimized
218- pub const MIR_SUITES : usize = 3 ;
219-
220- /// Run the passes we need to do constant qualification and evaluation.
221- pub const MIR_CONST : MirSuite = MirSuite ( 0 ) ;
222-
223- /// Run the passes we need to consider the MIR validated and ready for borrowck etc.
224- pub const MIR_VALIDATED : MirSuite = MirSuite ( 1 ) ;
136+ pub macro run_passes( $tcx: ident, $mir: ident, $source: ident, $suite_index: expr; $( $pass: expr, ) * ) { {
137+ let suite_index: usize = $suite_index;
138+ let run_passes = |mir : & mut _ , source| {
139+ let mut index = 0 ;
140+ let mut run_pass = |pass : & MirPass | {
141+ let run_hooks = |mir : & _ , index, is_after| {
142+ dump_mir:: on_mir_pass ( $tcx, & format_args ! ( "{:03}-{:03}" , suite_index, index) ,
143+ & pass. name ( ) , source, mir, is_after) ;
144+ } ;
145+ run_hooks ( mir, index, false ) ;
146+ pass. run_pass ( $tcx, source, mir) ;
147+ run_hooks ( mir, index, true ) ;
148+
149+ index += 1 ;
150+ } ;
151+ $( run_pass ( & $pass) ; ) *
152+ } ;
153+ run_passes ( & mut $mir, $source) ;
225154
226- /// Run the passes we need to consider the MIR *optimized*.
227- pub const MIR_OPTIMIZED : MirSuite = MirSuite ( 2 ) ;
155+ for ( index , promoted_mir ) in $mir . promoted . iter_enumerated_mut ( ) {
156+ run_passes ( promoted_mir , MirSource :: Promoted ( $source . item_id ( ) , index ) ) ;
228157
229- impl < ' a , ' tcx > Passes {
230- pub fn new ( ) -> Passes {
231- Passes {
232- pass_hooks : Vec :: new ( ) ,
233- suites : ( 0 ..MIR_SUITES ) . map ( |_| Vec :: new ( ) ) . collect ( ) ,
234- }
158+ // Let's make sure we don't miss any nested instances
159+ assert ! ( promoted_mir. promoted. is_empty( ) ) ;
235160 }
161+ } }
236162
237- /// Pushes a built-in pass.
238- pub fn push_pass < T : MirPass + ' static > ( & mut self , suite : MirSuite , pass : T ) {
239- self . suites [ suite. 0 ] . push ( Rc :: new ( pass) ) ;
240- }
163+ fn mir_const < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , def_id : DefId ) -> & ' tcx Steal < Mir < ' tcx > > {
164+ // Unsafety check uses the raw mir, so make sure it is run
165+ let _ = tcx. unsafety_check_result ( def_id) ;
241166
242- /// Pushes a pass hook.
243- pub fn push_hook < T : PassHook + ' static > ( & mut self , hook : T ) {
244- self . pass_hooks . push ( Rc :: new ( hook) ) ;
245- }
167+ let mut mir = tcx. mir_built ( def_id) . steal ( ) ;
168+ let source = MirSource :: from_local_def_id ( tcx, def_id) ;
169+ run_passes ! [ tcx, mir, source, 0 ;
170+ // Remove all `EndRegion` statements that are not involved in borrows.
171+ clean_end_regions:: CleanEndRegions ,
172+
173+ // What we need to do constant evaluation.
174+ simplify:: SimplifyCfg :: new( "initial" ) ,
175+ type_check:: TypeckMir ,
176+ rustc_peek:: SanityCheck ,
177+ ] ;
178+ tcx. alloc_steal_mir ( mir)
179+ }
246180
247- pub fn passes ( & self , suite : MirSuite ) -> & [ Rc < MirPass > ] {
248- & self . suites [ suite. 0 ]
181+ fn mir_validated < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , def_id : DefId ) -> & ' tcx Steal < Mir < ' tcx > > {
182+ let source = MirSource :: from_local_def_id ( tcx, def_id) ;
183+ if let MirSource :: Const ( _) = source {
184+ // Ensure that we compute the `mir_const_qualif` for constants at
185+ // this point, before we steal the mir-const result.
186+ let _ = tcx. mir_const_qualif ( def_id) ;
249187 }
250188
251- pub fn hooks ( & self ) -> & [ Rc < PassHook > ] {
252- & self . pass_hooks
253- }
189+ let mut mir = tcx. mir_const ( def_id) . steal ( ) ;
190+ run_passes ! [ tcx, mir, source, 1 ;
191+ // What we need to run borrowck etc.
192+ qualify_consts:: QualifyAndPromoteConstants ,
193+ simplify:: SimplifyCfg :: new( "qualify-consts" ) ,
194+ ] ;
195+ tcx. alloc_steal_mir ( mir)
254196}
255197
256- fn run_suite < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
257- source : MirSource ,
258- suite : MirSuite ,
259- mir : & mut Mir < ' tcx > )
260- {
261- // Setup the MIR passes that we want to run.
262- let mut passes = Passes :: new ( ) ;
263- passes. push_hook ( dump_mir:: DumpMir ) ;
264-
265- // Remove all `EndRegion` statements that are not involved in borrows.
266- passes. push_pass ( MIR_CONST , clean_end_regions:: CleanEndRegions ) ;
267-
268- // What we need to do constant evaluation.
269- passes. push_pass ( MIR_CONST , simplify:: SimplifyCfg :: new ( "initial" ) ) ;
270- passes. push_pass ( MIR_CONST , type_check:: TypeckMir ) ;
271- passes. push_pass ( MIR_CONST , rustc_peek:: SanityCheck ) ;
272-
273- // We compute "constant qualifications" between MIR_CONST and MIR_VALIDATED.
274-
275- // What we need to run borrowck etc.
276-
277- passes. push_pass ( MIR_VALIDATED , qualify_consts:: QualifyAndPromoteConstants ) ;
278- passes. push_pass ( MIR_VALIDATED , simplify:: SimplifyCfg :: new ( "qualify-consts" ) ) ;
279-
280- // borrowck runs between MIR_VALIDATED and MIR_OPTIMIZED.
281-
282- passes. push_pass ( MIR_OPTIMIZED , no_landing_pads:: NoLandingPads ) ;
283- passes. push_pass ( MIR_OPTIMIZED ,
284- simplify_branches:: SimplifyBranches :: new ( "initial" ) ) ;
285-
286- // These next passes must be executed together
287- passes. push_pass ( MIR_OPTIMIZED , add_call_guards:: CriticalCallEdges ) ;
288- passes. push_pass ( MIR_OPTIMIZED , elaborate_drops:: ElaborateDrops ) ;
289- passes. push_pass ( MIR_OPTIMIZED , no_landing_pads:: NoLandingPads ) ;
290- // AddValidation needs to run after ElaborateDrops and before EraseRegions, and it needs
291- // an AllCallEdges pass right before it.
292- passes. push_pass ( MIR_OPTIMIZED , add_call_guards:: AllCallEdges ) ;
293- passes. push_pass ( MIR_OPTIMIZED , add_validation:: AddValidation ) ;
294- passes. push_pass ( MIR_OPTIMIZED , simplify:: SimplifyCfg :: new ( "elaborate-drops" ) ) ;
295- // No lifetime analysis based on borrowing can be done from here on out.
296-
297- // From here on out, regions are gone.
298- passes. push_pass ( MIR_OPTIMIZED , erase_regions:: EraseRegions ) ;
299-
300- // Optimizations begin.
301- passes. push_pass ( MIR_OPTIMIZED , inline:: Inline ) ;
302- passes. push_pass ( MIR_OPTIMIZED , instcombine:: InstCombine ) ;
303- passes. push_pass ( MIR_OPTIMIZED , deaggregator:: Deaggregator ) ;
304- passes. push_pass ( MIR_OPTIMIZED , copy_prop:: CopyPropagation ) ;
305- passes. push_pass ( MIR_OPTIMIZED , simplify:: SimplifyLocals ) ;
306-
307- passes. push_pass ( MIR_OPTIMIZED , generator:: StateTransform ) ;
308- passes. push_pass ( MIR_OPTIMIZED , add_call_guards:: CriticalCallEdges ) ;
309- passes. push_pass ( MIR_OPTIMIZED , dump_mir:: Marker ( "PreTrans" ) ) ;
310-
311- for ( index, pass) in passes. passes ( suite) . iter ( ) . enumerate ( ) {
312- let pass_num = MirPassIndex ( index) ;
313-
314- for hook in passes. hooks ( ) {
315- hook. on_mir_pass ( tcx, suite, pass_num, & pass. name ( ) , source, & mir, false ) ;
316- }
317-
318- pass. run_pass ( tcx, source, mir) ;
319-
320- for ( index, promoted_mir) in mir. promoted . iter_enumerated_mut ( ) {
321- let promoted_source = MirSource :: Promoted ( source. item_id ( ) , index) ;
322- pass. run_pass ( tcx, promoted_source, promoted_mir) ;
323-
324- // Let's make sure we don't miss any nested instances
325- assert ! ( promoted_mir. promoted. is_empty( ) ) ;
326- }
198+ fn optimized_mir < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , def_id : DefId ) -> & ' tcx Mir < ' tcx > {
199+ // (Mir-)Borrowck uses `mir_validated`, so we have to force it to
200+ // execute before we can steal.
201+ let _ = tcx. mir_borrowck ( def_id) ;
202+ let _ = tcx. borrowck ( def_id) ;
327203
328- for hook in passes. hooks ( ) {
329- hook. on_mir_pass ( tcx, suite, pass_num, & pass. name ( ) , source, & mir, true ) ;
330- }
331- }
204+ let mut mir = tcx. mir_validated ( def_id) . steal ( ) ;
205+ let source = MirSource :: from_local_def_id ( tcx, def_id) ;
206+ run_passes ! [ tcx, mir, source, 2 ;
207+ no_landing_pads:: NoLandingPads ,
208+ simplify_branches:: SimplifyBranches :: new( "initial" ) ,
209+
210+ // These next passes must be executed together
211+ add_call_guards:: CriticalCallEdges ,
212+ elaborate_drops:: ElaborateDrops ,
213+ no_landing_pads:: NoLandingPads ,
214+ // AddValidation needs to run after ElaborateDrops and before EraseRegions, and it needs
215+ // an AllCallEdges pass right before it.
216+ add_call_guards:: AllCallEdges ,
217+ add_validation:: AddValidation ,
218+ simplify:: SimplifyCfg :: new( "elaborate-drops" ) ,
219+ // No lifetime analysis based on borrowing can be done from here on out.
220+
221+ // From here on out, regions are gone.
222+ erase_regions:: EraseRegions ,
223+
224+ // Optimizations begin.
225+ inline:: Inline ,
226+ instcombine:: InstCombine ,
227+ deaggregator:: Deaggregator ,
228+ copy_prop:: CopyPropagation ,
229+ simplify:: SimplifyLocals ,
230+
231+ generator:: StateTransform ,
232+ add_call_guards:: CriticalCallEdges ,
233+ dump_mir:: Marker ( "PreTrans" ) ,
234+ ] ;
235+ tcx. alloc_mir ( mir)
332236}
0 commit comments