codegen.rs 11 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// Copyright 2017 The Australian National University
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

15 16
use ast::ptr::P;
use ast::ir::*;
qinsoon's avatar
qinsoon committed
17
use runtime::ValueLocation;
18

qinsoon's avatar
qinsoon committed
19
use compiler::machine_code::MachineCode;
20
use compiler::backend::{Reg, Mem};
21

22
pub trait CodeGenerator {
23
    fn start_code(&mut self, func_name: MuName, entry: MuName) -> ValueLocation;
24
    fn finish_code(&mut self, func_name: MuName) -> (Box<MachineCode + Sync + Send>, ValueLocation);
25 26 27 28

    // generate unnamed sequence of linear code (no branch)
    fn start_code_sequence(&mut self);
    fn finish_code_sequence(&mut self) -> Box<MachineCode + Sync + Send>;
29 30 31
    
    fn print_cur_code(&self);
    
qinsoon's avatar
qinsoon committed
32
    fn start_block(&mut self, block_name: MuName);
qinsoon's avatar
qinsoon committed
33
    fn start_exception_block(&mut self, block_name: MuName) -> ValueLocation;
qinsoon's avatar
qinsoon committed
34 35 36
    fn set_block_livein(&mut self, block_name: MuName, live_in: &Vec<P<Value>>);
    fn set_block_liveout(&mut self, block_name: MuName, live_out: &Vec<P<Value>>);
    fn end_block(&mut self, block_name: MuName);
qinsoon's avatar
qinsoon committed
37

qinsoon's avatar
qinsoon committed
38 39 40 41 42 43 44 45
    // add CFI info
    fn add_cfi_startproc(&mut self);
    fn add_cfi_endproc(&mut self);
    fn add_cfi_def_cfa_register(&mut self, reg: Reg);
    fn add_cfi_def_cfa_offset(&mut self, offset: i32);
    fn add_cfi_offset(&mut self, reg: Reg, offset: i32);

    // emit code to adjust frame
qinsoon's avatar
qinsoon committed
46 47
    fn emit_frame_grow(&mut self);
    fn emit_frame_shrink(&mut self);
48
    
49
    fn emit_nop(&mut self, bytes: usize);
50 51

    // comparison
52 53 54
    fn emit_cmp_r_r  (&mut self, op1: Reg, op2: Reg);
    fn emit_cmp_imm_r(&mut self, op1: i32, op2: Reg);
    fn emit_cmp_mem_r(&mut self, op1: Reg, op2: Reg);
55

qinsoon's avatar
qinsoon committed
56 57
    fn emit_test_r_r  (&mut self, op1: Reg, op2: Reg);
    fn emit_test_imm_r(&mut self, op1: i32, op2: Reg);
58

59
    // gpr move
qinsoon's avatar
qinsoon committed
60 61

    // mov imm64 to r64
62
    fn emit_mov_r64_imm64  (&mut self, dest: Reg, src: i64);
qinsoon's avatar
qinsoon committed
63 64
    // mov r64 to fpr
    fn emit_mov_fpr_r64 (&mut self, dest: Reg, src: Reg);
65 66 67 68 69

    fn emit_mov_r_imm  (&mut self, dest: Reg, src: i32);
    fn emit_mov_r_mem  (&mut self, dest: Reg, src: Mem); // load
    fn emit_mov_r_r    (&mut self, dest: Reg, src: Reg);
    fn emit_mov_mem_r  (&mut self, dest: Mem, src: Reg); // store
70 71 72
    // we can infer imm length from Reg, but cannot from Mem
    // because mem may only have type as ADDRESS_TYPE
    fn emit_mov_mem_imm(&mut self, dest: Mem, src: i32, oplen: usize); // store
73

74 75 76 77
    fn emit_mov_mem_r_callee_saved  (&mut self, dest: Mem, src: Reg); // store callee saved register
    fn emit_mov_r_mem_callee_saved  (&mut self, dest: Reg, src: Mem); // load callee saved register


78 79 80
    // zero/sign extend mov
    fn emit_movs_r_r   (&mut self, dest: Reg, src: Reg);
    fn emit_movz_r_r   (&mut self, dest: Reg, src: Reg);
81

qinsoon's avatar
qinsoon committed
82 83 84 85 86 87
    // set byte
    fn emit_sets_r8    (&mut self, dest: Reg);
    fn emit_setz_r8    (&mut self, dest: Reg);
    fn emit_seto_r8    (&mut self, dest: Reg);
    fn emit_setb_r8    (&mut self, dest: Reg);

88 89 90 91 92 93 94 95 96 97 98
    fn emit_seta_r  (&mut self, dest: Reg);
    fn emit_setae_r  (&mut self, dest: Reg);
    fn emit_setb_r  (&mut self, dest: Reg);
    fn emit_setbe_r  (&mut self, dest: Reg);
    fn emit_sete_r  (&mut self, dest: Reg);
    fn emit_setg_r  (&mut self, dest: Reg);
    fn emit_setge_r  (&mut self, dest: Reg);
    fn emit_setl_r  (&mut self, dest: Reg);
    fn emit_setle_r  (&mut self, dest: Reg);
    fn emit_setne_r  (&mut self, dest: Reg);

qinsoon's avatar
qinsoon committed
99 100
    // gpr conditional move

101 102
    fn emit_cmova_r_r  (&mut self, dest: Reg, src: Reg);
    fn emit_cmova_r_mem(&mut self, dest: Reg, src: Mem); // load
qinsoon's avatar
qinsoon committed
103

104 105
    fn emit_cmovae_r_r  (&mut self, dest: Reg, src: Reg);
    fn emit_cmovae_r_mem(&mut self, dest: Reg, src: Mem); // load
qinsoon's avatar
qinsoon committed
106

107 108
    fn emit_cmovb_r_r  (&mut self, dest: Reg, src: Reg);
    fn emit_cmovb_r_mem(&mut self, dest: Reg, src: Mem); // load
qinsoon's avatar
qinsoon committed
109

110 111
    fn emit_cmovbe_r_r  (&mut self, dest: Reg, src: Reg);
    fn emit_cmovbe_r_mem(&mut self, dest: Reg, src: Mem); // load
qinsoon's avatar
qinsoon committed
112

113 114
    fn emit_cmove_r_r  (&mut self, dest: Reg, src: Reg);
    fn emit_cmove_r_mem(&mut self, dest: Reg, src: Mem); // load
qinsoon's avatar
qinsoon committed
115

116 117
    fn emit_cmovg_r_r  (&mut self, dest: Reg, src: Reg);
    fn emit_cmovg_r_mem(&mut self, dest: Reg, src: Mem); // load
qinsoon's avatar
qinsoon committed
118

119 120
    fn emit_cmovge_r_r  (&mut self, dest: Reg, src: Reg);
    fn emit_cmovge_r_mem(&mut self, dest: Reg, src: Mem); // load
qinsoon's avatar
qinsoon committed
121

122 123
    fn emit_cmovl_r_r  (&mut self, dest: Reg, src: Reg);
    fn emit_cmovl_r_mem(&mut self, dest: Reg, src: Mem); // load
qinsoon's avatar
qinsoon committed
124

125 126
    fn emit_cmovle_r_r  (&mut self, dest: Reg, src: Reg);
    fn emit_cmovle_r_mem(&mut self, dest: Reg, src: Mem); // load
qinsoon's avatar
qinsoon committed
127

128 129
    fn emit_cmovne_r_r  (&mut self, dest: Reg, src: Reg);
    fn emit_cmovne_r_mem(&mut self, dest: Reg, src: Mem); // load
qinsoon's avatar
qinsoon committed
130

131
    // lea
132
    fn emit_lea_r64(&mut self, dest: Reg, src: Mem);
133 134

    // and
135 136 137
    fn emit_and_r_imm(&mut self, dest: Reg, src: i32);
    fn emit_and_r_r  (&mut self, dest: Reg, src: Reg);
    fn emit_and_r_mem(&mut self, dest: Reg, src: Mem);
138

139 140 141 142
    // or
    fn emit_or_r_r  (&mut self, dest: Reg, src: Reg);
    fn emit_or_r_imm(&mut self, dest: Reg, src: i32);
    fn emit_or_r_mem(&mut self, dest: Reg, src: Mem);
143

144
    // xor
145 146 147
    fn emit_xor_r_r  (&mut self, dest: Reg, src: Reg);
    fn emit_xor_r_mem(&mut self, dest: Reg, src: Mem);
    fn emit_xor_r_imm(&mut self, dest: Reg, src: i32);
148

149
    // add
150 151 152
    fn emit_add_r_r  (&mut self, dest: Reg, src: Reg);
    fn emit_add_r_mem(&mut self, dest: Reg, src: Mem);
    fn emit_add_r_imm(&mut self, dest: Reg, src: i32);
qinsoon's avatar
qinsoon committed
153 154 155 156 157

    // add with carry
    fn emit_adc_r_r  (&mut self, dest: Reg, src: Reg);
    fn emit_adc_r_mem(&mut self, dest: Reg, src: Mem);
    fn emit_adc_r_imm(&mut self, dest: Reg, src: i32);
qinsoon's avatar
qinsoon committed
158
    
159
    // sub
160 161 162
    fn emit_sub_r_r  (&mut self, dest: Reg, src: Reg);
    fn emit_sub_r_mem(&mut self, dest: Reg, src: Mem);
    fn emit_sub_r_imm(&mut self, dest: Reg, src: i32);
163

164 165 166 167 168
    // sub with borrow
    fn emit_sbb_r_r  (&mut self, dest: Reg, src: Reg);
    fn emit_sbb_r_mem(&mut self, dest: Reg, src: Mem);
    fn emit_sbb_r_imm(&mut self, dest: Reg, src: i32);

169
    // multiply
170 171
    fn emit_mul_r  (&mut self, src: Reg);
    fn emit_mul_mem(&mut self, src: Mem);
172

173 174 175
    // signed multiply
    fn emit_imul_r_r(&mut self, dest: Reg, src: Reg);

176
    // div
177 178
    fn emit_div_r   (&mut self, src: Reg);
    fn emit_div_mem (&mut self, src: Mem);
179 180

    // idiv
181 182
    fn emit_idiv_r  (&mut self, src: Reg);
    fn emit_idiv_mem(&mut self, src: Mem);
183 184

    // shl
185 186 187
    fn emit_shl_r_cl    (&mut self, dest: Reg);
    fn emit_shl_r_imm8  (&mut self, dest: Reg, src: i8);

qinsoon's avatar
qinsoon committed
188 189
    fn emit_shld_r_r_cl (&mut self, dest: Reg, src: Reg);

190 191 192
    fn emit_shr_r_cl    (&mut self, dest: &P<Value>);
    fn emit_shr_r_imm8  (&mut self, dest: &P<Value>, src: i8);

qinsoon's avatar
qinsoon committed
193 194
    fn emit_shrd_r_r_cl (&mut self, dest: Reg, src: Reg);

195 196
    fn emit_sar_r_cl    (&mut self, dest: &P<Value>);
    fn emit_sar_r_imm8  (&mut self, dest: &P<Value>, src: i8);
qinsoon's avatar
qinsoon committed
197

qinsoon's avatar
qinsoon committed
198 199 200
    fn emit_cqo(&mut self); // sign extend rax to rdx:rax
    fn emit_cdq(&mut self); // sign extend eax to edx:eax
    fn emit_cwd(&mut self); // sign extend ax  to dx:ax
201
    
202
    fn emit_jmp(&mut self, dest: MuName);
qinsoon's avatar
qinsoon committed
203
    fn emit_je (&mut self, dest: MuName);
204
    fn emit_jne(&mut self, dest: MuName);
qinsoon's avatar
qinsoon committed
205
    fn emit_ja (&mut self, dest: MuName);
206
    fn emit_jae(&mut self, dest: MuName);
qinsoon's avatar
qinsoon committed
207
    fn emit_jb (&mut self, dest: MuName);
208
    fn emit_jbe(&mut self, dest: MuName);
qinsoon's avatar
qinsoon committed
209
    fn emit_jg (&mut self, dest: MuName);
210
    fn emit_jge(&mut self, dest: MuName);
qinsoon's avatar
qinsoon committed
211
    fn emit_jl (&mut self, dest: MuName);
212
    fn emit_jle(&mut self, dest: MuName);
213 214

    fn emit_js(&mut self, dest: MuName);
qinsoon's avatar
qinsoon committed
215
    
216 217 218
    fn emit_call_near_rel32(&mut self, callsite: String, func: MuName,    pe: Option<MuName>) -> ValueLocation;
    fn emit_call_near_r64  (&mut self, callsite: String, func: &P<Value>, pe: Option<MuName>) -> ValueLocation;
    fn emit_call_near_mem64(&mut self, callsite: String, func: &P<Value>, pe: Option<MuName>) -> ValueLocation;
219
    
qinsoon's avatar
qinsoon committed
220
    fn emit_ret(&mut self);
qinsoon's avatar
qinsoon committed
221

222
    fn emit_push_r64(&mut self, src: &P<Value>);
223
    fn emit_push_imm32(&mut self, src: i32);
224
    fn emit_pop_r64(&mut self, dest: &P<Value>);
225 226 227 228 229

    // fpr move
    fn emit_movsd_f64_f64  (&mut self, dest: &P<Value>, src: &P<Value>);
    fn emit_movsd_f64_mem64(&mut self, dest: &P<Value>, src: &P<Value>); // load
    fn emit_movsd_mem64_f64(&mut self, dest: &P<Value>, src: &P<Value>); // store
qinsoon's avatar
qinsoon committed
230

231 232 233 234
    fn emit_movss_f32_f32  (&mut self, dest: &P<Value>, src: &P<Value>);
    fn emit_movss_f32_mem32(&mut self, dest: &P<Value>, src: &P<Value>); // load
    fn emit_movss_mem32_f32(&mut self, dest: &P<Value>, src: &P<Value>); // store

qinsoon's avatar
qinsoon committed
235 236 237 238
    // fp add
    fn emit_addsd_f64_f64  (&mut self, dest: Reg, src: Reg);
    fn emit_addsd_f64_mem64(&mut self, dest: Reg, src: Mem);

239 240 241
    fn emit_addss_f32_f32  (&mut self, dest: Reg, src: Reg);
    fn emit_addss_f32_mem32(&mut self, dest: Reg, src: Mem);

qinsoon's avatar
qinsoon committed
242 243 244 245
    // fp sub
    fn emit_subsd_f64_f64  (&mut self, dest: Reg, src: Reg);
    fn emit_subsd_f64_mem64(&mut self, dest: Reg, src: Mem);

246 247 248
    fn emit_subss_f32_f32  (&mut self, dest: Reg, src: Reg);
    fn emit_subss_f32_mem32(&mut self, dest: Reg, src: Mem);

qinsoon's avatar
qinsoon committed
249 250 251 252
    // fp div
    fn emit_divsd_f64_f64  (&mut self, dest: Reg, src: Reg);
    fn emit_divsd_f64_mem64(&mut self, dest: Reg, src: Mem);

253 254 255
    fn emit_divss_f32_f32  (&mut self, dest: Reg, src: Reg);
    fn emit_divss_f32_mem32(&mut self, dest: Reg, src: Mem);

qinsoon's avatar
qinsoon committed
256 257 258 259
    // fp mul
    fn emit_mulsd_f64_f64  (&mut self, dest: Reg, src: Reg);
    fn emit_mulsd_f64_mem64(&mut self, dest: Reg, src: Mem);

260 261 262
    fn emit_mulss_f32_f32  (&mut self, dest: Reg, src: Reg);
    fn emit_mulss_f32_mem32(&mut self, dest: Reg, src: Mem);

qinsoon's avatar
qinsoon committed
263 264 265
    // fp comparison
    fn emit_comisd_f64_f64  (&mut self, op1: Reg, op2: Reg);
    fn emit_ucomisd_f64_f64 (&mut self, op1: Reg, op2: Reg);
266

267 268 269
    fn emit_comiss_f32_f32  (&mut self, op1: Reg, op2: Reg);
    fn emit_ucomiss_f32_f32 (&mut self, op1: Reg, op2: Reg);

270 271 272
    // fp conversion
    fn emit_cvtsi2sd_f64_r  (&mut self, dest: Reg, src: Reg);
    fn emit_cvtsd2si_r_f64  (&mut self, dest: Reg, src: Reg);
273 274 275

    fn emit_cvtsi2ss_f32_r  (&mut self, dest: Reg, src: Reg);
    fn emit_cvtss2si_r_f32  (&mut self, dest: Reg, src: Reg);
276 277 278

    // used for unsigned int to fp conversion

279
    fn emit_cvttsd2si_r_f64 (&mut self, dest: Reg, src: Reg);
280
    fn emit_cvttss2si_r_f32 (&mut self, dest: Reg, src: Reg);
281

282 283 284 285 286 287
    // unpack low data - interleave low byte
    fn emit_punpckldq_f64_mem128(&mut self, dest: Reg, src: Mem);
    // substract packed double-fp
    fn emit_subpd_f64_mem128   (&mut self, dest: Reg, src: Mem);
    // packed double-fp horizontal add
    fn emit_haddpd_f64_f64     (&mut self, dest: Reg, src: Reg);
288 289 290 291

    // move aligned packed double-precision fp values
    fn emit_movapd_f64_mem128(&mut self, dest: Reg, src: Mem);
    fn emit_movapd_f64_f64   (&mut self, dest: Reg, src: Mem);
292 293

    fn emit_movaps_f32_f32   (&mut self, dest: Reg, src: Reg);
294
}