Skip to content

Commit a9ab0e3

Browse files
committed
brilirs: Add call support
This is a simple recursive implementation of the `call` operation (both in the value and effect contexts). I originally tried an iterative version, but the borrow checker gave me a tough fight. This is much more readable than tracking a stack of function call environments directly anyway.
1 parent 7896a09 commit a9ab0e3

File tree

7 files changed

+345
-89
lines changed

7 files changed

+345
-89
lines changed

brilirs/src/basic_block.rs

Lines changed: 69 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,61 @@
11
use std::collections::HashMap;
22

3-
// A program composed of basic blocks.
4-
// (BB index of main program, list of BBs, mapping of label -> BB index)
5-
pub type BBProgram = (Option<usize>, Vec<BasicBlock>, HashMap<String, usize>);
6-
7-
#[derive(Debug)]
8-
pub struct BasicBlock {
9-
pub instrs: Vec<bril_rs::Code>,
10-
pub exit: Vec<usize>,
3+
pub struct FuncInfo {
4+
pub args: Vec<bril_rs::Argument>,
5+
pub return_type: Option<bril_rs::Type>,
6+
pub start_block: usize,
117
}
128

13-
impl BasicBlock {
14-
fn new() -> BasicBlock {
15-
BasicBlock {
16-
instrs: Vec::new(),
17-
exit: Vec::new(),
9+
impl FuncInfo {
10+
fn new(f: &bril_rs::Function, start_block: usize) -> FuncInfo {
11+
FuncInfo {
12+
args: f.args.clone(),
13+
return_type: f.return_type.clone(),
14+
start_block: start_block,
1815
}
1916
}
2017
}
2118

22-
pub fn find_basic_blocks(prog: bril_rs::Program) -> BBProgram {
23-
let mut main_fn = None;
24-
let mut blocks = Vec::new();
25-
let mut labels = HashMap::new();
19+
// A program represented as basic blocks.
20+
pub struct BBProgram {
21+
pub blocks: Vec<BasicBlock>,
22+
23+
// Map from label name to index in `blocks` of the block named by that label.
24+
pub label_index: HashMap<String, usize>,
25+
26+
// Map from function name to information needed during runtime about the
27+
// function.
28+
pub func_index: HashMap<String, FuncInfo>,
29+
}
30+
31+
impl BBProgram {
32+
pub fn new(prog: bril_rs::Program) -> BBProgram {
33+
let mut bbprog = BBProgram {
34+
blocks: vec![],
35+
label_index: HashMap::new(),
36+
func_index: HashMap::new(),
37+
};
38+
for func in prog.functions {
39+
bbprog.add_func_bbs(func);
40+
}
41+
bbprog
42+
}
2643

27-
let mut bb_helper = |func: bril_rs::Function| -> usize {
44+
fn add_func_bbs(&mut self, func: bril_rs::Function) -> usize {
45+
self
46+
.func_index
47+
.insert(func.name.clone(), FuncInfo::new(&func, self.blocks.len()));
2848
let mut curr_block = BasicBlock::new();
29-
let root_block = blocks.len();
49+
let root_block = self.blocks.len();
3050
let mut curr_label = None;
51+
3152
for instr in func.instrs.into_iter() {
3253
match instr {
3354
bril_rs::Code::Label { ref label } => {
3455
if !curr_block.instrs.is_empty() {
35-
blocks.push(curr_block);
56+
self.blocks.push(curr_block);
3657
if let Some(old_label) = curr_label {
37-
labels.insert(old_label, blocks.len() - 1);
58+
self.label_index.insert(old_label, self.blocks.len() - 1);
3859
}
3960
curr_block = BasicBlock::new();
4061
}
@@ -46,9 +67,9 @@ pub fn find_basic_blocks(prog: bril_rs::Program) -> BBProgram {
4667
|| op == bril_rs::EffectOps::Return =>
4768
{
4869
curr_block.instrs.push(instr);
49-
blocks.push(curr_block);
70+
self.blocks.push(curr_block);
5071
if let Some(l) = curr_label {
51-
labels.insert(l, blocks.len() - 1);
72+
self.label_index.insert(l, self.blocks.len() - 1);
5273
curr_label = None;
5374
}
5475
curr_block = BasicBlock::new();
@@ -60,22 +81,36 @@ pub fn find_basic_blocks(prog: bril_rs::Program) -> BBProgram {
6081
}
6182

6283
if !curr_block.instrs.is_empty() {
63-
blocks.push(curr_block);
84+
// If we are here, the function ends without an explicit ret. To make
85+
// processing easier, push a Return op onto the last block.
86+
curr_block.instrs.push(RET.clone());
87+
self.blocks.push(curr_block);
6488
if let Some(l) = curr_label {
65-
labels.insert(l, blocks.len() - 1);
89+
self.label_index.insert(l, self.blocks.len() - 1);
6690
}
6791
}
68-
6992
root_block
70-
};
93+
}
94+
}
95+
96+
#[derive(Debug)]
97+
pub struct BasicBlock {
98+
pub instrs: Vec<bril_rs::Code>,
99+
pub exit: Vec<usize>,
100+
}
71101

72-
for func in prog.functions.into_iter() {
73-
let func_name = func.name.clone();
74-
let func_block = bb_helper(func);
75-
if func_name == "main" {
76-
main_fn = Some(func_block);
102+
impl BasicBlock {
103+
fn new() -> BasicBlock {
104+
BasicBlock {
105+
instrs: Vec::new(),
106+
exit: Vec::new(),
77107
}
78108
}
79-
80-
(main_fn, blocks, labels)
81109
}
110+
111+
const RET: bril_rs::Code = bril_rs::Code::Instruction(bril_rs::Instruction::Effect {
112+
op: bril_rs::EffectOps::Return,
113+
args: vec![],
114+
funcs: vec![],
115+
labels: vec![],
116+
});

brilirs/src/cfg.rs

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,23 @@
1-
use crate::basic_block::BasicBlock;
1+
use crate::basic_block::BBProgram;
22

3-
use std::collections::HashMap;
4-
5-
type CFG = Vec<BasicBlock>;
6-
7-
pub fn build_cfg(mut blocks: Vec<BasicBlock>, label_to_block_idx: &HashMap<String, usize>) -> CFG {
8-
let last_idx = blocks.len() - 1;
9-
for (i, block) in blocks.iter_mut().enumerate() {
3+
pub fn build_cfg(prog: &mut BBProgram) {
4+
let last_idx = prog.blocks.len() - 1;
5+
for (i, block) in prog.blocks.iter_mut().enumerate() {
106
// If we're before the last block
117
if i < last_idx {
128
// Get the last instruction
139
let last_instr: &bril_rs::Code = block.instrs.last().unwrap();
1410
if let bril_rs::Code::Instruction(bril_rs::Instruction::Effect { op, labels, .. }) =
1511
last_instr
1612
{
17-
match op {
18-
bril_rs::EffectOps::Jump | bril_rs::EffectOps::Branch => {
19-
for l in labels {
20-
block.exit.push(label_to_block_idx[l]);
21-
}
13+
if let bril_rs::EffectOps::Jump | bril_rs::EffectOps::Branch = op {
14+
for l in labels {
15+
block.exit.push(prog.label_index[l]);
2216
}
23-
bril_rs::EffectOps::Return => {}
24-
// TODO(yati): Do all effect ops end a BB?
25-
_ => {}
2617
}
2718
} else {
2819
block.exit.push(i + 1);
2920
}
3021
}
3122
}
32-
33-
blocks
3423
}

0 commit comments

Comments
 (0)