Skip to content

Commit

Permalink
Add reaching definitions data-flow analysis
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinjoseph1995 committed Nov 17, 2024
1 parent d608d85 commit 304fde4
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 4 deletions.
1 change: 1 addition & 0 deletions dataflow_analysis/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ edition = "2021"
[dependencies]
clap = "4.5.20"
common = { version = "0.1.0", path = "../common" }
derivative = "2.2.0"

[dependencies.bril-rs]
version = "0.1.0"
Expand Down
122 changes: 118 additions & 4 deletions dataflow_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ use std::collections::HashSet;
use std::fmt::Display;
use std::hash::Hash;

use bril_rs::Program;
use bril_rs::{Argument, Program};
use clap::ValueEnum;
use common::cfg::{Cfg, NodeIndex};
use derivative::Derivative;

#[derive(ValueEnum, Clone, Debug, PartialEq, Copy)]
pub enum DataflowAnalyses {
LiveVariable,
ReachingDefinitions,
}

enum Direction {
Expand Down Expand Up @@ -88,7 +90,7 @@ trait Analysis<'a, ValueType: Clone + Hash + Eq + Display> {
.iter()
.map(|value| format!("{}", value))
.collect();
let out = format!(" out: {}", {
let out = format!("\\nout: {}", {
if formatted_values.is_empty() {
"∅".to_string()
} else {
Expand Down Expand Up @@ -126,6 +128,18 @@ trait Analysis<'a, ValueType: Clone + Hash + Eq + Display> {

struct LiveVariableAnalysis {}

#[derive(Derivative)]
#[derivative(Eq, PartialEq, Hash, Clone)]
struct Definition<'a> {
destination_variable: &'a str,
basic_block_index: usize,
instruction_index: usize,
arg_index: Option<usize>,
#[derivative(PartialEq = "ignore", Hash = "ignore")]
cfg: &'a Cfg,
}
struct ReachingDefinitions {}

impl<'a> Analysis<'a, &'a str> for LiveVariableAnalysis {
fn merge(
&self,
Expand Down Expand Up @@ -185,14 +199,114 @@ impl<'a> Analysis<'a, &'a str> for LiveVariableAnalysis {
}
}

impl std::fmt::Display for Definition<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.destination_variable)
}
}

impl<'a> Analysis<'a, Definition<'a>> for ReachingDefinitions {
fn merge(
&self,
accumulator: HashSet<Definition<'a>>,
new_value: &HashSet<Definition<'a>>,
) -> HashSet<Definition<'a>> {
accumulator.union(new_value).map(|a| a.clone()).collect()
}

fn transfer(
&self,
cfg: &'a Cfg,
index: NodeIndex,
input: &HashSet<Definition<'a>>,
) -> HashSet<Definition<'a>> {
let mut output = input.clone();
let basic_block = cfg.get_basic_block(index);
for (instruction_index, instruction) in basic_block.instruction_stream.iter().enumerate() {
match instruction {
bril_rs::Instruction::Constant {
dest,
op: _,
pos: _,
const_type: _,
value: _,
} => {
// Kill any previous definitions that were assigning to the same variable
output.retain(|def| def.destination_variable != dest.as_str());
// Insert the current definition
output.insert(Definition {
destination_variable: dest,
basic_block_index: index,
instruction_index,
arg_index: None,
cfg,
});
}
bril_rs::Instruction::Value {
args: _,
dest,
funcs: _,
labels: _,
op: _,
pos: _,
op_type: _,
} => {
// Kill any previous definitions that were assigning to the same variable
output.retain(|def| def.destination_variable != dest.as_str());
// Insert the current definition
output.insert(Definition {
destination_variable: dest,
basic_block_index: index,
instruction_index,
arg_index: None,
cfg,
});
}
bril_rs::Instruction::Effect {
args: _,
funcs: _,
labels: _,
op: _,
pos: _,
} => {}
}
}
return output;
}
}

fn create_set_of_definitions_from_function_arguments<'a>(
cfg: &'a Cfg,
function_arguments: &'a Vec<Argument>,
) -> HashSet<Definition<'a>> {
function_arguments
.iter()
.enumerate()
.map(|(index, arg)| Definition {
destination_variable: &arg.name,
basic_block_index: 0,
instruction_index: 0,
arg_index: Some(index),
cfg,
})
.collect()
}

pub fn run_analysis(dataflow_analysis_name: DataflowAnalyses, program: &Program) -> () {
program
.functions
.iter()
.map(|f| Cfg::new(f))
.for_each(|cfg| match dataflow_analysis_name {
.map(|f| (f, Cfg::new(f)))
.for_each(|(f, cfg)| match dataflow_analysis_name {
DataflowAnalyses::LiveVariable => {
LiveVariableAnalysis {}.run(&cfg, HashSet::new(), Direction::Backward);
}
DataflowAnalyses::ReachingDefinitions => {
ReachingDefinitions {}.run(
&cfg,
create_set_of_definitions_from_function_arguments(&cfg, &f.args),
Direction::Forward,
);
}
});
}

0 comments on commit 304fde4

Please sign in to comment.