Skip to content

Commit

Permalink
Everything but spec and benchmarks
Browse files Browse the repository at this point in the history
  • Loading branch information
Pat-Lafon committed Jan 4, 2021
1 parent 5142a2b commit ca0a217
Show file tree
Hide file tree
Showing 12 changed files with 636 additions and 346 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ yarn.lock
.pytest_cache/
hypothesis_*
__pycache__
.vscode
3 changes: 3 additions & 0 deletions benchmarks/turnt_brilirs.toml
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"
2 changes: 1 addition & 1 deletion bril-rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ pub enum Literal {

impl Literal {
pub fn get_type(&self) -> Type {
match *self {
match self {
Literal::Int(_) => Type::Int,
Literal::Bool(_) => Type::Bool,
#[cfg(feature = "float")]
Expand Down
12 changes: 12 additions & 0 deletions brilirs/Makefile
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/interp/call-with-args.bril | cargo run --
203 changes: 104 additions & 99 deletions brilirs/src/basic_block.rs
Original file line number Diff line number Diff line change
@@ -1,136 +1,141 @@
use bril_rs::{Function, Program};
use std::collections::HashMap;

pub struct Function {
// A program represented as basic blocks.
pub struct BBProgram {
pub func_index: HashMap<String, BBFunction>,
}

impl BBProgram {
pub fn new(prog: Program) -> BBProgram {
BBProgram {
func_index: prog
.functions
.into_iter()
.map(|func| (func.name.clone(), BBFunction::new(func)))
.collect(),
}
}

pub fn get(&self, func_name: &str) -> Option<&BBFunction> {
self.func_index.get(func_name)
}
}

#[derive(Debug)]
pub struct BasicBlock {
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 struct BBFunction {
pub name: String,
pub args: Vec<bril_rs::Argument>,
pub return_type: Option<bril_rs::Type>,
pub blocks: Vec<BasicBlock>,

// Map from label to the index of the block that is the target of the label.
pub label_index: HashMap<String, usize>,
pub label_map: HashMap<String, usize>,
}

impl Function {
pub fn new(f: bril_rs::Function) -> Function {
let mut func = Function {
args: f.args.clone(),
return_type: f.return_type.clone(),
blocks: vec![],
label_index: HashMap::new(),
};
func.add_blocks(f.instrs);
impl BBFunction {
pub fn new(f: Function) -> BBFunction {
let mut func = BBFunction::find_basic_blocks(f);
func.build_cfg();
func
}

fn build_cfg(&mut self) {
let last_idx = self.blocks.len() - 1;
for (i, block) in self.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 bril_rs::EffectOps::Jump | bril_rs::EffectOps::Branch = op {
for l in labels {
block.exit.push(
*self
.label_index
.get(l)
.expect(&format!("No label {} found.", &l)),
);
}
}
} else {
block.exit.push(i + 1);
}
}
}
}
fn find_basic_blocks(func: bril_rs::Function) -> BBFunction {
let mut blocks = Vec::new();
let mut label_map = HashMap::new();

fn add_blocks(&mut self, instrs: Vec<bril_rs::Code>) {
let mut curr_block = BasicBlock::new();
let mut curr_label = None;
for instr in instrs {
for instr in func.instrs.into_iter() {
match instr {
bril_rs::Code::Label { ref label } => {
if !curr_block.instrs.is_empty() {
self.blocks.push(curr_block);
if let Some(old_label) = curr_label {
self.label_index.insert(old_label, self.blocks.len() - 1);
if let Some(old_label) = curr_block.label.as_ref() {
label_map.insert(old_label.to_string(), blocks.len());
}
blocks.push(curr_block);
curr_block = BasicBlock::new();
}
curr_label = Some(label.clone());
curr_block.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 =>
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(instr);
self.blocks.push(curr_block);
if let Some(l) = curr_label {
self.label_index.insert(l, self.blocks.len() - 1);
curr_label = None;
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();
}
_ => {
curr_block.instrs.push(instr);
bril_rs::Code::Instruction(code) => {
curr_block.instrs.push(code);
}
}
}

if !curr_block.instrs.is_empty() {
// If we are here, the function ends without an explicit ret. To make
// processing easier, push a Return op onto the last block.
curr_block.instrs.push(RET.clone());
self.blocks.push(curr_block);
if let Some(l) = curr_label {
self.label_index.insert(l, self.blocks.len() - 1);
if let Some(l) = curr_block.label.as_ref() {
label_map.insert(l.to_string(), blocks.len());
}
blocks.push(curr_block);
}
}
}

// A program represented as basic blocks.
pub struct BBProgram {
pub func_index: HashMap<String, Function>,
}

impl BBProgram {
pub fn new(prog: bril_rs::Program) -> BBProgram {
let mut bbprog = BBProgram {
func_index: HashMap::new(),
};
for func in prog.functions {
bbprog
.func_index
.insert(func.name.clone(), Function::new(func));
BBFunction {
name: func.name,
args: func.args,
return_type: func.return_type,
blocks,
label_map,
}
bbprog
}
}

#[derive(Debug)]
pub struct BasicBlock {
pub instrs: Vec<bril_rs::Code>,
pub exit: Vec<usize>,
}

impl BasicBlock {
fn new() -> BasicBlock {
BasicBlock {
instrs: Vec::new(),
exit: Vec::new(),
fn build_cfg(&mut self) {
let last_idx = self.blocks.len() - 1;
for (i, block) in self.blocks.iter_mut().enumerate() {
// If we're before the last block
if i < last_idx {
// Get the last instruction
if let Some(bril_rs::Instruction::Effect { op, labels, .. }) = block.instrs.last().cloned()
{
if let bril_rs::EffectOps::Jump | bril_rs::EffectOps::Branch = op {
for l in labels {
block.exit.push(
*self
.label_map
.get(&l)
.unwrap_or_else(|| panic!("No label {} found.", &l)),
);
}
}
} else {
block.exit.push(i + 1);
}
}
}
}
}

const RET: bril_rs::Code = bril_rs::Code::Instruction(bril_rs::Instruction::Effect {
op: bril_rs::EffectOps::Return,
args: vec![],
funcs: vec![],
labels: vec![],
});
Loading

0 comments on commit ca0a217

Please sign in to comment.