blob: 57888ee13ef043baec47c16c17344e4cdad5447e [file] [log] [blame]
Damien George04b91472014-05-03 23:27:38 +01001/*
2 * This file is part of the Micro Python project, http://micropython.org/
3 *
4 * The MIT License (MIT)
5 *
6 * Copyright (c) 2013, 2014 Damien P. George
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 */
26
Damien13ed3a62013-10-08 09:05:10 +010027// Essentially normal Python has 1 type: Python objects
28// Viper has more than 1 type, and is just a more complicated (a superset of) Python.
29// If you declare everything in Viper as a Python object (ie omit type decls) then
30// it should in principle be exactly the same as Python native.
31// Having types means having more opcodes, like binary_op_nat_nat, binary_op_nat_obj etc.
32// In practice we won't have a VM but rather do this in asm which is actually very minimal.
33
34// Because it breaks strict Python equivalence it should be a completely separate
35// decorator. It breaks equivalence because overflow on integers wraps around.
36// It shouldn't break equivalence if you don't use the new types, but since the
37// type decls might be used in normal Python for other reasons, it's probably safest,
38// cleanest and clearest to make it a separate decorator.
39
40// Actually, it does break equivalence because integers default to native integers,
41// not Python objects.
42
43// for x in l[0:8]: can be compiled into a native loop if l has pointer type
44
xbeefe34222014-03-16 00:14:26 -070045#include <stdbool.h>
Damien13ed3a62013-10-08 09:05:10 +010046#include <stdint.h>
47#include <stdio.h>
48#include <string.h>
49#include <assert.h>
50
Damiend99b0522013-12-21 18:17:45 +000051#include "mpconfig.h"
Damien Georgeb601d952014-06-30 05:17:25 +010052#include "nlr.h"
Paul Sokolovsky59c675a2014-06-21 22:43:22 +030053#include "misc.h"
Damien George55baff42014-01-21 21:40:13 +000054#include "qstr.h"
Damien13ed3a62013-10-08 09:05:10 +010055#include "lexer.h"
Damien13ed3a62013-10-08 09:05:10 +010056#include "parse.h"
Damien Georgedf8127a2014-04-13 11:04:33 +010057#include "obj.h"
58#include "emitglue.h"
Damien13ed3a62013-10-08 09:05:10 +010059#include "scope.h"
Damiend99b0522013-12-21 18:17:45 +000060#include "runtime0.h"
Damien13ed3a62013-10-08 09:05:10 +010061#include "emit.h"
Damiend99b0522013-12-21 18:17:45 +000062#include "runtime.h"
Damien13ed3a62013-10-08 09:05:10 +010063
Damien Georgecdd96df2014-04-06 12:58:40 +010064#if 0 // print debugging info
65#define DEBUG_PRINT (1)
66#define DEBUG_printf DEBUG_printf
67#else // don't print debugging info
68#define DEBUG_printf(...) (void)0
69#endif
70
Damien13ed3a62013-10-08 09:05:10 +010071// wrapper around everything in this file
Damien Georgec90f59e2014-09-06 23:06:36 +010072#if (MICROPY_EMIT_X64 && N_X64) \
73 || (MICROPY_EMIT_X86 && N_X86) \
74 || (MICROPY_EMIT_THUMB && N_THUMB) \
75 || (MICROPY_EMIT_ARM && N_ARM)
Damien13ed3a62013-10-08 09:05:10 +010076
Damien3ef4abb2013-10-12 16:53:13 +010077#if N_X64
Damien13ed3a62013-10-08 09:05:10 +010078
79// x64 specific stuff
80
81#include "asmx64.h"
82
Damien13ed3a62013-10-08 09:05:10 +010083#define EXPORT_FUN(name) emit_native_x64_##name
84
Damien George0b610de2014-09-29 16:25:04 +010085#define REG_RET ASM_X64_REG_RAX
86#define REG_ARG_1 ASM_X64_REG_RDI
87#define REG_ARG_2 ASM_X64_REG_RSI
88#define REG_ARG_3 ASM_X64_REG_RDX
89#define REG_ARG_4 ASM_X64_REG_RCX
Damien Georgec90f59e2014-09-06 23:06:36 +010090
Damien George81057362014-09-07 01:06:19 +010091// caller-save
Damien George0b610de2014-09-29 16:25:04 +010092#define REG_TEMP0 ASM_X64_REG_RAX
93#define REG_TEMP1 ASM_X64_REG_RDI
94#define REG_TEMP2 ASM_X64_REG_RSI
Damien George81057362014-09-07 01:06:19 +010095
96// callee-save
Damien George0b610de2014-09-29 16:25:04 +010097#define REG_LOCAL_1 ASM_X64_REG_RBX
98#define REG_LOCAL_2 ASM_X64_REG_R12
99#define REG_LOCAL_3 ASM_X64_REG_R13
Damien George81057362014-09-07 01:06:19 +0100100#define REG_LOCAL_NUM (3)
Damien Georgec90f59e2014-09-06 23:06:36 +0100101
102#define ASM_PASS_COMPUTE ASM_X64_PASS_COMPUTE
103#define ASM_PASS_EMIT ASM_X64_PASS_EMIT
104
105#define ASM_T asm_x64_t
106#define ASM_NEW asm_x64_new
107#define ASM_FREE asm_x64_free
108#define ASM_GET_CODE asm_x64_get_code
109#define ASM_GET_CODE_SIZE asm_x64_get_code_size
110#define ASM_START_PASS asm_x64_start_pass
111#define ASM_END_PASS asm_x64_end_pass
112#define ASM_ENTRY asm_x64_entry
113#define ASM_EXIT asm_x64_exit
114
115#define ASM_LABEL_ASSIGN asm_x64_label_assign
116#define ASM_JUMP asm_x64_jmp_label
117#define ASM_JUMP_IF_REG_ZERO(as, reg, label) \
118 do { \
119 asm_x64_test_r8_with_r8(as, reg, reg); \
120 asm_x64_jcc_label(as, ASM_X64_CC_JZ, label); \
121 } while (0)
122#define ASM_JUMP_IF_REG_NONZERO(as, reg, label) \
123 do { \
124 asm_x64_test_r8_with_r8(as, reg, reg); \
125 asm_x64_jcc_label(as, ASM_X64_CC_JNZ, label); \
126 } while (0)
127#define ASM_JUMP_IF_REG_EQ(as, reg1, reg2, label) \
128 do { \
129 asm_x64_cmp_r64_with_r64(as, reg1, reg2); \
130 asm_x64_jcc_label(as, ASM_X64_CC_JE, label); \
131 } while (0)
Damien George0b610de2014-09-29 16:25:04 +0100132#define ASM_CALL_IND(as, ptr, idx) asm_x64_call_ind(as, ptr, ASM_X64_REG_RAX)
Damien Georgec90f59e2014-09-06 23:06:36 +0100133
134#define ASM_MOV_REG_TO_LOCAL asm_x64_mov_r64_to_local
135#define ASM_MOV_IMM_TO_REG asm_x64_mov_i64_to_r64_optimised
136#define ASM_MOV_ALIGNED_IMM_TO_REG asm_x64_mov_i64_to_r64_aligned
137#define ASM_MOV_IMM_TO_LOCAL_USING(as, imm, local_num, reg_temp) \
138 do { \
139 asm_x64_mov_i64_to_r64_optimised(as, (imm), (reg_temp)); \
140 asm_x64_mov_r64_to_local(as, (reg_temp), (local_num)); \
141 } while (false)
142#define ASM_MOV_LOCAL_TO_REG asm_x64_mov_local_to_r64
Damien George3112cde2014-09-29 18:45:42 +0100143#define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_x64_mov_r64_r64((as), (reg_dest), (reg_src))
Damien Georgec90f59e2014-09-06 23:06:36 +0100144#define ASM_MOV_LOCAL_ADDR_TO_REG asm_x64_mov_local_addr_to_r64
145
Damien George3112cde2014-09-29 18:45:42 +0100146#define ASM_LSL_REG(as, reg) asm_x64_shl_r64_cl((as), (reg))
147#define ASM_ASR_REG(as, reg) asm_x64_sar_r64_cl((as), (reg))
Damien George1ef23482014-10-12 14:21:06 +0100148#define ASM_OR_REG_REG(as, reg_dest, reg_src) asm_x64_or_r64_r64((as), (reg_dest), (reg_src))
149#define ASM_XOR_REG_REG(as, reg_dest, reg_src) asm_x64_xor_r64_r64((as), (reg_dest), (reg_src))
150#define ASM_AND_REG_REG(as, reg_dest, reg_src) asm_x64_and_r64_r64((as), (reg_dest), (reg_src))
Damien George3112cde2014-09-29 18:45:42 +0100151#define ASM_ADD_REG_REG(as, reg_dest, reg_src) asm_x64_add_r64_r64((as), (reg_dest), (reg_src))
152#define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_x64_sub_r64_r64((as), (reg_dest), (reg_src))
153
Damien George91cfd412014-10-12 16:59:29 +0100154#define ASM_LOAD_REG_REG(as, reg_dest, reg_base) asm_x64_mov_mem64_to_r64((as), (reg_base), 0, (reg_dest))
155#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_x64_mov_mem8_to_r64zx((as), (reg_base), 0, (reg_dest))
156#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_x64_mov_mem16_to_r64zx((as), (reg_base), 0, (reg_dest))
157
158#define ASM_STORE_REG_REG(as, reg_src, reg_base) asm_x64_mov_r64_to_mem64((as), (reg_src), (reg_base), 0)
159#define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_x64_mov_r8_to_mem8((as), (reg_src), (reg_base), 0)
160#define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_x64_mov_r16_to_mem16((as), (reg_src), (reg_base), 0)
Damien Georgee9dac3b2014-09-29 22:10:41 +0100161
Damien Georgec90f59e2014-09-06 23:06:36 +0100162#elif N_X86
163
164// x86 specific stuff
165
166#include "asmx86.h"
167
168STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = {
169 [MP_F_CONVERT_OBJ_TO_NATIVE] = 2,
170 [MP_F_CONVERT_NATIVE_TO_OBJ] = 2,
171 [MP_F_LOAD_CONST_INT] = 1,
172 [MP_F_LOAD_CONST_DEC] = 1,
173 [MP_F_LOAD_CONST_STR] = 1,
174 [MP_F_LOAD_CONST_BYTES] = 1,
175 [MP_F_LOAD_NAME] = 1,
176 [MP_F_LOAD_GLOBAL] = 1,
177 [MP_F_LOAD_BUILD_CLASS] = 0,
178 [MP_F_LOAD_ATTR] = 2,
179 [MP_F_LOAD_METHOD] = 3,
180 [MP_F_STORE_NAME] = 2,
181 [MP_F_STORE_GLOBAL] = 2,
182 [MP_F_STORE_ATTR] = 3,
183 [MP_F_OBJ_SUBSCR] = 3,
184 [MP_F_OBJ_IS_TRUE] = 1,
185 [MP_F_UNARY_OP] = 2,
186 [MP_F_BINARY_OP] = 3,
187 [MP_F_BUILD_TUPLE] = 2,
188 [MP_F_BUILD_LIST] = 2,
189 [MP_F_LIST_APPEND] = 2,
190 [MP_F_BUILD_MAP] = 1,
191 [MP_F_STORE_MAP] = 3,
192#if MICROPY_PY_BUILTINS_SET
193 [MP_F_BUILD_SET] = 2,
194 [MP_F_STORE_SET] = 2,
195#endif
196 [MP_F_MAKE_FUNCTION_FROM_RAW_CODE] = 3,
197 [MP_F_NATIVE_CALL_FUNCTION_N_KW] = 3,
198 [MP_F_CALL_METHOD_N_KW] = 3,
199 [MP_F_GETITER] = 1,
200 [MP_F_ITERNEXT] = 1,
201 [MP_F_NLR_PUSH] = 1,
202 [MP_F_NLR_POP] = 0,
203 [MP_F_NATIVE_RAISE] = 1,
204 [MP_F_IMPORT_NAME] = 3,
205 [MP_F_IMPORT_FROM] = 2,
206 [MP_F_IMPORT_ALL] = 1,
207#if MICROPY_PY_BUILTINS_SLICE
208 [MP_F_NEW_SLICE] = 3,
209#endif
210 [MP_F_UNPACK_SEQUENCE] = 3,
211 [MP_F_UNPACK_EX] = 3,
212 [MP_F_DELETE_NAME] = 1,
213 [MP_F_DELETE_GLOBAL] = 1,
214};
215
216#define EXPORT_FUN(name) emit_native_x86_##name
217
Damien George0b610de2014-09-29 16:25:04 +0100218#define REG_RET ASM_X86_REG_EAX
Damien George6eae8612014-09-08 22:16:35 +0000219#define REG_ARG_1 ASM_X86_REG_ARG_1
220#define REG_ARG_2 ASM_X86_REG_ARG_2
221#define REG_ARG_3 ASM_X86_REG_ARG_3
Damien George81057362014-09-07 01:06:19 +0100222
Damien George25d90412014-09-06 23:24:32 +0000223// caller-save, so can be used as temporaries
Damien George0b610de2014-09-29 16:25:04 +0100224#define REG_TEMP0 ASM_X86_REG_EAX
225#define REG_TEMP1 ASM_X86_REG_ECX
226#define REG_TEMP2 ASM_X86_REG_EDX
Damien Georgec90f59e2014-09-06 23:06:36 +0100227
Damien George25d90412014-09-06 23:24:32 +0000228// callee-save, so can be used as locals
Damien George0b610de2014-09-29 16:25:04 +0100229#define REG_LOCAL_1 ASM_X86_REG_EBX
230#define REG_LOCAL_2 ASM_X86_REG_ESI
231#define REG_LOCAL_3 ASM_X86_REG_EDI
Damien George25d90412014-09-06 23:24:32 +0000232#define REG_LOCAL_NUM (3)
Damien Georgec90f59e2014-09-06 23:06:36 +0100233
234#define ASM_PASS_COMPUTE ASM_X86_PASS_COMPUTE
235#define ASM_PASS_EMIT ASM_X86_PASS_EMIT
236
237#define ASM_T asm_x86_t
238#define ASM_NEW asm_x86_new
239#define ASM_FREE asm_x86_free
240#define ASM_GET_CODE asm_x86_get_code
241#define ASM_GET_CODE_SIZE asm_x86_get_code_size
242#define ASM_START_PASS asm_x86_start_pass
243#define ASM_END_PASS asm_x86_end_pass
244#define ASM_ENTRY asm_x86_entry
245#define ASM_EXIT asm_x86_exit
246
247#define ASM_LABEL_ASSIGN asm_x86_label_assign
248#define ASM_JUMP asm_x86_jmp_label
249#define ASM_JUMP_IF_REG_ZERO(as, reg, label) \
250 do { \
251 asm_x86_test_r8_with_r8(as, reg, reg); \
252 asm_x86_jcc_label(as, ASM_X86_CC_JZ, label); \
253 } while (0)
254#define ASM_JUMP_IF_REG_NONZERO(as, reg, label) \
255 do { \
256 asm_x86_test_r8_with_r8(as, reg, reg); \
257 asm_x86_jcc_label(as, ASM_X86_CC_JNZ, label); \
258 } while (0)
259#define ASM_JUMP_IF_REG_EQ(as, reg1, reg2, label) \
260 do { \
261 asm_x86_cmp_r32_with_r32(as, reg1, reg2); \
262 asm_x86_jcc_label(as, ASM_X86_CC_JE, label); \
263 } while (0)
Damien George0b610de2014-09-29 16:25:04 +0100264#define ASM_CALL_IND(as, ptr, idx) asm_x86_call_ind(as, ptr, mp_f_n_args[idx], ASM_X86_REG_EAX)
Damien Georgec90f59e2014-09-06 23:06:36 +0100265
266#define ASM_MOV_REG_TO_LOCAL asm_x86_mov_r32_to_local
267#define ASM_MOV_IMM_TO_REG asm_x86_mov_i32_to_r32
268#define ASM_MOV_ALIGNED_IMM_TO_REG asm_x86_mov_i32_to_r32_aligned
269#define ASM_MOV_IMM_TO_LOCAL_USING(as, imm, local_num, reg_temp) \
270 do { \
271 asm_x86_mov_i32_to_r32(as, (imm), (reg_temp)); \
272 asm_x86_mov_r32_to_local(as, (reg_temp), (local_num)); \
273 } while (false)
274#define ASM_MOV_LOCAL_TO_REG asm_x86_mov_local_to_r32
Damien George3112cde2014-09-29 18:45:42 +0100275#define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_x86_mov_r32_r32((as), (reg_dest), (reg_src))
Damien Georgec90f59e2014-09-06 23:06:36 +0100276#define ASM_MOV_LOCAL_ADDR_TO_REG asm_x86_mov_local_addr_to_r32
Damien13ed3a62013-10-08 09:05:10 +0100277
Damien George3112cde2014-09-29 18:45:42 +0100278#define ASM_LSL_REG(as, reg) asm_x86_shl_r32_cl((as), (reg))
279#define ASM_ASR_REG(as, reg) asm_x86_sar_r32_cl((as), (reg))
Damien George1ef23482014-10-12 14:21:06 +0100280#define ASM_OR_REG_REG(as, reg_dest, reg_src) asm_x86_or_r32_r32((as), (reg_dest), (reg_src))
281#define ASM_XOR_REG_REG(as, reg_dest, reg_src) asm_x86_xor_r32_r32((as), (reg_dest), (reg_src))
282#define ASM_AND_REG_REG(as, reg_dest, reg_src) asm_x86_and_r32_r32((as), (reg_dest), (reg_src))
Damien George3112cde2014-09-29 18:45:42 +0100283#define ASM_ADD_REG_REG(as, reg_dest, reg_src) asm_x86_add_r32_r32((as), (reg_dest), (reg_src))
284#define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_x86_sub_r32_r32((as), (reg_dest), (reg_src))
285
Damien George91cfd412014-10-12 16:59:29 +0100286#define ASM_LOAD_REG_REG(as, reg_dest, reg_base) asm_x86_mov_mem32_to_r32((as), (reg_base), 0, (reg_dest))
Damien George3c34d412014-10-12 16:10:25 +0000287#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_x86_mov_mem8_to_r32zx((as), (reg_base), 0, (reg_dest))
288#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_x86_mov_mem16_to_r32zx((as), (reg_base), 0, (reg_dest))
Damien George91cfd412014-10-12 16:59:29 +0100289
290#define ASM_STORE_REG_REG(as, reg_src, reg_base) asm_x86_mov_r32_to_mem32((as), (reg_src), (reg_base), 0)
291#define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_x86_mov_r8_to_mem8((as), (reg_src), (reg_base), 0)
292#define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_x86_mov_r16_to_mem16((as), (reg_src), (reg_base), 0)
Damien Georgee9dac3b2014-09-29 22:10:41 +0100293
Damien3ef4abb2013-10-12 16:53:13 +0100294#elif N_THUMB
Damien13ed3a62013-10-08 09:05:10 +0100295
296// thumb specific stuff
297
298#include "asmthumb.h"
299
Damien13ed3a62013-10-08 09:05:10 +0100300#define EXPORT_FUN(name) emit_native_thumb_##name
301
Damien George0b610de2014-09-29 16:25:04 +0100302#define REG_RET ASM_THUMB_REG_R0
303#define REG_ARG_1 ASM_THUMB_REG_R0
304#define REG_ARG_2 ASM_THUMB_REG_R1
305#define REG_ARG_3 ASM_THUMB_REG_R2
306#define REG_ARG_4 ASM_THUMB_REG_R3
Damien George81057362014-09-07 01:06:19 +0100307
Damien George0b610de2014-09-29 16:25:04 +0100308#define REG_TEMP0 ASM_THUMB_REG_R0
309#define REG_TEMP1 ASM_THUMB_REG_R1
310#define REG_TEMP2 ASM_THUMB_REG_R2
Damien Georgec90f59e2014-09-06 23:06:36 +0100311
Damien George0b610de2014-09-29 16:25:04 +0100312#define REG_LOCAL_1 ASM_THUMB_REG_R4
313#define REG_LOCAL_2 ASM_THUMB_REG_R5
314#define REG_LOCAL_3 ASM_THUMB_REG_R6
Damien Georgec90f59e2014-09-06 23:06:36 +0100315#define REG_LOCAL_NUM (3)
316
317#define ASM_PASS_COMPUTE ASM_THUMB_PASS_COMPUTE
318#define ASM_PASS_EMIT ASM_THUMB_PASS_EMIT
319
320#define ASM_T asm_thumb_t
321#define ASM_NEW asm_thumb_new
322#define ASM_FREE asm_thumb_free
323#define ASM_GET_CODE asm_thumb_get_code
324#define ASM_GET_CODE_SIZE asm_thumb_get_code_size
325#define ASM_START_PASS asm_thumb_start_pass
326#define ASM_END_PASS asm_thumb_end_pass
327#define ASM_ENTRY asm_thumb_entry
328#define ASM_EXIT asm_thumb_exit
329
330#define ASM_LABEL_ASSIGN asm_thumb_label_assign
331#define ASM_JUMP asm_thumb_b_label
332#define ASM_JUMP_IF_REG_ZERO(as, reg, label) \
333 do { \
334 asm_thumb_cmp_rlo_i8(as, reg, 0); \
Damien George0b610de2014-09-29 16:25:04 +0100335 asm_thumb_bcc_label(as, ASM_THUMB_CC_EQ, label); \
Damien Georgec90f59e2014-09-06 23:06:36 +0100336 } while (0)
337#define ASM_JUMP_IF_REG_NONZERO(as, reg, label) \
338 do { \
339 asm_thumb_cmp_rlo_i8(as, reg, 0); \
Damien George0b610de2014-09-29 16:25:04 +0100340 asm_thumb_bcc_label(as, ASM_THUMB_CC_NE, label); \
Damien Georgec90f59e2014-09-06 23:06:36 +0100341 } while (0)
342#define ASM_JUMP_IF_REG_EQ(as, reg1, reg2, label) \
343 do { \
344 asm_thumb_cmp_rlo_rlo(as, reg1, reg2); \
Damien George0b610de2014-09-29 16:25:04 +0100345 asm_thumb_bcc_label(as, ASM_THUMB_CC_EQ, label); \
Damien Georgec90f59e2014-09-06 23:06:36 +0100346 } while (0)
Damien George0b610de2014-09-29 16:25:04 +0100347#define ASM_CALL_IND(as, ptr, idx) asm_thumb_bl_ind(as, ptr, idx, ASM_THUMB_REG_R3)
Damien Georgec90f59e2014-09-06 23:06:36 +0100348
349#define ASM_MOV_REG_TO_LOCAL(as, reg, local_num) asm_thumb_mov_local_reg(as, (local_num), (reg))
350#define ASM_MOV_IMM_TO_REG(as, imm, reg) asm_thumb_mov_reg_i32_optimised(as, (reg), (imm))
351#define ASM_MOV_ALIGNED_IMM_TO_REG(as, imm, reg) asm_thumb_mov_reg_i32_aligned(as, (reg), (imm))
352#define ASM_MOV_IMM_TO_LOCAL_USING(as, imm, local_num, reg_temp) \
353 do { \
354 asm_thumb_mov_reg_i32_optimised(as, (reg_temp), (imm)); \
355 asm_thumb_mov_local_reg(as, (local_num), (reg_temp)); \
356 } while (false)
357#define ASM_MOV_LOCAL_TO_REG(as, local_num, reg) asm_thumb_mov_reg_local(as, (reg), (local_num))
Damien George3112cde2014-09-29 18:45:42 +0100358#define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_thumb_mov_reg_reg((as), (reg_dest), (reg_src))
Damien Georgec90f59e2014-09-06 23:06:36 +0100359#define ASM_MOV_LOCAL_ADDR_TO_REG(as, local_num, reg) asm_thumb_mov_reg_local_addr(as, (reg), (local_num))
Damien13ed3a62013-10-08 09:05:10 +0100360
Damien George3112cde2014-09-29 18:45:42 +0100361#define ASM_LSL_REG_REG(as, reg_dest, reg_shift) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_LSL, (reg_dest), (reg_shift))
362#define ASM_ASR_REG_REG(as, reg_dest, reg_shift) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_ASR, (reg_dest), (reg_shift))
Damien George1ef23482014-10-12 14:21:06 +0100363#define ASM_OR_REG_REG(as, reg_dest, reg_src) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_ORR, (reg_dest), (reg_src))
364#define ASM_XOR_REG_REG(as, reg_dest, reg_src) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_EOR, (reg_dest), (reg_src))
365#define ASM_AND_REG_REG(as, reg_dest, reg_src) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_AND, (reg_dest), (reg_src))
Damien George3112cde2014-09-29 18:45:42 +0100366#define ASM_ADD_REG_REG(as, reg_dest, reg_src) asm_thumb_add_rlo_rlo_rlo((as), (reg_dest), (reg_dest), (reg_src))
367#define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_thumb_sub_rlo_rlo_rlo((as), (reg_dest), (reg_dest), (reg_src))
368
Damien George91cfd412014-10-12 16:59:29 +0100369#define ASM_LOAD_REG_REG(as, reg_dest, reg_base) asm_thumb_ldr_rlo_rlo_i5((as), (reg_dest), (reg_base), 0)
370#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_thumb_ldrb_rlo_rlo_i5((as), (reg_dest), (reg_base), 0)
371#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_thumb_ldrh_rlo_rlo_i5((as), (reg_dest), (reg_base), 0)
372
Damien Georgee9dac3b2014-09-29 22:10:41 +0100373#define ASM_STORE_REG_REG(as, reg_src, reg_base) asm_thumb_str_rlo_rlo_i5((as), (reg_src), (reg_base), 0)
374#define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_thumb_strb_rlo_rlo_i5((as), (reg_src), (reg_base), 0)
375#define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_thumb_strh_rlo_rlo_i5((as), (reg_src), (reg_base), 0)
376
Fabian Vogtfe3d16e2014-08-16 22:55:53 +0200377#elif N_ARM
378
379// ARM specific stuff
380
381#include "asmarm.h"
382
Fabian Vogtfe3d16e2014-08-16 22:55:53 +0200383#define EXPORT_FUN(name) emit_native_arm_##name
384
Damien George0b610de2014-09-29 16:25:04 +0100385#define REG_RET ASM_ARM_REG_R0
386#define REG_ARG_1 ASM_ARM_REG_R0
387#define REG_ARG_2 ASM_ARM_REG_R1
388#define REG_ARG_3 ASM_ARM_REG_R2
389#define REG_ARG_4 ASM_ARM_REG_R3
Damien George81057362014-09-07 01:06:19 +0100390
Damien George0b610de2014-09-29 16:25:04 +0100391#define REG_TEMP0 ASM_ARM_REG_R0
392#define REG_TEMP1 ASM_ARM_REG_R1
393#define REG_TEMP2 ASM_ARM_REG_R2
Damien Georgec90f59e2014-09-06 23:06:36 +0100394
Damien George0b610de2014-09-29 16:25:04 +0100395#define REG_LOCAL_1 ASM_ARM_REG_R4
396#define REG_LOCAL_2 ASM_ARM_REG_R5
397#define REG_LOCAL_3 ASM_ARM_REG_R6
Damien Georgec90f59e2014-09-06 23:06:36 +0100398#define REG_LOCAL_NUM (3)
399
400#define ASM_PASS_COMPUTE ASM_ARM_PASS_COMPUTE
401#define ASM_PASS_EMIT ASM_ARM_PASS_EMIT
402
403#define ASM_T asm_arm_t
404#define ASM_NEW asm_arm_new
405#define ASM_FREE asm_arm_free
406#define ASM_GET_CODE asm_arm_get_code
407#define ASM_GET_CODE_SIZE asm_arm_get_code_size
408#define ASM_START_PASS asm_arm_start_pass
409#define ASM_END_PASS asm_arm_end_pass
410#define ASM_ENTRY asm_arm_entry
411#define ASM_EXIT asm_arm_exit
412
413#define ASM_LABEL_ASSIGN asm_arm_label_assign
414#define ASM_JUMP asm_arm_b_label
415#define ASM_JUMP_IF_REG_ZERO(as, reg, label) \
416 do { \
417 asm_arm_cmp_reg_i8(as, reg, 0); \
Damien George0b610de2014-09-29 16:25:04 +0100418 asm_arm_bcc_label(as, ASM_ARM_CC_EQ, label); \
Damien Georgec90f59e2014-09-06 23:06:36 +0100419 } while (0)
420#define ASM_JUMP_IF_REG_NONZERO(as, reg, label) \
421 do { \
422 asm_arm_cmp_reg_i8(as, reg, 0); \
Damien George0b610de2014-09-29 16:25:04 +0100423 asm_arm_bcc_label(as, ASM_ARM_CC_NE, label); \
Damien Georgec90f59e2014-09-06 23:06:36 +0100424 } while (0)
425#define ASM_JUMP_IF_REG_EQ(as, reg1, reg2, label) \
426 do { \
427 asm_arm_cmp_reg_reg(as, reg1, reg2); \
Damien George0b610de2014-09-29 16:25:04 +0100428 asm_arm_bcc_label(as, ASM_ARM_CC_EQ, label); \
Damien Georgec90f59e2014-09-06 23:06:36 +0100429 } while (0)
Damien George0b610de2014-09-29 16:25:04 +0100430#define ASM_CALL_IND(as, ptr, idx) asm_arm_bl_ind(as, ptr, idx, ASM_ARM_REG_R3)
Damien Georgec90f59e2014-09-06 23:06:36 +0100431
432#define ASM_MOV_REG_TO_LOCAL(as, reg, local_num) asm_arm_mov_local_reg(as, (local_num), (reg))
433#define ASM_MOV_IMM_TO_REG(as, imm, reg) asm_arm_mov_reg_i32(as, (reg), (imm))
434#define ASM_MOV_ALIGNED_IMM_TO_REG(as, imm, reg) asm_arm_mov_reg_i32(as, (reg), (imm))
435#define ASM_MOV_IMM_TO_LOCAL_USING(as, imm, local_num, reg_temp) \
436 do { \
437 asm_arm_mov_reg_i32(as, (reg_temp), (imm)); \
438 asm_arm_mov_local_reg(as, (local_num), (reg_temp)); \
439 } while (false)
440#define ASM_MOV_LOCAL_TO_REG(as, local_num, reg) asm_arm_mov_reg_local(as, (reg), (local_num))
Damien George3112cde2014-09-29 18:45:42 +0100441#define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_arm_mov_reg_reg((as), (reg_dest), (reg_src))
Damien Georgec90f59e2014-09-06 23:06:36 +0100442#define ASM_MOV_LOCAL_ADDR_TO_REG(as, local_num, reg) asm_arm_mov_reg_local_addr(as, (reg), (local_num))
443
Fabian Vogte5268962014-10-04 00:53:46 +0200444#define ASM_LSL_REG_REG(as, reg_dest, reg_shift) asm_arm_lsl_reg_reg((as), (reg_dest), (reg_shift))
445#define ASM_ASR_REG_REG(as, reg_dest, reg_shift) asm_arm_asr_reg_reg((as), (reg_dest), (reg_shift))
Damien George1ef23482014-10-12 14:21:06 +0100446#define ASM_OR_REG_REG(as, reg_dest, reg_src) asm_arm_orr_reg_reg_reg((as), (reg_dest), (reg_dest), (reg_src))
447#define ASM_XOR_REG_REG(as, reg_dest, reg_src) asm_arm_eor_reg_reg_reg((as), (reg_dest), (reg_dest), (reg_src))
448#define ASM_AND_REG_REG(as, reg_dest, reg_src) asm_arm_and_reg_reg_reg((as), (reg_dest), (reg_dest), (reg_src))
Damien George3112cde2014-09-29 18:45:42 +0100449#define ASM_ADD_REG_REG(as, reg_dest, reg_src) asm_arm_add_reg_reg_reg((as), (reg_dest), (reg_dest), (reg_src))
450#define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_arm_sub_reg_reg_reg((as), (reg_dest), (reg_dest), (reg_src))
451
Damien George91cfd412014-10-12 16:59:29 +0100452#define ASM_LOAD_REG_REG(as, reg_dest, reg_base) asm_arm_ldr_reg_reg((as), (reg_dest), (reg_base))
453#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_arm_ldrb_reg_reg((as), (reg_dest), (reg_base))
454#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_arm_ldrh_reg_reg((as), (reg_dest), (reg_base))
455
Fabian Vogte5268962014-10-04 00:53:46 +0200456#define ASM_STORE_REG_REG(as, reg_value, reg_base) asm_arm_str_reg_reg((as), (reg_value), (reg_base))
457#define ASM_STORE8_REG_REG(as, reg_value, reg_base) asm_arm_strb_reg_reg((as), (reg_value), (reg_base))
458#define ASM_STORE16_REG_REG(as, reg_value, reg_base) asm_arm_strh_reg_reg((as), (reg_value), (reg_base))
Damien Georgee9dac3b2014-09-29 22:10:41 +0100459
Damien Georgec90f59e2014-09-06 23:06:36 +0100460#else
461
462#error unknown native emitter
Fabian Vogtfe3d16e2014-08-16 22:55:53 +0200463
Damien13ed3a62013-10-08 09:05:10 +0100464#endif
465
466typedef enum {
Damienff8ed772013-10-08 22:18:32 +0100467 STACK_VALUE,
468 STACK_REG,
469 STACK_IMM,
470} stack_info_kind_t;
Damien13ed3a62013-10-08 09:05:10 +0100471
Damien Georgee9dac3b2014-09-29 22:10:41 +0100472// these enums must be distinct and the bottom 2 bits
473// must correspond to the correct MP_NATIVE_TYPE_xxx value
Damien13ed3a62013-10-08 09:05:10 +0100474typedef enum {
Damien Georgee9dac3b2014-09-29 22:10:41 +0100475 VTYPE_PYOBJ = 0x00 | MP_NATIVE_TYPE_OBJ,
476 VTYPE_BOOL = 0x00 | MP_NATIVE_TYPE_BOOL,
477 VTYPE_INT = 0x00 | MP_NATIVE_TYPE_INT,
478 VTYPE_UINT = 0x00 | MP_NATIVE_TYPE_UINT,
479
480 VTYPE_PTR = 0x10 | MP_NATIVE_TYPE_UINT, // pointer to word sized entity
481 VTYPE_PTR8 = 0x20 | MP_NATIVE_TYPE_UINT,
482 VTYPE_PTR16 = 0x30 | MP_NATIVE_TYPE_UINT,
483 VTYPE_PTR_NONE = 0x40 | MP_NATIVE_TYPE_UINT,
484
485 VTYPE_UNBOUND = 0x50 | MP_NATIVE_TYPE_OBJ,
486 VTYPE_BUILTIN_CAST = 0x60 | MP_NATIVE_TYPE_OBJ,
Damien13ed3a62013-10-08 09:05:10 +0100487} vtype_kind_t;
488
Damienff8ed772013-10-08 22:18:32 +0100489typedef struct _stack_info_t {
490 vtype_kind_t vtype;
491 stack_info_kind_t kind;
492 union {
493 int u_reg;
Damien George40f3c022014-07-03 13:25:24 +0100494 mp_int_t u_imm;
Damienff8ed772013-10-08 22:18:32 +0100495 };
496} stack_info_t;
497
Damien13ed3a62013-10-08 09:05:10 +0100498struct _emit_t {
499 int pass;
500
501 bool do_viper_types;
Damienff8ed772013-10-08 22:18:32 +0100502
Damien George2ac4af62014-08-15 16:45:41 +0100503 vtype_kind_t return_vtype;
504
Damien George7ff996c2014-09-08 23:05:16 +0100505 mp_uint_t local_vtype_alloc;
Damien13ed3a62013-10-08 09:05:10 +0100506 vtype_kind_t *local_vtype;
Damienff8ed772013-10-08 22:18:32 +0100507
Damien George7ff996c2014-09-08 23:05:16 +0100508 mp_uint_t stack_info_alloc;
Damienff8ed772013-10-08 22:18:32 +0100509 stack_info_t *stack_info;
510
Damien13ed3a62013-10-08 09:05:10 +0100511 int stack_start;
512 int stack_size;
513
514 bool last_emit_was_return_value;
515
Damien13ed3a62013-10-08 09:05:10 +0100516 scope_t *scope;
517
Damien Georgec90f59e2014-09-06 23:06:36 +0100518 ASM_T *as;
Damien13ed3a62013-10-08 09:05:10 +0100519};
520
Damien George7ff996c2014-09-08 23:05:16 +0100521emit_t *EXPORT_FUN(new)(mp_uint_t max_num_labels) {
Damien George36db6bc2014-05-07 17:24:22 +0100522 emit_t *emit = m_new0(emit_t, 1);
Damien Georgec90f59e2014-09-06 23:06:36 +0100523 emit->as = ASM_NEW(max_num_labels);
Damien13ed3a62013-10-08 09:05:10 +0100524 return emit;
525}
526
Damien George41d02b62014-01-24 22:42:28 +0000527void EXPORT_FUN(free)(emit_t *emit) {
Damien Georgec90f59e2014-09-06 23:06:36 +0100528 ASM_FREE(emit->as, false);
Damien George36db6bc2014-05-07 17:24:22 +0100529 m_del(vtype_kind_t, emit->local_vtype, emit->local_vtype_alloc);
530 m_del(stack_info_t, emit->stack_info, emit->stack_info_alloc);
Paul Sokolovskyf46d87a2014-01-24 16:20:11 +0200531 m_del_obj(emit_t, emit);
532}
533
Damien George2ac4af62014-08-15 16:45:41 +0100534STATIC void emit_native_set_native_type(emit_t *emit, mp_uint_t op, mp_uint_t arg1, qstr arg2) {
535 switch (op) {
536 case MP_EMIT_NATIVE_TYPE_ENABLE:
537 emit->do_viper_types = arg1;
538 break;
539
540 default: {
541 vtype_kind_t type;
542 switch (arg2) {
543 case MP_QSTR_object: type = VTYPE_PYOBJ; break;
544 case MP_QSTR_bool: type = VTYPE_BOOL; break;
545 case MP_QSTR_int: type = VTYPE_INT; break;
546 case MP_QSTR_uint: type = VTYPE_UINT; break;
Damien Georgee9dac3b2014-09-29 22:10:41 +0100547 case MP_QSTR_ptr: type = VTYPE_PTR; break;
548 case MP_QSTR_ptr8: type = VTYPE_PTR8; break;
549 case MP_QSTR_ptr16: type = VTYPE_PTR16; break;
Damien George2ac4af62014-08-15 16:45:41 +0100550 default: printf("ViperTypeError: unknown type %s\n", qstr_str(arg2)); return;
551 }
552 if (op == MP_EMIT_NATIVE_TYPE_RETURN) {
553 emit->return_vtype = type;
554 } else {
555 assert(arg1 < emit->local_vtype_alloc);
556 emit->local_vtype[arg1] = type;
557 }
558 break;
559 }
560 }
Damien13ed3a62013-10-08 09:05:10 +0100561}
562
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200563STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
Damien Georged6230f62014-09-23 14:10:03 +0000564 DEBUG_printf("start_pass(pass=%u, scope=%p)\n", pass, scope);
565
Damien13ed3a62013-10-08 09:05:10 +0100566 emit->pass = pass;
567 emit->stack_start = 0;
568 emit->stack_size = 0;
569 emit->last_emit_was_return_value = false;
Damien13ed3a62013-10-08 09:05:10 +0100570 emit->scope = scope;
571
Damien George36db6bc2014-05-07 17:24:22 +0100572 // allocate memory for keeping track of the types of locals
573 if (emit->local_vtype_alloc < scope->num_locals) {
574 emit->local_vtype = m_renew(vtype_kind_t, emit->local_vtype, emit->local_vtype_alloc, scope->num_locals);
575 emit->local_vtype_alloc = scope->num_locals;
Damienff8ed772013-10-08 22:18:32 +0100576 }
Damien George36db6bc2014-05-07 17:24:22 +0100577
578 // allocate memory for keeping track of the objects on the stack
579 // XXX don't know stack size on entry, and it should be maximum over all scopes
Damienff8ed772013-10-08 22:18:32 +0100580 if (emit->stack_info == NULL) {
Damien George36db6bc2014-05-07 17:24:22 +0100581 emit->stack_info_alloc = scope->stack_size + 50;
Damienff8ed772013-10-08 22:18:32 +0100582 emit->stack_info = m_new(stack_info_t, emit->stack_info_alloc);
Damien13ed3a62013-10-08 09:05:10 +0100583 }
584
Damien George2ac4af62014-08-15 16:45:41 +0100585 // set default type for return and arguments
586 emit->return_vtype = VTYPE_PYOBJ;
Damien Georgea5190a72014-08-15 22:39:08 +0100587 for (mp_uint_t i = 0; i < emit->scope->num_pos_args; i++) {
Damien George2ac4af62014-08-15 16:45:41 +0100588 emit->local_vtype[i] = VTYPE_PYOBJ;
589 }
Damien Georgea5190a72014-08-15 22:39:08 +0100590
591 // local variables begin unbound, and have unknown type
592 for (mp_uint_t i = emit->scope->num_pos_args; i < emit->local_vtype_alloc; i++) {
593 emit->local_vtype[i] = VTYPE_UNBOUND;
594 }
595
596 // values on stack begin unbound
597 for (mp_uint_t i = 0; i < emit->stack_info_alloc; i++) {
Damien George2ac4af62014-08-15 16:45:41 +0100598 emit->stack_info[i].kind = STACK_VALUE;
Damien Georgea5190a72014-08-15 22:39:08 +0100599 emit->stack_info[i].vtype = VTYPE_UNBOUND;
Damien13ed3a62013-10-08 09:05:10 +0100600 }
601
Damien Georgec90f59e2014-09-06 23:06:36 +0100602 ASM_START_PASS(emit->as, pass == MP_PASS_EMIT ? ASM_PASS_EMIT : ASM_PASS_COMPUTE);
Damien13ed3a62013-10-08 09:05:10 +0100603
604 // entry to function
605 int num_locals = 0;
Damien George36db6bc2014-05-07 17:24:22 +0100606 if (pass > MP_PASS_SCOPE) {
Damien13ed3a62013-10-08 09:05:10 +0100607 num_locals = scope->num_locals - REG_LOCAL_NUM;
608 if (num_locals < 0) {
609 num_locals = 0;
610 }
611 emit->stack_start = num_locals;
612 num_locals += scope->stack_size;
613 }
Damien Georgec90f59e2014-09-06 23:06:36 +0100614 ASM_ENTRY(emit->as, num_locals);
Damien13ed3a62013-10-08 09:05:10 +0100615
616 // initialise locals from parameters
Damien3ef4abb2013-10-12 16:53:13 +0100617#if N_X64
Damien George2827d622014-04-27 15:50:52 +0100618 for (int i = 0; i < scope->num_pos_args; i++) {
Damien13ed3a62013-10-08 09:05:10 +0100619 if (i == 0) {
Damien George3112cde2014-09-29 18:45:42 +0100620 ASM_MOV_REG_REG(emit->as, REG_LOCAL_1, REG_ARG_1);
Damien13ed3a62013-10-08 09:05:10 +0100621 } else if (i == 1) {
Damien George3112cde2014-09-29 18:45:42 +0100622 ASM_MOV_REG_REG(emit->as, REG_LOCAL_2, REG_ARG_2);
Damien13ed3a62013-10-08 09:05:10 +0100623 } else if (i == 2) {
Damien George3112cde2014-09-29 18:45:42 +0100624 ASM_MOV_REG_REG(emit->as, REG_LOCAL_3, REG_ARG_3);
Damien George81057362014-09-07 01:06:19 +0100625 } else if (i == 3) {
626 asm_x64_mov_r64_to_local(emit->as, REG_ARG_4, i - REG_LOCAL_NUM);
Damien13ed3a62013-10-08 09:05:10 +0100627 } else {
628 // TODO not implemented
629 assert(0);
630 }
631 }
Damien Georgec90f59e2014-09-06 23:06:36 +0100632#elif N_X86
633 for (int i = 0; i < scope->num_pos_args; i++) {
Damien Georgec90f59e2014-09-06 23:06:36 +0100634 if (i == 0) {
Damien George03281b32014-09-06 22:38:50 +0000635 asm_x86_mov_arg_to_r32(emit->as, i, REG_LOCAL_1);
Damien Georgec90f59e2014-09-06 23:06:36 +0100636 } else if (i == 1) {
Damien George03281b32014-09-06 22:38:50 +0000637 asm_x86_mov_arg_to_r32(emit->as, i, REG_LOCAL_2);
Damien George25d90412014-09-06 23:24:32 +0000638 } else if (i == 2) {
639 asm_x86_mov_arg_to_r32(emit->as, i, REG_LOCAL_3);
Damien Georgec90f59e2014-09-06 23:06:36 +0100640 } else {
Damien George03281b32014-09-06 22:38:50 +0000641 asm_x86_mov_arg_to_r32(emit->as, i, REG_TEMP0);
642 asm_x86_mov_r32_to_local(emit->as, REG_TEMP0, i - REG_LOCAL_NUM);
Damien Georgec90f59e2014-09-06 23:06:36 +0100643 }
644 }
Damien3ef4abb2013-10-12 16:53:13 +0100645#elif N_THUMB
Damien George2827d622014-04-27 15:50:52 +0100646 for (int i = 0; i < scope->num_pos_args; i++) {
Damien13ed3a62013-10-08 09:05:10 +0100647 if (i == 0) {
Damien George3112cde2014-09-29 18:45:42 +0100648 ASM_MOV_REG_REG(emit->as, REG_LOCAL_1, REG_ARG_1);
Damien13ed3a62013-10-08 09:05:10 +0100649 } else if (i == 1) {
Damien George3112cde2014-09-29 18:45:42 +0100650 ASM_MOV_REG_REG(emit->as, REG_LOCAL_2, REG_ARG_2);
Damien13ed3a62013-10-08 09:05:10 +0100651 } else if (i == 2) {
Damien George3112cde2014-09-29 18:45:42 +0100652 ASM_MOV_REG_REG(emit->as, REG_LOCAL_3, REG_ARG_3);
Damien13ed3a62013-10-08 09:05:10 +0100653 } else if (i == 3) {
654 asm_thumb_mov_local_reg(emit->as, i - REG_LOCAL_NUM, REG_ARG_4);
655 } else {
656 // TODO not implemented
657 assert(0);
658 }
659 }
660
Damien Georgee9dac3b2014-09-29 22:10:41 +0100661 // TODO don't load r7 if we don't need it
Damien George0b610de2014-09-29 16:25:04 +0100662 asm_thumb_mov_reg_i32(emit->as, ASM_THUMB_REG_R7, (mp_uint_t)mp_fun_table);
Fabian Vogtfe3d16e2014-08-16 22:55:53 +0200663#elif N_ARM
664 for (int i = 0; i < scope->num_pos_args; i++) {
665 if (i == 0) {
Damien George3112cde2014-09-29 18:45:42 +0100666 ASM_MOV_REG_REG(emit->as, REG_LOCAL_1, REG_ARG_1);
Fabian Vogtfe3d16e2014-08-16 22:55:53 +0200667 } else if (i == 1) {
Damien George3112cde2014-09-29 18:45:42 +0100668 ASM_MOV_REG_REG(emit->as, REG_LOCAL_2, REG_ARG_2);
Fabian Vogtfe3d16e2014-08-16 22:55:53 +0200669 } else if (i == 2) {
Damien George3112cde2014-09-29 18:45:42 +0100670 ASM_MOV_REG_REG(emit->as, REG_LOCAL_3, REG_ARG_3);
Fabian Vogtfe3d16e2014-08-16 22:55:53 +0200671 } else if (i == 3) {
672 asm_arm_mov_local_reg(emit->as, i - REG_LOCAL_NUM, REG_ARG_4);
673 } else {
674 // TODO not implemented
675 assert(0);
676 }
677 }
678
Damien Georgee9dac3b2014-09-29 22:10:41 +0100679 // TODO don't load r7 if we don't need it
Damien George0b610de2014-09-29 16:25:04 +0100680 asm_arm_mov_reg_i32(emit->as, ASM_ARM_REG_R7, (mp_uint_t)mp_fun_table);
Damien Georgec90f59e2014-09-06 23:06:36 +0100681#else
682 #error not implemented
Damien13ed3a62013-10-08 09:05:10 +0100683#endif
684}
685
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200686STATIC void emit_native_end_pass(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +0100687 if (!emit->last_emit_was_return_value) {
Damien Georgec90f59e2014-09-06 23:06:36 +0100688 ASM_EXIT(emit->as);
Damien13ed3a62013-10-08 09:05:10 +0100689 }
Damien Georgec90f59e2014-09-06 23:06:36 +0100690 ASM_END_PASS(emit->as);
Damien13ed3a62013-10-08 09:05:10 +0100691
692 // check stack is back to zero size
693 if (emit->stack_size != 0) {
694 printf("ERROR: stack size not back to zero; got %d\n", emit->stack_size);
695 }
696
Damien George36db6bc2014-05-07 17:24:22 +0100697 if (emit->pass == MP_PASS_EMIT) {
Damien Georgec90f59e2014-09-06 23:06:36 +0100698 void *f = ASM_GET_CODE(emit->as);
699 mp_uint_t f_len = ASM_GET_CODE_SIZE(emit->as);
Damien George2ac4af62014-08-15 16:45:41 +0100700
701 // compute type signature
Damien Georgee9dac3b2014-09-29 22:10:41 +0100702 // note that the lower 2 bits of a vtype are tho correct MP_NATIVE_TYPE_xxx
Damien George2ac4af62014-08-15 16:45:41 +0100703 mp_uint_t type_sig = emit->return_vtype & 3;
704 for (mp_uint_t i = 0; i < emit->scope->num_pos_args; i++) {
705 type_sig |= (emit->local_vtype[i] & 3) << (i * 2 + 2);
706 }
707
708 mp_emit_glue_assign_native(emit->scope->raw_code, emit->do_viper_types ? MP_CODE_NATIVE_VIPER : MP_CODE_NATIVE_PY, f, f_len, emit->scope->num_pos_args, type_sig);
Damien13ed3a62013-10-08 09:05:10 +0100709 }
710}
711
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200712STATIC bool emit_native_last_emit_was_return_value(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +0100713 return emit->last_emit_was_return_value;
714}
715
Damien Georged6230f62014-09-23 14:10:03 +0000716STATIC void adjust_stack(emit_t *emit, mp_int_t stack_size_delta) {
717 DEBUG_printf(" adjust_stack; stack_size=%d, delta=%d\n", emit->stack_size, stack_size_delta);
718 assert((mp_int_t)emit->stack_size + stack_size_delta >= 0);
Damien13ed3a62013-10-08 09:05:10 +0100719 emit->stack_size += stack_size_delta;
Damien George36db6bc2014-05-07 17:24:22 +0100720 if (emit->pass > MP_PASS_SCOPE && emit->stack_size > emit->scope->stack_size) {
Damien13ed3a62013-10-08 09:05:10 +0100721 emit->scope->stack_size = emit->stack_size;
722 }
723}
724
Damien Georged6230f62014-09-23 14:10:03 +0000725STATIC void emit_native_adjust_stack_size(emit_t *emit, mp_int_t delta) {
726 // If we are adjusting the stack in a positive direction (pushing) then we
727 // need to fill in values for the stack kind and vtype of the newly-pushed
728 // entries. These should be set to "value" (ie not reg or imm) because we
729 // should only need to adjust the stack due to a jump to this part in the
730 // code (and hence we have settled the stack before the jump).
731 for (mp_int_t i = 0; i < delta; i++) {
732 stack_info_t *si = &emit->stack_info[emit->stack_size + i];
733 si->kind = STACK_VALUE;
734 si->vtype = VTYPE_PYOBJ; // XXX we don't know the vtype...
735 }
736 adjust_stack(emit, delta);
737}
738
739STATIC void emit_native_set_source_line(emit_t *emit, mp_uint_t source_line) {
740}
741
Damienff8ed772013-10-08 22:18:32 +0100742/*
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200743STATIC void emit_pre_raw(emit_t *emit, int stack_size_delta) {
Damien13ed3a62013-10-08 09:05:10 +0100744 adjust_stack(emit, stack_size_delta);
745 emit->last_emit_was_return_value = false;
746}
Damienff8ed772013-10-08 22:18:32 +0100747*/
Damien13ed3a62013-10-08 09:05:10 +0100748
Damienff8ed772013-10-08 22:18:32 +0100749// this must be called at start of emit functions
Damien Georgece8f07a2014-03-27 23:30:26 +0000750STATIC void emit_native_pre(emit_t *emit) {
Damienff8ed772013-10-08 22:18:32 +0100751 emit->last_emit_was_return_value = false;
752 // settle the stack
753 /*
754 if (regs_needed != 0) {
755 for (int i = 0; i < emit->stack_size; i++) {
756 switch (emit->stack_info[i].kind) {
757 case STACK_VALUE:
758 break;
759
760 case STACK_REG:
761 // TODO only push reg if in regs_needed
762 emit->stack_info[i].kind = STACK_VALUE;
Damien Georgec90f59e2014-09-06 23:06:36 +0100763 ASM_MOV_REG_TO_LOCAL(emit->as, emit->stack_info[i].u_reg, emit->stack_start + i);
Damienff8ed772013-10-08 22:18:32 +0100764 break;
765
766 case STACK_IMM:
767 // don't think we ever need to push imms for settling
768 //ASM_MOV_IMM_TO_LOCAL(emit->last_imm, emit->stack_start + i);
769 break;
770 }
771 }
772 }
773 */
Damien13ed3a62013-10-08 09:05:10 +0100774}
775
Damien George3112cde2014-09-29 18:45:42 +0100776// depth==0 is top, depth==1 is before top, etc
777STATIC stack_info_t *peek_stack(emit_t *emit, mp_uint_t depth) {
778 return &emit->stack_info[emit->stack_size - 1 - depth];
779}
780
781// depth==0 is top, depth==1 is before top, etc
782STATIC vtype_kind_t peek_vtype(emit_t *emit, mp_uint_t depth) {
783 return peek_stack(emit, depth)->vtype;
Damienff8ed772013-10-08 22:18:32 +0100784}
Damien13ed3a62013-10-08 09:05:10 +0100785
Damiend2755ec2013-10-16 23:58:48 +0100786// pos=1 is TOS, pos=2 is next, etc
787// use pos=0 for no skipping
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200788STATIC void need_reg_single(emit_t *emit, int reg_needed, int skip_stack_pos) {
Damiend2755ec2013-10-16 23:58:48 +0100789 skip_stack_pos = emit->stack_size - skip_stack_pos;
Damienff8ed772013-10-08 22:18:32 +0100790 for (int i = 0; i < emit->stack_size; i++) {
Damiend2755ec2013-10-16 23:58:48 +0100791 if (i != skip_stack_pos) {
792 stack_info_t *si = &emit->stack_info[i];
793 if (si->kind == STACK_REG && si->u_reg == reg_needed) {
794 si->kind = STACK_VALUE;
Damien Georgec90f59e2014-09-06 23:06:36 +0100795 ASM_MOV_REG_TO_LOCAL(emit->as, si->u_reg, emit->stack_start + i);
Damiend2755ec2013-10-16 23:58:48 +0100796 }
Damienff8ed772013-10-08 22:18:32 +0100797 }
798 }
799}
Damien13ed3a62013-10-08 09:05:10 +0100800
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200801STATIC void need_reg_all(emit_t *emit) {
Damienff8ed772013-10-08 22:18:32 +0100802 for (int i = 0; i < emit->stack_size; i++) {
803 stack_info_t *si = &emit->stack_info[i];
804 if (si->kind == STACK_REG) {
805 si->kind = STACK_VALUE;
Damien Georgec90f59e2014-09-06 23:06:36 +0100806 ASM_MOV_REG_TO_LOCAL(emit->as, si->u_reg, emit->stack_start + i);
Damienff8ed772013-10-08 22:18:32 +0100807 }
Damien13ed3a62013-10-08 09:05:10 +0100808 }
809}
810
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200811STATIC void need_stack_settled(emit_t *emit) {
Damien Georged6230f62014-09-23 14:10:03 +0000812 DEBUG_printf(" need_stack_settled; stack_size=%d\n", emit->stack_size);
Damiend2755ec2013-10-16 23:58:48 +0100813 for (int i = 0; i < emit->stack_size; i++) {
814 stack_info_t *si = &emit->stack_info[i];
815 if (si->kind == STACK_REG) {
Damien Georged6230f62014-09-23 14:10:03 +0000816 DEBUG_printf(" reg(%u) to local(%u)\n", si->u_reg, emit->stack_start + i);
Damiend2755ec2013-10-16 23:58:48 +0100817 si->kind = STACK_VALUE;
Damien Georgec90f59e2014-09-06 23:06:36 +0100818 ASM_MOV_REG_TO_LOCAL(emit->as, si->u_reg, emit->stack_start + i);
Damiend2755ec2013-10-16 23:58:48 +0100819 }
820 }
821 for (int i = 0; i < emit->stack_size; i++) {
822 stack_info_t *si = &emit->stack_info[i];
823 if (si->kind == STACK_IMM) {
Damien Georged6230f62014-09-23 14:10:03 +0000824 DEBUG_printf(" imm(" INT_FMT ") to local(%u)\n", si->u_imm, emit->stack_start + i);
Damien George02d95d72014-08-29 20:05:32 +0100825 si->kind = STACK_VALUE;
Damien Georgec90f59e2014-09-06 23:06:36 +0100826 ASM_MOV_IMM_TO_LOCAL_USING(emit->as, si->u_imm, emit->stack_start + i, REG_TEMP0);
Damiend2755ec2013-10-16 23:58:48 +0100827 }
828 }
829}
830
831// pos=1 is TOS, pos=2 is next, etc
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200832STATIC void emit_access_stack(emit_t *emit, int pos, vtype_kind_t *vtype, int reg_dest) {
Damiend2755ec2013-10-16 23:58:48 +0100833 need_reg_single(emit, reg_dest, pos);
834 stack_info_t *si = &emit->stack_info[emit->stack_size - pos];
Damienff8ed772013-10-08 22:18:32 +0100835 *vtype = si->vtype;
836 switch (si->kind) {
837 case STACK_VALUE:
Damien Georgec90f59e2014-09-06 23:06:36 +0100838 ASM_MOV_LOCAL_TO_REG(emit->as, emit->stack_start + emit->stack_size - pos, reg_dest);
Damien13ed3a62013-10-08 09:05:10 +0100839 break;
840
Damienff8ed772013-10-08 22:18:32 +0100841 case STACK_REG:
842 if (si->u_reg != reg_dest) {
Damien George3112cde2014-09-29 18:45:42 +0100843 ASM_MOV_REG_REG(emit->as, reg_dest, si->u_reg);
Damien13ed3a62013-10-08 09:05:10 +0100844 }
845 break;
846
Damienff8ed772013-10-08 22:18:32 +0100847 case STACK_IMM:
Damien Georgec90f59e2014-09-06 23:06:36 +0100848 ASM_MOV_IMM_TO_REG(emit->as, si->u_imm, reg_dest);
Damien13ed3a62013-10-08 09:05:10 +0100849 break;
850 }
Damien13ed3a62013-10-08 09:05:10 +0100851}
852
Damien Georgee9dac3b2014-09-29 22:10:41 +0100853// does an efficient X=pop(); discard(); push(X)
854// needs a (non-temp) register in case the poped element was stored in the stack
855STATIC void emit_fold_stack_top(emit_t *emit, int reg_dest) {
856 stack_info_t *si = &emit->stack_info[emit->stack_size - 2];
857 si[0] = si[1];
858 if (si->kind == STACK_VALUE) {
859 // if folded element was on the stack we need to put it in a register
860 ASM_MOV_LOCAL_TO_REG(emit->as, emit->stack_start + emit->stack_size - 1, reg_dest);
861 si->kind = STACK_REG;
862 si->u_reg = reg_dest;
863 }
864 adjust_stack(emit, -1);
865}
866
867// If stacked value is in a register and the register is not r1 or r2, then
868// *reg_dest is set to that register. Otherwise the value is put in *reg_dest.
869STATIC void emit_pre_pop_reg_flexible(emit_t *emit, vtype_kind_t *vtype, int *reg_dest, int not_r1, int not_r2) {
Damien George3112cde2014-09-29 18:45:42 +0100870 emit->last_emit_was_return_value = false;
871 stack_info_t *si = peek_stack(emit, 0);
Damien Georgee9dac3b2014-09-29 22:10:41 +0100872 if (si->kind == STACK_REG && si->u_reg != not_r1 && si->u_reg != not_r2) {
Damien George3112cde2014-09-29 18:45:42 +0100873 *vtype = si->vtype;
874 *reg_dest = si->u_reg;
875 need_reg_single(emit, *reg_dest, 1);
876 } else {
877 emit_access_stack(emit, 1, vtype, *reg_dest);
878 }
879 adjust_stack(emit, -1);
880}
881
Damien Georgee6ce10a2014-09-06 18:38:20 +0100882STATIC void emit_pre_pop_discard(emit_t *emit) {
Damien Georgeccc85ea2014-05-10 13:40:46 +0100883 emit->last_emit_was_return_value = false;
884 adjust_stack(emit, -1);
885}
886
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200887STATIC void emit_pre_pop_reg(emit_t *emit, vtype_kind_t *vtype, int reg_dest) {
Damiend2755ec2013-10-16 23:58:48 +0100888 emit->last_emit_was_return_value = false;
889 emit_access_stack(emit, 1, vtype, reg_dest);
890 adjust_stack(emit, -1);
891}
892
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200893STATIC void emit_pre_pop_reg_reg(emit_t *emit, vtype_kind_t *vtypea, int rega, vtype_kind_t *vtypeb, int regb) {
Damien13ed3a62013-10-08 09:05:10 +0100894 emit_pre_pop_reg(emit, vtypea, rega);
Damienff8ed772013-10-08 22:18:32 +0100895 emit_pre_pop_reg(emit, vtypeb, regb);
Damien13ed3a62013-10-08 09:05:10 +0100896}
897
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200898STATIC void emit_pre_pop_reg_reg_reg(emit_t *emit, vtype_kind_t *vtypea, int rega, vtype_kind_t *vtypeb, int regb, vtype_kind_t *vtypec, int regc) {
Damien13ed3a62013-10-08 09:05:10 +0100899 emit_pre_pop_reg(emit, vtypea, rega);
Damienff8ed772013-10-08 22:18:32 +0100900 emit_pre_pop_reg(emit, vtypeb, regb);
901 emit_pre_pop_reg(emit, vtypec, regc);
Damien13ed3a62013-10-08 09:05:10 +0100902}
903
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200904STATIC void emit_post(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +0100905}
906
Damien Georgee9dac3b2014-09-29 22:10:41 +0100907STATIC void emit_post_top_set_vtype(emit_t *emit, vtype_kind_t new_vtype) {
908 stack_info_t *si = &emit->stack_info[emit->stack_size - 1];
909 si->vtype = new_vtype;
910}
911
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200912STATIC void emit_post_push_reg(emit_t *emit, vtype_kind_t vtype, int reg) {
Damienff8ed772013-10-08 22:18:32 +0100913 stack_info_t *si = &emit->stack_info[emit->stack_size];
914 si->vtype = vtype;
915 si->kind = STACK_REG;
916 si->u_reg = reg;
Damien13ed3a62013-10-08 09:05:10 +0100917 adjust_stack(emit, 1);
918}
919
Damien George40f3c022014-07-03 13:25:24 +0100920STATIC void emit_post_push_imm(emit_t *emit, vtype_kind_t vtype, mp_int_t imm) {
Damienff8ed772013-10-08 22:18:32 +0100921 stack_info_t *si = &emit->stack_info[emit->stack_size];
922 si->vtype = vtype;
923 si->kind = STACK_IMM;
924 si->u_imm = imm;
925 adjust_stack(emit, 1);
926}
927
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200928STATIC void emit_post_push_reg_reg(emit_t *emit, vtype_kind_t vtypea, int rega, vtype_kind_t vtypeb, int regb) {
Damienff8ed772013-10-08 22:18:32 +0100929 emit_post_push_reg(emit, vtypea, rega);
930 emit_post_push_reg(emit, vtypeb, regb);
931}
932
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200933STATIC void emit_post_push_reg_reg_reg(emit_t *emit, vtype_kind_t vtypea, int rega, vtype_kind_t vtypeb, int regb, vtype_kind_t vtypec, int regc) {
Damienff8ed772013-10-08 22:18:32 +0100934 emit_post_push_reg(emit, vtypea, rega);
935 emit_post_push_reg(emit, vtypeb, regb);
936 emit_post_push_reg(emit, vtypec, regc);
Damien13ed3a62013-10-08 09:05:10 +0100937}
938
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200939STATIC void emit_post_push_reg_reg_reg_reg(emit_t *emit, vtype_kind_t vtypea, int rega, vtype_kind_t vtypeb, int regb, vtype_kind_t vtypec, int regc, vtype_kind_t vtyped, int regd) {
Damienff8ed772013-10-08 22:18:32 +0100940 emit_post_push_reg(emit, vtypea, rega);
941 emit_post_push_reg(emit, vtypeb, regb);
942 emit_post_push_reg(emit, vtypec, regc);
943 emit_post_push_reg(emit, vtyped, regd);
Damien13ed3a62013-10-08 09:05:10 +0100944}
945
Damien George7fe21912014-08-16 22:31:57 +0100946STATIC void emit_call(emit_t *emit, mp_fun_kind_t fun_kind) {
Damiend2755ec2013-10-16 23:58:48 +0100947 need_reg_all(emit);
Damien Georgec90f59e2014-09-06 23:06:36 +0100948 ASM_CALL_IND(emit->as, mp_fun_table[fun_kind], fun_kind);
Damien13ed3a62013-10-08 09:05:10 +0100949}
950
Damien George7fe21912014-08-16 22:31:57 +0100951STATIC void emit_call_with_imm_arg(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val, int arg_reg) {
Damieneb19efb2013-10-10 22:06:54 +0100952 need_reg_all(emit);
Damien Georgec90f59e2014-09-06 23:06:36 +0100953 ASM_MOV_IMM_TO_REG(emit->as, arg_val, arg_reg);
954 ASM_CALL_IND(emit->as, mp_fun_table[fun_kind], fun_kind);
Damien13ed3a62013-10-08 09:05:10 +0100955}
956
Damien George40f3c022014-07-03 13:25:24 +0100957// the first arg is stored in the code aligned on a mp_uint_t boundary
Damien George7fe21912014-08-16 22:31:57 +0100958STATIC void emit_call_with_imm_arg_aligned(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val, int arg_reg) {
Damien Georgea32c1e42014-05-07 18:30:52 +0100959 need_reg_all(emit);
Damien Georgec90f59e2014-09-06 23:06:36 +0100960 ASM_MOV_ALIGNED_IMM_TO_REG(emit->as, arg_val, arg_reg);
961 ASM_CALL_IND(emit->as, mp_fun_table[fun_kind], fun_kind);
Damien Georgea32c1e42014-05-07 18:30:52 +0100962}
963
Damien George7fe21912014-08-16 22:31:57 +0100964STATIC void emit_call_with_2_imm_args(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val1, int arg_reg1, mp_int_t arg_val2, int arg_reg2) {
Damien Georgecd82e022014-02-02 13:11:48 +0000965 need_reg_all(emit);
Damien Georgec90f59e2014-09-06 23:06:36 +0100966 ASM_MOV_IMM_TO_REG(emit->as, arg_val1, arg_reg1);
967 ASM_MOV_IMM_TO_REG(emit->as, arg_val2, arg_reg2);
968 ASM_CALL_IND(emit->as, mp_fun_table[fun_kind], fun_kind);
Damien Georgecd82e022014-02-02 13:11:48 +0000969}
970
Damien George40f3c022014-07-03 13:25:24 +0100971// the first arg is stored in the code aligned on a mp_uint_t boundary
Damien George7fe21912014-08-16 22:31:57 +0100972STATIC void emit_call_with_3_imm_args_and_first_aligned(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val1, int arg_reg1, mp_int_t arg_val2, int arg_reg2, mp_int_t arg_val3, int arg_reg3) {
Damien Georgecdd96df2014-04-06 12:58:40 +0100973 need_reg_all(emit);
Damien Georgec90f59e2014-09-06 23:06:36 +0100974 ASM_MOV_ALIGNED_IMM_TO_REG(emit->as, arg_val1, arg_reg1);
975 ASM_MOV_IMM_TO_REG(emit->as, arg_val2, arg_reg2);
976 ASM_MOV_IMM_TO_REG(emit->as, arg_val3, arg_reg3);
977 ASM_CALL_IND(emit->as, mp_fun_table[fun_kind], fun_kind);
Damien Georgecdd96df2014-04-06 12:58:40 +0100978}
979
Damien George86de21b2014-08-16 22:06:11 +0100980// vtype of all n_pop objects is VTYPE_PYOBJ
981// Will convert any items that are not VTYPE_PYOBJ to this type and put them back on the stack.
982// If any conversions of non-immediate values are needed, then it uses REG_ARG_1, REG_ARG_2 and REG_RET.
983// Otherwise, it does not use any temporary registers (but may use reg_dest before loading it with stack pointer).
984STATIC void emit_get_stack_pointer_to_reg_for_pop(emit_t *emit, mp_uint_t reg_dest, mp_uint_t n_pop) {
985 need_reg_all(emit);
Damien13ed3a62013-10-08 09:05:10 +0100986
Damien George86de21b2014-08-16 22:06:11 +0100987 // First, store any immediate values to their respective place on the stack.
988 for (mp_uint_t i = 0; i < n_pop; i++) {
989 stack_info_t *si = &emit->stack_info[emit->stack_size - 1 - i];
990 // must push any imm's to stack
991 // must convert them to VTYPE_PYOBJ for viper code
992 if (si->kind == STACK_IMM) {
993 si->kind = STACK_VALUE;
994 switch (si->vtype) {
995 case VTYPE_PYOBJ:
Damien Georgec90f59e2014-09-06 23:06:36 +0100996 ASM_MOV_IMM_TO_LOCAL_USING(emit->as, si->u_imm, emit->stack_start + emit->stack_size - 1 - i, reg_dest);
Damien George86de21b2014-08-16 22:06:11 +0100997 break;
998 case VTYPE_BOOL:
999 if (si->u_imm == 0) {
Damien Georgec90f59e2014-09-06 23:06:36 +01001000 ASM_MOV_IMM_TO_LOCAL_USING(emit->as, (mp_uint_t)mp_const_false, emit->stack_start + emit->stack_size - 1 - i, reg_dest);
Damien George86de21b2014-08-16 22:06:11 +01001001 } else {
Damien Georgec90f59e2014-09-06 23:06:36 +01001002 ASM_MOV_IMM_TO_LOCAL_USING(emit->as, (mp_uint_t)mp_const_true, emit->stack_start + emit->stack_size - 1 - i, reg_dest);
Damien George86de21b2014-08-16 22:06:11 +01001003 }
1004 si->vtype = VTYPE_PYOBJ;
1005 break;
1006 case VTYPE_INT:
1007 case VTYPE_UINT:
Damien Georgec90f59e2014-09-06 23:06:36 +01001008 ASM_MOV_IMM_TO_LOCAL_USING(emit->as, (si->u_imm << 1) | 1, emit->stack_start + emit->stack_size - 1 - i, reg_dest);
Damien George86de21b2014-08-16 22:06:11 +01001009 si->vtype = VTYPE_PYOBJ;
1010 break;
1011 default:
1012 // not handled
1013 assert(0);
1014 }
1015 }
1016
1017 // verify that this value is on the stack
1018 assert(si->kind == STACK_VALUE);
Damien13ed3a62013-10-08 09:05:10 +01001019 }
Damien George86de21b2014-08-16 22:06:11 +01001020
1021 // Second, convert any non-VTYPE_PYOBJ to that type.
1022 for (mp_uint_t i = 0; i < n_pop; i++) {
1023 stack_info_t *si = &emit->stack_info[emit->stack_size - 1 - i];
1024 if (si->vtype != VTYPE_PYOBJ) {
1025 mp_uint_t local_num = emit->stack_start + emit->stack_size - 1 - i;
Damien Georgec90f59e2014-09-06 23:06:36 +01001026 ASM_MOV_LOCAL_TO_REG(emit->as, local_num, REG_ARG_1);
Damien George7fe21912014-08-16 22:31:57 +01001027 emit_call_with_imm_arg(emit, MP_F_CONVERT_NATIVE_TO_OBJ, si->vtype, REG_ARG_2); // arg2 = type
Damien Georgec90f59e2014-09-06 23:06:36 +01001028 ASM_MOV_REG_TO_LOCAL(emit->as, REG_RET, local_num);
Damien George86de21b2014-08-16 22:06:11 +01001029 si->vtype = VTYPE_PYOBJ;
Damien Georgee9dac3b2014-09-29 22:10:41 +01001030 DEBUG_printf(" convert_native_to_obj(local_num=" UINT_FMT ")\n", local_num);
Damien George86de21b2014-08-16 22:06:11 +01001031 }
1032 }
1033
1034 // Adujust the stack for a pop of n_pop items, and load the stack pointer into reg_dest.
1035 adjust_stack(emit, -n_pop);
Damien Georgec90f59e2014-09-06 23:06:36 +01001036 ASM_MOV_LOCAL_ADDR_TO_REG(emit->as, emit->stack_start + emit->stack_size, reg_dest);
Damien George86de21b2014-08-16 22:06:11 +01001037}
1038
1039// vtype of all n_push objects is VTYPE_PYOBJ
1040STATIC void emit_get_stack_pointer_to_reg_for_push(emit_t *emit, mp_uint_t reg_dest, mp_uint_t n_push) {
1041 need_reg_all(emit);
1042 for (mp_uint_t i = 0; i < n_push; i++) {
1043 emit->stack_info[emit->stack_size + i].kind = STACK_VALUE;
1044 emit->stack_info[emit->stack_size + i].vtype = VTYPE_PYOBJ;
1045 }
Damien Georgec90f59e2014-09-06 23:06:36 +01001046 ASM_MOV_LOCAL_ADDR_TO_REG(emit->as, emit->stack_start + emit->stack_size, reg_dest);
Damien George86de21b2014-08-16 22:06:11 +01001047 adjust_stack(emit, n_push);
1048}
1049
Damien George7ff996c2014-09-08 23:05:16 +01001050STATIC void emit_native_load_id(emit_t *emit, qstr qst) {
1051 emit_common_load_id(emit, &EXPORT_FUN(method_table), emit->scope, qst);
Damien13ed3a62013-10-08 09:05:10 +01001052}
1053
Damien George7ff996c2014-09-08 23:05:16 +01001054STATIC void emit_native_store_id(emit_t *emit, qstr qst) {
1055 emit_common_store_id(emit, &EXPORT_FUN(method_table), emit->scope, qst);
Damien13ed3a62013-10-08 09:05:10 +01001056}
1057
Damien George7ff996c2014-09-08 23:05:16 +01001058STATIC void emit_native_delete_id(emit_t *emit, qstr qst) {
1059 emit_common_delete_id(emit, &EXPORT_FUN(method_table), emit->scope, qst);
Damien13ed3a62013-10-08 09:05:10 +01001060}
1061
Damien George7ff996c2014-09-08 23:05:16 +01001062STATIC void emit_native_label_assign(emit_t *emit, mp_uint_t l) {
Damien Georged6230f62014-09-23 14:10:03 +00001063 DEBUG_printf("label_assign(" UINT_FMT ")\n", l);
Damien Georgece8f07a2014-03-27 23:30:26 +00001064 emit_native_pre(emit);
Damiend2755ec2013-10-16 23:58:48 +01001065 // need to commit stack because we can jump here from elsewhere
1066 need_stack_settled(emit);
Damien Georgec90f59e2014-09-06 23:06:36 +01001067 ASM_LABEL_ASSIGN(emit->as, l);
Damien6ba13142013-11-02 20:34:54 +00001068 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001069}
1070
Damien Georgecdd96df2014-04-06 12:58:40 +01001071STATIC void emit_native_import_name(emit_t *emit, qstr qst) {
1072 DEBUG_printf("import_name %s\n", qstr_str(qst));
1073 vtype_kind_t vtype_fromlist;
1074 vtype_kind_t vtype_level;
1075 emit_pre_pop_reg_reg(emit, &vtype_fromlist, REG_ARG_2, &vtype_level, REG_ARG_3); // arg2 = fromlist, arg3 = level
1076 assert(vtype_fromlist == VTYPE_PYOBJ);
1077 assert(vtype_level == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001078 emit_call_with_imm_arg(emit, MP_F_IMPORT_NAME, qst, REG_ARG_1); // arg1 = import name
Damien Georgecdd96df2014-04-06 12:58:40 +01001079 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
Damien13ed3a62013-10-08 09:05:10 +01001080}
1081
Damien Georgecdd96df2014-04-06 12:58:40 +01001082STATIC void emit_native_import_from(emit_t *emit, qstr qst) {
1083 DEBUG_printf("import_from %s\n", qstr_str(qst));
1084 emit_native_pre(emit);
1085 vtype_kind_t vtype_module;
1086 emit_access_stack(emit, 1, &vtype_module, REG_ARG_1); // arg1 = module
1087 assert(vtype_module == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001088 emit_call_with_imm_arg(emit, MP_F_IMPORT_FROM, qst, REG_ARG_2); // arg2 = import name
Damien Georgecdd96df2014-04-06 12:58:40 +01001089 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
Damien13ed3a62013-10-08 09:05:10 +01001090}
1091
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001092STATIC void emit_native_import_star(emit_t *emit) {
Damien Georgecdd96df2014-04-06 12:58:40 +01001093 DEBUG_printf("import_star\n");
1094 vtype_kind_t vtype_module;
1095 emit_pre_pop_reg(emit, &vtype_module, REG_ARG_1); // arg1 = module
1096 assert(vtype_module == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001097 emit_call(emit, MP_F_IMPORT_ALL);
Damien Georgecdd96df2014-04-06 12:58:40 +01001098 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001099}
1100
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001101STATIC void emit_native_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
Damien Georged6230f62014-09-23 14:10:03 +00001102 DEBUG_printf("load_const_tok(tok=%u)\n", tok);
Damien Georgece8f07a2014-03-27 23:30:26 +00001103 emit_native_pre(emit);
Damien George39dc1452014-10-03 19:52:22 +01001104 vtype_kind_t vtype;
Damien George40f3c022014-07-03 13:25:24 +01001105 mp_uint_t val;
Damien13ed3a62013-10-08 09:05:10 +01001106 if (emit->do_viper_types) {
1107 switch (tok) {
Damiend99b0522013-12-21 18:17:45 +00001108 case MP_TOKEN_KW_NONE: vtype = VTYPE_PTR_NONE; val = 0; break;
1109 case MP_TOKEN_KW_FALSE: vtype = VTYPE_BOOL; val = 0; break;
1110 case MP_TOKEN_KW_TRUE: vtype = VTYPE_BOOL; val = 1; break;
Damien13ed3a62013-10-08 09:05:10 +01001111 default: assert(0); vtype = 0; val = 0; // shouldn't happen
1112 }
1113 } else {
1114 vtype = VTYPE_PYOBJ;
1115 switch (tok) {
Damien George40f3c022014-07-03 13:25:24 +01001116 case MP_TOKEN_KW_NONE: val = (mp_uint_t)mp_const_none; break;
1117 case MP_TOKEN_KW_FALSE: val = (mp_uint_t)mp_const_false; break;
1118 case MP_TOKEN_KW_TRUE: val = (mp_uint_t)mp_const_true; break;
Damien13ed3a62013-10-08 09:05:10 +01001119 default: assert(0); vtype = 0; val = 0; // shouldn't happen
1120 }
1121 }
1122 emit_post_push_imm(emit, vtype, val);
1123}
1124
Damien George40f3c022014-07-03 13:25:24 +01001125STATIC void emit_native_load_const_small_int(emit_t *emit, mp_int_t arg) {
Damien Georged6230f62014-09-23 14:10:03 +00001126 DEBUG_printf("load_const_small_int(int=" INT_FMT ")\n", arg);
Damien Georgece8f07a2014-03-27 23:30:26 +00001127 emit_native_pre(emit);
Damien13ed3a62013-10-08 09:05:10 +01001128 if (emit->do_viper_types) {
1129 emit_post_push_imm(emit, VTYPE_INT, arg);
1130 } else {
1131 emit_post_push_imm(emit, VTYPE_PYOBJ, (arg << 1) | 1);
1132 }
1133}
1134
Damien Georgecdd96df2014-04-06 12:58:40 +01001135STATIC void emit_native_load_const_int(emit_t *emit, qstr qst) {
Damien Georged6230f62014-09-23 14:10:03 +00001136 DEBUG_printf("load_const_int %s\n", qstr_str(qst));
Damien Georgecdd96df2014-04-06 12:58:40 +01001137 // for viper: load integer, check fits in 32 bits
1138 emit_native_pre(emit);
Damien George7fe21912014-08-16 22:31:57 +01001139 emit_call_with_imm_arg(emit, MP_F_LOAD_CONST_INT, qst, REG_ARG_1);
Damien Georgecdd96df2014-04-06 12:58:40 +01001140 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
Damien13ed3a62013-10-08 09:05:10 +01001141}
1142
Damien George7ff996c2014-09-08 23:05:16 +01001143STATIC void emit_native_load_const_dec(emit_t *emit, qstr qst) {
Damien6ba13142013-11-02 20:34:54 +00001144 // for viper, a float/complex is just a Python object
Damien Georgece8f07a2014-03-27 23:30:26 +00001145 emit_native_pre(emit);
Damien George7ff996c2014-09-08 23:05:16 +01001146 emit_call_with_imm_arg(emit, MP_F_LOAD_CONST_DEC, qst, REG_ARG_1);
Damien6ba13142013-11-02 20:34:54 +00001147 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
Damien13ed3a62013-10-08 09:05:10 +01001148}
1149
Damien George7ff996c2014-09-08 23:05:16 +01001150STATIC void emit_native_load_const_str(emit_t *emit, qstr qst, bool bytes) {
Damien Georgece8f07a2014-03-27 23:30:26 +00001151 emit_native_pre(emit);
Damien Georgebb295462014-09-12 23:15:06 +01001152 // TODO: Eventually we want to be able to work with raw pointers in viper to
1153 // do native array access. For now we just load them as any other object.
1154 /*
Damien13ed3a62013-10-08 09:05:10 +01001155 if (emit->do_viper_types) {
1156 // not implemented properly
1157 // load a pointer to the asciiz string?
1158 assert(0);
Damien George7ff996c2014-09-08 23:05:16 +01001159 emit_post_push_imm(emit, VTYPE_PTR, (mp_uint_t)qstr_str(qst));
Damien Georgebb295462014-09-12 23:15:06 +01001160 } else
1161 */
1162 {
Damien Georgeb601d952014-06-30 05:17:25 +01001163 if (bytes) {
Damien George7ff996c2014-09-08 23:05:16 +01001164 emit_call_with_imm_arg(emit, MP_F_LOAD_CONST_BYTES, qst, REG_ARG_1);
Damien Georgeb601d952014-06-30 05:17:25 +01001165 } else {
Damien George7ff996c2014-09-08 23:05:16 +01001166 emit_call_with_imm_arg(emit, MP_F_LOAD_CONST_STR, qst, REG_ARG_1);
Damien Georgeb601d952014-06-30 05:17:25 +01001167 }
Damien13ed3a62013-10-08 09:05:10 +01001168 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1169 }
1170}
1171
Damien George3558f622014-04-20 17:50:40 +01001172STATIC void emit_native_load_null(emit_t *emit) {
1173 emit_native_pre(emit);
1174 emit_post_push_imm(emit, VTYPE_PYOBJ, 0);
1175}
1176
Damien George7ff996c2014-09-08 23:05:16 +01001177STATIC void emit_native_load_fast(emit_t *emit, qstr qst, mp_uint_t id_flags, mp_uint_t local_num) {
Damien13ed3a62013-10-08 09:05:10 +01001178 vtype_kind_t vtype = emit->local_vtype[local_num];
1179 if (vtype == VTYPE_UNBOUND) {
Damien George7ff996c2014-09-08 23:05:16 +01001180 printf("ViperTypeError: local %s used before type known\n", qstr_str(qst));
Damien13ed3a62013-10-08 09:05:10 +01001181 }
Damien Georgece8f07a2014-03-27 23:30:26 +00001182 emit_native_pre(emit);
Damien3ef4abb2013-10-12 16:53:13 +01001183#if N_X64
Damien13ed3a62013-10-08 09:05:10 +01001184 if (local_num == 0) {
1185 emit_post_push_reg(emit, vtype, REG_LOCAL_1);
Damien George81057362014-09-07 01:06:19 +01001186 } else if (local_num == 1) {
1187 emit_post_push_reg(emit, vtype, REG_LOCAL_2);
1188 } else if (local_num == 2) {
1189 emit_post_push_reg(emit, vtype, REG_LOCAL_3);
Damien13ed3a62013-10-08 09:05:10 +01001190 } else {
Damien George0b610de2014-09-29 16:25:04 +01001191 need_reg_single(emit, REG_TEMP0, 0);
1192 asm_x64_mov_local_to_r64(emit->as, local_num - REG_LOCAL_NUM, REG_TEMP0);
1193 emit_post_push_reg(emit, vtype, REG_TEMP0);
Damien13ed3a62013-10-08 09:05:10 +01001194 }
Damien Georgec90f59e2014-09-06 23:06:36 +01001195#elif N_X86
1196 if (local_num == 0) {
1197 emit_post_push_reg(emit, vtype, REG_LOCAL_1);
Damien George03281b32014-09-06 22:38:50 +00001198 } else if (local_num == 1) {
1199 emit_post_push_reg(emit, vtype, REG_LOCAL_2);
Damien George25d90412014-09-06 23:24:32 +00001200 } else if (local_num == 2) {
1201 emit_post_push_reg(emit, vtype, REG_LOCAL_3);
Damien Georgec90f59e2014-09-06 23:06:36 +01001202 } else {
Damien George0b610de2014-09-29 16:25:04 +01001203 need_reg_single(emit, REG_TEMP0, 0);
1204 asm_x86_mov_local_to_r32(emit->as, local_num - REG_LOCAL_NUM, REG_TEMP0);
1205 emit_post_push_reg(emit, vtype, REG_TEMP0);
Damien Georgec90f59e2014-09-06 23:06:36 +01001206 }
Damien3ef4abb2013-10-12 16:53:13 +01001207#elif N_THUMB
Damien13ed3a62013-10-08 09:05:10 +01001208 if (local_num == 0) {
1209 emit_post_push_reg(emit, vtype, REG_LOCAL_1);
1210 } else if (local_num == 1) {
1211 emit_post_push_reg(emit, vtype, REG_LOCAL_2);
1212 } else if (local_num == 2) {
1213 emit_post_push_reg(emit, vtype, REG_LOCAL_3);
1214 } else {
Damien George0b610de2014-09-29 16:25:04 +01001215 need_reg_single(emit, REG_TEMP0, 0);
1216 asm_thumb_mov_reg_local(emit->as, REG_TEMP0, local_num - REG_LOCAL_NUM);
1217 emit_post_push_reg(emit, vtype, REG_TEMP0);
Damien13ed3a62013-10-08 09:05:10 +01001218 }
Fabian Vogtfe3d16e2014-08-16 22:55:53 +02001219#elif N_ARM
1220 if (local_num == 0) {
1221 emit_post_push_reg(emit, vtype, REG_LOCAL_1);
1222 } else if (local_num == 1) {
1223 emit_post_push_reg(emit, vtype, REG_LOCAL_2);
1224 } else if (local_num == 2) {
1225 emit_post_push_reg(emit, vtype, REG_LOCAL_3);
1226 } else {
Damien George0b610de2014-09-29 16:25:04 +01001227 need_reg_single(emit, REG_TEMP0, 0);
1228 asm_arm_mov_reg_local(emit->as, REG_TEMP0, local_num - REG_LOCAL_NUM);
1229 emit_post_push_reg(emit, vtype, REG_TEMP0);
Fabian Vogtfe3d16e2014-08-16 22:55:53 +02001230 }
Damien Georgec90f59e2014-09-06 23:06:36 +01001231#else
1232 #error not implemented
Damien13ed3a62013-10-08 09:05:10 +01001233#endif
1234}
1235
Damien George7ff996c2014-09-08 23:05:16 +01001236STATIC void emit_native_load_deref(emit_t *emit, qstr qst, mp_uint_t local_num) {
Damien9ecbcff2013-12-11 00:41:43 +00001237 // not implemented
1238 // in principle could support this quite easily (ldr r0, [r0, #0]) and then get closed over variables!
1239 assert(0);
1240}
1241
Damien George7ff996c2014-09-08 23:05:16 +01001242STATIC void emit_native_load_name(emit_t *emit, qstr qst) {
Damien Georged6230f62014-09-23 14:10:03 +00001243 DEBUG_printf("load_name(%s)\n", qstr_str(qst));
Damien Georgece8f07a2014-03-27 23:30:26 +00001244 emit_native_pre(emit);
Damien George7ff996c2014-09-08 23:05:16 +01001245 emit_call_with_imm_arg(emit, MP_F_LOAD_NAME, qst, REG_ARG_1);
Damien13ed3a62013-10-08 09:05:10 +01001246 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1247}
1248
Damien George7ff996c2014-09-08 23:05:16 +01001249STATIC void emit_native_load_global(emit_t *emit, qstr qst) {
Damien Georgee9dac3b2014-09-29 22:10:41 +01001250 DEBUG_printf("load_global(%s)\n", qstr_str(qst));
Damien Georgece8f07a2014-03-27 23:30:26 +00001251 emit_native_pre(emit);
Damien Georgee9dac3b2014-09-29 22:10:41 +01001252 // check for builtin casting operators
1253 if (emit->do_viper_types && qst == MP_QSTR_int) {
1254 emit_post_push_imm(emit, VTYPE_BUILTIN_CAST, VTYPE_INT);
1255 } else if (emit->do_viper_types && qst == MP_QSTR_uint) {
1256 emit_post_push_imm(emit, VTYPE_BUILTIN_CAST, VTYPE_UINT);
1257 } else if (emit->do_viper_types && qst == MP_QSTR_ptr) {
1258 emit_post_push_imm(emit, VTYPE_BUILTIN_CAST, VTYPE_PTR);
1259 } else if (emit->do_viper_types && qst == MP_QSTR_ptr8) {
1260 emit_post_push_imm(emit, VTYPE_BUILTIN_CAST, VTYPE_PTR8);
1261 } else if (emit->do_viper_types && qst == MP_QSTR_ptr16) {
1262 emit_post_push_imm(emit, VTYPE_BUILTIN_CAST, VTYPE_PTR16);
1263 } else {
1264 emit_call_with_imm_arg(emit, MP_F_LOAD_GLOBAL, qst, REG_ARG_1);
1265 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1266 }
Damien13ed3a62013-10-08 09:05:10 +01001267}
1268
Damien George7ff996c2014-09-08 23:05:16 +01001269STATIC void emit_native_load_attr(emit_t *emit, qstr qst) {
Damien13ed3a62013-10-08 09:05:10 +01001270 // depends on type of subject:
1271 // - integer, function, pointer to integers: error
1272 // - pointer to structure: get member, quite easy
Damien Georged17926d2014-03-30 13:35:08 +01001273 // - Python object: call mp_load_attr, and needs to be typed to convert result
Damien13ed3a62013-10-08 09:05:10 +01001274 vtype_kind_t vtype_base;
1275 emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base
1276 assert(vtype_base == VTYPE_PYOBJ);
Damien George7ff996c2014-09-08 23:05:16 +01001277 emit_call_with_imm_arg(emit, MP_F_LOAD_ATTR, qst, REG_ARG_2); // arg2 = attribute name
Damien13ed3a62013-10-08 09:05:10 +01001278 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1279}
1280
Damien George7ff996c2014-09-08 23:05:16 +01001281STATIC void emit_native_load_method(emit_t *emit, qstr qst) {
Damien13ed3a62013-10-08 09:05:10 +01001282 vtype_kind_t vtype_base;
1283 emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base
1284 assert(vtype_base == VTYPE_PYOBJ);
1285 emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, 2); // arg3 = dest ptr
Damien George7ff996c2014-09-08 23:05:16 +01001286 emit_call_with_imm_arg(emit, MP_F_LOAD_METHOD, qst, REG_ARG_2); // arg2 = method name
Damien13ed3a62013-10-08 09:05:10 +01001287}
1288
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001289STATIC void emit_native_load_build_class(emit_t *emit) {
Damien Georgece8f07a2014-03-27 23:30:26 +00001290 emit_native_pre(emit);
Damien George7fe21912014-08-16 22:31:57 +01001291 emit_call(emit, MP_F_LOAD_BUILD_CLASS);
Damien7f5dacf2013-10-10 11:24:39 +01001292 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
Damien13ed3a62013-10-08 09:05:10 +01001293}
1294
Damien George729f7b42014-04-17 22:10:53 +01001295STATIC void emit_native_load_subscr(emit_t *emit) {
Damien George91cfd412014-10-12 16:59:29 +01001296 DEBUG_printf("load_subscr\n");
1297 // need to compile: base[index]
1298
1299 // pop: index, base
1300 // optimise case where index is an immediate
1301 vtype_kind_t vtype_base = peek_vtype(emit, 1);
1302
1303 if (vtype_base == VTYPE_PYOBJ) {
1304 // standard Python call
1305 vtype_kind_t vtype_index;
1306 emit_pre_pop_reg_reg(emit, &vtype_index, REG_ARG_2, &vtype_base, REG_ARG_1);
1307 assert(vtype_index == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001308 emit_call_with_imm_arg(emit, MP_F_OBJ_SUBSCR, (mp_uint_t)MP_OBJ_SENTINEL, REG_ARG_3);
Damien George729f7b42014-04-17 22:10:53 +01001309 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1310 } else {
Damien George91cfd412014-10-12 16:59:29 +01001311 // viper load
1312 // TODO The different machine architectures have very different
1313 // capabilities and requirements for loads, so probably best to
1314 // write a completely separate load-optimiser for each one.
1315 stack_info_t *top = peek_stack(emit, 0);
1316 if (top->vtype == VTYPE_INT && top->kind == STACK_IMM) {
1317 // index is an immediate
1318 mp_int_t index_value = top->u_imm;
1319 emit_pre_pop_discard(emit); // discard index
1320 int reg_base = REG_ARG_1;
1321 int reg_index = REG_ARG_2;
1322 emit_pre_pop_reg_flexible(emit, &vtype_base, &reg_base, reg_index, reg_index);
1323 switch (vtype_base) {
1324 case VTYPE_PTR8: {
1325 // pointer to 8-bit memory
1326 // TODO optimise to use thumb ldrb r1, [r2, r3]
1327 if (index_value != 0) {
1328 // index is non-zero
1329 #if N_THUMB
1330 if (index_value > 0 && index_value < 32) {
1331 asm_thumb_ldrb_rlo_rlo_i5(emit->as, REG_RET, reg_base, index_value);
1332 break;
1333 }
1334 #endif
1335 ASM_MOV_IMM_TO_REG(emit->as, index_value, reg_index);
1336 ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add index to base
1337 reg_base = reg_index;
1338 }
1339 ASM_LOAD8_REG_REG(emit->as, REG_RET, reg_base); // load from (base+index)
1340 break;
1341 }
1342 case VTYPE_PTR16: {
1343 // pointer to 16-bit memory
1344 if (index_value != 0) {
1345 // index is a non-zero immediate
1346 #if N_THUMB
1347 if (index_value > 0 && index_value < 32) {
1348 asm_thumb_ldrh_rlo_rlo_i5(emit->as, REG_RET, reg_base, index_value);
1349 break;
1350 }
1351 #endif
1352 ASM_MOV_IMM_TO_REG(emit->as, index_value << 1, reg_index);
1353 ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 2*index to base
1354 reg_base = reg_index;
1355 }
1356 ASM_LOAD16_REG_REG(emit->as, REG_RET, reg_base); // load from (base+2*index)
1357 break;
1358 }
1359 default:
1360 printf("ViperTypeError: can't load from type %d\n", vtype_base);
1361 }
1362 } else {
1363 // index is not an immediate
1364 vtype_kind_t vtype_index;
1365 int reg_index = REG_ARG_2;
1366 emit_pre_pop_reg_flexible(emit, &vtype_index, &reg_index, REG_ARG_1, REG_ARG_1);
1367 emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1);
1368 switch (vtype_base) {
1369 case VTYPE_PTR8: {
1370 // pointer to 8-bit memory
1371 // TODO optimise to use thumb ldrb r1, [r2, r3]
1372 assert(vtype_index == VTYPE_INT);
1373 ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base
1374 ASM_LOAD8_REG_REG(emit->as, REG_RET, REG_ARG_1); // store value to (base+index)
1375 break;
1376 }
1377 case VTYPE_PTR16: {
1378 // pointer to 16-bit memory
1379 assert(vtype_index == VTYPE_INT);
1380 ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base
1381 ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base
1382 ASM_LOAD16_REG_REG(emit->as, REG_RET, REG_ARG_1); // load from (base+2*index)
1383 break;
1384 }
1385 default:
1386 printf("ViperTypeError: can't load from type %d\n", vtype_base);
1387 }
1388 }
1389 emit_post_push_reg(emit, VTYPE_INT, REG_RET);
Damien George729f7b42014-04-17 22:10:53 +01001390 }
1391}
1392
Damien George7ff996c2014-09-08 23:05:16 +01001393STATIC void emit_native_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {
Damien13ed3a62013-10-08 09:05:10 +01001394 vtype_kind_t vtype;
Damien3ef4abb2013-10-12 16:53:13 +01001395#if N_X64
Damien13ed3a62013-10-08 09:05:10 +01001396 if (local_num == 0) {
1397 emit_pre_pop_reg(emit, &vtype, REG_LOCAL_1);
Damien George81057362014-09-07 01:06:19 +01001398 } else if (local_num == 1) {
1399 emit_pre_pop_reg(emit, &vtype, REG_LOCAL_2);
1400 } else if (local_num == 2) {
1401 emit_pre_pop_reg(emit, &vtype, REG_LOCAL_3);
Damien13ed3a62013-10-08 09:05:10 +01001402 } else {
Damien George0b610de2014-09-29 16:25:04 +01001403 emit_pre_pop_reg(emit, &vtype, REG_TEMP0);
1404 asm_x64_mov_r64_to_local(emit->as, REG_TEMP0, local_num - REG_LOCAL_NUM);
Damien13ed3a62013-10-08 09:05:10 +01001405 }
Damien Georgec90f59e2014-09-06 23:06:36 +01001406#elif N_X86
1407 if (local_num == 0) {
1408 emit_pre_pop_reg(emit, &vtype, REG_LOCAL_1);
Damien George03281b32014-09-06 22:38:50 +00001409 } else if (local_num == 1) {
1410 emit_pre_pop_reg(emit, &vtype, REG_LOCAL_2);
Damien George25d90412014-09-06 23:24:32 +00001411 } else if (local_num == 2) {
1412 emit_pre_pop_reg(emit, &vtype, REG_LOCAL_3);
Damien Georgec90f59e2014-09-06 23:06:36 +01001413 } else {
Damien George0b610de2014-09-29 16:25:04 +01001414 emit_pre_pop_reg(emit, &vtype, REG_TEMP0);
1415 asm_x86_mov_r32_to_local(emit->as, REG_TEMP0, local_num - REG_LOCAL_NUM);
Damien Georgec90f59e2014-09-06 23:06:36 +01001416 }
Damien3ef4abb2013-10-12 16:53:13 +01001417#elif N_THUMB
Damien13ed3a62013-10-08 09:05:10 +01001418 if (local_num == 0) {
1419 emit_pre_pop_reg(emit, &vtype, REG_LOCAL_1);
1420 } else if (local_num == 1) {
1421 emit_pre_pop_reg(emit, &vtype, REG_LOCAL_2);
1422 } else if (local_num == 2) {
1423 emit_pre_pop_reg(emit, &vtype, REG_LOCAL_3);
1424 } else {
Damien George0b610de2014-09-29 16:25:04 +01001425 emit_pre_pop_reg(emit, &vtype, REG_TEMP0);
1426 asm_thumb_mov_local_reg(emit->as, local_num - REG_LOCAL_NUM, REG_TEMP0);
Damien13ed3a62013-10-08 09:05:10 +01001427 }
Fabian Vogtfe3d16e2014-08-16 22:55:53 +02001428#elif N_ARM
1429 if (local_num == 0) {
1430 emit_pre_pop_reg(emit, &vtype, REG_LOCAL_1);
1431 } else if (local_num == 1) {
1432 emit_pre_pop_reg(emit, &vtype, REG_LOCAL_2);
1433 } else if (local_num == 2) {
1434 emit_pre_pop_reg(emit, &vtype, REG_LOCAL_3);
1435 } else {
Damien George0b610de2014-09-29 16:25:04 +01001436 emit_pre_pop_reg(emit, &vtype, REG_TEMP0);
1437 asm_arm_mov_local_reg(emit->as, local_num - REG_LOCAL_NUM, REG_TEMP0);
Fabian Vogtfe3d16e2014-08-16 22:55:53 +02001438 }
Damien Georgec90f59e2014-09-06 23:06:36 +01001439#else
1440 #error not implemented
Damien13ed3a62013-10-08 09:05:10 +01001441#endif
1442
1443 emit_post(emit);
1444
1445 // check types
1446 if (emit->local_vtype[local_num] == VTYPE_UNBOUND) {
1447 // first time this local is assigned, so give it a type of the object stored in it
1448 emit->local_vtype[local_num] = vtype;
1449 } else if (emit->local_vtype[local_num] != vtype) {
1450 // type of local is not the same as object stored in it
Damien George7ff996c2014-09-08 23:05:16 +01001451 printf("ViperTypeError: type mismatch, local %s has type %d but source object has type %d\n", qstr_str(qst), emit->local_vtype[local_num], vtype);
Damien13ed3a62013-10-08 09:05:10 +01001452 }
1453}
1454
Damien George7ff996c2014-09-08 23:05:16 +01001455STATIC void emit_native_store_deref(emit_t *emit, qstr qst, mp_uint_t local_num) {
Damien9ecbcff2013-12-11 00:41:43 +00001456 // not implemented
1457 assert(0);
1458}
1459
Damien George7ff996c2014-09-08 23:05:16 +01001460STATIC void emit_native_store_name(emit_t *emit, qstr qst) {
Damien Georged17926d2014-03-30 13:35:08 +01001461 // mp_store_name, but needs conversion of object (maybe have mp_viper_store_name(obj, type))
Damien13ed3a62013-10-08 09:05:10 +01001462 vtype_kind_t vtype;
1463 emit_pre_pop_reg(emit, &vtype, REG_ARG_2);
1464 assert(vtype == VTYPE_PYOBJ);
Damien George7ff996c2014-09-08 23:05:16 +01001465 emit_call_with_imm_arg(emit, MP_F_STORE_NAME, qst, REG_ARG_1); // arg1 = name
Damien13ed3a62013-10-08 09:05:10 +01001466 emit_post(emit);
1467}
1468
Damien George7ff996c2014-09-08 23:05:16 +01001469STATIC void emit_native_store_global(emit_t *emit, qstr qst) {
Damien George3112cde2014-09-29 18:45:42 +01001470 vtype_kind_t vtype = peek_vtype(emit, 0);
Damien Georgee6c0dff2014-08-15 23:47:59 +01001471 if (vtype == VTYPE_PYOBJ) {
1472 emit_pre_pop_reg(emit, &vtype, REG_ARG_2);
1473 } else {
1474 emit_pre_pop_reg(emit, &vtype, REG_ARG_1);
Damien George7fe21912014-08-16 22:31:57 +01001475 emit_call_with_imm_arg(emit, MP_F_CONVERT_NATIVE_TO_OBJ, vtype, REG_ARG_2); // arg2 = type
Damien George3112cde2014-09-29 18:45:42 +01001476 ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_RET);
Damien Georgee6c0dff2014-08-15 23:47:59 +01001477 }
Damien George7ff996c2014-09-08 23:05:16 +01001478 emit_call_with_imm_arg(emit, MP_F_STORE_GLOBAL, qst, REG_ARG_1); // arg1 = name
Damien Georgee6c0dff2014-08-15 23:47:59 +01001479 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001480}
1481
Damien George7ff996c2014-09-08 23:05:16 +01001482STATIC void emit_native_store_attr(emit_t *emit, qstr qst) {
Damien7f5dacf2013-10-10 11:24:39 +01001483 vtype_kind_t vtype_base, vtype_val;
1484 emit_pre_pop_reg_reg(emit, &vtype_base, REG_ARG_1, &vtype_val, REG_ARG_3); // arg1 = base, arg3 = value
1485 assert(vtype_base == VTYPE_PYOBJ);
1486 assert(vtype_val == VTYPE_PYOBJ);
Damien George7ff996c2014-09-08 23:05:16 +01001487 emit_call_with_imm_arg(emit, MP_F_STORE_ATTR, qst, REG_ARG_2); // arg2 = attribute name
Damien7f5dacf2013-10-10 11:24:39 +01001488 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001489}
1490
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001491STATIC void emit_native_store_subscr(emit_t *emit) {
Damien Georgee9dac3b2014-09-29 22:10:41 +01001492 DEBUG_printf("store_subscr\n");
1493 // need to compile: base[index] = value
1494
1495 // pop: index, base, value
1496 // optimise case where index is an immediate
1497 vtype_kind_t vtype_base = peek_vtype(emit, 1);
1498
1499 if (vtype_base == VTYPE_PYOBJ) {
1500 // standard Python call
1501 vtype_kind_t vtype_index, vtype_value;
1502 emit_pre_pop_reg_reg_reg(emit, &vtype_index, REG_ARG_2, &vtype_base, REG_ARG_1, &vtype_value, REG_ARG_3);
1503 assert(vtype_index == VTYPE_PYOBJ);
1504 assert(vtype_value == VTYPE_PYOBJ);
1505 emit_call(emit, MP_F_OBJ_SUBSCR);
1506 } else {
Damien Georgedfef4242014-09-29 21:41:41 +00001507 // viper store
1508 // TODO The different machine architectures have very different
1509 // capabilities and requirements for stores, so probably best to
1510 // write a completely separate store-optimiser for each one.
Damien Georgee9dac3b2014-09-29 22:10:41 +01001511 stack_info_t *top = peek_stack(emit, 0);
1512 if (top->vtype == VTYPE_INT && top->kind == STACK_IMM) {
1513 // index is an immediate
1514 mp_int_t index_value = top->u_imm;
1515 emit_pre_pop_discard(emit); // discard index
1516 vtype_kind_t vtype_value;
1517 int reg_base = REG_ARG_1;
1518 int reg_index = REG_ARG_2;
1519 int reg_value = REG_ARG_3;
1520 emit_pre_pop_reg_flexible(emit, &vtype_base, &reg_base, reg_index, reg_value);
Damien Georgedfef4242014-09-29 21:41:41 +00001521 #if N_X86
1522 // special case: x86 needs byte stores to be from lower 4 regs (REG_ARG_3 is EDX)
1523 emit_pre_pop_reg(emit, &vtype_value, reg_value);
1524 #else
Damien Georgee9dac3b2014-09-29 22:10:41 +01001525 emit_pre_pop_reg_flexible(emit, &vtype_value, &reg_value, reg_base, reg_index);
Damien Georgedfef4242014-09-29 21:41:41 +00001526 #endif
Damien Georgee9dac3b2014-09-29 22:10:41 +01001527 switch (vtype_base) {
1528 case VTYPE_PTR8: {
1529 // pointer to 8-bit memory
1530 // TODO optimise to use thumb strb r1, [r2, r3]
1531 if (index_value != 0) {
1532 // index is non-zero
1533 #if N_THUMB
1534 if (index_value > 0 && index_value < 32) {
1535 asm_thumb_strb_rlo_rlo_i5(emit->as, reg_value, reg_base, index_value);
1536 break;
1537 }
1538 #endif
1539 ASM_MOV_IMM_TO_REG(emit->as, index_value, reg_index);
Fabian Vogte5268962014-10-04 00:53:46 +02001540 #if N_ARM
1541 asm_arm_strb_reg_reg_reg(emit->as, reg_value, reg_base, reg_index);
1542 return;
1543 #endif
Damien Georgee9dac3b2014-09-29 22:10:41 +01001544 ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add index to base
1545 reg_base = reg_index;
1546 }
1547 ASM_STORE8_REG_REG(emit->as, reg_value, reg_base); // store value to (base+index)
1548 break;
1549 }
1550 case VTYPE_PTR16: {
1551 // pointer to 16-bit memory
1552 if (index_value != 0) {
1553 // index is a non-zero immediate
1554 #if N_THUMB
1555 if (index_value > 0 && index_value < 32) {
1556 asm_thumb_strh_rlo_rlo_i5(emit->as, reg_value, reg_base, index_value);
1557 break;
1558 }
1559 #endif
1560 ASM_MOV_IMM_TO_REG(emit->as, index_value << 1, reg_index);
Fabian Vogte5268962014-10-04 00:53:46 +02001561 #if N_ARM
1562 asm_arm_strh_reg_reg_reg(emit->as, reg_value, reg_base, reg_index);
1563 return;
1564 #endif
Damien Georgee9dac3b2014-09-29 22:10:41 +01001565 ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 2*index to base
1566 reg_base = reg_index;
1567 }
1568 ASM_STORE16_REG_REG(emit->as, reg_value, reg_base); // store value to (base+2*index)
1569 break;
1570 }
1571 default:
1572 printf("ViperTypeError: can't store to type %d\n", vtype_base);
1573 }
1574 } else {
1575 // index is not an immediate
1576 vtype_kind_t vtype_index, vtype_value;
1577 int reg_index = REG_ARG_2;
1578 int reg_value = REG_ARG_3;
1579 emit_pre_pop_reg_flexible(emit, &vtype_index, &reg_index, REG_ARG_1, reg_value);
1580 emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1);
Damien Georgedfef4242014-09-29 21:41:41 +00001581 #if N_X86
1582 // special case: x86 needs byte stores to be from lower 4 regs (REG_ARG_3 is EDX)
1583 emit_pre_pop_reg(emit, &vtype_value, reg_value);
1584 #else
Damien Georgee9dac3b2014-09-29 22:10:41 +01001585 emit_pre_pop_reg_flexible(emit, &vtype_value, &reg_value, REG_ARG_1, reg_index);
Damien Georgedfef4242014-09-29 21:41:41 +00001586 #endif
Damien Georgee9dac3b2014-09-29 22:10:41 +01001587 switch (vtype_base) {
1588 case VTYPE_PTR8: {
1589 // pointer to 8-bit memory
1590 // TODO optimise to use thumb strb r1, [r2, r3]
1591 assert(vtype_index == VTYPE_INT);
Fabian Vogte5268962014-10-04 00:53:46 +02001592 #if N_ARM
1593 asm_arm_strb_reg_reg_reg(emit->as, reg_value, REG_ARG_1, reg_index);
1594 break;
1595 #endif
Damien Georgee9dac3b2014-09-29 22:10:41 +01001596 ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base
1597 ASM_STORE8_REG_REG(emit->as, reg_value, REG_ARG_1); // store value to (base+index)
1598 break;
1599 }
1600 case VTYPE_PTR16: {
1601 // pointer to 16-bit memory
1602 assert(vtype_index == VTYPE_INT);
Fabian Vogte5268962014-10-04 00:53:46 +02001603 #if N_ARM
1604 asm_arm_strh_reg_reg_reg(emit->as, reg_value, REG_ARG_1, reg_index);
1605 break;
1606 #endif
Damien Georgee9dac3b2014-09-29 22:10:41 +01001607 ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base
1608 ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base
1609 ASM_STORE16_REG_REG(emit->as, reg_value, REG_ARG_1); // store value to (base+2*index)
1610 break;
1611 }
1612 default:
1613 printf("ViperTypeError: can't store to type %d\n", vtype_base);
1614 }
1615 }
1616
1617 }
Damien13ed3a62013-10-08 09:05:10 +01001618}
1619
Damien George7ff996c2014-09-08 23:05:16 +01001620STATIC void emit_native_delete_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {
Damien Georgee6ce10a2014-09-06 18:38:20 +01001621 // TODO implement me!
Damien13ed3a62013-10-08 09:05:10 +01001622 // could support for Python types, just set to None (so GC can reclaim it)
Damien13ed3a62013-10-08 09:05:10 +01001623}
1624
Damien George7ff996c2014-09-08 23:05:16 +01001625STATIC void emit_native_delete_deref(emit_t *emit, qstr qst, mp_uint_t local_num) {
Damien Georgee6ce10a2014-09-06 18:38:20 +01001626 // TODO implement me!
Damien9ecbcff2013-12-11 00:41:43 +00001627}
1628
Damien Georgee6ce10a2014-09-06 18:38:20 +01001629STATIC void emit_native_delete_name(emit_t *emit, qstr qst) {
1630 emit_native_pre(emit);
1631 emit_call_with_imm_arg(emit, MP_F_DELETE_NAME, qst, REG_ARG_1);
1632 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001633}
1634
Damien Georgee6ce10a2014-09-06 18:38:20 +01001635STATIC void emit_native_delete_global(emit_t *emit, qstr qst) {
1636 emit_native_pre(emit);
1637 emit_call_with_imm_arg(emit, MP_F_DELETE_GLOBAL, qst, REG_ARG_1);
1638 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001639}
1640
Damien Georgee6ce10a2014-09-06 18:38:20 +01001641STATIC void emit_native_delete_attr(emit_t *emit, qstr qst) {
Damien George780e54c2014-06-22 18:35:04 +01001642 vtype_kind_t vtype_base;
1643 emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base
1644 assert(vtype_base == VTYPE_PYOBJ);
Damien Georgee6ce10a2014-09-06 18:38:20 +01001645 emit_call_with_2_imm_args(emit, MP_F_STORE_ATTR, qst, REG_ARG_2, (mp_uint_t)MP_OBJ_NULL, REG_ARG_3); // arg2 = attribute name, arg3 = value (null for delete)
Damien George780e54c2014-06-22 18:35:04 +01001646 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001647}
1648
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001649STATIC void emit_native_delete_subscr(emit_t *emit) {
Damien George729f7b42014-04-17 22:10:53 +01001650 vtype_kind_t vtype_index, vtype_base;
1651 emit_pre_pop_reg_reg(emit, &vtype_index, REG_ARG_2, &vtype_base, REG_ARG_1); // index, base
1652 assert(vtype_index == VTYPE_PYOBJ);
1653 assert(vtype_base == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001654 emit_call_with_imm_arg(emit, MP_F_OBJ_SUBSCR, (mp_uint_t)MP_OBJ_NULL, REG_ARG_3);
Damien13ed3a62013-10-08 09:05:10 +01001655}
1656
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001657STATIC void emit_native_dup_top(emit_t *emit) {
Damien Georged6230f62014-09-23 14:10:03 +00001658 DEBUG_printf("dup_top\n");
Damien13ed3a62013-10-08 09:05:10 +01001659 vtype_kind_t vtype;
1660 emit_pre_pop_reg(emit, &vtype, REG_TEMP0);
1661 emit_post_push_reg_reg(emit, vtype, REG_TEMP0, vtype, REG_TEMP0);
1662}
1663
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001664STATIC void emit_native_dup_top_two(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +01001665 vtype_kind_t vtype0, vtype1;
1666 emit_pre_pop_reg_reg(emit, &vtype0, REG_TEMP0, &vtype1, REG_TEMP1);
1667 emit_post_push_reg_reg_reg_reg(emit, vtype1, REG_TEMP1, vtype0, REG_TEMP0, vtype1, REG_TEMP1, vtype0, REG_TEMP0);
1668}
1669
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001670STATIC void emit_native_pop_top(emit_t *emit) {
Damien Georged6230f62014-09-23 14:10:03 +00001671 DEBUG_printf("pop_top\n");
Damien Georgee6ce10a2014-09-06 18:38:20 +01001672 emit_pre_pop_discard(emit);
Damien13ed3a62013-10-08 09:05:10 +01001673 emit_post(emit);
1674}
1675
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001676STATIC void emit_native_rot_two(emit_t *emit) {
Damien Georged6230f62014-09-23 14:10:03 +00001677 DEBUG_printf("rot_two\n");
Damienff8ed772013-10-08 22:18:32 +01001678 vtype_kind_t vtype0, vtype1;
1679 emit_pre_pop_reg_reg(emit, &vtype0, REG_TEMP0, &vtype1, REG_TEMP1);
1680 emit_post_push_reg_reg(emit, vtype0, REG_TEMP0, vtype1, REG_TEMP1);
Damien13ed3a62013-10-08 09:05:10 +01001681}
1682
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001683STATIC void emit_native_rot_three(emit_t *emit) {
Damien Georged6230f62014-09-23 14:10:03 +00001684 DEBUG_printf("rot_three\n");
Damien13ed3a62013-10-08 09:05:10 +01001685 vtype_kind_t vtype0, vtype1, vtype2;
1686 emit_pre_pop_reg_reg_reg(emit, &vtype0, REG_TEMP0, &vtype1, REG_TEMP1, &vtype2, REG_TEMP2);
1687 emit_post_push_reg_reg_reg(emit, vtype0, REG_TEMP0, vtype2, REG_TEMP2, vtype1, REG_TEMP1);
1688}
1689
Damien George7ff996c2014-09-08 23:05:16 +01001690STATIC void emit_native_jump(emit_t *emit, mp_uint_t label) {
Damien Georged6230f62014-09-23 14:10:03 +00001691 DEBUG_printf("jump(label=" UINT_FMT ")\n", label);
Damien Georgece8f07a2014-03-27 23:30:26 +00001692 emit_native_pre(emit);
Damien Georgea32c1e42014-05-07 18:30:52 +01001693 // need to commit stack because we are jumping elsewhere
1694 need_stack_settled(emit);
Damien Georgec90f59e2014-09-06 23:06:36 +01001695 ASM_JUMP(emit->as, label);
Damien13ed3a62013-10-08 09:05:10 +01001696 emit_post(emit);
1697}
1698
Damien George7ff996c2014-09-08 23:05:16 +01001699STATIC void emit_native_jump_helper(emit_t *emit, mp_uint_t label, bool pop) {
Damien George3112cde2014-09-29 18:45:42 +01001700 vtype_kind_t vtype = peek_vtype(emit, 0);
Damien George6f813482014-09-29 16:41:37 +01001701 switch (vtype) {
1702 case VTYPE_PYOBJ:
1703 emit_pre_pop_reg(emit, &vtype, REG_ARG_1);
1704 if (!pop) {
1705 adjust_stack(emit, 1);
1706 }
1707 emit_call(emit, MP_F_OBJ_IS_TRUE);
1708 break;
1709 case VTYPE_BOOL:
1710 case VTYPE_INT:
1711 case VTYPE_UINT:
1712 emit_pre_pop_reg(emit, &vtype, REG_RET);
1713 if (!pop) {
1714 adjust_stack(emit, 1);
1715 }
1716 break;
1717 default:
1718 printf("ViperTypeError: expecting a bool or pyobj, got %d\n", vtype);
1719 assert(0);
Damien13ed3a62013-10-08 09:05:10 +01001720 }
Damien Georgea32c1e42014-05-07 18:30:52 +01001721 // need to commit stack because we may jump elsewhere
1722 need_stack_settled(emit);
Damien13ed3a62013-10-08 09:05:10 +01001723}
1724
Damien George7ff996c2014-09-08 23:05:16 +01001725STATIC void emit_native_pop_jump_if_true(emit_t *emit, mp_uint_t label) {
Damien Georged6230f62014-09-23 14:10:03 +00001726 DEBUG_printf("pop_jump_if_true(label=" UINT_FMT ")\n", label);
Damien Georgea32c1e42014-05-07 18:30:52 +01001727 emit_native_jump_helper(emit, label, true);
Damien Georgec90f59e2014-09-06 23:06:36 +01001728 ASM_JUMP_IF_REG_NONZERO(emit->as, REG_RET, label);
Damien1a6633a2013-11-03 13:58:19 +00001729 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001730}
Damien1a6633a2013-11-03 13:58:19 +00001731
Damien George7ff996c2014-09-08 23:05:16 +01001732STATIC void emit_native_pop_jump_if_false(emit_t *emit, mp_uint_t label) {
Damien Georged6230f62014-09-23 14:10:03 +00001733 DEBUG_printf("pop_jump_if_false(label=" UINT_FMT ")\n", label);
Damien Georgea32c1e42014-05-07 18:30:52 +01001734 emit_native_jump_helper(emit, label, true);
Damien Georgec90f59e2014-09-06 23:06:36 +01001735 ASM_JUMP_IF_REG_ZERO(emit->as, REG_RET, label);
Damien Georgea32c1e42014-05-07 18:30:52 +01001736 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001737}
Damien Georgea32c1e42014-05-07 18:30:52 +01001738
Damien George7ff996c2014-09-08 23:05:16 +01001739STATIC void emit_native_jump_if_true_or_pop(emit_t *emit, mp_uint_t label) {
Damien Georged6230f62014-09-23 14:10:03 +00001740 DEBUG_printf("jump_if_true_or_pop(label=" UINT_FMT ")\n", label);
Damien Georgea32c1e42014-05-07 18:30:52 +01001741 emit_native_jump_helper(emit, label, false);
Damien Georgec90f59e2014-09-06 23:06:36 +01001742 ASM_JUMP_IF_REG_NONZERO(emit->as, REG_RET, label);
Damien Georgea32c1e42014-05-07 18:30:52 +01001743 adjust_stack(emit, -1);
1744 emit_post(emit);
1745}
1746
Damien George7ff996c2014-09-08 23:05:16 +01001747STATIC void emit_native_jump_if_false_or_pop(emit_t *emit, mp_uint_t label) {
Damien Georged6230f62014-09-23 14:10:03 +00001748 DEBUG_printf("jump_if_false_or_pop(label=" UINT_FMT ")\n", label);
Damien Georgea32c1e42014-05-07 18:30:52 +01001749 emit_native_jump_helper(emit, label, false);
Damien Georgec90f59e2014-09-06 23:06:36 +01001750 ASM_JUMP_IF_REG_ZERO(emit->as, REG_RET, label);
Damien Georgea32c1e42014-05-07 18:30:52 +01001751 adjust_stack(emit, -1);
1752 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001753}
1754
Damien George7ff996c2014-09-08 23:05:16 +01001755STATIC void emit_native_break_loop(emit_t *emit, mp_uint_t label, mp_uint_t except_depth) {
Damien George25c84642014-05-30 15:20:41 +01001756 emit_native_jump(emit, label & ~MP_EMIT_BREAK_FROM_FOR); // TODO properly
Damien13ed3a62013-10-08 09:05:10 +01001757}
Damien Georgea32c1e42014-05-07 18:30:52 +01001758
Damien George7ff996c2014-09-08 23:05:16 +01001759STATIC void emit_native_continue_loop(emit_t *emit, mp_uint_t label, mp_uint_t except_depth) {
Damien Georgea32c1e42014-05-07 18:30:52 +01001760 emit_native_jump(emit, label); // TODO properly
Damien13ed3a62013-10-08 09:05:10 +01001761}
Damien Georgea32c1e42014-05-07 18:30:52 +01001762
Damien George7ff996c2014-09-08 23:05:16 +01001763STATIC void emit_native_setup_with(emit_t *emit, mp_uint_t label) {
Damien13ed3a62013-10-08 09:05:10 +01001764 // not supported, or could be with runtime call
1765 assert(0);
1766}
Damien Georgeb601d952014-06-30 05:17:25 +01001767
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001768STATIC void emit_native_with_cleanup(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +01001769 assert(0);
1770}
Damien Georgeb601d952014-06-30 05:17:25 +01001771
Damien George7ff996c2014-09-08 23:05:16 +01001772STATIC void emit_native_setup_except(emit_t *emit, mp_uint_t label) {
Damien Georgeb601d952014-06-30 05:17:25 +01001773 emit_native_pre(emit);
1774 // need to commit stack because we may jump elsewhere
1775 need_stack_settled(emit);
Damien George40f3c022014-07-03 13:25:24 +01001776 emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_1, sizeof(nlr_buf_t) / sizeof(mp_uint_t)); // arg1 = pointer to nlr buf
Damien George7fe21912014-08-16 22:31:57 +01001777 emit_call(emit, MP_F_NLR_PUSH);
Damien Georgec90f59e2014-09-06 23:06:36 +01001778 ASM_JUMP_IF_REG_NONZERO(emit->as, REG_RET, label);
Damien Georgeb601d952014-06-30 05:17:25 +01001779 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001780}
Damien Georgeb601d952014-06-30 05:17:25 +01001781
Damien George7ff996c2014-09-08 23:05:16 +01001782STATIC void emit_native_setup_finally(emit_t *emit, mp_uint_t label) {
Damien Georgee6ce10a2014-09-06 18:38:20 +01001783 emit_native_setup_except(emit, label);
Damien13ed3a62013-10-08 09:05:10 +01001784}
Damien Georgeb601d952014-06-30 05:17:25 +01001785
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001786STATIC void emit_native_end_finally(emit_t *emit) {
Damien Georgee6ce10a2014-09-06 18:38:20 +01001787 emit_pre_pop_discard(emit);
1788 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001789}
Damiend2755ec2013-10-16 23:58:48 +01001790
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001791STATIC void emit_native_get_iter(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +01001792 // perhaps the difficult one, as we want to rewrite for loops using native code
1793 // in cases where we iterate over a Python object, can we use normal runtime calls?
Damiend2755ec2013-10-16 23:58:48 +01001794
1795 vtype_kind_t vtype;
1796 emit_pre_pop_reg(emit, &vtype, REG_ARG_1);
1797 assert(vtype == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001798 emit_call(emit, MP_F_GETITER);
Damiend2755ec2013-10-16 23:58:48 +01001799 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
Damien13ed3a62013-10-08 09:05:10 +01001800}
Damiend2755ec2013-10-16 23:58:48 +01001801
Damien George7ff996c2014-09-08 23:05:16 +01001802STATIC void emit_native_for_iter(emit_t *emit, mp_uint_t label) {
Damien Georgece8f07a2014-03-27 23:30:26 +00001803 emit_native_pre(emit);
Damiend2755ec2013-10-16 23:58:48 +01001804 vtype_kind_t vtype;
1805 emit_access_stack(emit, 1, &vtype, REG_ARG_1);
1806 assert(vtype == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001807 emit_call(emit, MP_F_ITERNEXT);
Damien Georgec90f59e2014-09-06 23:06:36 +01001808 ASM_MOV_IMM_TO_REG(emit->as, (mp_uint_t)MP_OBJ_STOP_ITERATION, REG_TEMP1);
1809 ASM_JUMP_IF_REG_EQ(emit->as, REG_RET, REG_TEMP1, label);
Damiend2755ec2013-10-16 23:58:48 +01001810 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1811}
1812
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001813STATIC void emit_native_for_iter_end(emit_t *emit) {
Damiend2755ec2013-10-16 23:58:48 +01001814 // adjust stack counter (we get here from for_iter ending, which popped the value for us)
Damien Georgece8f07a2014-03-27 23:30:26 +00001815 emit_native_pre(emit);
Damiend2755ec2013-10-16 23:58:48 +01001816 adjust_stack(emit, -1);
1817 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001818}
1819
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001820STATIC void emit_native_pop_block(emit_t *emit) {
Damien Georgece8f07a2014-03-27 23:30:26 +00001821 emit_native_pre(emit);
Damien George7fe21912014-08-16 22:31:57 +01001822 emit_call(emit, MP_F_NLR_POP);
Damien George40f3c022014-07-03 13:25:24 +01001823 adjust_stack(emit, -(mp_int_t)(sizeof(nlr_buf_t) / sizeof(mp_uint_t)));
Damien13ed3a62013-10-08 09:05:10 +01001824 emit_post(emit);
1825}
1826
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001827STATIC void emit_native_pop_except(emit_t *emit) {
Damien Georgeb601d952014-06-30 05:17:25 +01001828 /*
1829 emit_native_pre(emit);
Damien George7fe21912014-08-16 22:31:57 +01001830 emit_call(emit, MP_F_NLR_POP);
Damien George40f3c022014-07-03 13:25:24 +01001831 adjust_stack(emit, -(mp_int_t)(sizeof(nlr_buf_t) / sizeof(mp_uint_t)));
Damien Georgeb601d952014-06-30 05:17:25 +01001832 emit_post(emit);
1833 */
Damien13ed3a62013-10-08 09:05:10 +01001834}
1835
Damien Georged17926d2014-03-30 13:35:08 +01001836STATIC void emit_native_unary_op(emit_t *emit, mp_unary_op_t op) {
Damien Georged6230f62014-09-23 14:10:03 +00001837 vtype_kind_t vtype;
1838 emit_pre_pop_reg(emit, &vtype, REG_ARG_2);
1839 assert(vtype == VTYPE_PYOBJ);
Damien Georgeb601d952014-06-30 05:17:25 +01001840 if (op == MP_UNARY_OP_NOT) {
Damien Georged6230f62014-09-23 14:10:03 +00001841 // we need to synthesise this operation by converting to bool first
1842 emit_call_with_imm_arg(emit, MP_F_UNARY_OP, MP_UNARY_OP_BOOL, REG_ARG_1);
Damien George3112cde2014-09-29 18:45:42 +01001843 ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_RET);
Damien Georgeb601d952014-06-30 05:17:25 +01001844 }
Damien Georged6230f62014-09-23 14:10:03 +00001845 emit_call_with_imm_arg(emit, MP_F_UNARY_OP, op, REG_ARG_1);
1846 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
Damien13ed3a62013-10-08 09:05:10 +01001847}
1848
Damien Georged17926d2014-03-30 13:35:08 +01001849STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) {
Damien Georged6230f62014-09-23 14:10:03 +00001850 DEBUG_printf("binary_op(" UINT_FMT ")\n", op);
Damien George3112cde2014-09-29 18:45:42 +01001851 vtype_kind_t vtype_lhs = peek_vtype(emit, 1);
1852 vtype_kind_t vtype_rhs = peek_vtype(emit, 0);
Damien13ed3a62013-10-08 09:05:10 +01001853 if (vtype_lhs == VTYPE_INT && vtype_rhs == VTYPE_INT) {
Damien George3112cde2014-09-29 18:45:42 +01001854 #if N_X64 || N_X86
1855 // special cases for x86 and shifting
1856 if (op == MP_BINARY_OP_LSHIFT
1857 || op == MP_BINARY_OP_INPLACE_LSHIFT
1858 || op == MP_BINARY_OP_RSHIFT
1859 || op == MP_BINARY_OP_INPLACE_RSHIFT) {
1860 #if N_X64
1861 emit_pre_pop_reg_reg(emit, &vtype_rhs, ASM_X64_REG_RCX, &vtype_lhs, REG_RET);
1862 #else
1863 emit_pre_pop_reg_reg(emit, &vtype_rhs, ASM_X86_REG_ECX, &vtype_lhs, REG_RET);
1864 #endif
1865 if (op == MP_BINARY_OP_LSHIFT || op == MP_BINARY_OP_INPLACE_LSHIFT) {
1866 ASM_LSL_REG(emit->as, REG_RET);
1867 } else {
1868 ASM_ASR_REG(emit->as, REG_RET);
1869 }
1870 emit_post_push_reg(emit, VTYPE_INT, REG_RET);
1871 return;
1872 }
1873 #endif
1874 int reg_rhs = REG_ARG_3;
Damien Georgee9dac3b2014-09-29 22:10:41 +01001875 emit_pre_pop_reg_flexible(emit, &vtype_rhs, &reg_rhs, REG_RET, REG_ARG_2);
Damien George3112cde2014-09-29 18:45:42 +01001876 emit_pre_pop_reg(emit, &vtype_lhs, REG_ARG_2);
1877 if (0) {
1878 // dummy
1879 #if !(N_X64 || N_X86)
1880 } else if (op == MP_BINARY_OP_LSHIFT || op == MP_BINARY_OP_INPLACE_LSHIFT) {
1881 ASM_LSL_REG_REG(emit->as, REG_ARG_2, reg_rhs);
Damien Georgebc1d3692014-01-11 09:47:06 +00001882 emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);
Damien George3112cde2014-09-29 18:45:42 +01001883 } else if (op == MP_BINARY_OP_RSHIFT || op == MP_BINARY_OP_INPLACE_RSHIFT) {
1884 ASM_ASR_REG_REG(emit->as, REG_ARG_2, reg_rhs);
1885 emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);
1886 #endif
Damien George1ef23482014-10-12 14:21:06 +01001887 } else if (op == MP_BINARY_OP_OR || op == MP_BINARY_OP_INPLACE_OR) {
1888 ASM_OR_REG_REG(emit->as, REG_ARG_2, reg_rhs);
1889 emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);
1890 } else if (op == MP_BINARY_OP_XOR || op == MP_BINARY_OP_INPLACE_XOR) {
1891 ASM_XOR_REG_REG(emit->as, REG_ARG_2, reg_rhs);
1892 emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);
1893 } else if (op == MP_BINARY_OP_AND || op == MP_BINARY_OP_INPLACE_AND) {
1894 ASM_AND_REG_REG(emit->as, REG_ARG_2, reg_rhs);
1895 emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);
Damien George3112cde2014-09-29 18:45:42 +01001896 } else if (op == MP_BINARY_OP_ADD || op == MP_BINARY_OP_INPLACE_ADD) {
1897 ASM_ADD_REG_REG(emit->as, REG_ARG_2, reg_rhs);
1898 emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);
1899 } else if (op == MP_BINARY_OP_SUBTRACT || op == MP_BINARY_OP_INPLACE_SUBTRACT) {
1900 ASM_SUB_REG_REG(emit->as, REG_ARG_2, reg_rhs);
1901 emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);
1902 } else if (MP_BINARY_OP_LESS <= op && op <= MP_BINARY_OP_NOT_EQUAL) {
1903 // comparison ops are (in enum order):
1904 // MP_BINARY_OP_LESS
1905 // MP_BINARY_OP_MORE
1906 // MP_BINARY_OP_EQUAL
1907 // MP_BINARY_OP_LESS_EQUAL
1908 // MP_BINARY_OP_MORE_EQUAL
1909 // MP_BINARY_OP_NOT_EQUAL
1910 #if N_X64
1911 asm_x64_xor_r64_r64(emit->as, REG_RET, REG_RET);
1912 asm_x64_cmp_r64_with_r64(emit->as, reg_rhs, REG_ARG_2);
1913 static byte ops[6] = {
1914 ASM_X64_CC_JL,
1915 ASM_X64_CC_JG,
1916 ASM_X64_CC_JE,
1917 ASM_X64_CC_JLE,
1918 ASM_X64_CC_JGE,
1919 ASM_X64_CC_JNE,
1920 };
1921 asm_x64_setcc_r8(emit->as, ops[op - MP_BINARY_OP_LESS], REG_RET);
1922 #elif N_X86
1923 asm_x86_xor_r32_r32(emit->as, REG_RET, REG_RET);
1924 asm_x86_cmp_r32_with_r32(emit->as, reg_rhs, REG_ARG_2);
1925 static byte ops[6] = {
1926 ASM_X86_CC_JL,
1927 ASM_X86_CC_JG,
1928 ASM_X86_CC_JE,
1929 ASM_X86_CC_JLE,
1930 ASM_X86_CC_JGE,
1931 ASM_X86_CC_JNE,
1932 };
1933 asm_x86_setcc_r8(emit->as, ops[op - MP_BINARY_OP_LESS], REG_RET);
1934 #elif N_THUMB
1935 asm_thumb_cmp_rlo_rlo(emit->as, REG_ARG_2, reg_rhs);
1936 static uint16_t ops[6] = {
1937 ASM_THUMB_OP_ITE_GE,
1938 ASM_THUMB_OP_ITE_GT,
1939 ASM_THUMB_OP_ITE_EQ,
1940 ASM_THUMB_OP_ITE_GT,
1941 ASM_THUMB_OP_ITE_GE,
1942 ASM_THUMB_OP_ITE_EQ,
1943 };
1944 static byte ret[6] = { 0, 1, 1, 0, 1, 0, };
1945 asm_thumb_op16(emit->as, ops[op - MP_BINARY_OP_LESS]);
1946 asm_thumb_mov_rlo_i8(emit->as, REG_RET, ret[op - MP_BINARY_OP_LESS]);
1947 asm_thumb_mov_rlo_i8(emit->as, REG_RET, ret[op - MP_BINARY_OP_LESS] ^ 1);
1948 #elif N_ARM
Fabian Vogte5268962014-10-04 00:53:46 +02001949 asm_arm_cmp_reg_reg(emit->as, REG_ARG_2, reg_rhs);
1950 static uint ccs[6] = {
1951 ASM_ARM_CC_LT,
1952 ASM_ARM_CC_GT,
1953 ASM_ARM_CC_EQ,
1954 ASM_ARM_CC_LE,
1955 ASM_ARM_CC_GE,
1956 ASM_ARM_CC_NE,
1957 };
1958 asm_arm_setcc_reg(emit->as, REG_RET, ccs[op - MP_BINARY_OP_LESS]);
Damien George3112cde2014-09-29 18:45:42 +01001959 #else
1960 #error not implemented
1961 #endif
Damien Georgebc1d3692014-01-11 09:47:06 +00001962 emit_post_push_reg(emit, VTYPE_BOOL, REG_RET);
1963 } else {
1964 // TODO other ops not yet implemented
1965 assert(0);
1966 }
Damien13ed3a62013-10-08 09:05:10 +01001967 } else if (vtype_lhs == VTYPE_PYOBJ && vtype_rhs == VTYPE_PYOBJ) {
Damien George3112cde2014-09-29 18:45:42 +01001968 emit_pre_pop_reg_reg(emit, &vtype_rhs, REG_ARG_3, &vtype_lhs, REG_ARG_2);
Damien Georged6230f62014-09-23 14:10:03 +00001969 bool invert = false;
1970 if (op == MP_BINARY_OP_NOT_IN) {
1971 invert = true;
1972 op = MP_BINARY_OP_IN;
1973 } else if (op == MP_BINARY_OP_IS_NOT) {
1974 invert = true;
1975 op = MP_BINARY_OP_IS;
1976 }
Damien George7fe21912014-08-16 22:31:57 +01001977 emit_call_with_imm_arg(emit, MP_F_BINARY_OP, op, REG_ARG_1);
Damien Georged6230f62014-09-23 14:10:03 +00001978 if (invert) {
Damien George3112cde2014-09-29 18:45:42 +01001979 ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_RET);
Damien Georged6230f62014-09-23 14:10:03 +00001980 emit_call_with_imm_arg(emit, MP_F_UNARY_OP, MP_UNARY_OP_NOT, REG_ARG_1);
1981 }
Damien13ed3a62013-10-08 09:05:10 +01001982 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1983 } else {
1984 printf("ViperTypeError: can't do binary op between types %d and %d\n", vtype_lhs, vtype_rhs);
Damien Georgea5190a72014-08-15 22:39:08 +01001985 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
Damien13ed3a62013-10-08 09:05:10 +01001986 }
1987}
1988
Damien George7ff996c2014-09-08 23:05:16 +01001989STATIC void emit_native_build_tuple(emit_t *emit, mp_uint_t n_args) {
Damiend2755ec2013-10-16 23:58:48 +01001990 // for viper: call runtime, with types of args
1991 // if wrapped in byte_array, or something, allocates memory and fills it
Damien Georgece8f07a2014-03-27 23:30:26 +00001992 emit_native_pre(emit);
Damien Georgecd82e022014-02-02 13:11:48 +00001993 emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, n_args); // pointer to items
Damien George7fe21912014-08-16 22:31:57 +01001994 emit_call_with_imm_arg(emit, MP_F_BUILD_TUPLE, n_args, REG_ARG_1);
Damiend2755ec2013-10-16 23:58:48 +01001995 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new tuple
Damien13ed3a62013-10-08 09:05:10 +01001996}
1997
Damien George7ff996c2014-09-08 23:05:16 +01001998STATIC void emit_native_build_list(emit_t *emit, mp_uint_t n_args) {
Damien Georgece8f07a2014-03-27 23:30:26 +00001999 emit_native_pre(emit);
Damien Georgecd82e022014-02-02 13:11:48 +00002000 emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, n_args); // pointer to items
Damien George7fe21912014-08-16 22:31:57 +01002001 emit_call_with_imm_arg(emit, MP_F_BUILD_LIST, n_args, REG_ARG_1);
Damien13ed3a62013-10-08 09:05:10 +01002002 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new list
2003}
2004
Damien George7ff996c2014-09-08 23:05:16 +01002005STATIC void emit_native_list_append(emit_t *emit, mp_uint_t list_index) {
Damiend2755ec2013-10-16 23:58:48 +01002006 // only used in list comprehension
2007 vtype_kind_t vtype_list, vtype_item;
2008 emit_pre_pop_reg(emit, &vtype_item, REG_ARG_2);
2009 emit_access_stack(emit, list_index, &vtype_list, REG_ARG_1);
2010 assert(vtype_list == VTYPE_PYOBJ);
2011 assert(vtype_item == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01002012 emit_call(emit, MP_F_LIST_APPEND);
Damiend2755ec2013-10-16 23:58:48 +01002013 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01002014}
2015
Damien George7ff996c2014-09-08 23:05:16 +01002016STATIC void emit_native_build_map(emit_t *emit, mp_uint_t n_args) {
Damien Georgece8f07a2014-03-27 23:30:26 +00002017 emit_native_pre(emit);
Damien George7fe21912014-08-16 22:31:57 +01002018 emit_call_with_imm_arg(emit, MP_F_BUILD_MAP, n_args, REG_ARG_1);
Damien13ed3a62013-10-08 09:05:10 +01002019 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new map
2020}
2021
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02002022STATIC void emit_native_store_map(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +01002023 vtype_kind_t vtype_key, vtype_value, vtype_map;
2024 emit_pre_pop_reg_reg_reg(emit, &vtype_key, REG_ARG_2, &vtype_value, REG_ARG_3, &vtype_map, REG_ARG_1); // key, value, map
2025 assert(vtype_key == VTYPE_PYOBJ);
2026 assert(vtype_value == VTYPE_PYOBJ);
2027 assert(vtype_map == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01002028 emit_call(emit, MP_F_STORE_MAP);
Damien13ed3a62013-10-08 09:05:10 +01002029 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // map
2030}
2031
Damien George7ff996c2014-09-08 23:05:16 +01002032STATIC void emit_native_map_add(emit_t *emit, mp_uint_t map_index) {
Damiend2755ec2013-10-16 23:58:48 +01002033 // only used in list comprehension
2034 vtype_kind_t vtype_map, vtype_key, vtype_value;
2035 emit_pre_pop_reg_reg(emit, &vtype_key, REG_ARG_2, &vtype_value, REG_ARG_3);
2036 emit_access_stack(emit, map_index, &vtype_map, REG_ARG_1);
2037 assert(vtype_map == VTYPE_PYOBJ);
2038 assert(vtype_key == VTYPE_PYOBJ);
2039 assert(vtype_value == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01002040 emit_call(emit, MP_F_STORE_MAP);
Damiend2755ec2013-10-16 23:58:48 +01002041 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01002042}
2043
Damien George7ff996c2014-09-08 23:05:16 +01002044STATIC void emit_native_build_set(emit_t *emit, mp_uint_t n_args) {
Damien Georgece8f07a2014-03-27 23:30:26 +00002045 emit_native_pre(emit);
Damien Georgecd82e022014-02-02 13:11:48 +00002046 emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, n_args); // pointer to items
Damien George7fe21912014-08-16 22:31:57 +01002047 emit_call_with_imm_arg(emit, MP_F_BUILD_SET, n_args, REG_ARG_1);
Damien13ed3a62013-10-08 09:05:10 +01002048 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new set
2049}
2050
Damien George7ff996c2014-09-08 23:05:16 +01002051STATIC void emit_native_set_add(emit_t *emit, mp_uint_t set_index) {
Damiend2755ec2013-10-16 23:58:48 +01002052 // only used in set comprehension
2053 vtype_kind_t vtype_set, vtype_item;
2054 emit_pre_pop_reg(emit, &vtype_item, REG_ARG_2);
2055 emit_access_stack(emit, set_index, &vtype_set, REG_ARG_1);
2056 assert(vtype_set == VTYPE_PYOBJ);
2057 assert(vtype_item == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01002058 emit_call(emit, MP_F_STORE_SET);
Damiend2755ec2013-10-16 23:58:48 +01002059 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01002060}
Damiend2755ec2013-10-16 23:58:48 +01002061
Damien George7ff996c2014-09-08 23:05:16 +01002062STATIC void emit_native_build_slice(emit_t *emit, mp_uint_t n_args) {
Damien Georgecdd96df2014-04-06 12:58:40 +01002063 DEBUG_printf("build_slice %d\n", n_args);
Damien Georgeb601d952014-06-30 05:17:25 +01002064 if (n_args == 2) {
2065 vtype_kind_t vtype_start, vtype_stop;
2066 emit_pre_pop_reg_reg(emit, &vtype_stop, REG_ARG_2, &vtype_start, REG_ARG_1); // arg1 = start, arg2 = stop
2067 assert(vtype_start == VTYPE_PYOBJ);
2068 assert(vtype_stop == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01002069 emit_call_with_imm_arg(emit, MP_F_NEW_SLICE, (mp_uint_t)mp_const_none, REG_ARG_3); // arg3 = step
Damien Georgeb601d952014-06-30 05:17:25 +01002070 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
2071 } else {
2072 assert(n_args == 3);
2073 vtype_kind_t vtype_start, vtype_stop, vtype_step;
2074 emit_pre_pop_reg_reg_reg(emit, &vtype_step, REG_ARG_3, &vtype_stop, REG_ARG_2, &vtype_start, REG_ARG_1); // arg1 = start, arg2 = stop, arg3 = step
2075 assert(vtype_start == VTYPE_PYOBJ);
2076 assert(vtype_stop == VTYPE_PYOBJ);
2077 assert(vtype_step == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01002078 emit_call(emit, MP_F_NEW_SLICE);
Damien Georgeb601d952014-06-30 05:17:25 +01002079 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
2080 }
Damien13ed3a62013-10-08 09:05:10 +01002081}
Damien Georgecdd96df2014-04-06 12:58:40 +01002082
Damien George7ff996c2014-09-08 23:05:16 +01002083STATIC void emit_native_unpack_sequence(emit_t *emit, mp_uint_t n_args) {
Damien Georgecdd96df2014-04-06 12:58:40 +01002084 DEBUG_printf("unpack_sequence %d\n", n_args);
2085 vtype_kind_t vtype_base;
2086 emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = seq
2087 assert(vtype_base == VTYPE_PYOBJ);
2088 emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, n_args); // arg3 = dest ptr
Damien George7fe21912014-08-16 22:31:57 +01002089 emit_call_with_imm_arg(emit, MP_F_UNPACK_SEQUENCE, n_args, REG_ARG_2); // arg2 = n_args
Damien13ed3a62013-10-08 09:05:10 +01002090}
Damien Georgecdd96df2014-04-06 12:58:40 +01002091
Damien George7ff996c2014-09-08 23:05:16 +01002092STATIC void emit_native_unpack_ex(emit_t *emit, mp_uint_t n_left, mp_uint_t n_right) {
Damien Georgea32c1e42014-05-07 18:30:52 +01002093 DEBUG_printf("unpack_ex %d %d\n", n_left, n_right);
2094 vtype_kind_t vtype_base;
2095 emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = seq
2096 assert(vtype_base == VTYPE_PYOBJ);
Damien Georgeb601d952014-06-30 05:17:25 +01002097 emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, n_left + n_right + 1); // arg3 = dest ptr
Damien George7fe21912014-08-16 22:31:57 +01002098 emit_call_with_imm_arg(emit, MP_F_UNPACK_EX, n_left | (n_right << 8), REG_ARG_2); // arg2 = n_left + n_right
Damien13ed3a62013-10-08 09:05:10 +01002099}
2100
Damien George7ff996c2014-09-08 23:05:16 +01002101STATIC void emit_native_make_function(emit_t *emit, scope_t *scope, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults) {
Damien13ed3a62013-10-08 09:05:10 +01002102 // call runtime, with type info for args, or don't support dict/default params, or only support Python objects for them
Damien Georgece8f07a2014-03-27 23:30:26 +00002103 emit_native_pre(emit);
Damien Georgea32c1e42014-05-07 18:30:52 +01002104 if (n_pos_defaults == 0 && n_kw_defaults == 0) {
Damien George7fe21912014-08-16 22:31:57 +01002105 emit_call_with_3_imm_args_and_first_aligned(emit, MP_F_MAKE_FUNCTION_FROM_RAW_CODE, (mp_uint_t)scope->raw_code, REG_ARG_1, (mp_uint_t)MP_OBJ_NULL, REG_ARG_2, (mp_uint_t)MP_OBJ_NULL, REG_ARG_3);
Damien Georgea32c1e42014-05-07 18:30:52 +01002106 } else {
2107 vtype_kind_t vtype_def_tuple, vtype_def_dict;
2108 emit_pre_pop_reg_reg(emit, &vtype_def_dict, REG_ARG_3, &vtype_def_tuple, REG_ARG_2);
2109 assert(vtype_def_tuple == VTYPE_PYOBJ);
2110 assert(vtype_def_dict == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01002111 emit_call_with_imm_arg_aligned(emit, MP_F_MAKE_FUNCTION_FROM_RAW_CODE, (mp_uint_t)scope->raw_code, REG_ARG_1);
Damien Georgea32c1e42014-05-07 18:30:52 +01002112 }
Damien13ed3a62013-10-08 09:05:10 +01002113 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
2114}
2115
Damien George7ff996c2014-09-08 23:05:16 +01002116STATIC void emit_native_make_closure(emit_t *emit, scope_t *scope, mp_uint_t n_closed_over, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults) {
Damien13ed3a62013-10-08 09:05:10 +01002117 assert(0);
2118}
2119
Damien George7ff996c2014-09-08 23:05:16 +01002120STATIC void emit_native_call_function(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) {
Damien Georged6230f62014-09-23 14:10:03 +00002121 DEBUG_printf("call_function(n_pos=" UINT_FMT ", n_kw=" UINT_FMT ", star_flags=" UINT_FMT ")\n", n_positional, n_keyword, star_flags);
2122
Damien Georgee9dac3b2014-09-29 22:10:41 +01002123 // TODO: in viper mode, call special runtime routine with type info for args,
2124 // and wanted type info for return, to remove need for boxing/unboxing
2125
Damien George922ddd62014-04-09 12:43:17 +01002126 assert(!star_flags);
Damien Georgecd82e022014-02-02 13:11:48 +00002127
Damien Georgee9dac3b2014-09-29 22:10:41 +01002128 emit_native_pre(emit);
2129 vtype_kind_t vtype_fun = peek_vtype(emit, n_positional + 2 * n_keyword);
2130 if (vtype_fun == VTYPE_BUILTIN_CAST) {
2131 // casting operator
2132 assert(n_positional == 1 && n_keyword == 0);
2133 DEBUG_printf(" cast to %d\n", vtype_fun);
2134 vtype_kind_t vtype_cast = peek_stack(emit, 1)->u_imm;
2135 switch (peek_vtype(emit, 0)) {
2136 case VTYPE_PYOBJ: {
2137 vtype_kind_t vtype;
2138 emit_pre_pop_reg(emit, &vtype, REG_ARG_1);
2139 emit_pre_pop_discard(emit);
2140 emit_call_with_imm_arg(emit, MP_F_CONVERT_OBJ_TO_NATIVE, MP_NATIVE_TYPE_UINT, REG_ARG_2); // arg2 = type
2141 emit_post_push_reg(emit, vtype_cast, REG_RET);
2142 break;
2143 }
2144 case VTYPE_BOOL:
2145 case VTYPE_INT:
2146 case VTYPE_UINT:
2147 case VTYPE_PTR:
2148 case VTYPE_PTR8:
2149 case VTYPE_PTR16:
2150 case VTYPE_PTR_NONE:
2151 emit_fold_stack_top(emit, REG_ARG_1);
2152 emit_post_top_set_vtype(emit, vtype_cast);
2153 break;
2154 default:
2155 assert(!"TODO: convert obj to int");
2156 }
2157 } else {
2158 if (n_positional != 0 || n_keyword != 0) {
2159 emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_positional + 2 * n_keyword); // pointer to args
2160 }
Damien13ed3a62013-10-08 09:05:10 +01002161 emit_pre_pop_reg(emit, &vtype_fun, REG_ARG_1); // the function
2162 assert(vtype_fun == VTYPE_PYOBJ);
Damien Georgee9dac3b2014-09-29 22:10:41 +01002163 emit_call_with_imm_arg(emit, MP_F_NATIVE_CALL_FUNCTION_N_KW, n_positional | (n_keyword << 8), REG_ARG_2);
2164 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
Damien Georgecd82e022014-02-02 13:11:48 +00002165 }
Damien13ed3a62013-10-08 09:05:10 +01002166}
2167
Damien George7ff996c2014-09-08 23:05:16 +01002168STATIC void emit_native_call_method(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) {
Damien George922ddd62014-04-09 12:43:17 +01002169 assert(!star_flags);
Damien Georgece8f07a2014-03-27 23:30:26 +00002170 emit_native_pre(emit);
Damien Georgecdd96df2014-04-06 12:58:40 +01002171 emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, 2 + n_positional + 2 * n_keyword); // pointer to items, including meth and self
Damien George7fe21912014-08-16 22:31:57 +01002172 emit_call_with_2_imm_args(emit, MP_F_CALL_METHOD_N_KW, n_positional, REG_ARG_1, n_keyword, REG_ARG_2);
Damien13ed3a62013-10-08 09:05:10 +01002173 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
2174}
2175
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02002176STATIC void emit_native_return_value(emit_t *emit) {
Damien Georgecdd96df2014-04-06 12:58:40 +01002177 DEBUG_printf("return_value\n");
Damien13ed3a62013-10-08 09:05:10 +01002178 if (emit->do_viper_types) {
Damien Georgee9dac3b2014-09-29 22:10:41 +01002179 if (peek_vtype(emit, 0) == VTYPE_PTR_NONE) {
2180 emit_pre_pop_discard(emit);
Damien Georgee6c0dff2014-08-15 23:47:59 +01002181 if (emit->return_vtype == VTYPE_PYOBJ) {
Damien Georgec90f59e2014-09-06 23:06:36 +01002182 ASM_MOV_IMM_TO_REG(emit->as, (mp_uint_t)mp_const_none, REG_RET);
Damien Georgee9dac3b2014-09-29 22:10:41 +01002183 } else {
2184 ASM_MOV_IMM_TO_REG(emit->as, 0, REG_RET);
Damien Georgee6c0dff2014-08-15 23:47:59 +01002185 }
Damien Georgee9dac3b2014-09-29 22:10:41 +01002186 } else {
2187 vtype_kind_t vtype;
2188 emit_pre_pop_reg(emit, &vtype, REG_RET);
2189 if (vtype != emit->return_vtype) {
2190 printf("ViperTypeError: incompatible return type\n");
2191 }
Damien George2ac4af62014-08-15 16:45:41 +01002192 }
Damien13ed3a62013-10-08 09:05:10 +01002193 } else {
Damien Georgee9dac3b2014-09-29 22:10:41 +01002194 vtype_kind_t vtype;
2195 emit_pre_pop_reg(emit, &vtype, REG_RET);
Damien13ed3a62013-10-08 09:05:10 +01002196 assert(vtype == VTYPE_PYOBJ);
2197 }
2198 emit->last_emit_was_return_value = true;
Damien Georgec90f59e2014-09-06 23:06:36 +01002199 //ASM_BREAK_POINT(emit->as); // to insert a break-point for debugging
2200 ASM_EXIT(emit->as);
Damien13ed3a62013-10-08 09:05:10 +01002201}
2202
Damien George7ff996c2014-09-08 23:05:16 +01002203STATIC void emit_native_raise_varargs(emit_t *emit, mp_uint_t n_args) {
Damien Georgeb601d952014-06-30 05:17:25 +01002204 assert(n_args == 1);
Damien George86de21b2014-08-16 22:06:11 +01002205 vtype_kind_t vtype_exc;
2206 emit_pre_pop_reg(emit, &vtype_exc, REG_ARG_1); // arg1 = object to raise
2207 if (vtype_exc != VTYPE_PYOBJ) {
2208 printf("ViperTypeError: must raise an object\n");
2209 }
2210 // TODO probably make this 1 call to the runtime (which could even call convert, native_raise(obj, type))
Damien George7fe21912014-08-16 22:31:57 +01002211 emit_call(emit, MP_F_NATIVE_RAISE);
Damien13ed3a62013-10-08 09:05:10 +01002212}
Damien Georgeb601d952014-06-30 05:17:25 +01002213
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02002214STATIC void emit_native_yield_value(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +01002215 // not supported (for now)
2216 assert(0);
2217}
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02002218STATIC void emit_native_yield_from(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +01002219 // not supported (for now)
2220 assert(0);
2221}
2222
Damien Georgeb601d952014-06-30 05:17:25 +01002223STATIC void emit_native_start_except_handler(emit_t *emit) {
2224 // This instruction follows an nlr_pop, so the stack counter is back to zero, when really
2225 // it should be up by a whole nlr_buf_t. We then want to pop the nlr_buf_t here, but save
2226 // the first 2 elements, so we can get the thrown value.
2227 adjust_stack(emit, 2);
2228 vtype_kind_t vtype_nlr;
2229 emit_pre_pop_reg(emit, &vtype_nlr, REG_ARG_1); // get the thrown value
Damien Georgee6ce10a2014-09-06 18:38:20 +01002230 emit_pre_pop_discard(emit); // discard the linked-list pointer in the nlr_buf
Damien Georgeb601d952014-06-30 05:17:25 +01002231 emit_post_push_reg_reg_reg(emit, VTYPE_PYOBJ, REG_ARG_1, VTYPE_PYOBJ, REG_ARG_1, VTYPE_PYOBJ, REG_ARG_1); // push the 3 exception items
2232}
2233
2234STATIC void emit_native_end_except_handler(emit_t *emit) {
Damien Georgee6ce10a2014-09-06 18:38:20 +01002235 adjust_stack(emit, -2);
Damien Georgeb601d952014-06-30 05:17:25 +01002236}
2237
Damien13ed3a62013-10-08 09:05:10 +01002238const emit_method_table_t EXPORT_FUN(method_table) = {
Damien George2ac4af62014-08-15 16:45:41 +01002239 emit_native_set_native_type,
Damien13ed3a62013-10-08 09:05:10 +01002240 emit_native_start_pass,
2241 emit_native_end_pass,
2242 emit_native_last_emit_was_return_value,
Damien Georged66ae182014-04-10 17:28:54 +00002243 emit_native_adjust_stack_size,
Damien George08335002014-01-18 23:24:36 +00002244 emit_native_set_source_line,
Damien13ed3a62013-10-08 09:05:10 +01002245
2246 emit_native_load_id,
2247 emit_native_store_id,
2248 emit_native_delete_id,
2249
2250 emit_native_label_assign,
2251 emit_native_import_name,
2252 emit_native_import_from,
2253 emit_native_import_star,
2254 emit_native_load_const_tok,
2255 emit_native_load_const_small_int,
2256 emit_native_load_const_int,
2257 emit_native_load_const_dec,
Damien13ed3a62013-10-08 09:05:10 +01002258 emit_native_load_const_str,
Damien George3558f622014-04-20 17:50:40 +01002259 emit_native_load_null,
Damien13ed3a62013-10-08 09:05:10 +01002260 emit_native_load_fast,
Damien13ed3a62013-10-08 09:05:10 +01002261 emit_native_load_deref,
Damien9ecbcff2013-12-11 00:41:43 +00002262 emit_native_load_name,
2263 emit_native_load_global,
Damien13ed3a62013-10-08 09:05:10 +01002264 emit_native_load_attr,
2265 emit_native_load_method,
2266 emit_native_load_build_class,
Damien George729f7b42014-04-17 22:10:53 +01002267 emit_native_load_subscr,
Damien13ed3a62013-10-08 09:05:10 +01002268 emit_native_store_fast,
Damien9ecbcff2013-12-11 00:41:43 +00002269 emit_native_store_deref,
Damien13ed3a62013-10-08 09:05:10 +01002270 emit_native_store_name,
2271 emit_native_store_global,
Damien13ed3a62013-10-08 09:05:10 +01002272 emit_native_store_attr,
Damien13ed3a62013-10-08 09:05:10 +01002273 emit_native_store_subscr,
Damien13ed3a62013-10-08 09:05:10 +01002274 emit_native_delete_fast,
Damien9ecbcff2013-12-11 00:41:43 +00002275 emit_native_delete_deref,
Damien13ed3a62013-10-08 09:05:10 +01002276 emit_native_delete_name,
2277 emit_native_delete_global,
Damien13ed3a62013-10-08 09:05:10 +01002278 emit_native_delete_attr,
2279 emit_native_delete_subscr,
2280 emit_native_dup_top,
2281 emit_native_dup_top_two,
2282 emit_native_pop_top,
2283 emit_native_rot_two,
2284 emit_native_rot_three,
2285 emit_native_jump,
2286 emit_native_pop_jump_if_true,
2287 emit_native_pop_jump_if_false,
2288 emit_native_jump_if_true_or_pop,
2289 emit_native_jump_if_false_or_pop,
Damien13ed3a62013-10-08 09:05:10 +01002290 emit_native_break_loop,
2291 emit_native_continue_loop,
2292 emit_native_setup_with,
2293 emit_native_with_cleanup,
2294 emit_native_setup_except,
2295 emit_native_setup_finally,
2296 emit_native_end_finally,
2297 emit_native_get_iter,
2298 emit_native_for_iter,
2299 emit_native_for_iter_end,
2300 emit_native_pop_block,
2301 emit_native_pop_except,
2302 emit_native_unary_op,
2303 emit_native_binary_op,
Damien13ed3a62013-10-08 09:05:10 +01002304 emit_native_build_tuple,
2305 emit_native_build_list,
2306 emit_native_list_append,
2307 emit_native_build_map,
2308 emit_native_store_map,
2309 emit_native_map_add,
2310 emit_native_build_set,
2311 emit_native_set_add,
2312 emit_native_build_slice,
2313 emit_native_unpack_sequence,
2314 emit_native_unpack_ex,
2315 emit_native_make_function,
2316 emit_native_make_closure,
2317 emit_native_call_function,
2318 emit_native_call_method,
2319 emit_native_return_value,
2320 emit_native_raise_varargs,
2321 emit_native_yield_value,
2322 emit_native_yield_from,
Damien Georgeb601d952014-06-30 05:17:25 +01002323
2324 emit_native_start_except_handler,
2325 emit_native_end_except_handler,
Damien13ed3a62013-10-08 09:05:10 +01002326};
2327
Damien Georgec90f59e2014-09-06 23:06:36 +01002328#endif