Diff
Not logged in

Differences From Artifact [9339be6648]:

To Artifact [7cc651e42d]:


4
5
6
7
8
9
10
11

12

13
14
15

16
17
18
19
20
21
22
23
24
25
26
27
..
32
33
34
35
36
37
38





39
40
41
42
43
44
45
..
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85


86
87
88
89
90
91
92
93
94











95
96
97
98



99
100
101
102
103
104
105
106







107
108
109


110
111
112
113
114
115
116
117
118
119
120


121
122
123
124
125
126
127
128
129
130
131
132


133
134
135

136
137
138
139
140

141
142

143
144
145
146


147


148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173

174
175
176
177
178
179
180
181
182
183
184
185
186


187
188
189
190

191

192
193
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use dep_graph::DepNode;

use hir;

use hir::map::DefPathData;
use mir::{Mir, Promoted};
use ty::TyCtxt;

use syntax::ast::NodeId;
use util::common::time;

use std::borrow::Cow;
use std::fmt;

/// Where a specific Mir comes from.
#[derive(Debug, Copy, Clone)]
pub enum MirSource {
    /// Functions and methods.
    Fn(NodeId),

................................................................................
    Static(NodeId, hir::Mutability),

    /// Promoted rvalues within a function.
    Promoted(NodeId, Promoted)
}

impl<'a, 'tcx> MirSource {





    pub fn from_node(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId) -> MirSource {
        use hir::*;

        // Handle constants in enum discriminants, types, and repeat expressions.
        let def_id = tcx.hir.local_def_id(id);
        let def_key = tcx.def_key(def_id);
        if def_key.disambiguated_data.data == DefPathData::Initializer {
................................................................................
            MirSource::Const(id) |
            MirSource::Static(id, _) |
            MirSource::Promoted(id, _) => id
        }
    }
}

/// Various information about pass.
pub trait Pass {
    // fn should_run(Session) to check if pass should run?
    fn name<'a>(&self) -> Cow<'static, str> {
        let name = unsafe { ::std::intrinsics::type_name::<Self>() };
        if let Some(tail) = name.rfind(":") {
            Cow::from(&name[tail+1..])
        } else {
            Cow::from(name)
        }
    }
    fn disambiguator<'a>(&'a self) -> Option<Box<fmt::Display+'a>> { None }
}



/// A pass which inspects the whole Mir map.
pub trait MirMapPass<'tcx>: Pass {
    fn run_pass<'a>(
        &mut self,
        tcx: TyCtxt<'a, 'tcx, 'tcx>,
        hooks: &mut [Box<for<'s> MirPassHook<'s>>]);
}












pub trait MirPassHook<'tcx>: Pass {
    fn on_mir_pass<'a>(
        &mut self,
        tcx: TyCtxt<'a, 'tcx, 'tcx>,



        src: MirSource,
        mir: &Mir<'tcx>,
        pass: &Pass,
        is_after: bool
    );
}

/// A pass which inspects Mir of functions in isolation.







pub trait MirPass<'tcx>: Pass {
    fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                    src: MirSource, mir: &mut Mir<'tcx>);


}

impl<'tcx, T: MirPass<'tcx>> MirMapPass<'tcx> for T {
    fn run_pass<'a>(&mut self,
                    tcx: TyCtxt<'a, 'tcx, 'tcx>,
                    hooks: &mut [Box<for<'s> MirPassHook<'s>>])
    {
        let def_ids = tcx.maps.mir.borrow().keys();
        for def_id in def_ids {
            if !def_id.is_local() {
                continue;


            }

            let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id));
            let mir = &mut tcx.maps.mir.borrow()[&def_id].borrow_mut();
            tcx.dep_graph.write(DepNode::Mir(def_id));

            let id = tcx.hir.as_local_node_id(def_id).unwrap();
            let src = MirSource::from_node(tcx, id);

            for hook in &mut *hooks {
                hook.on_mir_pass(tcx, src, mir, self, false);
            }


            MirPass::run_pass(self, tcx, src, mir);
            for hook in &mut *hooks {
                hook.on_mir_pass(tcx, src, mir, self, true);

            }

            for (i, mir) in mir.promoted.iter_enumerated_mut() {
                let src = MirSource::Promoted(id, i);
                for hook in &mut *hooks {

                    hook.on_mir_pass(tcx, src, mir, self, false);
                }

                MirPass::run_pass(self, tcx, src, mir);
                for hook in &mut *hooks {
                    hook.on_mir_pass(tcx, src, mir, self, true);
                }


            }


        }
    }
}

/// A manager for MIR passes.
pub struct Passes {
    passes: Vec<Box<for<'tcx> MirMapPass<'tcx>>>,
    pass_hooks: Vec<Box<for<'tcx> MirPassHook<'tcx>>>,
    plugin_passes: Vec<Box<for<'tcx> MirMapPass<'tcx>>>
}

impl<'a, 'tcx> Passes {
    pub fn new() -> Passes {
        let passes = Passes {
            passes: Vec::new(),
            pass_hooks: Vec::new(),
            plugin_passes: Vec::new()
        };
        passes
    }

    pub fn run_passes(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>) {
        let Passes { ref mut passes, ref mut plugin_passes, ref mut pass_hooks } = *self;
        for pass in plugin_passes.iter_mut().chain(passes.iter_mut()) {
            time(tcx.sess.time_passes(), &*pass.name(),
                 || pass.run_pass(tcx, pass_hooks));

        }
    }

    /// Pushes a built-in pass.
    pub fn push_pass(&mut self, pass: Box<for<'b> MirMapPass<'b>>) {
        self.passes.push(pass);
    }

    /// Pushes a pass hook.
    pub fn push_hook(&mut self, hook: Box<for<'b> MirPassHook<'b>>) {
        self.pass_hooks.push(hook);
    }
}



/// Copies the plugin passes.
impl ::std::iter::Extend<Box<for<'a> MirMapPass<'a>>> for Passes {
    fn extend<I: IntoIterator<Item=Box<for <'a> MirMapPass<'a>>>>(&mut self, it: I) {

        self.plugin_passes.extend(it);

    }
}







|
>

>



>

<


<







 







>
>
>
>
>







 







|
|
<
|
|
|
|
|
|
|
|
<
|
>
>

|
|
<
<
<
<
|
<
>
>
>
>
>
>
>
>
>
>
>
|
|
<
|
>
>
>
|
|
<
|
<


<
>
>
>
>
>
>
>
|
<
<
>
>
|

<
|
|
<
<
<
<
<
<
>
>
|

<
<
<
<
<
<
<
|
<
<
>
>
|
|
|
>
|

<
|
<
>
|
<
>
|
|
<
|
>
>
|
>
>
|
<
<
<
|
|
<
<
<
|
<


|
<

<
<
<
<
<
<
<
<
<
<
>




|
|



|
|

|
>
>
|
<
<
<
>
|
>


4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

20
21

22
23
24
25
26
27
28
..
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
..
72
73
74
75
76
77
78
79
80

81
82
83
84
85
86
87
88

89
90
91
92
93
94




95

96
97
98
99
100
101
102
103
104
105
106
107
108

109
110
111
112
113
114

115

116
117

118
119
120
121
122
123
124
125


126
127
128
129

130
131






132
133
134
135







136


137
138
139
140
141
142
143
144

145

146
147

148
149
150

151
152
153
154
155
156
157



158
159



160

161
162
163

164










165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181



182
183
184
185
186
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! See [the README](README.md) for details on writing your own pass.

use hir;
use hir::def_id::DefId;
use hir::map::DefPathData;
use mir::{Mir, Promoted};
use ty::TyCtxt;
use std::rc::Rc;
use syntax::ast::NodeId;


use std::borrow::Cow;


/// Where a specific Mir comes from.
#[derive(Debug, Copy, Clone)]
pub enum MirSource {
    /// Functions and methods.
    Fn(NodeId),

................................................................................
    Static(NodeId, hir::Mutability),

    /// Promoted rvalues within a function.
    Promoted(NodeId, Promoted)
}

impl<'a, 'tcx> MirSource {
    pub fn from_local_def_id(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> MirSource {
        let id = tcx.hir.as_local_node_id(def_id).expect("mir source requires local def-id");
        Self::from_node(tcx, id)
    }

    pub fn from_node(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId) -> MirSource {
        use hir::*;

        // Handle constants in enum discriminants, types, and repeat expressions.
        let def_id = tcx.hir.local_def_id(id);
        let def_key = tcx.def_key(def_id);
        if def_key.disambiguated_data.data == DefPathData::Initializer {
................................................................................
            MirSource::Const(id) |
            MirSource::Static(id, _) |
            MirSource::Promoted(id, _) => id
        }
    }
}

/// Generates a default name for the pass based on the name of the
/// type `T`.

pub fn default_name<T: ?Sized>() -> Cow<'static, str> {
    let name = unsafe { ::std::intrinsics::type_name::<T>() };
    if let Some(tail) = name.rfind(":") {
        Cow::from(&name[tail+1..])
    } else {
        Cow::from(name)
    }
}


#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct MirSuite(pub usize);

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct MirPassIndex(pub usize);






/// A pass hook is invoked both before and after each pass executes.
/// This is primarily used to dump MIR for debugging.
///
/// You can tell whether this is before or after by inspecting the
/// `mir` parameter -- before the pass executes, it will be `None` (in
/// which case you can inspect the MIR from previous pass by executing
/// `mir_cx.read_previous_mir()`); after the pass executes, it will be
/// `Some()` with the result of the pass (in which case the output
/// from the previous pass is most likely stolen, so you would not
/// want to try and access it). If the pass is interprocedural, then
/// the hook will be invoked once per output.
pub trait PassHook {
    fn on_mir_pass<'a, 'tcx: 'a>(&self,

                                 tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                 suite: MirSuite,
                                 pass_num: MirPassIndex,
                                 pass_name: &str,
                                 source: MirSource,
                                 mir: &Mir<'tcx>,

                                 is_after: bool);

}


/// The full suite of types that identifies a particular
/// application of a pass to a def-id.
pub type PassId = (MirSuite, MirPassIndex, DefId);

/// A streamlined trait that you can implement to create a pass; the
/// pass will be named after the type, and it will consist of a main
/// loop that goes over each available MIR and applies `run_pass`.
pub trait MirPass {


    fn name<'a>(&'a self) -> Cow<'a, str> {
        default_name::<Self>()
    }


    fn run_pass<'a, 'tcx>(&self,
                          tcx: TyCtxt<'a, 'tcx, 'tcx>,






                          source: MirSource,
                          mir: &mut Mir<'tcx>);
}








/// A manager for MIR passes.


///
/// FIXME(#41712) -- it is unclear whether we should have this struct.
#[derive(Clone)]
pub struct Passes {
    pass_hooks: Vec<Rc<PassHook>>,
    suites: Vec<Vec<Rc<MirPass>>>,
}


/// The number of "pass suites" that we have:

///
/// - ready for constant evaluation

/// - unopt
/// - optimized
pub const MIR_SUITES: usize = 3;


/// Run the passes we need to do constant qualification and evaluation.
pub const MIR_CONST: MirSuite = MirSuite(0);

/// Run the passes we need to consider the MIR validated and ready for borrowck etc.
pub const MIR_VALIDATED: MirSuite = MirSuite(1);




/// Run the passes we need to consider the MIR *optimized*.
pub const MIR_OPTIMIZED: MirSuite = MirSuite(2);





impl<'a, 'tcx> Passes {
    pub fn new() -> Passes {
        Passes {

            pass_hooks: Vec::new(),










            suites: (0..MIR_SUITES).map(|_| Vec::new()).collect(),
        }
    }

    /// Pushes a built-in pass.
    pub fn push_pass<T: MirPass + 'static>(&mut self, suite: MirSuite, pass: T) {
        self.suites[suite.0].push(Rc::new(pass));
    }

    /// Pushes a pass hook.
    pub fn push_hook<T: PassHook + 'static>(&mut self, hook: T) {
        self.pass_hooks.push(Rc::new(hook));
    }

    pub fn passes(&self, suite: MirSuite) -> &[Rc<MirPass>] {
        &self.suites[suite.0]
    }




    pub fn hooks(&self) -> &[Rc<PassHook>] {
        &self.pass_hooks
    }
}