GitLab will continue to be upgraded from 11.4.5-ce.0 on November 25th 2019 at 4.00pm (AEDT) to 5.00pm (AEDT) due to Critical Security Patch Availability. During the update, GitLab and Mattermost services will not be available.

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