Skip to content

Commit

Permalink
feat(dataflow): Untested reaching definitions analysis
Browse files Browse the repository at this point in the history
  • Loading branch information
ethanuppal committed Feb 13, 2025
1 parent 985e65e commit 9fda4eb
Show file tree
Hide file tree
Showing 8 changed files with 351 additions and 9 deletions.
19 changes: 19 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[workspace]
resolver = "2"
members = ["lesson2/build-cfg", "lesson3/lvn", "lesson3/tdce"]
members = ["lesson2/build-cfg", "lesson3/lvn", "lesson3/tdce", "lesson4/bril-util", "lesson4/dataflow"]

[workspace.package]
version = "0.1.0"
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,5 @@ test_equivalence:
${EQUIV_FLAGS}

# https://stackoverflow.com/questions/8889035/how-to-document-a-makefile
help: ## Shows this help.
help: ## Shows this help
@sed -ne '/@sed/!s/## //p' ${MAKEFILE_LIST}
73 changes: 66 additions & 7 deletions lesson2/build-cfg/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,44 @@ pub struct FunctionSignature {
#[derive(Default)]
pub struct FunctionCfg {
pub signature: FunctionSignature,
pub entry: BasicBlockIdx,
pub vertices: SlotMap<BasicBlockIdx, BasicBlock>,
pub edges: SecondaryMap<BasicBlockIdx, Exit>,
rev_edges: SecondaryMap<BasicBlockIdx, Vec<BasicBlockIdx>>,
}

impl FunctionCfg {
pub fn successors(&self, block: BasicBlockIdx) -> Vec<BasicBlockIdx> {
match &self.edges[block] {
Exit::Fallthrough(destination_idx) => {
destination_idx.iter().copied().collect()
}
Exit::Unconditional(destination_idx) => vec![*destination_idx],
Exit::Conditional {
condition: _,
if_true,
if_false,
} => vec![*if_true, *if_false],
Exit::Return(_) => vec![],
}
}

pub fn predecessors(&self, block: BasicBlockIdx) -> &[BasicBlockIdx] {
self.rev_edges
.get(block)
.map_or(&[] as &[BasicBlockIdx], |edges| edges.as_slice())
}
}

struct FunctionCfgBuilder {
cfg: FunctionCfg,
/// Whether the entry point to the CFG has been initialized (in
/// `cfg.entry`).
entry_is_init: bool,
current_block: BasicBlock,
labels_to_blocks: HashMap<String, BasicBlockIdx>,
previous_idx: Option<BasicBlockIdx>,
successors: HashMap<BasicBlockIdx, BasicBlockIdx>,
input_block_order: SecondaryMap<BasicBlockIdx, BasicBlockIdx>,
}

impl FunctionCfgBuilder {
Expand All @@ -102,10 +130,11 @@ impl FunctionCfgBuilder {
},
..Default::default()
},
entry_is_init: false,
current_block: BasicBlock::default(),
labels_to_blocks: HashMap::default(),
previous_idx: None,
successors: HashMap::new(),
input_block_order: SecondaryMap::new(),
}
}

Expand All @@ -131,8 +160,13 @@ impl FunctionCfgBuilder {
let current_block = mem::take(&mut self.current_block);
let block_idx = self.cfg.vertices.insert(current_block);

if !self.entry_is_init {
self.cfg.entry = block_idx;
self.entry_is_init = true;
}

if let Some(previous_idx) = self.previous_idx {
self.successors.insert(previous_idx, block_idx);
self.input_block_order.insert(previous_idx, block_idx);
}
self.previous_idx = Some(block_idx);

Expand All @@ -145,13 +179,20 @@ impl FunctionCfgBuilder {
for (block_idx, block) in &self.cfg.vertices {
match &block.exit {
LabeledExit::Fallthrough => {
let exit = self
.successors
.get(&block_idx)
.copied()
let after_idx_opt =
self.input_block_order.get(block_idx).copied();
let exit = after_idx_opt
.map(|after_idx| Exit::Fallthrough(Some(after_idx)))
.unwrap_or(Exit::Fallthrough(None));
self.cfg.edges.insert(block_idx, exit);
if let Some(after_idx) = after_idx_opt {
self.cfg
.rev_edges
.entry(after_idx)
.unwrap()
.or_default()
.push(block_idx);
}
}
LabeledExit::Unconditional { label: always, pos } => {
let destination_index = *self
Expand All @@ -166,6 +207,12 @@ impl FunctionCfgBuilder {
block_idx,
Exit::Unconditional(destination_index),
);
self.cfg
.rev_edges
.entry(destination_index)
.unwrap()
.or_default()
.push(block_idx);
}
LabeledExit::Conditional {
condition,
Expand Down Expand Up @@ -197,6 +244,18 @@ impl FunctionCfgBuilder {
if_false: if_false_index,
},
);
self.cfg
.rev_edges
.entry(if_true_index)
.unwrap()
.or_default()
.push(block_idx);
self.cfg
.rev_edges
.entry(if_false_index)
.unwrap()
.or_default()
.push(block_idx);
}
LabeledExit::Return(value) => {
self.cfg
Expand Down
8 changes: 8 additions & 0 deletions lesson4/bril-util/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "bril-util"
version.workspace = true
edition.workspace = true
license-file.workspace = true

[dependencies]
bril-rs.workspace = true
49 changes: 49 additions & 0 deletions lesson4/bril-util/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use bril_rs::{Instruction, Literal};

#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub enum InstructionValue {
Argument,
/// literal string + is float
Constant(String, bool),
Op(String, Vec<String>, Vec<String>, Vec<String>),
}

pub trait InstructionExt {
fn kill(&self) -> Option<&String>;

fn value(&self) -> Option<InstructionValue>;
}

impl InstructionExt for Instruction {
fn kill(&self) -> Option<&String> {
match self {
Instruction::Constant { dest, .. }
| Instruction::Value { dest, .. } => Some(dest),
Instruction::Effect { .. } => None,
}
}

fn value(&self) -> Option<InstructionValue> {
match self {
Instruction::Constant { value, .. } => {
Some(InstructionValue::Constant(
value.to_string(),
matches!(value, Literal::Float(_)),
))
}
Instruction::Value {
op,
args,
funcs,
labels,
..
} => Some(InstructionValue::Op(
op.to_string(),
args.clone(),
funcs.clone(),
labels.clone(),
)),
Instruction::Effect { .. } => None,
}
}
}
13 changes: 13 additions & 0 deletions lesson4/dataflow/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "dataflow"
version.workspace = true
edition.workspace = true
license-file.workspace = true

[dependencies]
argh.workspace = true
snafu.workspace = true
bril-rs.workspace = true
serde_json.workspace = true
build-cfg = { path = "../../lesson2/build-cfg" }
bril-util = { path = "../bril-util/" }
Loading

0 comments on commit 9fda4eb

Please sign in to comment.