ssa: move optimizations from P_BinaryOp to P_BinaryConstOp
[ajla.git] / code-op.h
blobf61331f33632609277092705bd47da05532c567e
1 /*
2 * Copyright (C) 2024 Mikulas Patocka
4 * This file is part of Ajla.
6 * Ajla is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
9 * version.
11 * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * Ajla. If not, see <https://www.gnu.org/licenses/>.
19 #ifndef AJLA_OPCODE_H
20 #define AJLA_OPCODE_H
22 typedef uint16_t code_t;
24 #define OPCODE_MASK 0xffff
26 #define OPCODE_OP_FLAG_STRICT 0x0001
27 #define OPCODE_FLAG_FREE_ARGUMENT 0x0002
28 #define OPCODE_FLAG_FREE_ARGUMENT_2 0x0004
29 #define OPCODE_CALL_MAY_LEND 0x0004 /* OPCODE_FLAG_FREE_ARGUMENT must not be set */
30 #define OPCODE_CALL_MAY_GIVE 0x0008 /* OPCODE_FLAG_FREE_ARGUMENT must be set */
31 #define OPCODE_FLAG_FUSED 0x0008
32 #define OPCODE_ARRAY_FILL_FLAG_SPARSE 0x0004
33 #define OPCODE_ARRAY_INDEX_IN_RANGE 0x0004
34 #define OPCODE_STRUCT_MAY_BORROW 0x0008
35 #define FLAG_NEED_BOTH_EXCEPTIONS_TO_FAIL 0x0100 /* not used in code, used internally in ipret.c */
36 #define FLAG_FIRST_EXCEPTION 0x0200 /* not used in code, used internally in ipret.c */
37 #define FLAG_TESTING_FOR_EXCEPTION 0x0400 /* not used in code, used internally in ipret.c */
38 #define OPCODE_MAY_RETURN_FLAT 0x0001
40 #define OPCODE_FIXED_OP_MULT 1
41 #define OPCODE_FIXED_OP_add 0
42 #define OPCODE_FIXED_OP_subtract 1
43 #define OPCODE_FIXED_OP_multiply 2
44 #define OPCODE_FIXED_OP_divide 3
45 #define OPCODE_FIXED_OP_divide_alt1 4
46 #define OPCODE_FIXED_OP_udivide 5
47 #define OPCODE_FIXED_OP_udivide_alt1 6
48 #define OPCODE_FIXED_OP_modulo 7
49 #define OPCODE_FIXED_OP_modulo_alt1 8
50 #define OPCODE_FIXED_OP_umodulo 9
51 #define OPCODE_FIXED_OP_umodulo_alt1 10
52 #define OPCODE_FIXED_OP_power 11
53 #define OPCODE_FIXED_OP_and 12
54 #define OPCODE_FIXED_OP_or 13
55 #define OPCODE_FIXED_OP_xor 14
56 #define OPCODE_FIXED_OP_shl 15
57 #define OPCODE_FIXED_OP_shr 16
58 #define OPCODE_FIXED_OP_ushr 17
59 #define OPCODE_FIXED_OP_rol 18
60 #define OPCODE_FIXED_OP_ror 19
61 #define OPCODE_FIXED_OP_bts 20
62 #define OPCODE_FIXED_OP_btr 21
63 #define OPCODE_FIXED_OP_btc 22
64 #define OPCODE_FIXED_OP_equal 23
65 #define OPCODE_FIXED_OP_not_equal 24
66 #define OPCODE_FIXED_OP_less 25
67 #define OPCODE_FIXED_OP_less_equal 26
68 #define OPCODE_FIXED_OP_uless 27
69 #define OPCODE_FIXED_OP_uless_equal 28
70 #define OPCODE_FIXED_OP_bt 29
71 #define OPCODE_FIXED_OP_UNARY 30
72 #define OPCODE_FIXED_OP_not 30
73 #define OPCODE_FIXED_OP_neg 31
74 #define OPCODE_FIXED_OP_inc 32
75 #define OPCODE_FIXED_OP_dec 33
76 #define OPCODE_FIXED_OP_bswap 34
77 #define OPCODE_FIXED_OP_bswap_alt1 35
78 #define OPCODE_FIXED_OP_brev 36
79 #define OPCODE_FIXED_OP_brev_alt1 37
80 #define OPCODE_FIXED_OP_bsf 38
81 #define OPCODE_FIXED_OP_bsf_alt1 39
82 #define OPCODE_FIXED_OP_bsr 40
83 #define OPCODE_FIXED_OP_bsr_alt1 41
84 #define OPCODE_FIXED_OP_popcnt 42
85 #define OPCODE_FIXED_OP_popcnt_alt1 43
86 #define OPCODE_FIXED_OP_to_int 44
87 #define OPCODE_FIXED_OP_uto_int 45
88 #define OPCODE_FIXED_OP_from_int 46
89 #define OPCODE_FIXED_OP_ufrom_int 47
90 #define OPCODE_FIXED_OP_N 48
91 #define OPCODE_FIXED_OP_move 48
92 #define OPCODE_FIXED_OP_copy 49
93 #define OPCODE_FIXED_OP_ldc 50
94 #define OPCODE_FIXED_OP_ldc16 51
96 #define OPCODE_FIXED_TYPE_MULT 52
97 #define OPCODE_FIXED_TYPE_int8_t 0
98 #define OPCODE_FIXED_TYPE_int16_t 1
99 #define OPCODE_FIXED_TYPE_int32_t 2
100 #define OPCODE_FIXED_TYPE_int64_t 3
101 #define OPCODE_FIXED_TYPE_int128_t 4
103 #define OPCODE_INT_OP_MULT 1
104 #define OPCODE_INT_OP_add 0
105 #define OPCODE_INT_OP_subtract 1
106 #define OPCODE_INT_OP_multiply 2
107 #define OPCODE_INT_OP_divide 3
108 #define OPCODE_INT_OP_divide_alt1 4
109 #define OPCODE_INT_OP_modulo 5
110 #define OPCODE_INT_OP_modulo_alt1 6
111 #define OPCODE_INT_OP_power 7
112 #define OPCODE_INT_OP_and 8
113 #define OPCODE_INT_OP_or 9
114 #define OPCODE_INT_OP_xor 10
115 #define OPCODE_INT_OP_shl 11
116 #define OPCODE_INT_OP_shr 12
117 #define OPCODE_INT_OP_bts 13
118 #define OPCODE_INT_OP_btr 14
119 #define OPCODE_INT_OP_btc 15
120 #define OPCODE_INT_OP_equal 16
121 #define OPCODE_INT_OP_not_equal 17
122 #define OPCODE_INT_OP_less 18
123 #define OPCODE_INT_OP_less_equal 19
124 #define OPCODE_INT_OP_bt 20
125 #define OPCODE_INT_OP_C 21
126 #define OPCODE_INT_OP_C_add 21
127 #define OPCODE_INT_OP_C_subtract 22
128 #define OPCODE_INT_OP_C_multiply 23
129 #define OPCODE_INT_OP_C_divide 24
130 #define OPCODE_INT_OP_C_divide_alt1 25
131 #define OPCODE_INT_OP_C_modulo 26
132 #define OPCODE_INT_OP_C_modulo_alt1 27
133 #define OPCODE_INT_OP_C_power 28
134 #define OPCODE_INT_OP_C_and 29
135 #define OPCODE_INT_OP_C_or 30
136 #define OPCODE_INT_OP_C_xor 31
137 #define OPCODE_INT_OP_C_shl 32
138 #define OPCODE_INT_OP_C_shr 33
139 #define OPCODE_INT_OP_C_bts 34
140 #define OPCODE_INT_OP_C_btr 35
141 #define OPCODE_INT_OP_C_btc 36
142 #define OPCODE_INT_OP_C_equal 37
143 #define OPCODE_INT_OP_C_not_equal 38
144 #define OPCODE_INT_OP_C_less 39
145 #define OPCODE_INT_OP_C_less_equal 40
146 #define OPCODE_INT_OP_C_bt 41
147 #define OPCODE_INT_OP_UNARY 42
148 #define OPCODE_INT_OP_not 42
149 #define OPCODE_INT_OP_neg 43
150 #define OPCODE_INT_OP_inc 44
151 #define OPCODE_INT_OP_dec 45
152 #define OPCODE_INT_OP_bsf 46
153 #define OPCODE_INT_OP_bsr 47
154 #define OPCODE_INT_OP_popcnt 48
155 #define OPCODE_INT_OP_popcnt_alt1 49
156 #define OPCODE_INT_OP_to_int 50
157 #define OPCODE_INT_OP_from_int 51
158 #define OPCODE_INT_OP_N 52
159 #define OPCODE_INT_OP_move 52
160 #define OPCODE_INT_OP_copy 53
161 #define OPCODE_INT_OP_ldc 54
162 #define OPCODE_INT_OP_ldc16 55
164 #define OPCODE_INT_TYPE_MULT 56
165 #define OPCODE_INT_TYPE_int8_t 0
166 #define OPCODE_INT_TYPE_int16_t 1
167 #define OPCODE_INT_TYPE_int32_t 2
168 #define OPCODE_INT_TYPE_int64_t 3
169 #define OPCODE_INT_TYPE_int128_t 4
171 #define OPCODE_REAL_OP_MULT 1
172 #define OPCODE_REAL_OP_add 0
173 #define OPCODE_REAL_OP_add_alt1 1
174 #define OPCODE_REAL_OP_add_alt2 2
175 #define OPCODE_REAL_OP_subtract 3
176 #define OPCODE_REAL_OP_subtract_alt1 4
177 #define OPCODE_REAL_OP_subtract_alt2 5
178 #define OPCODE_REAL_OP_multiply 6
179 #define OPCODE_REAL_OP_multiply_alt1 7
180 #define OPCODE_REAL_OP_multiply_alt2 8
181 #define OPCODE_REAL_OP_divide 9
182 #define OPCODE_REAL_OP_divide_alt1 10
183 #define OPCODE_REAL_OP_divide_alt2 11
184 #define OPCODE_REAL_OP_modulo 12
185 #define OPCODE_REAL_OP_power 13
186 #define OPCODE_REAL_OP_ldexp 14
187 #define OPCODE_REAL_OP_atan2 15
188 #define OPCODE_REAL_OP_equal 16
189 #define OPCODE_REAL_OP_equal_alt1 17
190 #define OPCODE_REAL_OP_equal_alt2 18
191 #define OPCODE_REAL_OP_not_equal 19
192 #define OPCODE_REAL_OP_not_equal_alt1 20
193 #define OPCODE_REAL_OP_not_equal_alt2 21
194 #define OPCODE_REAL_OP_less 22
195 #define OPCODE_REAL_OP_less_alt1 23
196 #define OPCODE_REAL_OP_less_alt2 24
197 #define OPCODE_REAL_OP_less_equal 25
198 #define OPCODE_REAL_OP_less_equal_alt1 26
199 #define OPCODE_REAL_OP_less_equal_alt2 27
200 #define OPCODE_REAL_OP_UNARY 28
201 #define OPCODE_REAL_OP_neg 28
202 #define OPCODE_REAL_OP_neg_alt1 29
203 #define OPCODE_REAL_OP_neg_alt2 30
204 #define OPCODE_REAL_OP_sqrt 31
205 #define OPCODE_REAL_OP_sqrt_alt1 32
206 #define OPCODE_REAL_OP_sqrt_alt2 33
207 #define OPCODE_REAL_OP_cbrt 35
208 #define OPCODE_REAL_OP_sin 36
209 #define OPCODE_REAL_OP_cos 37
210 #define OPCODE_REAL_OP_tan 38
211 #define OPCODE_REAL_OP_asin 39
212 #define OPCODE_REAL_OP_acos 40
213 #define OPCODE_REAL_OP_atan 41
214 #define OPCODE_REAL_OP_sinh 42
215 #define OPCODE_REAL_OP_cosh 43
216 #define OPCODE_REAL_OP_tanh 44
217 #define OPCODE_REAL_OP_asinh 45
218 #define OPCODE_REAL_OP_acosh 46
219 #define OPCODE_REAL_OP_atanh 47
220 #define OPCODE_REAL_OP_exp2 48
221 #define OPCODE_REAL_OP_exp 49
222 #define OPCODE_REAL_OP_exp10 50
223 #define OPCODE_REAL_OP_log2 51
224 #define OPCODE_REAL_OP_log 52
225 #define OPCODE_REAL_OP_log10 53
226 #define OPCODE_REAL_OP_round 54
227 #define OPCODE_REAL_OP_floor 55
228 #define OPCODE_REAL_OP_ceil 56
229 #define OPCODE_REAL_OP_trunc 57
230 #define OPCODE_REAL_OP_fract 58
231 #define OPCODE_REAL_OP_mantissa 59
232 #define OPCODE_REAL_OP_exponent 60
233 #define OPCODE_REAL_OP_next_number 61
234 #define OPCODE_REAL_OP_prev_number 62
235 #define OPCODE_REAL_OP_to_int 63
236 #define OPCODE_REAL_OP_to_int_alt1 64
237 #define OPCODE_REAL_OP_to_int_alt2 65
238 #define OPCODE_REAL_OP_from_int 66
239 #define OPCODE_REAL_OP_from_int_alt1 67
240 #define OPCODE_REAL_OP_from_int_alt2 68
241 #define OPCODE_REAL_OP_is_exception 69
242 #define OPCODE_REAL_OP_is_exception_alt1 70
243 #define OPCODE_REAL_OP_is_exception_alt2 71
244 #define OPCODE_REAL_OP_N 72
245 #define OPCODE_REAL_OP_move 72
246 #define OPCODE_REAL_OP_copy 73
247 #define OPCODE_REAL_OP_ldc 74
249 #define OPCODE_REAL_TYPE_MULT 75
250 #define OPCODE_REAL_TYPE_real16_t 0
251 #define OPCODE_REAL_TYPE_real32_t 1
252 #define OPCODE_REAL_TYPE_real64_t 2
253 #define OPCODE_REAL_TYPE_real80_t 3
254 #define OPCODE_REAL_TYPE_real128_t 4
256 #define OPCODE_BOOL_OP_MULT 1
257 #define OPCODE_BOOL_OP_and 0
258 #define OPCODE_BOOL_OP_or 1
259 #define OPCODE_BOOL_OP_equal 2
260 #define OPCODE_BOOL_OP_not_equal 3
261 #define OPCODE_BOOL_OP_less 4
262 #define OPCODE_BOOL_OP_less_equal 5
263 #define OPCODE_BOOL_OP_UNARY 6
264 #define OPCODE_BOOL_OP_not 6
265 #define OPCODE_BOOL_OP_N 7
266 #define OPCODE_BOOL_OP_move 7
267 #define OPCODE_BOOL_OP_copy 8
269 #define OPCODE_BOOL_TYPE_MULT 9
271 #define OPCODE_FIXED_OP 0
272 #define OPCODE_INT_OP (OPCODE_FIXED_OP + OPCODE_FIXED_TYPE_MULT * TYPE_FIXED_N)
273 #define OPCODE_REAL_OP (OPCODE_INT_OP + OPCODE_INT_TYPE_MULT * TYPE_INT_N)
274 #define OPCODE_BOOL_OP (OPCODE_REAL_OP + OPCODE_REAL_TYPE_MULT * TYPE_REAL_N)
275 #define OPCODE_EXTRA (OPCODE_BOOL_OP + OPCODE_BOOL_TYPE_MULT)
277 enum {
278 OPCODE_INT_LDC_LONG = OPCODE_EXTRA,
279 OPCODE_IS_EXCEPTION, /* src, dest, strict flag */
280 OPCODE_EXCEPTION_CLASS, /* src, dest, strict flag */
281 OPCODE_EXCEPTION_TYPE, /* src, dest, strict flag */
282 OPCODE_EXCEPTION_AUX, /* src, dest, strict flag */
283 OPCODE_SYSTEM_PROPERTY, /* src, dest, strict flag */
284 OPCODE_FLAT_MOVE,
285 OPCODE_FLAT_COPY,
286 OPCODE_REF_MOVE,
287 OPCODE_REF_MOVE_CLEAR,
288 OPCODE_REF_COPY,
289 OPCODE_BOX_MOVE_CLEAR,
290 OPCODE_BOX_COPY,
291 OPCODE_TAKE_BORROWED,
292 OPCODE_DEREFERENCE,
293 OPCODE_DEREFERENCE_CLEAR,
294 OPCODE_EVAL,
295 OPCODE_ESCAPE_NONFLAT,
296 OPCODE_CHECKPOINT,
297 OPCODE_JMP,
298 OPCODE_JMP_BACK_16,
299 OPCODE_JMP_FALSE, /* var, false_offset*2, exception_offset*2 */
300 OPCODE_LABEL,
301 OPCODE_LOAD_FN, /* n_arg, result, fn_idx, [arg_var, arg_deref] */
302 OPCODE_CURRY, /* n_arg, result, fn_thunk, fn_deref, [arg_var, arg_deref] */
303 OPCODE_CALL, /* n_arg, n_ret, fn_idx, [arg_var, arg_deref], [ret_var(32), ret_flag(16)] */
304 OPCODE_CALL_STRICT, /* n_arg, n_ret, fn_idx, [arg_var, arg_deref], [ret_var(32), ret_flag(16)] */
305 OPCODE_CALL_SPARK, /* n_arg, n_ret, fn_idx, [arg_var, arg_deref], [ret_var(32), ret_flag(16)] */
306 OPCODE_CALL_LAZY, /* n_arg, n_ret, fn_idx, [arg_var, arg_deref], [ret_var(32), ret_flag(16)] */
307 OPCODE_CALL_CACHE, /* n_arg, n_ret, fn_idx, [arg_var, arg_deref], [ret_var(32), ret_flag(16)] */
308 OPCODE_CALL_SAVE, /* n_arg, n_ret, fn_idx, [arg_var, arg_deref], [ret_var(32), ret_flag(16)] */
309 OPCODE_CALL_INDIRECT, /* n_arg, n_ret, fn_thunk, fn_deref, [arg_var, arg_deref], [ret_var(32), ret_flag(16)] */
310 OPCODE_CALL_INDIRECT_STRICT, /* n_arg, n_ret, fn_thunk, fn_deref, [arg_var, arg_deref], [ret_var(32), ret_flag(16)] */
311 OPCODE_CALL_INDIRECT_SPARK, /* n_arg, n_ret, fn_thunk, fn_deref, [arg_var, arg_deref], [ret_var(32), ret_flag(16)] */
312 OPCODE_CALL_INDIRECT_LAZY, /* n_arg, n_ret, fn_thunk, fn_deref, [arg_var, arg_deref], [ret_var(32), ret_flag(16)] */
313 OPCODE_CALL_INDIRECT_CACHE, /* n_arg, n_ret, fn_thunk, fn_deref, [arg_var, arg_deref], [ret_var(32), ret_flag(16)] */
314 OPCODE_CALL_INDIRECT_SAVE, /* n_arg, n_ret, fn_thunk, fn_deref, [arg_var, arg_deref], [ret_var(32), ret_flag(16)] */
315 OPCODE_RETURN, /* val, arg_deref ... */
316 OPCODE_STRUCTURED, /* struct, element ... */
317 #define OPCODE_STRUCTURED_RECORD 0x01 /* + element_slot, record_type */
318 #define OPCODE_STRUCTURED_OPTION 0x02 /* + option, nothing */
319 #define OPCODE_STRUCTURED_ARRAY 0x03 /* + index_slot, nothing */
320 #define OPCODE_STRUCTURED_MASK 0x0f
321 #define OPCODE_STRUCTURED_FREE_VARIABLE 0x10
322 #define OPCODE_STRUCTURED_FLAG_END 0x20
323 OPCODE_RECORD_CREATE, /* result, n_entries, [entry_var, arg_deref] */
324 OPCODE_RECORD_LOAD, /* record, slot, result, (strict_flag | borrow_flag) */
325 OPCODE_OPTION_CREATE_EMPTY_FLAT,/* result, option */
326 OPCODE_OPTION_CREATE_EMPTY, /* result, option */
327 OPCODE_OPTION_CREATE, /* result, option, arg_var, arg_deref */
328 OPCODE_OPTION_LOAD, /* option, idx, result, (strict_flag | borrow_flag) */
329 OPCODE_OPTION_TEST_FLAT, /* var, option, result */
330 OPCODE_OPTION_TEST, /* var, option, result */
331 OPCODE_OPTION_ORD_FLAT, /* var, result */
332 OPCODE_OPTION_ORD, /* var, result */
333 OPCODE_ARRAY_CREATE, /* result, n_entries, [entry_var, arg_deref] */
334 OPCODE_ARRAY_CREATE_EMPTY_FLAT, /* result, local_type */
335 OPCODE_ARRAY_CREATE_EMPTY, /* result */
336 OPCODE_ARRAY_FILL, /* content_var, content_deref | flag_sparse, length_var, result */
337 OPCODE_ARRAY_STRING, /* result, length, [chars] */
338 OPCODE_ARRAY_UNICODE, /* result, length, [chars] */
339 OPCODE_ARRAY_LOAD, /* array, idx slot, result, (strict_flag | borrow_flag) */
340 OPCODE_ARRAY_LEN, /* array, result, strict_flag */
341 OPCODE_ARRAY_LEN_GREATER_THAN, /* array, size, result, strict_flag */
342 OPCODE_ARRAY_SUB, /* array, start, end, result, strict_flags | deref */
343 OPCODE_ARRAY_SKIP, /* array, start, result, strict_flags | deref */
344 OPCODE_ARRAY_APPEND, /* result, arg_deref1 | arg_deref2, arg1, arg2 */
345 OPCODE_ARRAY_APPEND_ONE_FLAT, /* result, arg_deref1 | arg_deref2, arg1, arg2 */
346 OPCODE_ARRAY_APPEND_ONE, /* result, arg_deref1 | arg_deref2, arg1, arg2 */
347 OPCODE_ARRAY_FLATTEN, /* result, arg_deref1, arg1 */
348 OPCODE_IO, /* (code, n_outputs, n_inputs, n_params), 32-bit: outputs, inputs, params */
349 OPCODE_INTERNAL_FUNCTION,
350 OPCODE_EXIT_THREAD,
351 OPCODE_UNREACHABLE,
352 OPCODE_N,
355 enum {
356 OPCODE_MODE_MULT_0 = (OPCODE_N - 1),
357 OPCODE_MODE_MULT_1 = (OPCODE_MODE_MULT_0 | (OPCODE_MODE_MULT_0 >> 1)),
358 OPCODE_MODE_MULT_2 = (OPCODE_MODE_MULT_1 | (OPCODE_MODE_MULT_1 >> 2)),
359 OPCODE_MODE_MULT_4 = (OPCODE_MODE_MULT_2 | (OPCODE_MODE_MULT_2 >> 4)),
360 OPCODE_MODE_MULT_8 = (OPCODE_MODE_MULT_4 | (OPCODE_MODE_MULT_4 >> 8)),
361 OPCODE_MODE_MULT = OPCODE_MODE_MULT_8 + 1,
364 #endif