To protect your data, the CISO officer has suggested users to enable GitLab 2FA as soon as possible.

machine_code.rs 6.82 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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
            let mut i = 0;

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

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

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

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

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

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

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

            try!(s.emit_struct_field("end",         i, |s| self.end.encode(s)));
qinsoon's avatar
qinsoon committed
58
59
60
61
62
63
64
65
66
            
            Ok(())
        })
    }
}

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

qinsoon's avatar
qinsoon committed
69
            let func_id = 
70
71
                try!(d.read_struct_field("func_id",     i, |d| Decodable::decode(d)));
            i += 1;
qinsoon's avatar
qinsoon committed
72
            let func_ver_id = 
73
74
                try!(d.read_struct_field("func_ver_id", i, |d| Decodable::decode(d)));
            i += 1;
qinsoon's avatar
qinsoon committed
75
            let temps = 
76
77
78
79
80
81
82
83
                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
84
            let frame = 
85
86
                try!(d.read_struct_field("frame",       i, |d| Decodable::decode(d)));
            i += 1;
qinsoon's avatar
qinsoon committed
87
            let start = 
88
89
                try!(d.read_struct_field("start",       i, |d| Decodable::decode(d)));
            i += 1;
qinsoon's avatar
qinsoon committed
90
            let end =
91
                try!(d.read_struct_field("end",         i, |d| Decodable::decode(d)));
qinsoon's avatar
qinsoon committed
92
93
94
95
96
            
            Ok(CompiledFunction{
                func_id: func_id,
                func_ver_id: func_ver_id,
                temps: temps,
97
98
                consts: consts,
                const_mem: const_mem,
qinsoon's avatar
qinsoon committed
99
100
101
102
103
104
105
106
107
108
                mc: None,
                frame: frame,
                start: start,
                end: end
            })
        })
    }
}

impl CompiledFunction {
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
    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
        }
    }

125
    pub fn mc(&self) -> &Box<MachineCode + Send + Sync> {
qinsoon's avatar
qinsoon committed
126
127
128
129
130
131
132
133
        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)")
        }
    }
    
134
    pub fn mc_mut(&mut self) -> &mut Box<MachineCode + Send + Sync> {
qinsoon's avatar
qinsoon committed
135
136
137
138
139
        match self.mc {
            Some(ref mut mc) => mc,
            None => panic!("no mc found from a compiled function")
        }
    }
140
141
}

142
143
use std::any::Any;

144
pub trait MachineCode {
145
146
147
    fn trace_mc(&self);
    fn trace_inst(&self, index: usize);
    
148
    fn emit(&self) -> Vec<u8>;
149
    fn emit_inst(&self, index: usize) -> Vec<u8>;
150
151
    
    fn number_of_insts(&self) -> usize;
qinsoon's avatar
qinsoon committed
152
    
153
    fn is_move(&self, index: usize) -> bool;
qinsoon's avatar
qinsoon committed
154
    fn is_using_mem_op(&self, index: usize) -> bool;
155
156
    fn is_jmp(&self, index: usize) -> Option<MuName>;
    fn is_label(&self, index: usize) -> Option<MuName>;
qinsoon's avatar
qinsoon committed
157
158
159

    fn is_spill_load(&self, index: usize) -> Option<P<Value>>;
    fn is_spill_store(&self, index: usize) -> Option<P<Value>>;
qinsoon's avatar
qinsoon committed
160
    
qinsoon's avatar
qinsoon committed
161
162
    fn get_succs(&self, index: usize) -> &Vec<usize>;
    fn get_preds(&self, index: usize) -> &Vec<usize>;
163
164
165

    fn get_next_inst(&self, index: usize) -> Option<usize>;
    fn get_last_inst(&self, index: usize) -> Option<usize>;
166
    
qinsoon's avatar
qinsoon committed
167
168
    fn get_inst_reg_uses(&self, index: usize) -> Vec<MuID>;
    fn get_inst_reg_defines(&self, index: usize) -> Vec<MuID>;
169
    
170
171
    fn get_ir_block_livein(&self, block: &str) -> Option<&Vec<MuID>>;
    fn get_ir_block_liveout(&self, block: &str) -> Option<&Vec<MuID>>;
172
173
    fn set_ir_block_livein(&mut self, block: &str, set: Vec<MuID>);
    fn set_ir_block_liveout(&mut self, block: &str, set: Vec<MuID>);
174
    
qinsoon's avatar
qinsoon committed
175
    fn get_all_blocks(&self) -> Vec<MuName>;
176
    fn get_entry_block(&self) -> MuName;
177
    // returns [start_inst, end_inst) // end_inst not included
178
    fn get_block_range(&self, block: &str) -> Option<ops::Range<usize>>;
179
    fn get_block_for_inst(&self, index: usize) -> Option<MuName>;
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
    /// patch frame size
195
    fn patch_frame_size(&mut self, size: usize, size_used: usize);
196
197

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

pub trait MachineInst {

202
}