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
111
use std::fmt;
use std::fmt::Formatter;

use id_arena::{Arena, Id};

use crate::core;

pub type BasicBlockId = Id<BasicBlock>;

/// An representation of LLVMBasicBlock.
/// LLVMBasicBlock を表す構造体
pub struct BasicBlock {
    label: core::llvm_string::LLVMString,
    pub predecessor: Option<BasicBlockId>,
    pub kind: BasicBlockKind,

    instructions: Vec<core::instruction::InstructionId>,
    inst_allocator: Arena<core::instruction::Instruction>,
}

impl fmt::Display for BasicBlock {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        if !self.label.is_empty() {
            writeln!(f, "{}:", self.label)?;
        }

        for inst_id in self.instructions.iter() {
            let inst = self.inst_allocator.get(*inst_id).unwrap();

            writeln!(f, "  {}", inst)?;
        }
        Ok(())
    }
}

#[allow(dead_code)]
impl BasicBlock {
    pub fn new(
        l: core::llvm_string::LLVMString,
        pred: Option<BasicBlockId>,
        k: BasicBlockKind,
    ) -> Self {
        Self {
            label: l,
            predecessor: pred,
            kind: k,
            instructions: Vec::new(),
            inst_allocator: Arena::new(),
        }
    }

    pub fn print_successors(
        &self,
        f: &mut Formatter<'_>,
        allocator: &Arena<core::basic_block::BasicBlock>,
    ) -> fmt::Result {
        match self.kind {
            BasicBlockKind::TERMINATED => {}
            BasicBlockKind::UNCONDITIONAL(succ_id) => {
                let succ_bb = allocator.get(succ_id).unwrap();
                write!(f, "{}", succ_bb)?;
            }
        }

        Ok(())
    }

    /// get a reference of the bb's label
    pub fn get_label_ref(&self) -> &core::llvm_string::LLVMString {
        &self.label
    }

    /// whether the bb's instructions aren't there or not.
    pub fn insts_empty(&self) -> bool {
        self.instructions.is_empty()
    }

    pub fn new_inst(
        &mut self,
        inst: core::instruction::Instruction,
    ) -> core::instruction::InstructionId {
        let inst_id = self.inst_allocator.alloc(inst);
        self.instructions.push(inst_id);

        inst_id
    }
}

impl Default for BasicBlock {
    fn default() -> Self {
        Self {
            label: core::llvm_string::LLVMString::from(String::new()),
            predecessor: None,
            kind: BasicBlockKind::TERMINATED,
            instructions: Vec::new(),
            inst_allocator: Arena::new(),
        }
    }
}

/// a basic block may have one or more successors.
/// BasicBlock が持つ後続節の定義
#[derive(Eq, PartialEq, PartialOrd, Ord, Hash)]
pub enum BasicBlockKind {
    /// 後続節が存在しない場合
    /// TERMINATED can be used at end of the function.
    TERMINATED,

    /// UNCONDITIONAL can be used at start of while-statement, goto, etc.
    UNCONDITIONAL(BasicBlockId),
}