machine_code.rs 5.08 KB
Newer Older
1
use ast::ir::*;
qinsoon's avatar
qinsoon committed
2
use compiler::frame::*;
qinsoon's avatar
qinsoon committed
3 4
use runtime::ValueLocation;

5
use std::ops;
6
use std::collections::HashMap;
7

qinsoon's avatar
qinsoon committed
8 9
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};

10
pub struct CompiledFunction {
qinsoon's avatar
qinsoon committed
11
    pub func_id: MuID,
qinsoon's avatar
qinsoon committed
12
    pub func_ver_id: MuID,
qinsoon's avatar
qinsoon committed
13 14 15

    // assumes one temporary maps to one register
    pub temps: HashMap<MuID, MuID>,
qinsoon's avatar
qinsoon committed
16
    
qinsoon's avatar
qinsoon committed
17
    // not emitting this
18
    pub mc: Option<Box<MachineCode + Send + Sync>>,
qinsoon's avatar
qinsoon committed
19 20 21 22 23 24 25 26 27 28 29
    
    pub frame: Frame,
    pub start: ValueLocation,
    pub end: ValueLocation
}

const CF_SERIALIZE_FIELDS : usize = 6;

impl Encodable for CompiledFunction {
    fn encode<S: Encoder> (&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_struct("CompiledFunction", CF_SERIALIZE_FIELDS, |s| {
qinsoon's avatar
qinsoon committed
30
            trace!("......serializing func_id");    
qinsoon's avatar
qinsoon committed
31
            try!(s.emit_struct_field("func_id",     0, |s| self.func_id.encode(s)));
qinsoon's avatar
qinsoon committed
32
            trace!("......serializing func_ver_id");
qinsoon's avatar
qinsoon committed
33
            try!(s.emit_struct_field("func_ver_id", 1, |s| self.func_ver_id.encode(s)));
qinsoon's avatar
qinsoon committed
34
            trace!("......serializing temps");
qinsoon's avatar
qinsoon committed
35
            try!(s.emit_struct_field("temps",       2, |s| self.temps.encode(s)));
qinsoon's avatar
qinsoon committed
36 37
            trace!("......serializing frame");
            trace!("{}", self.frame);
qinsoon's avatar
qinsoon committed
38
            try!(s.emit_struct_field("frame",       3, |s| self.frame.encode(s)));
qinsoon's avatar
qinsoon committed
39
            trace!("......serializing start");
qinsoon's avatar
qinsoon committed
40
            try!(s.emit_struct_field("start",       4, |s| self.start.encode(s)));
qinsoon's avatar
qinsoon committed
41
            trace!("......serializing end");
qinsoon's avatar
qinsoon committed
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
            try!(s.emit_struct_field("end",         5, |s| self.end.encode(s)));
            
            Ok(())
        })
    }
}

impl Decodable for CompiledFunction {
    fn decode<D: Decoder>(d: &mut D) -> Result<CompiledFunction, D::Error> {
        d.read_struct("CompiledFunction", CF_SERIALIZE_FIELDS, |d| {
            let func_id = 
                try!(d.read_struct_field("func_id",     0, |d| Decodable::decode(d)));
            let func_ver_id = 
                try!(d.read_struct_field("func_ver_id", 1, |d| Decodable::decode(d)));
            let temps = 
                try!(d.read_struct_field("temps",       2, |d| Decodable::decode(d)));
            let frame = 
                try!(d.read_struct_field("frame",       3, |d| Decodable::decode(d)));
            let start = 
                try!(d.read_struct_field("start",       4, |d| Decodable::decode(d)));
            let end =
                try!(d.read_struct_field("end",         5, |d| Decodable::decode(d)));
            
            Ok(CompiledFunction{
                func_id: func_id,
                func_ver_id: func_ver_id,
                temps: temps,
                mc: None,
                frame: frame,
                start: start,
                end: end
            })
        })
    }
}

impl CompiledFunction {
79
    pub fn mc(&self) -> &Box<MachineCode + Send + Sync> {
qinsoon's avatar
qinsoon committed
80 81 82 83 84 85 86 87
        match self.mc {
            Some(ref mc) => mc,
            None => panic!("trying to get mc from a compiled function. 
                But machine code is None (probably this compiled function is restored from
                boot image and mc is thrown away)")
        }
    }
    
88
    pub fn mc_mut(&mut self) -> &mut Box<MachineCode + Send + Sync> {
qinsoon's avatar
qinsoon committed
89 90 91 92 93
        match self.mc {
            Some(ref mut mc) => mc,
            None => panic!("no mc found from a compiled function")
        }
    }
94 95
}

96 97
use std::any::Any;

98
pub trait MachineCode {
99 100 101
    fn trace_mc(&self);
    fn trace_inst(&self, index: usize);
    
102
    fn emit(&self) -> Vec<u8>;
103 104
    
    fn number_of_insts(&self) -> usize;
qinsoon's avatar
qinsoon committed
105
    
106
    fn is_move(&self, index: usize) -> bool;
qinsoon's avatar
qinsoon committed
107 108
    fn is_using_mem_op(&self, index: usize) -> bool;
    
qinsoon's avatar
qinsoon committed
109 110
    fn get_succs(&self, index: usize) -> &Vec<usize>;
    fn get_preds(&self, index: usize) -> &Vec<usize>;
111
    
qinsoon's avatar
qinsoon committed
112 113
    fn get_inst_reg_uses(&self, index: usize) -> Vec<MuID>;
    fn get_inst_reg_defines(&self, index: usize) -> Vec<MuID>;
114
    
115 116
    fn get_ir_block_livein(&self, block: &str) -> Option<&Vec<MuID>>;
    fn get_ir_block_liveout(&self, block: &str) -> Option<&Vec<MuID>>;
117 118
    fn set_ir_block_livein(&mut self, block: &str, set: Vec<MuID>);
    fn set_ir_block_liveout(&mut self, block: &str, set: Vec<MuID>);
119
    
qinsoon's avatar
qinsoon committed
120 121
    fn get_all_blocks(&self) -> Vec<MuName>;
    // returns [start_inst, end_inst), inclusive at both end
122
    fn get_block_range(&self, block: &str) -> Option<ops::Range<usize>>;
qinsoon's avatar
qinsoon committed
123 124

    // functions for rewrite
125
    /// replace a temp with a machine register (to_reg must be a machine register)
126
    fn replace_reg(&mut self, from: MuID, to: MuID);
qinsoon's avatar
qinsoon committed
127
    /// replace a temp that is defined in the inst with another temp
128
    fn replace_define_tmp_for_inst(&mut self, from: MuID, to: MuID, inst: usize);
qinsoon's avatar
qinsoon committed
129
    /// replace a temp that is used in the inst with another temp
130
    fn replace_use_tmp_for_inst(&mut self, from: MuID, to: MuID, inst: usize);
qinsoon's avatar
qinsoon committed
131
    /// set an instruction as nop
132
    fn set_inst_nop(&mut self, index: usize);
qinsoon's avatar
qinsoon committed
133 134 135
    /// remove unnecessary push/pop if the callee saved register is not used
    /// returns what registers push/pop have been deleted
    fn remove_unnecessary_callee_saved(&mut self, used_callee_saved: Vec<MuID>) -> Vec<MuID>;
136 137

    fn as_any(&self) -> &Any;
138
}
139 140 141 142

pub trait MachineInst {

}