llvm_scratch/core/basic_block/
basic_block.rs

1use std::fmt;
2use std::fmt::Formatter;
3
4use id_arena::{Arena, Id};
5
6use crate::core;
7
8pub type BasicBlockId = Id<BasicBlock>;
9
10/// An representation of LLVMBasicBlock.
11/// LLVMBasicBlock を表す構造体
12pub struct BasicBlock {
13    label: core::llvm_string::LLVMString,
14    pub predecessor: Option<BasicBlockId>,
15    pub kind: BasicBlockKind,
16
17    instructions: Vec<core::instruction::InstructionId>,
18    inst_allocator: Arena<core::instruction::Instruction>,
19}
20
21impl fmt::Display for BasicBlock {
22    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
23        if !self.label.is_empty() {
24            writeln!(f, "{}:", self.label)?;
25        }
26
27        for inst_id in self.instructions.iter() {
28            let inst = self.inst_allocator.get(*inst_id).unwrap();
29
30            writeln!(f, "  {}", inst)?;
31        }
32        Ok(())
33    }
34}
35
36#[allow(dead_code)]
37impl BasicBlock {
38    pub fn new(
39        l: core::llvm_string::LLVMString,
40        pred: Option<BasicBlockId>,
41        k: BasicBlockKind,
42    ) -> Self {
43        Self {
44            label: l,
45            predecessor: pred,
46            kind: k,
47            instructions: Vec::new(),
48            inst_allocator: Arena::new(),
49        }
50    }
51
52    pub fn print_successors(
53        &self,
54        f: &mut Formatter<'_>,
55        allocator: &Arena<core::basic_block::BasicBlock>,
56    ) -> fmt::Result {
57        match self.kind {
58            BasicBlockKind::TERMINATED => {}
59            BasicBlockKind::UNCONDITIONAL(succ_id) => {
60                let succ_bb = allocator.get(succ_id).unwrap();
61                write!(f, "{}", succ_bb)?;
62            }
63        }
64
65        Ok(())
66    }
67
68    /// get a reference of the bb's label
69    pub fn get_label_ref(&self) -> &core::llvm_string::LLVMString {
70        &self.label
71    }
72
73    /// whether the bb's instructions aren't there or not.
74    pub fn insts_empty(&self) -> bool {
75        self.instructions.is_empty()
76    }
77
78    pub fn new_inst(
79        &mut self,
80        inst: core::instruction::Instruction,
81    ) -> core::instruction::InstructionId {
82        let inst_id = self.inst_allocator.alloc(inst);
83        self.instructions.push(inst_id);
84
85        inst_id
86    }
87}
88
89impl Default for BasicBlock {
90    fn default() -> Self {
91        Self {
92            label: core::llvm_string::LLVMString::from(String::new()),
93            predecessor: None,
94            kind: BasicBlockKind::TERMINATED,
95            instructions: Vec::new(),
96            inst_allocator: Arena::new(),
97        }
98    }
99}
100
101/// a basic block may have one or more successors.
102/// BasicBlock が持つ後続節の定義
103#[derive(Eq, PartialEq, PartialOrd, Ord, Hash)]
104pub enum BasicBlockKind {
105    /// 後続節が存在しない場合
106    /// TERMINATED can be used at end of the function.
107    TERMINATED,
108
109    /// UNCONDITIONAL can be used at start of while-statement, goto, etc.
110    UNCONDITIONAL(BasicBlockId),
111}