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

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

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

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

    // assumes one temporary maps to one register
16
17
18
19
    pub temps : HashMap<MuID, MuID>,

    pub consts: HashMap<MuID, P<Value>>,
    pub const_mem: HashMap<MuID, P<Value>>,
qinsoon's avatar
qinsoon committed
20
    
qinsoon's avatar
qinsoon committed
21
    // not emitting this
22
    pub mc: Option<Box<MachineCode + Send + Sync>>,
qinsoon's avatar
qinsoon committed
23
24
25
26
27
28
29
30
31
32
33
    
    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| {
34
35
            let mut i = 0;

qinsoon's avatar
qinsoon committed
36
            trace!("......serializing func_id");    
37
38
39
            try!(s.emit_struct_field("func_id",     i, |s| self.func_id.encode(s)));
            i += 1;

qinsoon's avatar
qinsoon committed
40
            trace!("......serializing func_ver_id");
41
42
43
            try!(s.emit_struct_field("func_ver_id", i, |s| self.func_ver_id.encode(s)));
            i += 1;

qinsoon's avatar
qinsoon committed
44
            trace!("......serializing temps");
45
46
47
48
49
50
51
52
53
54
55
            try!(s.emit_struct_field("temps",       i, |s| self.temps.encode(s)));
            i += 1;

            trace!("......serializing consts");
            try!(s.emit_struct_field("consts",      i, |s| self.consts.encode(s)));
            i += 1;

            trace!("......serializing const_mem");
            try!(s.emit_struct_field("const_mem",   i, |s| self.const_mem.encode(s)));
            i += 1;

qinsoon's avatar
qinsoon committed
56
57
            trace!("......serializing frame");
            trace!("{}", self.frame);
58
59
60
            try!(s.emit_struct_field("frame",       i, |s| self.frame.encode(s)));
            i += 1;

qinsoon's avatar
qinsoon committed
61
            trace!("......serializing start");
62
63
64
            try!(s.emit_struct_field("start",       i, |s| self.start.encode(s)));
            i += 1;

qinsoon's avatar
qinsoon committed
65
            trace!("......serializing end");
66
            try!(s.emit_struct_field("end",         i, |s| self.end.encode(s)));
qinsoon's avatar
qinsoon committed
67
68
69
70
71
72
73
74
75
            
            Ok(())
        })
    }
}

impl Decodable for CompiledFunction {
    fn decode<D: Decoder>(d: &mut D) -> Result<CompiledFunction, D::Error> {
        d.read_struct("CompiledFunction", CF_SERIALIZE_FIELDS, |d| {
76
77
            let mut i = 0;

qinsoon's avatar
qinsoon committed
78
            let func_id = 
79
80
                try!(d.read_struct_field("func_id",     i, |d| Decodable::decode(d)));
            i += 1;
qinsoon's avatar
qinsoon committed
81
            let func_ver_id = 
82
83
                try!(d.read_struct_field("func_ver_id", i, |d| Decodable::decode(d)));
            i += 1;
qinsoon's avatar
qinsoon committed
84
            let temps = 
85
86
87
88
89
90
91
92
                try!(d.read_struct_field("temps",       i, |d| Decodable::decode(d)));
            i += 1;
            let consts =
                try!(d.read_struct_field("consts",      i, |d| Decodable::decode(d)));
            i += 1;
            let const_mem =
                try!(d.read_struct_field("const_mem",   i, |d| Decodable::decode(d)));
            i += 1;
qinsoon's avatar
qinsoon committed
93
            let frame = 
94
95
                try!(d.read_struct_field("frame",       i, |d| Decodable::decode(d)));
            i += 1;
qinsoon's avatar
qinsoon committed
96
            let start = 
97
98
                try!(d.read_struct_field("start",       i, |d| Decodable::decode(d)));
            i += 1;
qinsoon's avatar
qinsoon committed
99
            let end =
100
                try!(d.read_struct_field("end",         i, |d| Decodable::decode(d)));
qinsoon's avatar
qinsoon committed
101
102
103
104
105
            
            Ok(CompiledFunction{
                func_id: func_id,
                func_ver_id: func_ver_id,
                temps: temps,
106
107
                consts: consts,
                const_mem: const_mem,
qinsoon's avatar
qinsoon committed
108
109
110
111
112
113
114
115
116
117
                mc: None,
                frame: frame,
                start: start,
                end: end
            })
        })
    }
}

impl CompiledFunction {
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
    pub fn new(func_id: MuID, fv_id: MuID, mc: Box<MachineCode + Send + Sync>,
               constants: HashMap<MuID, P<Value>>, constant_locs: HashMap<MuID, P<Value>>,
               frame: Frame, start_loc: ValueLocation, end_loc: ValueLocation) -> CompiledFunction {
        CompiledFunction {
            func_id: func_id,
            func_ver_id: fv_id,
            temps:  HashMap::new(),
            consts: constants,
            const_mem: constant_locs,
            mc: Some(mc),
            frame: frame,
            start: start_loc,
            end: end_loc
        }
    }

134
    pub fn mc(&self) -> &Box<MachineCode + Send + Sync> {
qinsoon's avatar
qinsoon committed
135
136
137
138
139
140
141
142
        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)")
        }
    }
    
143
    pub fn mc_mut(&mut self) -> &mut Box<MachineCode + Send + Sync> {
qinsoon's avatar
qinsoon committed
144
145
146
147
148
        match self.mc {
            Some(ref mut mc) => mc,
            None => panic!("no mc found from a compiled function")
        }
    }
149
150
}

151
152
use std::any::Any;

153
pub trait MachineCode {
154
155
156
    fn trace_mc(&self);
    fn trace_inst(&self, index: usize);
    
157
    fn emit(&self) -> Vec<u8>;
158
159
    
    fn number_of_insts(&self) -> usize;
qinsoon's avatar
qinsoon committed
160
    
161
    fn is_move(&self, index: usize) -> bool;
qinsoon's avatar
qinsoon committed
162
    fn is_using_mem_op(&self, index: usize) -> bool;
163
164
    fn is_jmp(&self, index: usize) -> Option<MuName>;
    fn is_label(&self, index: usize) -> Option<MuName>;
qinsoon's avatar
qinsoon committed
165
    
qinsoon's avatar
qinsoon committed
166
167
    fn get_succs(&self, index: usize) -> &Vec<usize>;
    fn get_preds(&self, index: usize) -> &Vec<usize>;
168
    
qinsoon's avatar
qinsoon committed
169
170
    fn get_inst_reg_uses(&self, index: usize) -> Vec<MuID>;
    fn get_inst_reg_defines(&self, index: usize) -> Vec<MuID>;
171
    
172
173
    fn get_ir_block_livein(&self, block: &str) -> Option<&Vec<MuID>>;
    fn get_ir_block_liveout(&self, block: &str) -> Option<&Vec<MuID>>;
174
175
    fn set_ir_block_livein(&mut self, block: &str, set: Vec<MuID>);
    fn set_ir_block_liveout(&mut self, block: &str, set: Vec<MuID>);
176
    
qinsoon's avatar
qinsoon committed
177
    fn get_all_blocks(&self) -> Vec<MuName>;
178
    // returns [start_inst, end_inst) // end_inst not included
179
    fn get_block_range(&self, block: &str) -> Option<ops::Range<usize>>;
qinsoon's avatar
qinsoon committed
180
181

    // functions for rewrite
qinsoon's avatar
qinsoon committed
182

183
    /// replace a temp with a machine register (to_reg must be a machine register)
184
    fn replace_reg(&mut self, from: MuID, to: MuID);
qinsoon's avatar
qinsoon committed
185
    /// replace a temp that is defined in the inst with another temp
186
    fn replace_define_tmp_for_inst(&mut self, from: MuID, to: MuID, inst: usize);
qinsoon's avatar
qinsoon committed
187
    /// replace a temp that is used in the inst with another temp
188
    fn replace_use_tmp_for_inst(&mut self, from: MuID, to: MuID, inst: usize);
qinsoon's avatar
qinsoon committed
189
    /// set an instruction as nop
190
    fn set_inst_nop(&mut self, index: usize);
qinsoon's avatar
qinsoon committed
191
192
193
    /// 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>;
qinsoon's avatar
qinsoon committed
194
195
    /// patch frame size
    fn patch_frame_size(&mut self, size: usize);
196
197

    fn as_any(&self) -> &Any;
198
}
199
200
201

pub trait MachineInst {

202
}