use ast::ir::*; use vm::context::VMContext; use std::cell::RefCell; use std::sync::Arc; pub mod passes; pub mod backend; pub struct Compiler { policy: RefCell, vm: Arc } impl Compiler { pub fn new(policy: CompilerPolicy, vm: Arc) -> Compiler { Compiler{ policy: RefCell::new(policy), vm: vm } } pub fn compile(&self, func: &mut MuFunction) { let mut cur_pass = 0; let n_passes = self.policy.borrow().passes.len(); let ref mut passes = self.policy.borrow_mut().passes; while cur_pass < n_passes { let result = passes[cur_pass].execute(&self.vm, func); match result { PassExecutionResult::ProceedToNext => cur_pass += 1, PassExecutionResult::GoBackTo(next) => cur_pass = next } } } } pub struct CompilerPolicy { passes: Vec> } pub const PASS0_DEF_USE : usize = 0; pub const PASS1_TREE_GEN : usize = 1; pub const PASS2_CFA : usize = 2; pub const PASS3_TRACE_GEN : usize = 3; pub const PASS4_INST_SEL : usize = 4; pub const PASS5_REG_ALLOC : usize = 5; impl CompilerPolicy { pub fn default() -> CompilerPolicy { let mut passes : Vec> = vec![]; passes.push(Box::new(passes::DefUse::new())); passes.push(Box::new(passes::TreeGen::new())); passes.push(Box::new(passes::ControlFlowAnalysis::new())); passes.push(Box::new(passes::TraceGen::new())); passes.push(Box::new(backend::inst_sel::InstructionSelection::new())); passes.push(Box::new(backend::reg_alloc::RegisterAllocation::new())); CompilerPolicy{passes: passes} } pub fn new(passes: Vec>) -> CompilerPolicy { CompilerPolicy{passes: passes} } } pub enum PassExecutionResult { ProceedToNext, GoBackTo(usize) } #[allow(unused_variables)] pub trait CompilerPass { fn name(&self) -> &'static str; fn execute(&mut self, vm_context: &VMContext, func: &mut MuFunction) -> PassExecutionResult { debug!("---CompilerPass {} for {}---", self.name(), func.fn_name); self.start_function(vm_context, func); self.visit_function(vm_context, func); self.finish_function(vm_context, func); debug!("---finish---"); PassExecutionResult::ProceedToNext } fn visit_function(&mut self, vm_context: &VMContext, func: &mut MuFunction) { for (label, ref mut block) in func.content.as_mut().unwrap().blocks.iter_mut() { debug!("block: {}", label); self.start_block(vm_context, &mut func.context, block); self.visit_block(vm_context, &mut func.context, block); self.finish_block(vm_context, &mut func.context, block); } } fn visit_block(&mut self, vm_context: &VMContext, func_context: &mut FunctionContext, block: &mut Block) { for inst in block.content.as_mut().unwrap().body.iter_mut() { debug!("{}", inst); self.visit_inst(vm_context, func_context, inst); } } fn start_function(&mut self, vm_context: &VMContext, func: &mut MuFunction) {} fn finish_function(&mut self, vm_context: &VMContext, func: &mut MuFunction) {} fn start_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) {} }