Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions src/cfa.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
use std::borrow::Borrow;
use std::cell::RefCell;
use std::collections::HashMap;
use auxtools::raw_types::values::ValueTag::Area;
use dmasm::Instruction::Ref;
use typed_arena::Arena;
use crate::dmir::DMIR;

pub struct ControlFlowGraph<'t> {
analyzer: &'t ControlFlowAnalyzer<'t>,
pub nodes: HashMap<String, &'t CFGNode<'t>>
}

pub struct CFGNode<'t> {
pub label: String,
pub inbound: RefCell<Vec<&'t CFGNode<'t>>>,
pub outbound: RefCell<Vec<&'t CFGNode<'t>>>
}

impl<'t> CFGNode<'t> {
fn new(label: String) -> Self {
Self {
label,
inbound: RefCell::new(vec![]),
outbound: RefCell::new(vec![])
}
}

fn add_outbound_edge(&self, target: &'t CFGNode<'t>) {
self.outbound.borrow_mut().push(target);
target.inbound.borrow_mut().push(target);
}

}

pub struct ControlFlowAnalyzer<'t> {
arena: Arena<CFGNode<'t>>
}


impl<'t> ControlFlowGraph<'t> {
fn get_or_create_node<'q>(&'q mut self, label: &'_ str) -> &'t CFGNode<'t> {
let arena = &self.analyzer.arena;
*self.nodes.entry(label.to_owned())
.or_insert_with(|| arena.alloc(CFGNode::new(label.to_owned())))
}
}

impl<'t> ControlFlowAnalyzer<'t> {
pub fn new() -> Self {
Self {
arena: Default::default()
}
}

pub fn analyze(&'t self, instructions: &Vec<DMIR>) -> ControlFlowGraph<'t> {
let mut graph = ControlFlowGraph {
analyzer: self,
nodes: Default::default()
};


let entry = graph.get_or_create_node("entry");
let exit = graph.get_or_create_node("exit");


let mut current_node = entry;

for instruction in instructions {
match instruction {
DMIR::ValueTagSwitch(_, cases) => {
for (_, label) in cases {
current_node.add_outbound_edge(graph.get_or_create_node(label));
}
}
DMIR::Ret => {
current_node.add_outbound_edge(exit);
}
DMIR::EnterBlock(label) => {
current_node = graph.get_or_create_node(label);
}
DMIR::JZ(label) |
DMIR::JZInternal(label) |
DMIR::JNZInternal(label) |
DMIR::Jmp(label) => {
current_node.add_outbound_edge(
graph.get_or_create_node(label)
)
}
DMIR::Deopt(_, _) => {}
DMIR::End => {
current_node.add_outbound_edge(exit);
}
_ => {}
}
}

graph
}
}
2 changes: 1 addition & 1 deletion src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -774,7 +774,7 @@ impl<'ctx> CodeGen<'ctx, '_> {
let meta_value = self.emit_load_meta_value(value);
let mut jumps = Vec::new();
let mut default = Option::None;
for (predicate, block) in cases.as_ref() {
for (predicate, block) in cases {
let mut predicates = Vec::new();
fn to_linear(predicate: &ValueTagPredicate, out: &mut Vec<ValueTagPredicate>) {
match predicate {
Expand Down
5 changes: 5 additions & 0 deletions src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ use llvm_sys::execution_engine::LLVMExecutionEngineGetErrMsg;

use crate::{ByondProcFunc, chad_hook_by_id, DisassembleEnv, dmir, guard, pads};
use crate::codegen::CodeGen;
use crate::dfa::analyze_and_dump_dfa;
use crate::dmir::DMIR;
use crate::proc_meta::{ProcMeta, ProcMetaModuleBuilder};
use crate::ref_count2::generate_ref_count_operations2;
use crate::ref_count::generate_ref_count_operations;
use crate::section_memory_manager_bindings::{Section, SectionMemoryManager};
use crate::stack_map::{read_stack_map, StackMap};
Expand Down Expand Up @@ -251,6 +253,9 @@ fn compile_proc<'ctx>(
log::debug!("DMIR created");
variable_termination_pass(&mut irs);
log::debug!("variable_termination_pass done");

generate_ref_count_operations2(&mut irs, proc.parameter_names().len());
log::debug!("====== DFA done ======");
generate_ref_count_operations(&mut irs, proc.parameter_names().len());
log::debug!("ref_count_pass done");

Expand Down
Loading