]>
Commit | Line | Data |
---|---|---|
3157f602 XL |
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 std::cell::{Ref, RefCell}; | |
12 | use rustc_data_structures::indexed_vec::IndexVec; | |
13 | ||
c30ab7b3 | 14 | use mir::{Mir, BasicBlock}; |
3157f602 XL |
15 | |
16 | use rustc_serialize as serialize; | |
17 | ||
18 | #[derive(Clone, Debug)] | |
19 | pub struct Cache { | |
20 | predecessors: RefCell<Option<IndexVec<BasicBlock, Vec<BasicBlock>>>> | |
21 | } | |
22 | ||
23 | ||
24 | impl serialize::Encodable for Cache { | |
25 | fn encode<S: serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> { | |
26 | serialize::Encodable::encode(&(), s) | |
27 | } | |
28 | } | |
29 | ||
30 | impl serialize::Decodable for Cache { | |
31 | fn decode<D: serialize::Decoder>(d: &mut D) -> Result<Self, D::Error> { | |
32 | serialize::Decodable::decode(d).map(|_v: ()| Self::new()) | |
33 | } | |
34 | } | |
35 | ||
36 | ||
37 | impl Cache { | |
38 | pub fn new() -> Self { | |
39 | Cache { | |
40 | predecessors: RefCell::new(None) | |
41 | } | |
42 | } | |
43 | ||
44 | pub fn invalidate(&self) { | |
45 | // FIXME: consider being more fine-grained | |
46 | *self.predecessors.borrow_mut() = None; | |
47 | } | |
48 | ||
49 | pub fn predecessors(&self, mir: &Mir) -> Ref<IndexVec<BasicBlock, Vec<BasicBlock>>> { | |
50 | if self.predecessors.borrow().is_none() { | |
51 | *self.predecessors.borrow_mut() = Some(calculate_predecessors(mir)); | |
52 | } | |
53 | ||
54 | Ref::map(self.predecessors.borrow(), |p| p.as_ref().unwrap()) | |
55 | } | |
56 | } | |
57 | ||
58 | fn calculate_predecessors(mir: &Mir) -> IndexVec<BasicBlock, Vec<BasicBlock>> { | |
59 | let mut result = IndexVec::from_elem(vec![], mir.basic_blocks()); | |
60 | for (bb, data) in mir.basic_blocks().iter_enumerated() { | |
61 | if let Some(ref term) = data.terminator { | |
62 | for &tgt in term.successors().iter() { | |
63 | result[tgt].push(bb); | |
64 | } | |
65 | } | |
66 | } | |
67 | ||
68 | result | |
69 | } |