Commit b9b363ec authored by qinsoon's avatar qinsoon

def use pass

parent 16930fc7
......@@ -16,7 +16,7 @@ pub struct MuFunction {
pub fn_name: MuTag,
pub sig: P<MuFuncSig>,
pub content: Option<FunctionContent>,
pub values: HashMap<MuID, ValueEntry>
pub context: FunctionContext
}
#[derive(Debug)]
......@@ -25,9 +25,26 @@ pub struct FunctionContent {
pub blocks: Vec<(MuTag, Block)>
}
#[derive(Debug)]
pub struct FunctionContext {
pub values: HashMap<MuID, ValueEntry>
}
impl FunctionContext {
fn new() -> FunctionContext {
FunctionContext {
values: HashMap::new()
}
}
pub fn get_value(&self, id: MuID) -> Option<&ValueEntry> {
self.values.get(&id)
}
}
impl MuFunction {
pub fn new(fn_name: MuTag, sig: P<MuFuncSig>) -> MuFunction {
MuFunction{fn_name: fn_name, sig: sig, content: None, values: HashMap::new()}
MuFunction{fn_name: fn_name, sig: sig, content: None, context: FunctionContext::new()}
}
pub fn define(&mut self, content: FunctionContent) {
......@@ -35,7 +52,7 @@ impl MuFunction {
}
pub fn new_ssa(&mut self, id: MuID, tag: MuTag, ty: P<MuType>) -> P<TreeNode> {
self.values.insert(id, ValueEntry{id: id, tag: tag, ty: ty.clone(), use_count: Cell::new(0)});
self.context.values.insert(id, ValueEntry{id: id, tag: tag, ty: ty.clone(), use_count: Cell::new(0)});
P(TreeNode {
v: TreeNode_::Value(P(Value{
......
......@@ -28,11 +28,15 @@ pub struct CompilerPolicy {
impl CompilerPolicy {
pub fn default() -> CompilerPolicy {
let mut passes : Vec<Box<CompilerPass>> = vec![];
passes.push(Box::new(passes::def_use::DefUsePass::new("DefUse")));
passes.push(Box::new(passes::tree_gen::TreeGenerationPass::new("Tree Generation")));
passes.push(Box::new(passes::DefUse::new()));
passes.push(Box::new(passes::TreeGen::new()));
CompilerPolicy{passes: passes}
}
pub fn new(passes: Vec<Box<CompilerPass>>) -> CompilerPolicy {
CompilerPolicy{passes: passes}
}
}
pub trait CompilerPass {
......@@ -49,17 +53,26 @@ pub trait CompilerPass {
debug!("block: {}", label);
self.visit_block(vm_context, &mut func.context, block);
for inst in block.content.as_mut().unwrap().body.iter_mut() {
debug!("{:?}", inst);
self.visit_inst(vm_context, inst);
self.visit_inst(vm_context, &mut func.context, inst);
}
debug!("---finish---");
self.finish_block(vm_context, &mut func.context, block);
}
self.finish_function(vm_context, func);
debug!("---finish---");
}
fn visit_function(&mut self, vm_context: &VMContext, func: &mut MuFunction) {}
fn visit_block(&mut self, vm_context: &VMContext, block: &mut Block) {}
fn visit_inst(&mut self, vm_context: &VMContext, node: &mut TreeNode) {}
fn finish_function(&mut self, vm_context: &VMContext, func: &mut MuFunction) {}
fn visit_block(&mut self, vm_context: &VMContext, func_context: &mut FunctionContext, block: &mut Block) {}
fn finish_block(&mut self, vm_context: &VMContext, func_context: &mut FunctionContext, block: &mut Block) {}
fn visit_inst(&mut self, vm_context: &VMContext, func_context: &mut FunctionContext, node: &mut TreeNode) {}
}
......@@ -3,22 +3,48 @@ use vm::context::VMContext;
use compiler::CompilerPass;
pub struct DefUsePass {
pub struct DefUse {
name: &'static str,
}
impl DefUsePass {
pub fn new(name: &'static str) -> DefUsePass {
DefUsePass{name: name}
impl DefUse {
pub fn new() -> DefUse {
DefUse{name: "Def-Use Pass"}
}
}
impl CompilerPass for DefUsePass {
impl CompilerPass for DefUse {
fn name(&self) -> &'static str {
self.name
}
fn visit_inst(&mut self, vm_context: &VMContext, node: &mut TreeNode) {
fn visit_inst(&mut self, vm_context: &VMContext, func_context: &mut FunctionContext, node: &mut TreeNode) {
match node.v {
TreeNode_::Instruction(ref inst) => {
for op in inst.list_operands() {
match op.v {
TreeNode_::Value(ref val) => {
match val.v {
Value_::SSAVar(ref id) => {
let mut entry = func_context.values.get_mut(id).unwrap();
entry.use_count.set(entry.use_count.get() + 1);
},
_ => {} // dont worry about constants
}
},
_ => {} // dont worry about instruction
}
}
},
_ => panic!("expected instruction node in visit_inst()")
}
}
fn finish_function(&mut self, vm_context: &VMContext, func: &mut MuFunction) {
debug!("check use count for variables");
for entry in func.context.values.values() {
debug!("{}({}): {}", entry.tag, entry.id, entry.use_count.get())
}
}
}
\ No newline at end of file
pub mod def_use;
pub mod tree_gen;
\ No newline at end of file
mod def_use;
mod tree_gen;
pub use compiler::passes::def_use::DefUse;
pub use compiler::passes::tree_gen::TreeGen;
\ No newline at end of file
......@@ -3,17 +3,17 @@ use vm::context::VMContext;
use compiler::CompilerPass;
pub struct TreeGenerationPass {
pub struct TreeGen {
name: &'static str,
}
impl TreeGenerationPass {
pub fn new(name: &'static str) -> TreeGenerationPass {
TreeGenerationPass{name: name}
impl TreeGen {
pub fn new() -> TreeGen {
TreeGen{name: "Tree Geenration"}
}
}
impl CompilerPass for TreeGenerationPass {
impl CompilerPass for TreeGen {
fn name(&self) -> &'static str {
self.name
}
......
mod test_ir;
mod test_compiler;
\ No newline at end of file
mod test_compiler;
#[macro_export]
macro_rules! init_logger {
($level : expr) => {
match simple_logger::init_with_level($level) {
Ok(_) => {},
Err(_) => {}
}
}
}
\ No newline at end of file
......@@ -6,12 +6,40 @@ use test_ir::test_ir::factorial;
use self::mu::compiler::*;
use self::mu::vm::context::VMContext;
#[test]
fn test_use_count() {
simple_logger::init_with_level(log::LogLevel::Trace).ok();
let vm_context : VMContext = factorial();
let compiler = Compiler::new(CompilerPolicy::new(
vec![Box::new(passes::DefUse::new())]
));
let mut factorial_func = {
vm_context.get_func("fac").unwrap().borrow_mut()
};
compiler.compile(&vm_context, &mut factorial_func);
assert!(factorial_func.context.get_value(0).unwrap().use_count.get() == 2, "blk_0_n_3 use should be 2");
assert!(factorial_func.context.get_value(1).unwrap().use_count.get() == 1, "blk_0_v48 use should be 1");
assert!(factorial_func.context.get_value(2).unwrap().use_count.get() == 1, "blk_2_v53 use should be 1");
assert!(factorial_func.context.get_value(3).unwrap().use_count.get() == 2, "blk_1_n_3 use should be 2");
assert!(factorial_func.context.get_value(4).unwrap().use_count.get() == 1, "blk_1_v50 use should be 1");
assert!(factorial_func.context.get_value(5).unwrap().use_count.get() == 1, "blk_1_v51 use should be 1");
assert!(factorial_func.context.get_value(6).unwrap().use_count.get() == 1, "blk_1_fac use should be 1");
assert!(factorial_func.context.get_value(7).unwrap().use_count.get() == 1, "blk_1_v52 use should be 1");
}
#[test]
fn test_tree_gen() {
simple_logger::init_with_level(log::LogLevel::Trace).unwrap();
simple_logger::init_with_level(log::LogLevel::Trace).ok();
let vm_context : VMContext = factorial();
let compiler = Compiler::new(CompilerPolicy::default());
let compiler = Compiler::new(CompilerPolicy::new(
vec![Box::new(passes::DefUse::new()),
Box::new(passes::TreeGen::new())]
));
let mut factorial_func = {
vm_context.get_func("fac").unwrap().borrow_mut()
......
......@@ -38,16 +38,15 @@ pub fn factorial() -> VMContext {
let fac_sig = vm.declare_func_sig("fac_sig", vec![type_def_int64.clone()], vec![type_def_int64.clone()]);
// .funcdef @fac VERSION @fac_v1 <@fac_sig>
let fac_func_ref = P(MuType::funcref(fac_sig.clone()));
let mut func = MuFunction::new("fac", fac_sig.clone());
// %blk_0(<@int_64> %n_3):
let mut blk_0 = Block::new("blk_0");
let blk_0_n_3 = func.new_ssa(0, "n_3", type_def_int64.clone());
let blk_0_n_3 = func.new_ssa(0, "blk_0_n_3", type_def_int64.clone());
let const_def_int64_1_local = func.new_value(const_def_int64_1.clone());
// %v48 = EQ <@int_64> %n_3 @int_64_1
let blk_0_v48 = func.new_ssa(2, "v48", type_def_int64.clone());
let blk_0_v48 = func.new_ssa(1, "blk_0_v48", type_def_int64.clone());
let blk_0_v48_expr = Expression_::CmpOp(
CmpOp::EQ,
blk_0_n_3.clone(),
......@@ -77,7 +76,7 @@ pub fn factorial() -> VMContext {
// %blk_2(<@int_64> %v53):
let mut blk_2 = Block::new("blk_2");
let blk_2_v53 = func.new_ssa(5, "v53", type_def_int64.clone());
let blk_2_v53 = func.new_ssa(2, "blk_2_v53", type_def_int64.clone());
// RET %v53
let blk_2_term = TreeNode::new_inst(Instruction::Term(Terminal::Return(vec![blk_2_v53.clone()])));
......@@ -91,10 +90,10 @@ pub fn factorial() -> VMContext {
// %blk_1(<@int_64> %n_3):
let mut blk_1 = Block::new("blk_1");
let blk_1_n_3 = func.new_ssa(7, "n_3", type_def_int64.clone());
let blk_1_n_3 = func.new_ssa(3, "blk_1_n_3", type_def_int64.clone());
// %v50 = SUB <@int_64> %n_3 @int_64_1
let blk_1_v50 = func.new_ssa(8, "v50", type_def_int64.clone());
let blk_1_v50 = func.new_ssa(4, "blk_1_v50", type_def_int64.clone());
let blk_1_v50_expr = Expression_::BinOp(
BinOp::Sub,
blk_1_n_3.clone(),
......@@ -103,12 +102,12 @@ pub fn factorial() -> VMContext {
let blk_1_inst0 = TreeNode::new_inst(Instruction::NonTerm(NonTermInstruction::Assign{left: vec![blk_1_v50.clone()], right: blk_1_v50_expr}));
// %v51 = CALL <@fac_sig> @fac (%v50)
let blk_1_v51 = func.new_ssa(10, "v51", type_def_int64.clone());
let blk_1_v51 = func.new_ssa(5, "blk_1_v51", type_def_int64.clone());
let blk_1_inst1 = TreeNode::new_inst(Instruction::NonTerm(NonTermInstruction::Assign{
left: vec![blk_1_v51.clone()],
right: Expression_::ExprCall {
data: CallData {
func: func.new_ssa(12, "fac", fac_func_ref.clone()),
func: func.new_ssa(6, "blk_1_fac", P(MuType::funcref(fac_sig.clone()))),
args: vec![blk_1_v50.clone()],
convention: CallConvention::Mu
},
......@@ -117,7 +116,7 @@ pub fn factorial() -> VMContext {
}));
// %v52 = MUL <@int_64> %n_3 %v51
let blk_1_v52 = func.new_ssa(13, "v52", type_def_int64.clone());
let blk_1_v52 = func.new_ssa(7, "blk_1_v52", type_def_int64.clone());
let blk_1_v52_expr = Expression_::BinOp(
BinOp::Mul,
blk_1_n_3.clone(),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment