-
Notifications
You must be signed in to change notification settings - Fork 242
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
656 additions
and
226 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,3 +7,4 @@ yarn.lock | |
.pytest_cache/ | ||
hypothesis_* | ||
__pycache__ | ||
.vscode |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
command = "bril2json < {filename} | cargo run --manifest-path ../../brilirs/Cargo.toml -- -p {args}" | ||
output.out = "-" | ||
output.prof = "2" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
TESTS := ../test/interp/*.bril \ | ||
../test/mem/*.bril \ | ||
../test/fail/*.bril \ | ||
../benchmarks/*.bril | ||
|
||
.PHONY: test | ||
test: | ||
turnt -c turnt_brilirs.toml $(TESTS) | ||
|
||
.PHONY: example | ||
example: | ||
bril2json < ../test/fail/double_free.bril | cargo run -- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,81 +1,97 @@ | ||
use std::collections::HashMap; | ||
|
||
// A program composed of basic blocks. | ||
// (BB index of main program, list of BBs, mapping of label -> BB index) | ||
pub type BBProgram = (Option<usize>, Vec<BasicBlock>, HashMap<String, usize>); | ||
|
||
pub type BBProgram = HashMap<String, BBFunction>; | ||
|
||
pub struct BBFunction { | ||
pub name: String, | ||
pub args: Vec<bril_rs::Argument>, | ||
pub return_type: Option<bril_rs::Type>, | ||
pub blocks: Vec<BasicBlock>, | ||
pub label_map: HashMap<String, usize>, | ||
} | ||
|
||
#[derive(Debug)] | ||
pub struct BasicBlock { | ||
pub instrs: Vec<bril_rs::Code>, | ||
pub label: Option<String>, | ||
pub instrs: Vec<bril_rs::Instruction>, | ||
pub exit: Vec<usize>, | ||
} | ||
|
||
impl BasicBlock { | ||
fn new() -> BasicBlock { | ||
BasicBlock { | ||
label: None, | ||
instrs: Vec::new(), | ||
exit: Vec::new(), | ||
} | ||
} | ||
} | ||
|
||
pub fn find_basic_blocks(prog: bril_rs::Program) -> BBProgram { | ||
let mut main_fn = None; | ||
fn find_basic_blocks(func: bril_rs::Function) -> BBFunction { | ||
let mut blocks = Vec::new(); | ||
let mut labels = HashMap::new(); | ||
let mut label_map = HashMap::new(); | ||
|
||
let mut bb_helper = |func: bril_rs::Function| -> usize { | ||
let mut curr_block = BasicBlock::new(); | ||
let root_block = blocks.len(); | ||
let mut curr_label = None; | ||
for instr in func.instrs.into_iter() { | ||
match instr { | ||
bril_rs::Code::Label { ref label } => { | ||
if !curr_block.instrs.is_empty() { | ||
blocks.push(curr_block); | ||
if let Some(old_label) = curr_label { | ||
labels.insert(old_label, blocks.len() - 1); | ||
} | ||
curr_block = BasicBlock::new(); | ||
let mut curr_block = BasicBlock::new(); | ||
for instr in func.instrs.into_iter() { | ||
match instr { | ||
bril_rs::Code::Label { ref label } => { | ||
if !curr_block.instrs.is_empty() { | ||
if let Some(old_label) = curr_block.label.as_ref() { | ||
label_map.insert(old_label.to_string(), blocks.len()); | ||
} | ||
curr_label = Some(label.clone()); | ||
} | ||
bril_rs::Code::Instruction(bril_rs::Instruction::Effect { op, .. }) | ||
if op == bril_rs::EffectOps::Jump | ||
|| op == bril_rs::EffectOps::Branch | ||
|| op == bril_rs::EffectOps::Return => | ||
{ | ||
curr_block.instrs.push(instr); | ||
blocks.push(curr_block); | ||
if let Some(l) = curr_label { | ||
labels.insert(l, blocks.len() - 1); | ||
curr_label = None; | ||
} | ||
curr_block = BasicBlock::new(); | ||
} | ||
_ => { | ||
curr_block.instrs.push(instr); | ||
curr_block.label = Some(label.clone()); | ||
} | ||
bril_rs::Code::Instruction(bril_rs::Instruction::Effect { | ||
op, | ||
args, | ||
funcs, | ||
labels, | ||
}) if op == bril_rs::EffectOps::Jump | ||
|| op == bril_rs::EffectOps::Branch | ||
|| op == bril_rs::EffectOps::Return => | ||
{ | ||
curr_block.instrs.push(bril_rs::Instruction::Effect { | ||
op, | ||
args, | ||
funcs, | ||
labels, | ||
}); | ||
if let Some(l) = curr_block.label.as_ref() { | ||
label_map.insert(l.to_string(), blocks.len()); | ||
} | ||
blocks.push(curr_block); | ||
curr_block = BasicBlock::new(); | ||
} | ||
} | ||
|
||
if !curr_block.instrs.is_empty() { | ||
blocks.push(curr_block); | ||
if let Some(l) = curr_label { | ||
labels.insert(l, blocks.len() - 1); | ||
bril_rs::Code::Instruction(code) => { | ||
curr_block.instrs.push(code); | ||
} | ||
} | ||
} | ||
|
||
root_block | ||
}; | ||
|
||
for func in prog.functions.into_iter() { | ||
let func_name = func.name.clone(); | ||
let func_block = bb_helper(func); | ||
if func_name == "main" { | ||
main_fn = Some(func_block); | ||
if !curr_block.instrs.is_empty() { | ||
if let Some(l) = curr_block.label.as_ref() { | ||
label_map.insert(l.to_string(), blocks.len()); | ||
} | ||
blocks.push(curr_block); | ||
} | ||
|
||
(main_fn, blocks, labels) | ||
BBFunction { | ||
name: func.name, | ||
args: func.args, | ||
return_type: func.return_type, | ||
blocks, | ||
label_map, | ||
} | ||
} | ||
|
||
pub fn to_bbprogram(prog: bril_rs::Program) -> BBProgram { | ||
prog | ||
.functions | ||
.into_iter() | ||
.map(|func| (func.name.clone(), find_basic_blocks(func))) | ||
.collect() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,34 +1,28 @@ | ||
use crate::basic_block::BasicBlock; | ||
use crate::basic_block::{BBFunction, BBProgram}; | ||
|
||
use std::collections::HashMap; | ||
|
||
type CFG = Vec<BasicBlock>; | ||
|
||
pub fn build_cfg(mut blocks: Vec<BasicBlock>, label_to_block_idx: &HashMap<String, usize>) -> CFG { | ||
let last_idx = blocks.len() - 1; | ||
for (i, block) in blocks.iter_mut().enumerate() { | ||
fn build_cfg_func(func: &mut BBFunction) { | ||
let last_idx = func.blocks.len() - 1; | ||
for (i, block) in func.blocks.iter_mut().enumerate() { | ||
// If we're before the last block | ||
if i < last_idx { | ||
// Get the last instruction | ||
let last_instr: &bril_rs::Code = block.instrs.last().unwrap(); | ||
if let bril_rs::Code::Instruction(bril_rs::Instruction::Effect { op, labels, .. }) = | ||
last_instr | ||
{ | ||
if let Some(bril_rs::Instruction::Effect { op, labels, .. }) = block.instrs.last() { | ||
match op { | ||
bril_rs::EffectOps::Jump | bril_rs::EffectOps::Branch => { | ||
for l in labels { | ||
block.exit.push(label_to_block_idx[l]); | ||
block.exit.push(func.label_map[l]); | ||
} | ||
} | ||
bril_rs::EffectOps::Return => {} | ||
// TODO(yati): Do all effect ops end a BB? | ||
_ => {} | ||
} | ||
} else { | ||
block.exit.push(i + 1); | ||
} | ||
} | ||
} | ||
} | ||
|
||
blocks | ||
pub fn build_cfg(prog: &mut BBProgram) { | ||
prog.iter_mut().for_each(|(_, func)| build_cfg_func(func)) | ||
} |
Oops, something went wrong.