Commit ab7dde71 authored by qinsoon's avatar qinsoon

control flow analysis for asm backend

parent dbb70ac9
......@@ -2,9 +2,11 @@ use ast::ptr::P;
use ast::ir::*;
use ast::inst::*;
use vm::machine_code::MachineCode;
pub trait CodeGenerator {
fn start_code(&mut self, func_name: MuTag);
fn finish_code(&mut self);
fn finish_code(&mut self) -> Box<MachineCode>;
fn print_cur_code(&self);
......
......@@ -9,6 +9,7 @@ use ast::op::OpCode;
use ast::types;
use ast::types::MuType_;
use vm::context::VMContext;
use vm::machine_code::CompiledFunction;
use compiler::CompilerPass;
use compiler::backend::x86_64;
......@@ -123,7 +124,7 @@ impl <'a> InstructionSelection {
debug_assert!(func_sig.arg_tys.len() == rets.len());
let mut gpr_arg_count = 0;
let mut fpr_arg_count = 0;
// TODO: let mut fpr_arg_count = 0;
for arg_index in data.args.iter() {
let ref arg = ops[*arg_index];
trace!("arg {}", arg);
......@@ -172,7 +173,7 @@ impl <'a> InstructionSelection {
// deal with ret vals
let mut gpr_ret_count = 0;
let mut fpr_ret_count = 0;
// TODO: let mut fpr_ret_count = 0;
for val in rets {
if val.is_int_reg() {
if gpr_ret_count < x86_64::RETURN_GPRs.len() {
......@@ -386,7 +387,7 @@ impl <'a> InstructionSelection {
// unload arguments
let mut gpr_arg_count = 0;
let mut fpr_arg_count = 0;
// TODO: let mut fpr_arg_count = 0;
for arg in args {
if arg.is_int_reg() {
if gpr_arg_count < x86_64::ARGUMENT_GPRs.len() {
......@@ -419,7 +420,7 @@ impl <'a> InstructionSelection {
};
let mut gpr_ret_count = 0;
let mut fpr_ret_count = 0;
// TODO: let mut fpr_ret_count = 0;
for i in ret_val_indices {
let ref ret_val = ops[*i];
if self.match_ireg(ret_val) {
......@@ -532,6 +533,7 @@ impl <'a> InstructionSelection {
}
}
#[allow(unused_variables)]
fn match_fpreg(&mut self, op: &P<TreeNode>) -> bool {
unimplemented!()
}
......@@ -583,10 +585,12 @@ impl <'a> InstructionSelection {
}
}
#[allow(unused_variables)]
fn match_mem(&mut self, op: &P<TreeNode>) -> bool {
unimplemented!()
}
#[allow(unused_variables)]
fn emit_mem(&mut self, op: &P<TreeNode>) -> P<Value> {
unimplemented!()
}
......@@ -650,6 +654,12 @@ impl CompilerPass for InstructionSelection {
fn finish_function(&mut self, vm_context: &VMContext, func: &mut MuFunction) {
self.backend.print_cur_code();
self.backend.finish_code();
let mc = self.backend.finish_code();
let compiled_func = CompiledFunction {
fn_name: func.fn_name,
mc: mc
};
vm_context.add_compiled_func(compiled_func);
}
}
\ No newline at end of file
......@@ -2,7 +2,9 @@ pub mod inst_sel;
pub mod reg_alloc;
#[cfg(target_arch = "x86_64")]
#[path = "arch/x86_64/mod.rs"]
mod x86_64;
#[cfg(target_arch = "arm")]
#[path = "arch/arm/mod.rs"]
mod arm;
\ No newline at end of file
use vm::machine_code::CompiledFunction;
use vm::machine_code::MachineCode;
use ast::ir::*;
use std::collections::LinkedList;
pub struct InterferenceGraph {
foo: usize
}
impl InterferenceGraph {
fn new() -> InterferenceGraph {
InterferenceGraph {foo: 0}
}
fn new_node(&mut self, node: MuID) {
}
}
// from tony's code src/RegAlloc/Liveness.java
pub fn build (cf: &CompiledFunction, f: &MuFunction) {
let mut ig = InterferenceGraph::new();
// FIXME: precolor nodes
// Liveness Analysis
let n_insts = cf.mc.number_of_insts();
let mut live_in : Vec<Vec<MuID>> = vec![vec![]; n_insts];
let mut live_out : Vec<Vec<MuID>> = vec![vec![]; n_insts];
let mut work_list : LinkedList<usize> = LinkedList::new();
// Initialize 'in' sets for each node in the flow graph
// and creates nodes for all the involved temps/regs
for i in 0..n_insts {
let ref mut in_set = live_in[i];
for reg_id in cf.mc.get_inst_reg_defines(i) {
ig.new_node(*reg_id);
}
for reg_id in cf.mc.get_inst_reg_uses(i) {
ig.new_node(*reg_id);
in_set.push(*reg_id);
}
work_list.push_front(i);
}
while !work_list.is_empty() {
let n = work_list.pop_front().unwrap();
let ref in_set = live_in[n];
let ref mut out_set = live_out[n];
}
}
\ No newline at end of file
......@@ -2,6 +2,8 @@ use compiler::CompilerPass;
use ast::ir::*;
use vm::context::VMContext;
mod liveness;
pub struct RegisterAllocation {
name: &'static str
}
......@@ -21,6 +23,11 @@ impl CompilerPass for RegisterAllocation {
#[allow(unused_variables)]
fn visit_function(&mut self, vm_context: &VMContext, func: &mut MuFunction) {
let mut compiled_funcs = vm_context.compiled_funcs().read().unwrap();
let mut cf = compiled_funcs.get(func.fn_name).unwrap().borrow_mut();
cf.mc.print();
// liveness::build(&mut cf, func);
}
}
\ No newline at end of file
......@@ -3,9 +3,8 @@ use std::collections::HashMap;
use ast::ptr::P;
use ast::ir::*;
use ast::types::*;
use vm::CompiledFunction;
use vm::machine_code::CompiledFunction;
use std::sync::Arc;
use std::sync::RwLock;
use std::cell::RefCell;
......@@ -29,7 +28,7 @@ impl <'a> VMContext {
}
}
pub fn declare_const(&mut self, const_name: MuTag, ty: P<MuType>, val: Constant) -> P<Value> {
pub fn declare_const(&self, const_name: MuTag, ty: P<MuType>, val: Constant) -> P<Value> {
let mut constants = self.constants.write().unwrap();
debug_assert!(!constants.contains_key(const_name));
......@@ -39,7 +38,7 @@ impl <'a> VMContext {
ret
}
pub fn declare_type(&mut self, type_name: MuTag, ty: P<MuType>) -> P<MuType> {
pub fn declare_type(&self, type_name: MuTag, ty: P<MuType>) -> P<MuType> {
let mut types = self.types.write().unwrap();
debug_assert!(!types.contains_key(type_name));
......@@ -48,7 +47,7 @@ impl <'a> VMContext {
ty
}
pub fn declare_func_sig(&mut self, sig_name: MuTag, ret_tys: Vec<P<MuType>>, arg_tys: Vec<P<MuType>>) -> P<MuFuncSig> {
pub fn declare_func_sig(&self, sig_name: MuTag, ret_tys: Vec<P<MuType>>, arg_tys: Vec<P<MuType>>) -> P<MuFuncSig> {
let mut func_sigs = self.func_sigs.write().unwrap();
debug_assert!(!func_sigs.contains_key(sig_name));
......@@ -58,14 +57,14 @@ impl <'a> VMContext {
ret
}
pub fn declare_func (&mut self, func: MuFunction) {
pub fn declare_func (&self, func: MuFunction) {
let mut funcs = self.funcs.write().unwrap();
debug_assert!(!funcs.contains_key(func.fn_name));
funcs.insert(func.fn_name, RefCell::new(func));
}
pub fn add_compiled_func (&mut self, func: CompiledFunction) {
pub fn add_compiled_func (&self, func: CompiledFunction) {
debug_assert!(self.funcs.read().unwrap().contains_key(func.fn_name));
self.compiled_funcs.write().unwrap().insert(func.fn_name, RefCell::new(func));
......@@ -74,4 +73,8 @@ impl <'a> VMContext {
pub fn funcs(&self) -> &RwLock<HashMap<MuTag, RefCell<MuFunction>>> {
&self.funcs
}
pub fn compiled_funcs(&self) -> &RwLock<HashMap<MuTag, RefCell<CompiledFunction>>> {
&self.compiled_funcs
}
}
\ No newline at end of file
use ast::ir::*;
use std::marker::Send;
use std::marker::Sync;
pub struct CompiledFunction {
pub fn_name: MuTag,
pub mc: Box<MachineCode + Send + Sync>
pub mc: Box<MachineCode>
}
pub trait MachineCode {
fn print(&self);
fn number_of_insts(&self) -> usize;
fn is_move(&self, index: usize) -> bool;
fn get_inst_reg_uses(&self, index: usize) -> Vec<MuID>;
fn get_inst_reg_defines(&self, index: usize) -> Vec<MuID>;
fn get_reg_uses(&self, id: MuID) -> Vec<MuID>;
fn get_reg_defines(&self, id: MuID) -> Vec<MuID>;
fn get_inst_reg_uses(&self, index: usize) -> &Vec<MuID>;
fn get_inst_reg_defines(&self, index: usize) -> &Vec<MuID>;
}
\ No newline at end of file
pub mod context;
mod compiled_func;
pub use vm::compiled_func::CompiledFunction;
pub use vm::compiled_func::MachineCode;
\ No newline at end of file
pub mod machine_code;
\ No newline at end of file
mod test_pre_instsel;
mod test_instsel;
\ No newline at end of file
mod test_instsel;
mod test_regalloc;
\ No newline at end of file
......@@ -4,7 +4,6 @@ extern crate simple_logger;
use test_ir::test_ir::factorial;
use self::mu::compiler::*;
use self::mu::vm::context::VMContext;
use std::sync::Arc;
......
......@@ -7,7 +7,6 @@ use test_ir::test_ir::factorial;
use test_ir::test_ir::sum;
use self::mu::ast::ir::*;
use self::mu::compiler::*;
use self::mu::vm::context::VMContext;
use std::sync::Arc;
......
extern crate mu;
extern crate log;
extern crate simple_logger;
use test_ir::test_ir::factorial;
use self::mu::compiler::*;
use std::sync::Arc;
#[test]
fn test_regalloc_fac() {
simple_logger::init_with_level(log::LogLevel::Trace).ok();
let vm_context = Arc::new(factorial());
let compiler = Compiler::new(CompilerPolicy::new(vec![
Box::new(passes::DefUse::new()),
Box::new(passes::TreeGen::new()),
Box::new(passes::ControlFlowAnalysis::new()),
Box::new(passes::TraceGen::new()),
Box::new(backend::inst_sel::InstructionSelection::new()),
Box::new(backend::reg_alloc::RegisterAllocation::new())
]), vm_context.clone());
let funcs = vm_context.funcs().read().unwrap();
let mut factorial_func = funcs.get("fac").unwrap().borrow_mut();
compiler.compile(&mut factorial_func);
}
\ No newline at end of file
......@@ -23,7 +23,7 @@ fn test_sum() {
}
pub fn sum() -> VMContext {
let mut vm = VMContext::new();
let vm = VMContext::new();
// .typedef @int_64 = int<64>
let type_def_int64 = vm.declare_type("int_64", P(MuType::int(64)));
......@@ -155,7 +155,7 @@ pub fn sum() -> VMContext {
#[allow(unused_variables)]
pub fn factorial() -> VMContext {
let mut vm = VMContext::new();
let vm = VMContext::new();
// .typedef @int_64 = int<64>
// .typedef @int_1 = int<1>
......
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