1 //! Lazily compute the inverse of each `SwitchInt`'s switch targets. Modeled after
2 //! `Predecessors`/`PredecessorCache`.
4 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
5 use rustc_data_structures::sync::OnceCell;
6 use rustc_index::vec::IndexVec;
7 use rustc_serialize as serialize;
8 use smallvec::SmallVec;
10 use crate::mir::{BasicBlock, BasicBlockData, Terminator, TerminatorKind};
12 pub type SwitchSources = IndexVec<BasicBlock, IndexVec<BasicBlock, SmallVec<[Option<u128>; 1]>>>;
14 #[derive(Clone, Debug)]
15 pub(super) struct SwitchSourceCache {
16 cache: OnceCell<SwitchSources>,
19 impl SwitchSourceCache {
21 pub(super) fn new() -> Self {
22 SwitchSourceCache { cache: OnceCell::new() }
25 /// Invalidates the switch source cache.
27 pub(super) fn invalidate(&mut self) {
28 self.cache = OnceCell::new();
31 /// Returns the switch sources for this MIR.
33 pub(super) fn compute(
35 basic_blocks: &IndexVec<BasicBlock, BasicBlockData<'_>>,
37 self.cache.get_or_init(|| {
38 let mut switch_sources = IndexVec::from_elem(
39 IndexVec::from_elem(SmallVec::new(), basic_blocks),
42 for (bb, data) in basic_blocks.iter_enumerated() {
43 if let Some(Terminator {
44 kind: TerminatorKind::SwitchInt { targets, .. }, ..
47 for (value, target) in targets.iter() {
48 switch_sources[target][bb].push(Some(value));
50 switch_sources[targets.otherwise()][bb].push(None);
59 impl<S: serialize::Encoder> serialize::Encodable<S> for SwitchSourceCache {
61 fn encode(&self, s: &mut S) -> Result<(), S::Error> {
66 impl<D: serialize::Decoder> serialize::Decodable<D> for SwitchSourceCache {
68 fn decode(_: &mut D) -> Self {
73 impl<CTX> HashStable<CTX> for SwitchSourceCache {
75 fn hash_stable(&self, _: &mut CTX, _: &mut StableHasher) {
80 TrivialTypeFoldableAndLiftImpls! {