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

3
use compiler::CompilerPass;
4 5
use compiler::PassExecutionResult;
use compiler;
6 7 8
use ast::ir::*;
use vm::context::VMContext;

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

11
mod graph_coloring;
12

13 14 15 16 17 18 19 20 21 22 23 24
pub struct RegisterAllocation {
    name: &'static str
}

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

impl CompilerPass for RegisterAllocation {
    fn name(&self) -> &'static str {
        self.name
    }
    
75
    fn execute(&mut self, vm_context: &VMContext, func: &mut MuFunctionVersion) -> PassExecutionResult {
76 77 78 79 80 81 82 83 84
        debug!("---CompilerPass {} for {}---", self.name(), func.fn_name);
        
        if self.coloring(vm_context, func) {
            debug!("---finish---");
            
            PassExecutionResult::ProceedToNext
        } else {
            PassExecutionResult::GoBackTo(compiler::PASS4_INST_SEL)
        }
85
    }
86
}