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
! {