GitLab will be upgraded on 31 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.6 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);

181
    // multiply
182
    fn emit_mul_r(&mut self, src: Reg);
qinsoon's avatar
qinsoon committed
183
    fn emit_mul_mem(&mut self, src: Mem);
184

185
186
187
    // signed multiply
    fn emit_imul_r_r(&mut self, dest: Reg, src: Reg);

188
    // div
189
190
    fn emit_div_r(&mut self, src: Reg);
    fn emit_div_mem(&mut self, src: Mem);
191
192

    // idiv
193
    fn emit_idiv_r(&mut self, src: Reg);
qinsoon's avatar
qinsoon committed
194
    fn emit_idiv_mem(&mut self, src: Mem);
195
196

    // shl
197
198
199
    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
200

201
202
203
    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
204

205
206
    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
207

qinsoon's avatar
qinsoon committed
208
209
210
    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
211
212

    // jump, conditional jump
213
    fn emit_jmp(&mut self, dest: MuName);
214
    fn emit_je(&mut self, dest: MuName);
215
    fn emit_jne(&mut self, dest: MuName);
216
    fn emit_ja(&mut self, dest: MuName);
217
    fn emit_jae(&mut self, dest: MuName);
218
    fn emit_jb(&mut self, dest: MuName);
219
    fn emit_jbe(&mut self, dest: MuName);
220
    fn emit_jg(&mut self, dest: MuName);
221
    fn emit_jge(&mut self, dest: MuName);
222
    fn emit_jl(&mut self, dest: MuName);
223
    fn emit_jle(&mut self, dest: MuName);
qinsoon's avatar
qinsoon committed
224
    fn emit_js(&mut self, dest: MuName);
qinsoon's avatar
qinsoon committed
225
226

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

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

qinsoon's avatar
qinsoon committed
272
    fn emit_ret(&mut self);
qinsoon's avatar
qinsoon committed
273

qinsoon's avatar
qinsoon committed
274
    // push/pop
qinsoon's avatar
qinsoon committed
275
    fn emit_push_r64(&mut self, src: &P<Value>);
276
    fn emit_push_imm32(&mut self, src: i32);
qinsoon's avatar
qinsoon committed
277
    fn emit_pop_r64(&mut self, dest: &P<Value>);
278
279

    // fpr move
280
    fn emit_movsd_f64_f64(&mut self, dest: &P<Value>, src: &P<Value>);
281
282
    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
283

284
    fn emit_movss_f32_f32(&mut self, dest: &P<Value>, src: &P<Value>);
285
286
287
    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
288
    // fp add
289
    fn emit_addsd_f64_f64(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
290
291
    fn emit_addsd_f64_mem64(&mut self, dest: Reg, src: Mem);

292
    fn emit_addss_f32_f32(&mut self, dest: Reg, src: Reg);
293
294
    fn emit_addss_f32_mem32(&mut self, dest: Reg, src: Mem);

qinsoon's avatar
qinsoon committed
295
    // fp sub
296
    fn emit_subsd_f64_f64(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
297
298
    fn emit_subsd_f64_mem64(&mut self, dest: Reg, src: Mem);

299
    fn emit_subss_f32_f32(&mut self, dest: Reg, src: Reg);
300
301
    fn emit_subss_f32_mem32(&mut self, dest: Reg, src: Mem);

qinsoon's avatar
qinsoon committed
302
    // fp div
303
    fn emit_divsd_f64_f64(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
304
305
    fn emit_divsd_f64_mem64(&mut self, dest: Reg, src: Mem);

306
    fn emit_divss_f32_f32(&mut self, dest: Reg, src: Reg);
307
308
    fn emit_divss_f32_mem32(&mut self, dest: Reg, src: Mem);

qinsoon's avatar
qinsoon committed
309
    // fp mul
310
    fn emit_mulsd_f64_f64(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
311
312
    fn emit_mulsd_f64_mem64(&mut self, dest: Reg, src: Mem);

313
    fn emit_mulss_f32_f32(&mut self, dest: Reg, src: Reg);
314
315
    fn emit_mulss_f32_mem32(&mut self, dest: Reg, src: Mem);

qinsoon's avatar
qinsoon committed
316
    // fp comparison
317
318
    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
319

320
321
    fn emit_comiss_f32_f32(&mut self, op1: Reg, op2: Reg);
    fn emit_ucomiss_f32_f32(&mut self, op1: Reg, op2: Reg);
322

qinsoon's avatar
qinsoon committed
323
    // fp conversion
324
325
    fn emit_cvtsi2sd_f64_r(&mut self, dest: Reg, src: Reg);
    fn emit_cvtsd2si_r_f64(&mut self, dest: Reg, src: Reg);
326

327
328
    fn emit_cvtsi2ss_f32_r(&mut self, dest: Reg, src: Reg);
    fn emit_cvtss2si_r_f32(&mut self, dest: Reg, src: Reg);
329

qinsoon's avatar
qinsoon committed
330
331
332
333
    // fp trunc
    fn emit_cvtsd2ss_f32_f64(&mut self, dest: Reg, src: Reg);
    fn emit_cvtss2sd_f64_f32(&mut self, dest: Reg, src: Reg);

334
335
    // used for unsigned int to fp conversion

336
337
    fn emit_cvttsd2si_r_f64(&mut self, dest: Reg, src: Reg);
    fn emit_cvttss2si_r_f32(&mut self, dest: Reg, src: Reg);
338

339
340
341
    // unpack low data - interleave low byte
    fn emit_punpckldq_f64_mem128(&mut self, dest: Reg, src: Mem);
    // substract packed double-fp
342
    fn emit_subpd_f64_mem128(&mut self, dest: Reg, src: Mem);
343
    // packed double-fp horizontal add
344
    fn emit_haddpd_f64_f64(&mut self, dest: Reg, src: Reg);
345
346
347

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

350
    fn emit_movaps_f32_f32(&mut self, dest: Reg, src: Reg);
351
352
353

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