Commit ddef13d8 authored by qinsoon's avatar qinsoon

use IDs and a seperate ValueEntry for values. cargo test somehow stuck

parent baa25cdf
......@@ -2,6 +2,7 @@ use ast::ptr::P;
use ast::op::{BinOp, CmpOp, AtomicRMWOp};
use ast::types::*;
use std::collections::HashMap;
use std::fmt;
use std::cell::Cell;
......@@ -14,10 +15,54 @@ pub type Address = usize; // TODO: replace this with Address(usize)
pub struct MuFunction {
pub fn_name: MuTag,
pub sig: P<MuFuncSig>,
pub content: Option<FunctionContent>,
pub values: HashMap<MuID, ValueEntry>
}
#[derive(Debug)]
pub struct FunctionContent {
pub entry: MuTag,
pub blocks: Vec<(MuTag, Block)>
}
impl MuFunction {
pub fn new(fn_name: MuTag, sig: P<MuFuncSig>) -> MuFunction {
MuFunction{fn_name: fn_name, sig: sig, content: None, values: HashMap::new()}
}
pub fn define(&mut self, content: FunctionContent) {
self.content = Some(content)
}
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)});
P(TreeNode {
v: TreeNode_::Value(P(Value{
tag: tag,
ty: ty,
v: Value_::SSAVar(id)
}))
})
}
pub fn new_constant(&mut self, id: MuID, tag: MuTag, ty: P<MuType>, v: Constant) -> P<TreeNode> {
P(TreeNode{
v: TreeNode_::Value(P(Value{
tag: tag,
ty: ty,
v: Value_::Constant(v)
}))
})
}
pub fn new_value(&mut self, v: P<Value>) -> P<TreeNode> {
P(TreeNode{
v: TreeNode_::Value(v)
})
}
}
#[derive(Debug)]
pub struct Block {
pub label: MuTag,
......@@ -44,43 +89,12 @@ pub trait OperandIteratable {
#[derive(Clone)]
/// always use with P<TreeNode>
pub struct TreeNode {
pub id: MuID,
pub tag: MuTag,
pub v: TreeNode_,
pub use_count: Cell<usize>
pub v: TreeNode_
}
impl TreeNode {
pub fn new_ssa(id: MuID, tag: MuTag, ty: P<MuType>) -> P<TreeNode> {
P(TreeNode{
id: id,
tag: tag,
v: TreeNode_::Value(P(Value{ty: ty, v: Value_::SSAVar})),
use_count: Cell::new(0)
})
}
pub fn new_constant(id: MuID, tag: MuTag, ty: P<MuType>, v: Constant) -> P<TreeNode> {
P(TreeNode{
id: id,
tag: tag,
v: TreeNode_::Value(P(Value{ty: ty, v: Value_::Constant(v)})),
use_count: Cell::new(0)
})
}
pub fn new_value(id: MuID, tag: MuTag, v: P<Value>) -> P<TreeNode> {
P(TreeNode{
id: id,
tag: tag,
v: TreeNode_::Value(v),
use_count: Cell::new(0)
}
)
}
pub fn new_inst(id: MuID, tag: MuTag, v: Instruction) -> P<TreeNode> {
P(TreeNode{id: id, tag: tag, v: TreeNode_::Instruction(v), use_count: Cell::new(0)})
impl TreeNode {
pub fn new_inst(v: Instruction) -> P<TreeNode> {
P(TreeNode{v: TreeNode_::Instruction(v)})
}
}
......@@ -89,8 +103,8 @@ impl fmt::Debug for TreeNode {
match self.v {
TreeNode_::Value(ref pv) => {
match pv.v {
Value_::SSAVar => {
write!(f, "{:?} %{}#{} (use: {})", pv.ty, self.tag, self.id, self.use_count.get())
Value_::SSAVar(id) => {
write!(f, "{:?} %{}#{}", pv.ty, pv.tag, id)
},
Value_::Constant(ref c) => {
write!(f, "{:?} {:?}", pv.ty, c)
......@@ -113,16 +127,31 @@ pub enum TreeNode_ {
/// always use with P<Value>
#[derive(Clone)]
pub struct Value {
pub tag: MuTag,
pub ty: P<MuType>,
pub v: Value_
}
#[derive(Clone)]
pub enum Value_ {
SSAVar,
SSAVar(MuID),
Constant(Constant)
}
#[derive(Clone)]
pub struct ValueEntry {
pub id: MuID,
pub tag: MuTag,
pub ty: P<MuType>,
pub use_count: Cell<usize> // how many times this entry is used
}
impl fmt::Debug for ValueEntry {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?} {}({})", self.ty, self.tag, self.id)
}
}
#[derive(Clone)]
pub enum Constant {
Int(usize),
......
......@@ -44,7 +44,7 @@ pub trait CompilerPass {
self.visit_function(vm_context, func);
for entry in func.blocks.iter_mut() {
for entry in func.content.as_mut().unwrap().blocks.iter_mut() {
let label : MuTag = entry.0;
let ref mut block : &mut Block = &mut entry.1;
......
......@@ -19,13 +19,6 @@ impl CompilerPass for DefUsePass {
}
fn visit_inst(&mut self, vm_context: &VMContext, node: &mut TreeNode) {
match node.v {
TreeNode_::Instruction(ref inst) => {
for p_node in inst.list_operands() {
p_node.use_count.set(p_node.use_count.get() + 1)
}
},
TreeNode_::Value(_) => panic!("expected instruction node")
}
}
}
\ No newline at end of file
......@@ -4,6 +4,7 @@ use ast::ptr::P;
use ast::ir::*;
use ast::types::*;
use std::cell::Cell;
use std::cell::RefCell;
pub struct VMContext {
......@@ -26,7 +27,7 @@ impl VMContext {
pub fn declare_const(&mut self, const_name: MuTag, ty: P<MuType>, val: Constant) -> P<Value> {
debug_assert!(!self.constants.contains_key(const_name));
let ret = P(Value{ty: ty, v: Value_::Constant(val)});
let ret = P(Value{tag: const_name, ty: ty, v: Value_::Constant(val)});
self.constants.insert(const_name, ret.clone());
ret
......@@ -49,11 +50,10 @@ impl VMContext {
ret
}
pub fn declare_func (&mut self, fn_name: MuTag, sig: P<MuFuncSig>, entry: MuTag, blocks: Vec<(MuTag, Block)>) {
debug_assert!(!self.funcs.contains_key(fn_name));
pub fn declare_func (&mut self, func: MuFunction) {
debug_assert!(!self.funcs.contains_key(func.fn_name));
let ret = MuFunction{fn_name: fn_name, sig: sig, entry: entry, blocks: blocks};
self.funcs.insert(fn_name, RefCell::new(ret));
self.funcs.insert(func.fn_name, RefCell::new(func));
}
pub fn get_func(&self, fn_name: MuTag) -> Option<&RefCell<MuFunction>> {
......
......@@ -39,23 +39,24 @@ pub fn factorial() -> VMContext {
// .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 = TreeNode::new_ssa(0, "n_3", type_def_int64.clone());
let const_def_int64_1_local = TreeNode::new_value(1, "int64_1", const_def_int64_1.clone());
let blk_0_n_3 = func.new_ssa(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 = TreeNode::new_ssa(2, "v48", type_def_int64.clone());
let blk_0_v48 = func.new_ssa(2, "v48", type_def_int64.clone());
let blk_0_v48_expr = Expression_::CmpOp(
CmpOp::EQ,
blk_0_n_3.clone(),
const_def_int64_1_local.clone()
);
let blk_0_inst0 = TreeNode::new_inst(3, "blk_0_inst0", Instruction::NonTerm(NonTermInstruction::Assign{left: vec![blk_0_v48.clone()], right: blk_0_v48_expr}));
let blk_0_inst0 = TreeNode::new_inst(Instruction::NonTerm(NonTermInstruction::Assign{left: vec![blk_0_v48.clone()], right: blk_0_v48_expr}));
// BRANCH2 %v48 %blk_2(@int_64_1) %blk_1(%n_3)
let blk_0_term = TreeNode::new_inst(4, "blk_0_term", Instruction::Term(Terminal::Branch2{
let blk_0_term = TreeNode::new_inst(Instruction::Term(Terminal::Branch2{
cond: blk_0_v48.clone(),
true_dest: Destination {
target: "blk_2",
......@@ -76,10 +77,10 @@ pub fn factorial() -> VMContext {
// %blk_2(<@int_64> %v53):
let mut blk_2 = Block::new("blk_2");
let blk_2_v53 = TreeNode::new_ssa(5, "v53", type_def_int64.clone());
let blk_2_v53 = func.new_ssa(5, "v53", type_def_int64.clone());
// RET %v53
let blk_2_term = TreeNode::new_inst(6, "blk_2_term", Instruction::Term(Terminal::Return(vec![blk_2_v53.clone()])));
let blk_2_term = TreeNode::new_inst(Instruction::Term(Terminal::Return(vec![blk_2_v53.clone()])));
let blk_2_content = BlockContent {
args: vec![blk_2_v53.clone()],
......@@ -90,24 +91,24 @@ pub fn factorial() -> VMContext {
// %blk_1(<@int_64> %n_3):
let mut blk_1 = Block::new("blk_1");
let blk_1_n_3 = TreeNode::new_ssa(7, "n_3", type_def_int64.clone());
let blk_1_n_3 = func.new_ssa(7, "n_3", type_def_int64.clone());
// %v50 = SUB <@int_64> %n_3 @int_64_1
let blk_1_v50 = TreeNode::new_ssa(8, "v50", type_def_int64.clone());
let blk_1_v50 = func.new_ssa(8, "v50", type_def_int64.clone());
let blk_1_v50_expr = Expression_::BinOp(
BinOp::Sub,
blk_1_n_3.clone(),
const_def_int64_1_local.clone()
);
let blk_1_inst0 = TreeNode::new_inst(9, "blk_1_inst0", Instruction::NonTerm(NonTermInstruction::Assign{left: vec![blk_1_v50.clone()], right: blk_1_v50_expr}));
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 = TreeNode::new_ssa(10, "v51", type_def_int64.clone());
let blk_1_inst1 = TreeNode::new_inst(11, "blk_1_inst1", Instruction::NonTerm(NonTermInstruction::Assign{
let blk_1_v51 = func.new_ssa(10, "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: TreeNode::new_ssa(12, "fac", fac_func_ref.clone()),
func: func.new_ssa(12, "fac", fac_func_ref.clone()),
args: vec![blk_1_v50.clone()],
convention: CallConvention::Mu
},
......@@ -116,18 +117,18 @@ pub fn factorial() -> VMContext {
}));
// %v52 = MUL <@int_64> %n_3 %v51
let blk_1_v52 = TreeNode::new_ssa(13, "v52", type_def_int64.clone());
let blk_1_v52 = func.new_ssa(13, "v52", type_def_int64.clone());
let blk_1_v52_expr = Expression_::BinOp(
BinOp::Mul,
blk_1_n_3.clone(),
blk_1_v51.clone()
);
let blk_1_inst2 = TreeNode::new_inst(14, "blk_1_inst2", Instruction::NonTerm(NonTermInstruction::Assign{
let blk_1_inst2 = TreeNode::new_inst(Instruction::NonTerm(NonTermInstruction::Assign{
left: vec![blk_1_v52.clone()],
right: blk_1_v52_expr
}));
let blk_1_term = TreeNode::new_inst(15, "blk_1_term", Instruction::Term(Terminal::Branch1 (
let blk_1_term = TreeNode::new_inst(Instruction::Term(Terminal::Branch1 (
Destination {
target: "blk_2",
args: vec![DestArg::Normal(blk_1_v52.clone())]
......@@ -142,12 +143,16 @@ pub fn factorial() -> VMContext {
blk_1.content = Some(blk_1_content);
// wrap into a function
vm.declare_func("fac", fac_sig.clone(), "blk_0", vec![
("blk_0", blk_0),
("blk_1", blk_1),
("blk_2", blk_2)
]
func.define(FunctionContent{
entry: "blk_0",
blocks: vec![
("blk_0", blk_0),
("blk_1", blk_1),
("blk_2", blk_2)
]}
);
vm.declare_func(func);
vm
}
\ No newline at end of file
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