99// except according to those terms.
1010
1111use hir;
12- use hir:: def_id:: { DefId , LOCAL_CRATE } ;
12+ use hir:: def_id:: DefId ;
1313use hir:: map:: DefPathData ;
1414use mir:: { Mir , Promoted } ;
1515use ty:: TyCtxt ;
16+ use std:: cell:: { Ref , RefCell } ;
1617use std:: rc:: Rc ;
1718use syntax:: ast:: NodeId ;
18- use util:: common:: time;
1919
2020use std:: borrow:: Cow ;
2121
@@ -90,12 +90,37 @@ pub fn default_name<T: ?Sized>() -> Cow<'static, str> {
9090 }
9191}
9292
93+ /// Gives you access to various bits of state during your MIR pass.
94+ pub trait MirCtxt < ' a , ' tcx : ' a > {
95+ fn tcx ( & self ) -> TyCtxt < ' a , ' tcx , ' tcx > ;
96+ fn def_id ( & self ) -> DefId ;
97+ fn pass_set ( & self ) -> MirPassSet ;
98+ fn pass_num ( & self ) -> MirPassIndex ;
99+ fn source ( & self ) -> MirSource ;
100+ fn read_previous_mir ( & self ) -> Ref < ' tcx , Mir < ' tcx > > ;
101+ fn steal_previous_mir ( & self ) -> & ' tcx RefCell < Mir < ' tcx > > ;
102+ }
103+
104+ #[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash , PartialOrd , Ord ) ]
105+ pub struct MirPassSet ( pub usize ) ;
106+
107+ #[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash , PartialOrd , Ord ) ]
108+ pub struct MirPassIndex ( pub usize ) ;
109+
110+ /// A pass hook is invoked both before and after each pass executes.
111+ /// This is primarily used to dump MIR for debugging.
112+ ///
113+ /// You can tell whether this is before or after by inspecting the
114+ /// `mir` parameter -- before the pass executes, it will be `None` (in
115+ /// which case you can inspect the MIR from previous pass by executing
116+ /// `mir_cx.read_previous_mir()`); after the pass executes, it will be
117+ /// `Some()` with the result of the pass (in which case the output
118+ /// from the previous pass is most likely stolen, so you would not
119+ /// want to try and access it).
93120pub trait PassHook {
94- fn on_mir_pass < ' a , ' tcx > ( & self ,
95- tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
96- pass_name : & str ,
97- pass_num : usize ,
98- is_after : bool ) ;
121+ fn on_mir_pass < ' a , ' tcx : ' a > ( & self ,
122+ mir_cx : & MirCtxt < ' a , ' tcx > ,
123+ mir : Option < & Mir < ' tcx > > ) ;
99124}
100125
101126/// A streamlined trait that you can implement to create a pass; the
@@ -107,21 +132,7 @@ pub trait DefIdPass {
107132 default_name :: < Self > ( )
108133 }
109134
110- fn run_pass < ' a , ' tcx > ( & self ,
111- tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
112- def_id : DefId ) ;
113- }
114-
115- impl < T : DefIdPass > Pass for T {
116- fn name < ' a > ( & ' a self ) -> Cow < ' a , str > {
117- DefIdPass :: name ( self )
118- }
119-
120- fn run_pass < ' a , ' tcx > ( & self , tcx : TyCtxt < ' a , ' tcx , ' tcx > ) {
121- for & def_id in tcx. mir_keys ( LOCAL_CRATE ) . iter ( ) {
122- DefIdPass :: run_pass ( self , tcx, def_id) ;
123- }
124- }
135+ fn run_pass < ' a , ' tcx : ' a > ( & self , mir_cx : & MirCtxt < ' a , ' tcx > ) -> & ' tcx RefCell < Mir < ' tcx > > ;
125136}
126137
127138/// A streamlined trait that you can implement to create a pass; the
@@ -138,42 +149,32 @@ pub trait MirPass: DepGraphSafe {
138149 mir : & mut Mir < ' tcx > ) ;
139150}
140151
141- fn for_each_assoc_mir < ' a , ' tcx , OP > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
142- def_id : DefId ,
143- mut op : OP )
144- where OP : FnMut ( MirSource , & mut Mir < ' tcx > )
145- {
146- let id = tcx. hir . as_local_node_id ( def_id) . expect ( "mir source requires local def-id" ) ;
147- let source = MirSource :: from_node ( tcx, id) ;
148- let mir = & mut tcx. mir ( def_id) . borrow_mut ( ) ;
149- op ( source, mir) ;
150-
151- for ( promoted_index, promoted_mir) in mir. promoted . iter_enumerated_mut ( ) {
152- let promoted_source = MirSource :: Promoted ( id, promoted_index) ;
153- op ( promoted_source, promoted_mir) ;
154- }
155- }
156-
157152impl < T : MirPass > DefIdPass for T {
158153 fn name < ' a > ( & ' a self ) -> Cow < ' a , str > {
159154 MirPass :: name ( self )
160155 }
161156
162- fn run_pass < ' a , ' tcx > ( & self , tcx : TyCtxt < ' a , ' tcx , ' tcx > , def_id : DefId ) {
163- for_each_assoc_mir ( tcx, def_id, |src, mir| MirPass :: run_pass ( self , tcx, src, mir) ) ;
157+ fn run_pass < ' a , ' tcx : ' a > ( & self , mir_cx : & MirCtxt < ' a , ' tcx > ) -> & ' tcx RefCell < Mir < ' tcx > > {
158+ let tcx = mir_cx. tcx ( ) ;
159+ let source = mir_cx. source ( ) ;
160+ let mir = mir_cx. steal_previous_mir ( ) ;
161+ MirPass :: run_pass ( self , tcx, source, & mut mir. borrow_mut ( ) ) ;
162+
163+ let item_id = source. item_id ( ) ;
164+ for ( promoted_index, promoted_mir) in mir. borrow_mut ( ) . promoted . iter_enumerated_mut ( ) {
165+ let promoted_source = MirSource :: Promoted ( item_id, promoted_index) ;
166+ MirPass :: run_pass ( self , tcx, promoted_source, promoted_mir) ;
167+ }
168+
169+ mir
164170 }
165171}
166172
167173/// A manager for MIR passes.
168174#[ derive( Clone ) ]
169175pub struct Passes {
170176 pass_hooks : Vec < Rc < PassHook > > ,
171- sets : Vec < PassSet > ,
172- }
173-
174- #[ derive( Clone ) ]
175- struct PassSet {
176- passes : Vec < Rc < DefIdPass > > ,
177+ sets : Vec < Vec < Rc < DefIdPass > > > ,
177178}
178179
179180/// The number of "pass sets" that we have:
@@ -184,52 +185,41 @@ struct PassSet {
184185pub const MIR_PASS_SETS : usize = 3 ;
185186
186187/// Run the passes we need to do constant qualification and evaluation.
187- pub const MIR_CONST : usize = 0 ;
188+ pub const MIR_CONST : MirPassSet = MirPassSet ( 0 ) ;
188189
189190/// Run the passes we need to consider the MIR validated and ready for borrowck etc.
190- pub const MIR_VALIDATED : usize = 1 ;
191+ pub const MIR_VALIDATED : MirPassSet = MirPassSet ( 1 ) ;
191192
192193/// Run the passes we need to consider the MIR *optimized*.
193- pub const MIR_OPTIMIZED : usize = 2 ;
194+ pub const MIR_OPTIMIZED : MirPassSet = MirPassSet ( 2 ) ;
194195
195196impl < ' a , ' tcx > Passes {
196197 pub fn new ( ) -> Passes {
197198 Passes {
198199 pass_hooks : Vec :: new ( ) ,
199- sets : ( 0 ..MIR_PASS_SETS ) . map ( |_| PassSet { passes : Vec :: new ( ) } ) . collect ( ) ,
200- }
201- }
202-
203- pub fn run_passes ( & self , tcx : TyCtxt < ' a , ' tcx , ' tcx > , set_index : usize ) {
204- let set = & self . sets [ set_index] ;
205-
206- let start_num: usize = self . sets [ ..set_index] . iter ( ) . map ( |s| s. passes . len ( ) ) . sum ( ) ;
207-
208- // NB: passes are numbered from 1, since "construction" is zero.
209- for ( pass, pass_num) in set. passes . iter ( ) . zip ( start_num + 1 ..) {
210- for hook in & self . pass_hooks {
211- hook. on_mir_pass ( tcx, & pass. name ( ) , pass_num, false ) ;
212- }
213-
214- time ( tcx. sess . time_passes ( ) , & * pass. name ( ) , || {
215- for & def_id in tcx. mir_keys ( LOCAL_CRATE ) . iter ( ) {
216- pass. run_pass ( tcx, def_id) ;
217- }
218- } ) ;
219-
220- for hook in & self . pass_hooks {
221- hook. on_mir_pass ( tcx, & pass. name ( ) , pass_num, true ) ;
222- }
200+ sets : ( 0 ..MIR_PASS_SETS ) . map ( |_| Vec :: new ( ) ) . collect ( ) ,
223201 }
224202 }
225203
226204 /// Pushes a built-in pass.
227- pub fn push_pass < T : DefIdPass + ' static > ( & mut self , set : usize , pass : T ) {
228- self . sets [ set] . passes . push ( Rc :: new ( pass) ) ;
205+ pub fn push_pass < T : DefIdPass + ' static > ( & mut self , set : MirPassSet , pass : T ) {
206+ self . sets [ set. 0 ] . push ( Rc :: new ( pass) ) ;
229207 }
230208
231209 /// Pushes a pass hook.
232210 pub fn push_hook < T : PassHook + ' static > ( & mut self , hook : T ) {
233211 self . pass_hooks . push ( Rc :: new ( hook) ) ;
234212 }
213+
214+ pub fn len_passes ( & self , set : MirPassSet ) -> usize {
215+ self . sets [ set. 0 ] . len ( )
216+ }
217+
218+ pub fn pass ( & self , set : MirPassSet , pass : MirPassIndex ) -> & DefIdPass {
219+ & * self . sets [ set. 0 ] [ pass. 0 ]
220+ }
221+
222+ pub fn hooks ( & self ) -> & [ Rc < PassHook > ] {
223+ & self . pass_hooks
224+ }
235225}
0 commit comments