1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
use crate::jump::{self, ForeachTarget};
use alloc::vec::Vec;

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum BasicBlockInner<S, C, T> {
    Concrete {
        statements: Vec<S>,
        condjmp: Option<C>,
        next: jump::Unconditional<T>,
    },
    /// placeholder for linker references to other files
    Placeholder { is_extern: bool },
}

impl<S, C, T> Default for BasicBlockInner<S, C, T> {
    #[inline]
    fn default() -> Self {
        Self::Placeholder { is_extern: false }
    }
}

impl<S, C, T> BasicBlockInner<S, C, T> {
    #[inline]
    pub fn is_concrete(&self) -> bool {
        if let Self::Concrete { .. } = self {
            true
        } else {
            false
        }
    }

    #[inline]
    pub fn is_placeholder(&self) -> bool {
        if let Self::Placeholder { .. } = self {
            true
        } else {
            false
        }
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BasicBlock<S, C, T> {
    pub inner: BasicBlockInner<S, C, T>,
    pub is_public: bool,
}

impl<S, C, T> ForeachTarget for BasicBlockInner<S, C, T>
where
    S: ForeachTarget<JumpTarget = T>,
    C: ForeachTarget<JumpTarget = T>,
{
    type JumpTarget = T;

    fn foreach_target<F>(&self, mut f: F)
    where
        F: FnMut(&Self::JumpTarget),
    {
        if let BasicBlockInner::Concrete {
            statements,
            condjmp,
            next,
        } = self
        {
            statements.foreach_target(&mut f);
            condjmp.foreach_target(&mut f);
            next.foreach_target(f);
        }
    }

    fn foreach_target_mut<F>(&mut self, mut f: F)
    where
        F: FnMut(&mut Self::JumpTarget),
    {
        if let BasicBlockInner::Concrete {
            statements,
            condjmp,
            next,
        } = self
        {
            statements.foreach_target_mut(&mut f);
            condjmp.foreach_target_mut(&mut f);
            next.foreach_target_mut(f);
        }
    }
}

impl<S, C, T> ForeachTarget for BasicBlock<S, C, T>
where
    S: ForeachTarget<JumpTarget = T>,
    C: ForeachTarget<JumpTarget = T>,
{
    type JumpTarget = T;

    #[inline(always)]
    fn foreach_target<F>(&self, f: F)
    where
        F: FnMut(&Self::JumpTarget),
    {
        self.inner.foreach_target(f);
    }

    #[inline(always)]
    fn foreach_target_mut<F>(&mut self, f: F)
    where
        F: FnMut(&mut Self::JumpTarget),
    {
        self.inner.foreach_target_mut(f);
    }
}