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.

codegen.rs 12.9 KB
Newer Older
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1
// Copyright 2017 The Australian National University
2
//
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
3
4
5
// 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
6
//
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
9
10
11
12
13
14
// 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;
qinsoon's avatar
qinsoon committed
20
use compiler::backend::{Reg, Mem};
21

qinsoon's avatar
qinsoon committed
22
23
24
25
26
/// CodeGenerator provides an interface to emit x86_64 code for instruction selection.
/// This allows us to implement the other parts of the compiler (mostly instruction selection)
/// without assuming code generator. Currently there is only an assembly backend
/// that implements this interface for ahead-of-time compilation. We plan to add
/// a binary backend for just-in-time compilation.
27
pub trait CodeGenerator {
qinsoon's avatar
qinsoon committed
28
    /// starts code for a function
29
    fn start_code(&mut self, func_name: MuName, entry: MuName) -> ValueLocation;
qinsoon's avatar
qinsoon committed
30
    /// finishes code for a function
31
32
    fn finish_code(&mut self, func_name: MuName)
        -> (Box<MachineCode + Sync + Send>, ValueLocation);
33

qinsoon's avatar
qinsoon committed
34
    /// starts a sequence of linear code (no branch)
35
    fn start_code_sequence(&mut self);
qinsoon's avatar
qinsoon committed
36
    /// finishes code for a sequence
37
    fn finish_code_sequence(&mut self) -> Box<MachineCode + Sync + Send>;
qinsoon's avatar
qinsoon committed
38
39

    /// outputs current code (via debug! log)
qinsoon's avatar
qinsoon committed
40
    fn print_cur_code(&self);
qinsoon's avatar
qinsoon committed
41
42

    /// starts a block
qinsoon's avatar
qinsoon committed
43
    fn start_block(&mut self, block_name: MuName);
qinsoon's avatar
qinsoon committed
44
    /// starts an exceptional block, and returns its code address
qinsoon's avatar
qinsoon committed
45
    fn start_exception_block(&mut self, block_name: MuName) -> ValueLocation;
qinsoon's avatar
qinsoon committed
46
47
    /// finishes a block (must have called start_block() or start_excpetion_block() first)
    fn end_block(&mut self, block_name: MuName);
qinsoon's avatar
qinsoon committed
48

qinsoon's avatar
qinsoon committed
49
    // adds CFI info
qinsoon's avatar
qinsoon committed
50
51
52
53
54
55
    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);

qinsoon's avatar
qinsoon committed
56
    // emit code to adjust frame size
qinsoon's avatar
qinsoon committed
57
    fn emit_frame_grow(&mut self);
58

qinsoon's avatar
qinsoon committed
59
    fn emit_nop(&mut self, bytes: usize);
60
61

    // comparison
62
    fn emit_cmp_r_r(&mut self, op1: Reg, op2: Reg);
qinsoon's avatar
qinsoon committed
63
64
    fn emit_cmp_imm_r(&mut self, op1: i32, op2: Reg);
    fn emit_cmp_mem_r(&mut self, op1: Reg, op2: Reg);
65

66
    fn emit_test_r_r(&mut self, op1: Reg, op2: Reg);
qinsoon's avatar
qinsoon committed
67
    fn emit_test_imm_r(&mut self, op1: i32, op2: Reg);
qinsoon's avatar
qinsoon committed
68

69
    // gpr move
qinsoon's avatar
qinsoon committed
70
71

    // mov imm64 to r64
72
    fn emit_mov_r64_imm64(&mut self, dest: Reg, src: i64);
qinsoon's avatar
qinsoon committed
73
    // bitcast between int and floatpoint of same length
74
    fn emit_mov_fpr_r64(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
75
76
77
    fn emit_mov_fpr_r32(&mut self, dest: Reg, src: Reg);
    fn emit_mov_r64_fpr(&mut self, dest: Reg, src: Reg);
    fn emit_mov_r32_fpr(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
78

79
80
81
82
    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
83
84
85
    // 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
qinsoon's avatar
qinsoon committed
86

87
88
    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
89

qinsoon's avatar
qinsoon committed
90
    // zero/sign extend mov
91
92
    fn emit_movs_r_r(&mut self, dest: Reg, src: Reg);
    fn emit_movz_r_r(&mut self, dest: Reg, src: Reg);
93

qinsoon's avatar
qinsoon committed
94
    // set byte
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
    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);

    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);
110

qinsoon's avatar
qinsoon committed
111
112
    // gpr conditional move

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

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

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

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

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

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

131
    fn emit_cmovge_r_r(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
132
    fn emit_cmovge_r_mem(&mut self, dest: Reg, src: Mem); // load
qinsoon's avatar
qinsoon committed
133

134
    fn emit_cmovl_r_r(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
135
    fn emit_cmovl_r_mem(&mut self, dest: Reg, src: Mem); // load
qinsoon's avatar
qinsoon committed
136

137
    fn emit_cmovle_r_r(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
138
    fn emit_cmovle_r_mem(&mut self, dest: Reg, src: Mem); // load
qinsoon's avatar
qinsoon committed
139

140
    fn emit_cmovne_r_r(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
141
    fn emit_cmovne_r_mem(&mut self, dest: Reg, src: Mem); // load
qinsoon's avatar
qinsoon committed
142

143
    // lea
qinsoon's avatar
qinsoon committed
144
    fn emit_lea_r64(&mut self, dest: Reg, src: Mem);
145
146

    // and
qinsoon's avatar
qinsoon committed
147
    fn emit_and_r_imm(&mut self, dest: Reg, src: i32);
148
    fn emit_and_r_r(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
149
    fn emit_and_r_mem(&mut self, dest: Reg, src: Mem);
150

qinsoon's avatar
qinsoon committed
151
    // or
152
    fn emit_or_r_r(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
153
154
    fn emit_or_r_imm(&mut self, dest: Reg, src: i32);
    fn emit_or_r_mem(&mut self, dest: Reg, src: Mem);
qinsoon's avatar
qinsoon committed
155

156
    // xor
157
    fn emit_xor_r_r(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
158
159
    fn emit_xor_r_mem(&mut self, dest: Reg, src: Mem);
    fn emit_xor_r_imm(&mut self, dest: Reg, src: i32);
160

161
    // add
162
    fn emit_add_r_r(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
163
164
    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
165
166

    // add with carry
167
    fn emit_adc_r_r(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
168
169
    fn emit_adc_r_mem(&mut self, dest: Reg, src: Mem);
    fn emit_adc_r_imm(&mut self, dest: Reg, src: i32);
170

171
    // sub
172
    fn emit_sub_r_r(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
173
174
    fn emit_sub_r_mem(&mut self, dest: Reg, src: Mem);
    fn emit_sub_r_imm(&mut self, dest: Reg, src: i32);
175

176
    // sub with borrow
177
    fn emit_sbb_r_r(&mut self, dest: Reg, src: Reg);
178
179
180
    fn emit_sbb_r_mem(&mut self, dest: Reg, src: Mem);
    fn emit_sbb_r_imm(&mut self, dest: Reg, src: i32);

qinsoon's avatar
qinsoon committed
181
182
183
184
185
186
    // inc and dec
    fn emit_inc_r(&mut self, dest: Reg);
    fn emit_inc_mem(&mut self, dest: Mem);
    fn emit_dec_r(&mut self, dest: Reg);
    fn emit_dec_mem(&mut self, dest: Mem);

187
    // multiply
188
    fn emit_mul_r(&mut self, src: Reg);
qinsoon's avatar
qinsoon committed
189
    fn emit_mul_mem(&mut self, src: Mem);
190

191
192
193
    // signed multiply
    fn emit_imul_r_r(&mut self, dest: Reg, src: Reg);

194
    // div
195
196
    fn emit_div_r(&mut self, src: Reg);
    fn emit_div_mem(&mut self, src: Mem);
197
198

    // idiv
199
    fn emit_idiv_r(&mut self, src: Reg);
qinsoon's avatar
qinsoon committed
200
    fn emit_idiv_mem(&mut self, src: Mem);
201
202

    // shl
203
204
205
    fn emit_shl_r_cl(&mut self, dest: Reg);
    fn emit_shl_r_imm8(&mut self, dest: Reg, src: i8);
    fn emit_shld_r_r_cl(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
206

207
208
209
    fn emit_shr_r_cl(&mut self, dest: &P<Value>);
    fn emit_shr_r_imm8(&mut self, dest: &P<Value>, src: i8);
    fn emit_shrd_r_r_cl(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
210

211
212
    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
213

qinsoon's avatar
qinsoon committed
214
215
216
    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
qinsoon's avatar
qinsoon committed
217
218

    // jump, conditional jump
219
    fn emit_jmp(&mut self, dest: MuName);
220
    fn emit_je(&mut self, dest: MuName);
221
    fn emit_jne(&mut self, dest: MuName);
222
    fn emit_ja(&mut self, dest: MuName);
223
    fn emit_jae(&mut self, dest: MuName);
224
    fn emit_jb(&mut self, dest: MuName);
225
    fn emit_jbe(&mut self, dest: MuName);
226
    fn emit_jg(&mut self, dest: MuName);
227
    fn emit_jge(&mut self, dest: MuName);
228
    fn emit_jl(&mut self, dest: MuName);
229
    fn emit_jle(&mut self, dest: MuName);
qinsoon's avatar
qinsoon committed
230
    fn emit_js(&mut self, dest: MuName);
qinsoon's avatar
qinsoon committed
231
232

    // call
233
234
    fn emit_call_near_rel32(
        &mut self,
235
        callsite: MuName,
236
237
        func: MuName,
        pe: Option<MuName>,
238
239
        uses: Vec<P<Value>>,
        defs: Vec<P<Value>>,
240
        is_native: bool
241
242
243
    ) -> ValueLocation;
    fn emit_call_near_r64(
        &mut self,
244
        callsite: MuName,
245
246
        func: &P<Value>,
        pe: Option<MuName>,
247
248
        uses: Vec<P<Value>>,
        defs: Vec<P<Value>>
249
250
251
    ) -> ValueLocation;
    fn emit_call_near_mem64(
        &mut self,
252
        callsite: MuName,
253
254
        func: &P<Value>,
        pe: Option<MuName>,
255
256
        uses: Vec<P<Value>>,
        defs: Vec<P<Value>>
257
258
    ) -> ValueLocation;

259
260
261
    // sometimes we use jmp as a call (but without pushing return address)
    fn emit_call_jmp(
        &mut self,
262
        callsite: MuName,
263
264
265
266
267
268
269
270
        func: MuName,
        pe: Option<MuName>,
        uses: Vec<P<Value>>,
        defs: Vec<P<Value>>,
        is_native: bool
    ) -> ValueLocation;
    fn emit_call_jmp_indirect(
        &mut self,
271
        callsite: MuName,
272
273
274
275
276
277
        func: &P<Value>,
        pe: Option<MuName>,
        uses: Vec<P<Value>>,
        defs: Vec<P<Value>>
    ) -> ValueLocation;

qinsoon's avatar
qinsoon committed
278
    fn emit_ret(&mut self);
qinsoon's avatar
qinsoon committed
279

qinsoon's avatar
qinsoon committed
280
    // push/pop
qinsoon's avatar
qinsoon committed
281
    fn emit_push_r64(&mut self, src: &P<Value>);
282
    fn emit_push_imm32(&mut self, src: i32);
qinsoon's avatar
qinsoon committed
283
    fn emit_pop_r64(&mut self, dest: &P<Value>);
284
285

    // fpr move
286
    fn emit_movsd_f64_f64(&mut self, dest: &P<Value>, src: &P<Value>);
287
288
    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
289

290
    fn emit_movss_f32_f32(&mut self, dest: &P<Value>, src: &P<Value>);
291
292
293
    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
294
    // fp add
295
    fn emit_addsd_f64_f64(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
296
297
    fn emit_addsd_f64_mem64(&mut self, dest: Reg, src: Mem);

298
    fn emit_addss_f32_f32(&mut self, dest: Reg, src: Reg);
299
300
    fn emit_addss_f32_mem32(&mut self, dest: Reg, src: Mem);

qinsoon's avatar
qinsoon committed
301
    // fp sub
302
    fn emit_subsd_f64_f64(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
303
304
    fn emit_subsd_f64_mem64(&mut self, dest: Reg, src: Mem);

305
    fn emit_subss_f32_f32(&mut self, dest: Reg, src: Reg);
306
307
    fn emit_subss_f32_mem32(&mut self, dest: Reg, src: Mem);

qinsoon's avatar
qinsoon committed
308
    // fp div
309
    fn emit_divsd_f64_f64(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
310
311
    fn emit_divsd_f64_mem64(&mut self, dest: Reg, src: Mem);

312
    fn emit_divss_f32_f32(&mut self, dest: Reg, src: Reg);
313
314
    fn emit_divss_f32_mem32(&mut self, dest: Reg, src: Mem);

qinsoon's avatar
qinsoon committed
315
    // fp mul
316
    fn emit_mulsd_f64_f64(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
317
318
    fn emit_mulsd_f64_mem64(&mut self, dest: Reg, src: Mem);

319
    fn emit_mulss_f32_f32(&mut self, dest: Reg, src: Reg);
320
321
    fn emit_mulss_f32_mem32(&mut self, dest: Reg, src: Mem);

qinsoon's avatar
qinsoon committed
322
    // fp comparison
323
324
    fn emit_comisd_f64_f64(&mut self, op1: Reg, op2: Reg);
    fn emit_ucomisd_f64_f64(&mut self, op1: Reg, op2: Reg);
qinsoon's avatar
qinsoon committed
325

326
327
    fn emit_comiss_f32_f32(&mut self, op1: Reg, op2: Reg);
    fn emit_ucomiss_f32_f32(&mut self, op1: Reg, op2: Reg);
328

qinsoon's avatar
qinsoon committed
329
330
331
332
    // fp bitwise
    fn emit_xorps_f32_f32(&mut self, dest: Reg, src: Reg);
    fn emit_xorpd_f64_f64(&mut self, dest: Reg, src: Reg);

qinsoon's avatar
qinsoon committed
333
    // fp conversion
334
335
    fn emit_cvtsi2sd_f64_r(&mut self, dest: Reg, src: Reg);
    fn emit_cvtsd2si_r_f64(&mut self, dest: Reg, src: Reg);
336

337
338
    fn emit_cvtsi2ss_f32_r(&mut self, dest: Reg, src: Reg);
    fn emit_cvtss2si_r_f32(&mut self, dest: Reg, src: Reg);
339

qinsoon's avatar
qinsoon committed
340
341
342
343
    // fp trunc
    fn emit_cvtsd2ss_f32_f64(&mut self, dest: Reg, src: Reg);
    fn emit_cvtss2sd_f64_f32(&mut self, dest: Reg, src: Reg);

344
    // used for unsigned int to fp conversion
345
346
    fn emit_cvttsd2si_r_f64(&mut self, dest: Reg, src: Reg);
    fn emit_cvttss2si_r_f32(&mut self, dest: Reg, src: Reg);
347

348
349
350
    // unpack low data - interleave low byte
    fn emit_punpckldq_f64_mem128(&mut self, dest: Reg, src: Mem);
    // substract packed double-fp
351
    fn emit_subpd_f64_mem128(&mut self, dest: Reg, src: Mem);
352
    // packed double-fp horizontal add
353
    fn emit_haddpd_f64_f64(&mut self, dest: Reg, src: Reg);
354
355
356

    // move aligned packed double-precision fp values
    fn emit_movapd_f64_mem128(&mut self, dest: Reg, src: Mem);
357
    fn emit_movapd_f64_f64(&mut self, dest: Reg, src: Mem);
qinsoon's avatar
qinsoon committed
358

359
    fn emit_movaps_f32_f32(&mut self, dest: Reg, src: Reg);
360
361
362

    // memory fence
    fn emit_mfence(&mut self);
363
}