GitLab will be upgraded to the 12.10.14-ce.0 on 28 Sept 2020 at 2.00pm (AEDT) to 2.30pm (AEDT). During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to us at N110 (b) CSIT building.

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