]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/transform/interprocedural.rs
convert the `inline` pass to use the new multi result
[rust.git] / src / librustc_mir / transform / interprocedural.rs
1 // Copyright 2016 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, PassId};
14 use rustc::ty::steal::Steal;
15 use rustc::ty::TyCtxt;
16 use rustc_data_structures::fx::FxHashMap;
17
18 /// When writing inter-procedural analyses etc, we need to read (and
19 /// steal) the MIR for a number of def-ids at once, not all of which
20 /// are local. This little cache code attempts to remember what you've
21 /// stolen and so forth. It is more of a placeholder meant to get
22 /// inlining up and going again, and is probably going to need heavy
23 /// revision as we scale up to more interesting optimizations.
24 pub struct InterproceduralCx<'a, 'mir: 'a, 'tcx: 'mir> {
25     pub tcx: TyCtxt<'mir, 'tcx, 'tcx>,
26     pub mir_cx: &'a MirCtxt<'mir, 'tcx>,
27     local_cache: FxHashMap<DefId, Mir<'tcx>>,
28 }
29
30 impl<'a, 'mir, 'tcx> InterproceduralCx<'a, 'mir, 'tcx> {
31     pub fn new(mir_cx: &'a MirCtxt<'mir, 'tcx>) -> Self {
32         InterproceduralCx {
33             mir_cx,
34             tcx: mir_cx.tcx(),
35             local_cache: FxHashMap::default(),
36         }
37     }
38
39     pub fn into_local_mirs(self) -> Vec<(PassId, &'tcx Steal<Mir<'tcx>>)> {
40         let tcx = self.tcx;
41         let suite = self.mir_cx.suite();
42         let pass_num = self.mir_cx.pass_num();
43         self.local_cache.into_iter()
44                         .map(|(def_id, mir)| {
45                             let mir = tcx.alloc_steal_mir(mir);
46                             ((suite, pass_num, def_id), mir)
47                         })
48                         .collect()
49     }
50
51     /// Ensures that the mir for `def_id` is available, if it can be
52     /// made available.
53     pub fn ensure_mir(&mut self, def_id: DefId) {
54         if def_id.is_local() {
55             self.ensure_mir_and_read(def_id);
56         }
57     }
58
59     /// Ensures that the mir for `def_id` is available and returns it if possible;
60     /// returns `None` if this is a cross-crate MIR that is not
61     /// available from metadata.
62     pub fn ensure_mir_and_read(&mut self, def_id: DefId) -> Option<&Mir<'tcx>> {
63         if def_id.is_local() {
64             Some(self.mir_mut(def_id))
65         } else {
66             self.tcx.maybe_item_mir(def_id)
67         }
68     }
69
70     /// True if the local cache contains MIR for `def-id`.
71     pub fn contains_mir(&self, def_id: DefId) -> bool {
72         if def_id.is_local() {
73             self.local_cache.contains_key(&def_id)
74         } else {
75             self.tcx.is_item_mir_available(def_id)
76         }
77     }
78
79     /// Reads the MIR for `def-id`. If the MIR is local, this will
80     /// panic if you have not previously invoked `ensure_mir`.
81     pub fn mir(&self, def_id: DefId) -> Option<&Mir<'tcx>> {
82         if def_id.is_local() {
83             match self.local_cache.get(&def_id) {
84                 Some(p) => Some(p),
85                 None => {
86                     panic!("MIR for local def-id `{:?}` not previously ensured", def_id)
87                 }
88             }
89         } else {
90             self.tcx.maybe_item_mir(def_id)
91         }
92     }
93
94     pub fn mir_mut(&mut self, def_id: DefId) -> &mut Mir<'tcx> {
95         assert!(def_id.is_local(), "cannot get mutable mir of remote entry");
96         let mir_cx = self.mir_cx;
97         self.local_cache.entry(def_id)
98                         .or_insert_with(|| mir_cx.steal_previous_mir_of(def_id))
99     }
100 }