1use crate::context::InstrId;
4
5#[derive(Clone, Debug)]
11pub struct BasicBlock {
12 pub name: String,
14 pub body: Vec<InstrId>,
16 pub terminator: Option<InstrId>,
18}
19
20impl BasicBlock {
21 pub fn new(name: impl Into<String>) -> Self {
23 BasicBlock {
24 name: name.into(),
25 body: Vec::new(),
26 terminator: None,
27 }
28 }
29
30 pub fn append_instr(&mut self, id: InstrId) {
32 self.body.push(id);
33 }
34
35 pub fn set_terminator(&mut self, id: InstrId) {
37 self.terminator = Some(id);
38 }
39
40 pub fn is_complete(&self) -> bool {
42 self.terminator.is_some()
43 }
44
45 pub fn instrs(&self) -> impl Iterator<Item = InstrId> + '_ {
47 self.body.iter().copied().chain(self.terminator.into_iter())
48 }
49
50 pub fn len(&self) -> usize {
52 self.body.len() + if self.terminator.is_some() { 1 } else { 0 }
53 }
54
55 pub fn is_empty(&self) -> bool {
57 self.len() == 0
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 #[test]
66 fn basic_block_new() {
67 let bb = BasicBlock::new("entry");
68 assert_eq!(bb.name, "entry");
69 assert!(bb.body.is_empty());
70 assert!(bb.terminator.is_none());
71 assert!(!bb.is_complete());
72 }
73
74 #[test]
75 fn append_and_terminate() {
76 let mut bb = BasicBlock::new("bb0");
77 bb.append_instr(InstrId(0));
78 bb.append_instr(InstrId(1));
79 bb.set_terminator(InstrId(2));
80 assert!(bb.is_complete());
81 assert_eq!(bb.len(), 3);
82 let ids: Vec<_> = bb.instrs().collect();
83 assert_eq!(ids, vec![InstrId(0), InstrId(1), InstrId(2)]);
84 }
85}