GitLab will be upgraded on 30 Jan 2023 from 2.00 pm (AEDT) to 3.00 pm (AEDT). During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to us at N110 (b) CSIT building.

machine_code.rs 6.71 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
150
    
    fn number_of_insts(&self) -> usize;
qinsoon's avatar
qinsoon committed
151
    
152
    fn is_move(&self, index: usize) -> bool;
qinsoon's avatar
qinsoon committed
153
    fn is_using_mem_op(&self, index: usize) -> bool;
154
155
    fn is_jmp(&self, index: usize) -> Option<MuName>;
    fn is_label(&self, index: usize) -> Option<MuName>;
qinsoon's avatar
qinsoon committed
156
157
158

    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
159
    
qinsoon's avatar
qinsoon committed
160
161
    fn get_succs(&self, index: usize) -> &Vec<usize>;
    fn get_preds(&self, index: usize) -> &Vec<usize>;
162
163
164

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

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

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

    fn as_any(&self) -> &Any;
196
}
197
198
199

pub trait MachineInst {

200
}