@@ -22,7 +22,6 @@ use std::borrow::Cow;
22
22
use std:: rc:: Rc ;
23
23
use syntax:: ast;
24
24
use syntax_pos:: Span ;
25
- use transform;
26
25
27
26
pub mod add_validation;
28
27
pub mod clean_end_regions;
@@ -109,41 +108,6 @@ fn mir_built<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Stea
109
108
tcx. alloc_steal_mir ( mir)
110
109
}
111
110
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
-
147
111
/// Generates a default name for the pass based on the name of the
148
112
/// type `T`.
149
113
pub fn default_name < T : ?Sized > ( ) -> Cow < ' static , str > {
@@ -155,38 +119,6 @@ pub fn default_name<T: ?Sized>() -> Cow<'static, str> {
155
119
}
156
120
}
157
121
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
-
190
122
/// A streamlined trait that you can implement to create a pass; the
191
123
/// pass will be named after the type, and it will consist of a main
192
124
/// loop that goes over each available MIR and applies `run_pass`.
@@ -201,132 +133,104 @@ pub trait MirPass {
201
133
mir : & mut Mir < ' tcx > ) ;
202
134
}
203
135
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) ;
225
154
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 ) ) ;
228
157
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( ) ) ;
235
160
}
161
+ } }
236
162
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) ;
241
166
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
+ }
246
180
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) ;
249
187
}
250
188
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)
254
196
}
255
197
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) ;
327
203
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)
332
236
}
0 commit comments