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.
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.
11 use rustc::hir::def_id::DefId;
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;
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>>,
30 impl<'a, 'mir, 'tcx> InterproceduralCx<'a, 'mir, 'tcx> {
31 pub fn new(mir_cx: &'a MirCtxt<'mir, 'tcx>) -> Self {
35 local_cache: FxHashMap::default(),
39 pub fn into_local_mirs(self) -> Vec<(PassId, &'tcx Steal<Mir<'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)
51 /// Ensures that the mir for `def_id` is available, if it can be
53 pub fn ensure_mir(&mut self, def_id: DefId) {
54 if def_id.is_local() {
55 self.ensure_mir_and_read(def_id);
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))
66 self.tcx.maybe_item_mir(def_id)
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)
75 self.tcx.is_item_mir_available(def_id)
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) {
86 panic!("MIR for local def-id `{:?}` not previously ensured", def_id)
90 self.tcx.maybe_item_mir(def_id)
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))