]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/transform/mod.rs
81af7c239608545635045fd7f066290a00051940
[rust.git] / src / librustc_mir / transform / mod.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use rustc::hir::def_id::DefId;
12 use rustc::mir::Mir;
13 use rustc::mir::transform::{MirCtxt, MirPassIndex, MirSuite, MirSource, MIR_OPTIMIZED, PassId};
14 use rustc::ty::steal::Steal;
15 use rustc::ty::TyCtxt;
16 use rustc::ty::maps::{Multi, Providers};
17 use std::cell::Ref;
18
19 pub mod simplify_branches;
20 pub mod simplify;
21 pub mod erase_regions;
22 pub mod no_landing_pads;
23 pub mod type_check;
24 pub mod add_call_guards;
25 pub mod promote_consts;
26 pub mod qualify_consts;
27 pub mod dump_mir;
28 pub mod deaggregator;
29 pub mod instcombine;
30 pub mod copy_prop;
31 pub mod inline;
32 pub mod interprocedural;
33
34 pub fn provide(providers: &mut Providers) {
35     self::qualify_consts::provide(providers);
36     *providers = Providers {
37         optimized_mir,
38         mir_suite,
39         mir_pass,
40         ..*providers
41     };
42 }
43
44 fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Mir<'tcx> {
45     let mir = tcx.mir_suite((MIR_OPTIMIZED, def_id)).steal();
46     tcx.alloc_mir(mir)
47 }
48
49 fn mir_suite<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
50                        (suite, def_id): (MirSuite, DefId))
51                        -> &'tcx Steal<Mir<'tcx>>
52 {
53     let passes = &tcx.mir_passes;
54     let len = passes.len_passes(suite);
55     assert!(len > 0, "no passes in {:?}", suite);
56     tcx.mir_pass((suite, MirPassIndex(len - 1), def_id))
57 }
58
59 fn mir_pass<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
60                       (suite, pass_num, def_id): (MirSuite, MirPassIndex, DefId))
61                       -> Multi<PassId, &'tcx Steal<Mir<'tcx>>>
62 {
63     let passes = &tcx.mir_passes;
64     let pass = passes.pass(suite, pass_num);
65     let mir_ctxt = MirCtxtImpl { tcx, pass_num, suite, def_id };
66
67     for hook in passes.hooks() {
68         hook.on_mir_pass(&mir_ctxt, None);
69     }
70
71     let mir = pass.run_pass(&mir_ctxt);
72
73     let key = &(suite, pass_num, def_id);
74     for hook in passes.hooks() {
75         for (&(_, _, k), v) in mir.iter(key) {
76             let v = &v.borrow();
77             hook.on_mir_pass(&mir_ctxt, Some((k, v)));
78         }
79     }
80
81     mir
82 }
83
84 struct MirCtxtImpl<'a, 'tcx: 'a> {
85     tcx: TyCtxt<'a, 'tcx, 'tcx>,
86     pass_num: MirPassIndex,
87     suite: MirSuite,
88     def_id: DefId
89 }
90
91 impl<'a, 'tcx> MirCtxt<'a, 'tcx> for MirCtxtImpl<'a, 'tcx> {
92     fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
93         self.tcx
94     }
95
96     fn suite(&self) -> MirSuite {
97         self.suite
98     }
99
100     fn pass_num(&self) -> MirPassIndex {
101         self.pass_num
102     }
103
104     fn def_id(&self) -> DefId {
105         self.def_id
106     }
107
108     fn source(&self) -> MirSource {
109         let id = self.tcx.hir.as_local_node_id(self.def_id)
110                              .expect("mir source requires local def-id");
111         MirSource::from_node(self.tcx, id)
112     }
113
114     fn read_previous_mir(&self) -> Ref<'tcx, Mir<'tcx>> {
115         self.previous_mir(self.def_id).borrow()
116     }
117
118     fn steal_previous_mir(&self) -> Mir<'tcx> {
119         self.previous_mir(self.def_id).steal()
120     }
121
122     fn read_previous_mir_of(&self, def_id: DefId) -> Ref<'tcx, Mir<'tcx>> {
123         self.previous_mir(def_id).borrow()
124     }
125
126     fn steal_previous_mir_of(&self, def_id: DefId) -> Mir<'tcx> {
127         self.previous_mir(def_id).steal()
128     }
129 }
130
131 impl<'a, 'tcx> MirCtxtImpl<'a, 'tcx> {
132     fn previous_mir(&self, def_id: DefId) -> &'tcx Steal<Mir<'tcx>> {
133         let MirSuite(suite) = self.suite;
134         let MirPassIndex(pass_num) = self.pass_num;
135         if pass_num > 0 {
136             self.tcx.mir_pass((MirSuite(suite), MirPassIndex(pass_num - 1), def_id))
137         } else if suite > 0 {
138             self.tcx.mir_suite((MirSuite(suite - 1), def_id))
139         } else {
140             self.tcx.mir_build(def_id)
141         }
142     }
143 }