mod.rs 2.64 KB
Newer Older
qinsoon's avatar
qinsoon committed
1 2
#![allow(dead_code)]

3
use compiler::CompilerPass;
4
use compiler::PassExecutionResult;
5
use ast::ir::*;
qinsoon's avatar
qinsoon committed
6
use vm::VM;
7

qinsoon's avatar
qinsoon committed
8 9
use compiler::backend::init_machine_regs_for_func;

10
mod graph_coloring;
11

12 13 14 15 16 17
enum RegAllocResult {
    Success,
    FailedForSpilling,
    FailedForUsingCallerSaved
}

18
pub struct RegisterAllocation {
19 20
    name: &'static str,
    is_fastpath: bool
21 22 23
}

impl RegisterAllocation {
24
    pub fn new(is_fastpath: bool) -> RegisterAllocation {
25
        RegisterAllocation {
26 27
            name: "Register Allcoation",
            is_fastpath: is_fastpath
28 29 30 31
        }
    }
    
    #[allow(unused_variables)]
32
    // returns true if we spill registers (which requires another instruction selection)
qinsoon's avatar
qinsoon committed
33 34
    fn coloring(&mut self, vm: &VM, func: &mut MuFunctionVersion) -> bool {
        let compiled_funcs = vm.compiled_funcs().read().unwrap();
qinsoon's avatar
qinsoon committed
35
        let mut cf = compiled_funcs.get(&func.id()).unwrap().write().unwrap();
36
        
qinsoon's avatar
qinsoon committed
37
        cf.mc().trace_mc();
38
        
qinsoon's avatar
qinsoon committed
39 40 41
        // initialize machine registers for the function context
        init_machine_regs_for_func(&mut func.context);
        
42
        let liveness = graph_coloring::build_inteference_graph(&mut cf, func);
43
        liveness.print();
qinsoon's avatar
qinsoon committed
44
        
45
        let coloring = graph_coloring::GraphColoring::start(liveness);
46
        let spills = coloring.spills();
47 48
        
        if !spills.is_empty() {
49
            return false;
50 51 52 53 54 55 56 57
        }
        
        // replace regs
        trace!("Replacing Registers...");
        for node in coloring.ig.nodes() {
            let temp = coloring.ig.get_temp_of(node);
            
            // skip machine registers
qinsoon's avatar
qinsoon committed
58
            if temp < MACHINE_ID_END {
59 60 61 62 63 64
                continue;
            } else {
                let alias = coloring.get_alias(node);
                let machine_reg = coloring.ig.get_color_of(alias).unwrap();
                
                trace!("replacing {} with {}", temp, machine_reg);
qinsoon's avatar
qinsoon committed
65
                cf.mc_mut().replace_reg(temp, machine_reg);
66 67
                
                cf.temps.insert(temp, machine_reg);
68 69 70
            }
        }
        
qinsoon's avatar
qinsoon committed
71
        cf.mc().trace_mc();
72 73 74 75 76 77 78 79 80 81
        
        true
    }    
}

impl CompilerPass for RegisterAllocation {
    fn name(&self) -> &'static str {
        self.name
    }
    
qinsoon's avatar
qinsoon committed
82
    fn execute(&mut self, vm: &VM, func: &mut MuFunctionVersion) -> PassExecutionResult {
qinsoon's avatar
qinsoon committed
83
        debug!("---CompilerPass {} for {}---", self.name(), func);
84
        
qinsoon's avatar
qinsoon committed
85
        if self.coloring(vm, func) {
86 87 88 89
            debug!("---finish---");
            
            PassExecutionResult::ProceedToNext
        } else {
90 91 92
            // PassExecutionResult::GoBackTo(compiler::PASS_INST_SEL)
                        
            unimplemented!()
93
        }
94
    }
95
}