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 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