blob: 782f4b60dd311e4f7a6abf8ea30351780cb18ed7 [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
85#define REG_TEMP0 (REG_RAX)
86#define REG_TEMP1 (REG_RDI)
87#define REG_TEMP2 (REG_RSI)
Damien Georgec90f59e2014-09-06 23:06:36 +010088
89#define REG_LOCAL_1 (REG_RBX)
90#define REG_LOCAL_NUM (1)
91
92#define ASM_PASS_COMPUTE ASM_X64_PASS_COMPUTE
93#define ASM_PASS_EMIT ASM_X64_PASS_EMIT
94
95#define ASM_T asm_x64_t
96#define ASM_NEW asm_x64_new
97#define ASM_FREE asm_x64_free
98#define ASM_GET_CODE asm_x64_get_code
99#define ASM_GET_CODE_SIZE asm_x64_get_code_size
100#define ASM_START_PASS asm_x64_start_pass
101#define ASM_END_PASS asm_x64_end_pass
102#define ASM_ENTRY asm_x64_entry
103#define ASM_EXIT asm_x64_exit
104
105#define ASM_LABEL_ASSIGN asm_x64_label_assign
106#define ASM_JUMP asm_x64_jmp_label
107#define ASM_JUMP_IF_REG_ZERO(as, reg, label) \
108 do { \
109 asm_x64_test_r8_with_r8(as, reg, reg); \
110 asm_x64_jcc_label(as, ASM_X64_CC_JZ, label); \
111 } while (0)
112#define ASM_JUMP_IF_REG_NONZERO(as, reg, label) \
113 do { \
114 asm_x64_test_r8_with_r8(as, reg, reg); \
115 asm_x64_jcc_label(as, ASM_X64_CC_JNZ, label); \
116 } while (0)
117#define ASM_JUMP_IF_REG_EQ(as, reg1, reg2, label) \
118 do { \
119 asm_x64_cmp_r64_with_r64(as, reg1, reg2); \
120 asm_x64_jcc_label(as, ASM_X64_CC_JE, label); \
121 } while (0)
122#define ASM_CALL_IND(as, ptr, idx) asm_x64_call_ind(as, ptr, REG_RAX)
123
124#define ASM_MOV_REG_TO_LOCAL asm_x64_mov_r64_to_local
125#define ASM_MOV_IMM_TO_REG asm_x64_mov_i64_to_r64_optimised
126#define ASM_MOV_ALIGNED_IMM_TO_REG asm_x64_mov_i64_to_r64_aligned
127#define ASM_MOV_IMM_TO_LOCAL_USING(as, imm, local_num, reg_temp) \
128 do { \
129 asm_x64_mov_i64_to_r64_optimised(as, (imm), (reg_temp)); \
130 asm_x64_mov_r64_to_local(as, (reg_temp), (local_num)); \
131 } while (false)
132#define ASM_MOV_LOCAL_TO_REG asm_x64_mov_local_to_r64
133#define ASM_MOV_REG_TO_REG asm_x64_mov_r64_to_r64
134#define ASM_MOV_LOCAL_ADDR_TO_REG asm_x64_mov_local_addr_to_r64
135
136#elif N_X86
137
138// x86 specific stuff
139
140#include "asmx86.h"
141
142STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = {
143 [MP_F_CONVERT_OBJ_TO_NATIVE] = 2,
144 [MP_F_CONVERT_NATIVE_TO_OBJ] = 2,
145 [MP_F_LOAD_CONST_INT] = 1,
146 [MP_F_LOAD_CONST_DEC] = 1,
147 [MP_F_LOAD_CONST_STR] = 1,
148 [MP_F_LOAD_CONST_BYTES] = 1,
149 [MP_F_LOAD_NAME] = 1,
150 [MP_F_LOAD_GLOBAL] = 1,
151 [MP_F_LOAD_BUILD_CLASS] = 0,
152 [MP_F_LOAD_ATTR] = 2,
153 [MP_F_LOAD_METHOD] = 3,
154 [MP_F_STORE_NAME] = 2,
155 [MP_F_STORE_GLOBAL] = 2,
156 [MP_F_STORE_ATTR] = 3,
157 [MP_F_OBJ_SUBSCR] = 3,
158 [MP_F_OBJ_IS_TRUE] = 1,
159 [MP_F_UNARY_OP] = 2,
160 [MP_F_BINARY_OP] = 3,
161 [MP_F_BUILD_TUPLE] = 2,
162 [MP_F_BUILD_LIST] = 2,
163 [MP_F_LIST_APPEND] = 2,
164 [MP_F_BUILD_MAP] = 1,
165 [MP_F_STORE_MAP] = 3,
166#if MICROPY_PY_BUILTINS_SET
167 [MP_F_BUILD_SET] = 2,
168 [MP_F_STORE_SET] = 2,
169#endif
170 [MP_F_MAKE_FUNCTION_FROM_RAW_CODE] = 3,
171 [MP_F_NATIVE_CALL_FUNCTION_N_KW] = 3,
172 [MP_F_CALL_METHOD_N_KW] = 3,
173 [MP_F_GETITER] = 1,
174 [MP_F_ITERNEXT] = 1,
175 [MP_F_NLR_PUSH] = 1,
176 [MP_F_NLR_POP] = 0,
177 [MP_F_NATIVE_RAISE] = 1,
178 [MP_F_IMPORT_NAME] = 3,
179 [MP_F_IMPORT_FROM] = 2,
180 [MP_F_IMPORT_ALL] = 1,
181#if MICROPY_PY_BUILTINS_SLICE
182 [MP_F_NEW_SLICE] = 3,
183#endif
184 [MP_F_UNPACK_SEQUENCE] = 3,
185 [MP_F_UNPACK_EX] = 3,
186 [MP_F_DELETE_NAME] = 1,
187 [MP_F_DELETE_GLOBAL] = 1,
188};
189
190#define EXPORT_FUN(name) emit_native_x86_##name
191
192#define REG_TEMP0 (REG_EAX)
193#define REG_TEMP1 (REG_EDI)
194#define REG_TEMP2 (REG_ESI)
195
196#define REG_LOCAL_1 (REG_EBX)
197#define REG_LOCAL_NUM (1)
198
199#define ASM_PASS_COMPUTE ASM_X86_PASS_COMPUTE
200#define ASM_PASS_EMIT ASM_X86_PASS_EMIT
201
202#define ASM_T asm_x86_t
203#define ASM_NEW asm_x86_new
204#define ASM_FREE asm_x86_free
205#define ASM_GET_CODE asm_x86_get_code
206#define ASM_GET_CODE_SIZE asm_x86_get_code_size
207#define ASM_START_PASS asm_x86_start_pass
208#define ASM_END_PASS asm_x86_end_pass
209#define ASM_ENTRY asm_x86_entry
210#define ASM_EXIT asm_x86_exit
211
212#define ASM_LABEL_ASSIGN asm_x86_label_assign
213#define ASM_JUMP asm_x86_jmp_label
214#define ASM_JUMP_IF_REG_ZERO(as, reg, label) \
215 do { \
216 asm_x86_test_r8_with_r8(as, reg, reg); \
217 asm_x86_jcc_label(as, ASM_X86_CC_JZ, label); \
218 } while (0)
219#define ASM_JUMP_IF_REG_NONZERO(as, reg, label) \
220 do { \
221 asm_x86_test_r8_with_r8(as, reg, reg); \
222 asm_x86_jcc_label(as, ASM_X86_CC_JNZ, label); \
223 } while (0)
224#define ASM_JUMP_IF_REG_EQ(as, reg1, reg2, label) \
225 do { \
226 asm_x86_cmp_r32_with_r32(as, reg1, reg2); \
227 asm_x86_jcc_label(as, ASM_X86_CC_JE, label); \
228 } while (0)
229#define ASM_CALL_IND(as, ptr, idx) asm_x86_call_ind(as, ptr, mp_f_n_args[idx], REG_EAX)
230
231#define ASM_MOV_REG_TO_LOCAL asm_x86_mov_r32_to_local
232#define ASM_MOV_IMM_TO_REG asm_x86_mov_i32_to_r32
233#define ASM_MOV_ALIGNED_IMM_TO_REG asm_x86_mov_i32_to_r32_aligned
234#define ASM_MOV_IMM_TO_LOCAL_USING(as, imm, local_num, reg_temp) \
235 do { \
236 asm_x86_mov_i32_to_r32(as, (imm), (reg_temp)); \
237 asm_x86_mov_r32_to_local(as, (reg_temp), (local_num)); \
238 } while (false)
239#define ASM_MOV_LOCAL_TO_REG asm_x86_mov_local_to_r32
240#define ASM_MOV_REG_TO_REG asm_x86_mov_r32_to_r32
241#define ASM_MOV_LOCAL_ADDR_TO_REG asm_x86_mov_local_addr_to_r32
Damien13ed3a62013-10-08 09:05:10 +0100242
Damien3ef4abb2013-10-12 16:53:13 +0100243#elif N_THUMB
Damien13ed3a62013-10-08 09:05:10 +0100244
245// thumb specific stuff
246
247#include "asmthumb.h"
248
Damien13ed3a62013-10-08 09:05:10 +0100249#define EXPORT_FUN(name) emit_native_thumb_##name
250
251#define REG_TEMP0 (REG_R0)
252#define REG_TEMP1 (REG_R1)
253#define REG_TEMP2 (REG_R2)
Damien Georgec90f59e2014-09-06 23:06:36 +0100254
255#define REG_LOCAL_1 (REG_R4)
256#define REG_LOCAL_2 (REG_R5)
257#define REG_LOCAL_3 (REG_R6)
258#define REG_LOCAL_NUM (3)
259
260#define ASM_PASS_COMPUTE ASM_THUMB_PASS_COMPUTE
261#define ASM_PASS_EMIT ASM_THUMB_PASS_EMIT
262
263#define ASM_T asm_thumb_t
264#define ASM_NEW asm_thumb_new
265#define ASM_FREE asm_thumb_free
266#define ASM_GET_CODE asm_thumb_get_code
267#define ASM_GET_CODE_SIZE asm_thumb_get_code_size
268#define ASM_START_PASS asm_thumb_start_pass
269#define ASM_END_PASS asm_thumb_end_pass
270#define ASM_ENTRY asm_thumb_entry
271#define ASM_EXIT asm_thumb_exit
272
273#define ASM_LABEL_ASSIGN asm_thumb_label_assign
274#define ASM_JUMP asm_thumb_b_label
275#define ASM_JUMP_IF_REG_ZERO(as, reg, label) \
276 do { \
277 asm_thumb_cmp_rlo_i8(as, reg, 0); \
278 asm_thumb_bcc_label(as, THUMB_CC_EQ, label); \
279 } while (0)
280#define ASM_JUMP_IF_REG_NONZERO(as, reg, label) \
281 do { \
282 asm_thumb_cmp_rlo_i8(as, reg, 0); \
283 asm_thumb_bcc_label(as, THUMB_CC_NE, label); \
284 } while (0)
285#define ASM_JUMP_IF_REG_EQ(as, reg1, reg2, label) \
286 do { \
287 asm_thumb_cmp_rlo_rlo(as, reg1, reg2); \
288 asm_thumb_bcc_label(as, THUMB_CC_EQ, label); \
289 } while (0)
290#define ASM_CALL_IND(as, ptr, idx) asm_thumb_bl_ind(as, ptr, idx, REG_R3)
291
292#define ASM_MOV_REG_TO_LOCAL(as, reg, local_num) asm_thumb_mov_local_reg(as, (local_num), (reg))
293#define ASM_MOV_IMM_TO_REG(as, imm, reg) asm_thumb_mov_reg_i32_optimised(as, (reg), (imm))
294#define ASM_MOV_ALIGNED_IMM_TO_REG(as, imm, reg) asm_thumb_mov_reg_i32_aligned(as, (reg), (imm))
295#define ASM_MOV_IMM_TO_LOCAL_USING(as, imm, local_num, reg_temp) \
296 do { \
297 asm_thumb_mov_reg_i32_optimised(as, (reg_temp), (imm)); \
298 asm_thumb_mov_local_reg(as, (local_num), (reg_temp)); \
299 } while (false)
300#define ASM_MOV_LOCAL_TO_REG(as, local_num, reg) asm_thumb_mov_reg_local(as, (reg), (local_num))
301#define ASM_MOV_REG_TO_REG(as, reg_src, reg_dest) asm_thumb_mov_reg_reg(as, (reg_dest), (reg_src))
302#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 +0100303
Fabian Vogtfe3d16e2014-08-16 22:55:53 +0200304#elif N_ARM
305
306// ARM specific stuff
307
308#include "asmarm.h"
309
Fabian Vogtfe3d16e2014-08-16 22:55:53 +0200310#define EXPORT_FUN(name) emit_native_arm_##name
311
312#define REG_TEMP0 (REG_R0)
313#define REG_TEMP1 (REG_R1)
314#define REG_TEMP2 (REG_R2)
Damien Georgec90f59e2014-09-06 23:06:36 +0100315
316#define REG_LOCAL_1 (REG_R4)
317#define REG_LOCAL_2 (REG_R5)
318#define REG_LOCAL_3 (REG_R6)
319#define REG_LOCAL_NUM (3)
320
321#define ASM_PASS_COMPUTE ASM_ARM_PASS_COMPUTE
322#define ASM_PASS_EMIT ASM_ARM_PASS_EMIT
323
324#define ASM_T asm_arm_t
325#define ASM_NEW asm_arm_new
326#define ASM_FREE asm_arm_free
327#define ASM_GET_CODE asm_arm_get_code
328#define ASM_GET_CODE_SIZE asm_arm_get_code_size
329#define ASM_START_PASS asm_arm_start_pass
330#define ASM_END_PASS asm_arm_end_pass
331#define ASM_ENTRY asm_arm_entry
332#define ASM_EXIT asm_arm_exit
333
334#define ASM_LABEL_ASSIGN asm_arm_label_assign
335#define ASM_JUMP asm_arm_b_label
336#define ASM_JUMP_IF_REG_ZERO(as, reg, label) \
337 do { \
338 asm_arm_cmp_reg_i8(as, reg, 0); \
339 asm_arm_bcc_label(as, ARM_CC_EQ, label); \
340 } while (0)
341#define ASM_JUMP_IF_REG_NONZERO(as, reg, label) \
342 do { \
343 asm_arm_cmp_reg_i8(as, reg, 0); \
344 asm_arm_bcc_label(as, ARM_CC_NE, label); \
345 } while (0)
346#define ASM_JUMP_IF_REG_EQ(as, reg1, reg2, label) \
347 do { \
348 asm_arm_cmp_reg_reg(as, reg1, reg2); \
349 asm_arm_bcc_label(as, ARM_CC_EQ, label); \
350 } while (0)
351#define ASM_CALL_IND(as, ptr, idx) asm_arm_bl_ind(as, ptr, idx, REG_R3)
352
353#define ASM_MOV_REG_TO_LOCAL(as, reg, local_num) asm_arm_mov_local_reg(as, (local_num), (reg))
354#define ASM_MOV_IMM_TO_REG(as, imm, reg) asm_arm_mov_reg_i32(as, (reg), (imm))
355#define ASM_MOV_ALIGNED_IMM_TO_REG(as, imm, reg) asm_arm_mov_reg_i32(as, (reg), (imm))
356#define ASM_MOV_IMM_TO_LOCAL_USING(as, imm, local_num, reg_temp) \
357 do { \
358 asm_arm_mov_reg_i32(as, (reg_temp), (imm)); \
359 asm_arm_mov_local_reg(as, (local_num), (reg_temp)); \
360 } while (false)
361#define ASM_MOV_LOCAL_TO_REG(as, local_num, reg) asm_arm_mov_reg_local(as, (reg), (local_num))
362#define ASM_MOV_REG_TO_REG(as, reg_src, reg_dest) asm_arm_mov_reg_reg(as, (reg_dest), (reg_src))
363#define ASM_MOV_LOCAL_ADDR_TO_REG(as, local_num, reg) asm_arm_mov_reg_local_addr(as, (reg), (local_num))
364
365#else
366
367#error unknown native emitter
Fabian Vogtfe3d16e2014-08-16 22:55:53 +0200368
Damien13ed3a62013-10-08 09:05:10 +0100369#endif
370
371typedef enum {
Damienff8ed772013-10-08 22:18:32 +0100372 STACK_VALUE,
373 STACK_REG,
374 STACK_IMM,
375} stack_info_kind_t;
Damien13ed3a62013-10-08 09:05:10 +0100376
377typedef enum {
Damien George2ac4af62014-08-15 16:45:41 +0100378 VTYPE_PYOBJ = MP_NATIVE_TYPE_OBJ,
379 VTYPE_BOOL = MP_NATIVE_TYPE_BOOL,
380 VTYPE_INT = MP_NATIVE_TYPE_INT,
381 VTYPE_UINT = MP_NATIVE_TYPE_UINT,
Damien13ed3a62013-10-08 09:05:10 +0100382 VTYPE_UNBOUND,
Damien13ed3a62013-10-08 09:05:10 +0100383 VTYPE_PTR,
384 VTYPE_PTR_NONE,
385 VTYPE_BUILTIN_V_INT,
386} vtype_kind_t;
387
Damienff8ed772013-10-08 22:18:32 +0100388typedef struct _stack_info_t {
389 vtype_kind_t vtype;
390 stack_info_kind_t kind;
391 union {
392 int u_reg;
Damien George40f3c022014-07-03 13:25:24 +0100393 mp_int_t u_imm;
Damienff8ed772013-10-08 22:18:32 +0100394 };
395} stack_info_t;
396
Damien13ed3a62013-10-08 09:05:10 +0100397struct _emit_t {
398 int pass;
399
400 bool do_viper_types;
Damienff8ed772013-10-08 22:18:32 +0100401
Damien George2ac4af62014-08-15 16:45:41 +0100402 vtype_kind_t return_vtype;
403
Damien George36db6bc2014-05-07 17:24:22 +0100404 uint local_vtype_alloc;
Damien13ed3a62013-10-08 09:05:10 +0100405 vtype_kind_t *local_vtype;
Damienff8ed772013-10-08 22:18:32 +0100406
Damien George36db6bc2014-05-07 17:24:22 +0100407 uint stack_info_alloc;
Damienff8ed772013-10-08 22:18:32 +0100408 stack_info_t *stack_info;
409
Damien13ed3a62013-10-08 09:05:10 +0100410 int stack_start;
411 int stack_size;
412
413 bool last_emit_was_return_value;
414
Damien13ed3a62013-10-08 09:05:10 +0100415 scope_t *scope;
416
Damien Georgec90f59e2014-09-06 23:06:36 +0100417 ASM_T *as;
Damien13ed3a62013-10-08 09:05:10 +0100418};
419
420emit_t *EXPORT_FUN(new)(uint max_num_labels) {
Damien George36db6bc2014-05-07 17:24:22 +0100421 emit_t *emit = m_new0(emit_t, 1);
Damien Georgec90f59e2014-09-06 23:06:36 +0100422 emit->as = ASM_NEW(max_num_labels);
Damien13ed3a62013-10-08 09:05:10 +0100423 return emit;
424}
425
Damien George41d02b62014-01-24 22:42:28 +0000426void EXPORT_FUN(free)(emit_t *emit) {
Damien Georgec90f59e2014-09-06 23:06:36 +0100427 ASM_FREE(emit->as, false);
Damien George36db6bc2014-05-07 17:24:22 +0100428 m_del(vtype_kind_t, emit->local_vtype, emit->local_vtype_alloc);
429 m_del(stack_info_t, emit->stack_info, emit->stack_info_alloc);
Paul Sokolovskyf46d87a2014-01-24 16:20:11 +0200430 m_del_obj(emit_t, emit);
431}
432
Damien George2ac4af62014-08-15 16:45:41 +0100433STATIC void emit_native_set_native_type(emit_t *emit, mp_uint_t op, mp_uint_t arg1, qstr arg2) {
434 switch (op) {
435 case MP_EMIT_NATIVE_TYPE_ENABLE:
436 emit->do_viper_types = arg1;
437 break;
438
439 default: {
440 vtype_kind_t type;
441 switch (arg2) {
442 case MP_QSTR_object: type = VTYPE_PYOBJ; break;
443 case MP_QSTR_bool: type = VTYPE_BOOL; break;
444 case MP_QSTR_int: type = VTYPE_INT; break;
445 case MP_QSTR_uint: type = VTYPE_UINT; break;
446 default: printf("ViperTypeError: unknown type %s\n", qstr_str(arg2)); return;
447 }
448 if (op == MP_EMIT_NATIVE_TYPE_RETURN) {
449 emit->return_vtype = type;
450 } else {
451 assert(arg1 < emit->local_vtype_alloc);
452 emit->local_vtype[arg1] = type;
453 }
454 break;
455 }
456 }
Damien13ed3a62013-10-08 09:05:10 +0100457}
458
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200459STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
Damien13ed3a62013-10-08 09:05:10 +0100460 emit->pass = pass;
461 emit->stack_start = 0;
462 emit->stack_size = 0;
463 emit->last_emit_was_return_value = false;
Damien13ed3a62013-10-08 09:05:10 +0100464 emit->scope = scope;
465
Damien George36db6bc2014-05-07 17:24:22 +0100466 // allocate memory for keeping track of the types of locals
467 if (emit->local_vtype_alloc < scope->num_locals) {
468 emit->local_vtype = m_renew(vtype_kind_t, emit->local_vtype, emit->local_vtype_alloc, scope->num_locals);
469 emit->local_vtype_alloc = scope->num_locals;
Damienff8ed772013-10-08 22:18:32 +0100470 }
Damien George36db6bc2014-05-07 17:24:22 +0100471
472 // allocate memory for keeping track of the objects on the stack
473 // XXX don't know stack size on entry, and it should be maximum over all scopes
Damienff8ed772013-10-08 22:18:32 +0100474 if (emit->stack_info == NULL) {
Damien George36db6bc2014-05-07 17:24:22 +0100475 emit->stack_info_alloc = scope->stack_size + 50;
Damienff8ed772013-10-08 22:18:32 +0100476 emit->stack_info = m_new(stack_info_t, emit->stack_info_alloc);
Damien13ed3a62013-10-08 09:05:10 +0100477 }
478
Damien George2ac4af62014-08-15 16:45:41 +0100479 // set default type for return and arguments
480 emit->return_vtype = VTYPE_PYOBJ;
Damien Georgea5190a72014-08-15 22:39:08 +0100481 for (mp_uint_t i = 0; i < emit->scope->num_pos_args; i++) {
Damien George2ac4af62014-08-15 16:45:41 +0100482 emit->local_vtype[i] = VTYPE_PYOBJ;
483 }
Damien Georgea5190a72014-08-15 22:39:08 +0100484
485 // local variables begin unbound, and have unknown type
486 for (mp_uint_t i = emit->scope->num_pos_args; i < emit->local_vtype_alloc; i++) {
487 emit->local_vtype[i] = VTYPE_UNBOUND;
488 }
489
490 // values on stack begin unbound
491 for (mp_uint_t i = 0; i < emit->stack_info_alloc; i++) {
Damien George2ac4af62014-08-15 16:45:41 +0100492 emit->stack_info[i].kind = STACK_VALUE;
Damien Georgea5190a72014-08-15 22:39:08 +0100493 emit->stack_info[i].vtype = VTYPE_UNBOUND;
Damien13ed3a62013-10-08 09:05:10 +0100494 }
495
Damien Georgec90f59e2014-09-06 23:06:36 +0100496 ASM_START_PASS(emit->as, pass == MP_PASS_EMIT ? ASM_PASS_EMIT : ASM_PASS_COMPUTE);
Damien13ed3a62013-10-08 09:05:10 +0100497
498 // entry to function
499 int num_locals = 0;
Damien George36db6bc2014-05-07 17:24:22 +0100500 if (pass > MP_PASS_SCOPE) {
Damien13ed3a62013-10-08 09:05:10 +0100501 num_locals = scope->num_locals - REG_LOCAL_NUM;
502 if (num_locals < 0) {
503 num_locals = 0;
504 }
505 emit->stack_start = num_locals;
506 num_locals += scope->stack_size;
507 }
Damien Georgec90f59e2014-09-06 23:06:36 +0100508 ASM_ENTRY(emit->as, num_locals);
Damien13ed3a62013-10-08 09:05:10 +0100509
510 // initialise locals from parameters
Damien3ef4abb2013-10-12 16:53:13 +0100511#if N_X64
Damien George2827d622014-04-27 15:50:52 +0100512 for (int i = 0; i < scope->num_pos_args; i++) {
Damien13ed3a62013-10-08 09:05:10 +0100513 if (i == 0) {
514 asm_x64_mov_r64_to_r64(emit->as, REG_ARG_1, REG_LOCAL_1);
515 } else if (i == 1) {
Damien Georged509ac22014-05-07 23:27:45 +0100516 asm_x64_mov_r64_to_local(emit->as, REG_ARG_2, i - REG_LOCAL_NUM);
Damien13ed3a62013-10-08 09:05:10 +0100517 } else if (i == 2) {
Damien Georged509ac22014-05-07 23:27:45 +0100518 asm_x64_mov_r64_to_local(emit->as, REG_ARG_3, i - REG_LOCAL_NUM);
Damien13ed3a62013-10-08 09:05:10 +0100519 } else {
520 // TODO not implemented
521 assert(0);
522 }
523 }
Damien Georgec90f59e2014-09-06 23:06:36 +0100524#elif N_X86
525 for (int i = 0; i < scope->num_pos_args; i++) {
526 // TODO
527 assert(0);
528 if (i == 0) {
529 asm_x86_mov_r32_to_r32(emit->as, REG_ARG_1, REG_LOCAL_1);
530 } else if (i == 1) {
531 asm_x86_mov_r32_to_local(emit->as, REG_ARG_2, i - REG_LOCAL_NUM);
532 } else if (i == 2) {
533 asm_x86_mov_r32_to_local(emit->as, REG_ARG_3, i - REG_LOCAL_NUM);
534 } else {
535 // TODO not implemented
536 assert(0);
537 }
538 }
Damien3ef4abb2013-10-12 16:53:13 +0100539#elif N_THUMB
Damien George2827d622014-04-27 15:50:52 +0100540 for (int i = 0; i < scope->num_pos_args; i++) {
Damien13ed3a62013-10-08 09:05:10 +0100541 if (i == 0) {
542 asm_thumb_mov_reg_reg(emit->as, REG_LOCAL_1, REG_ARG_1);
543 } else if (i == 1) {
544 asm_thumb_mov_reg_reg(emit->as, REG_LOCAL_2, REG_ARG_2);
545 } else if (i == 2) {
546 asm_thumb_mov_reg_reg(emit->as, REG_LOCAL_3, REG_ARG_3);
547 } else if (i == 3) {
548 asm_thumb_mov_local_reg(emit->as, i - REG_LOCAL_NUM, REG_ARG_4);
549 } else {
550 // TODO not implemented
551 assert(0);
552 }
553 }
554
Damien George40f3c022014-07-03 13:25:24 +0100555 asm_thumb_mov_reg_i32(emit->as, REG_R7, (mp_uint_t)mp_fun_table);
Fabian Vogtfe3d16e2014-08-16 22:55:53 +0200556#elif N_ARM
557 for (int i = 0; i < scope->num_pos_args; i++) {
558 if (i == 0) {
559 asm_arm_mov_reg_reg(emit->as, REG_LOCAL_1, REG_ARG_1);
560 } else if (i == 1) {
561 asm_arm_mov_reg_reg(emit->as, REG_LOCAL_2, REG_ARG_2);
562 } else if (i == 2) {
563 asm_arm_mov_reg_reg(emit->as, REG_LOCAL_3, REG_ARG_3);
564 } else if (i == 3) {
565 asm_arm_mov_local_reg(emit->as, i - REG_LOCAL_NUM, REG_ARG_4);
566 } else {
567 // TODO not implemented
568 assert(0);
569 }
570 }
571
572 asm_arm_mov_reg_i32(emit->as, REG_R7, (mp_uint_t)mp_fun_table);
Damien Georgec90f59e2014-09-06 23:06:36 +0100573#else
574 #error not implemented
Damien13ed3a62013-10-08 09:05:10 +0100575#endif
576}
577
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200578STATIC void emit_native_end_pass(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +0100579 if (!emit->last_emit_was_return_value) {
Damien Georgec90f59e2014-09-06 23:06:36 +0100580 ASM_EXIT(emit->as);
Damien13ed3a62013-10-08 09:05:10 +0100581 }
Damien Georgec90f59e2014-09-06 23:06:36 +0100582 ASM_END_PASS(emit->as);
Damien13ed3a62013-10-08 09:05:10 +0100583
584 // check stack is back to zero size
585 if (emit->stack_size != 0) {
586 printf("ERROR: stack size not back to zero; got %d\n", emit->stack_size);
587 }
588
Damien George36db6bc2014-05-07 17:24:22 +0100589 if (emit->pass == MP_PASS_EMIT) {
Damien Georgec90f59e2014-09-06 23:06:36 +0100590 void *f = ASM_GET_CODE(emit->as);
591 mp_uint_t f_len = ASM_GET_CODE_SIZE(emit->as);
Damien George2ac4af62014-08-15 16:45:41 +0100592
593 // compute type signature
594 // TODO check that viper types here convert correctly to valid types for emit glue
595 mp_uint_t type_sig = emit->return_vtype & 3;
596 for (mp_uint_t i = 0; i < emit->scope->num_pos_args; i++) {
597 type_sig |= (emit->local_vtype[i] & 3) << (i * 2 + 2);
598 }
599
600 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 +0100601 }
602}
603
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200604STATIC bool emit_native_last_emit_was_return_value(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +0100605 return emit->last_emit_was_return_value;
606}
607
Damien Georged66ae182014-04-10 17:28:54 +0000608STATIC void emit_native_adjust_stack_size(emit_t *emit, int delta) {
609 emit->stack_size += delta;
Damien13ed3a62013-10-08 09:05:10 +0100610}
611
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200612STATIC void emit_native_set_source_line(emit_t *emit, int source_line) {
Damien George08335002014-01-18 23:24:36 +0000613}
614
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200615STATIC void adjust_stack(emit_t *emit, int stack_size_delta) {
Damien Georgecdd96df2014-04-06 12:58:40 +0100616 DEBUG_printf("adjust stack: stack:%d + delta:%d\n", emit->stack_size, stack_size_delta);
Damien George78035b92014-04-09 12:27:39 +0100617 assert((int)emit->stack_size + stack_size_delta >= 0);
Damien13ed3a62013-10-08 09:05:10 +0100618 emit->stack_size += stack_size_delta;
Damien George36db6bc2014-05-07 17:24:22 +0100619 if (emit->pass > MP_PASS_SCOPE && emit->stack_size > emit->scope->stack_size) {
Damien13ed3a62013-10-08 09:05:10 +0100620 emit->scope->stack_size = emit->stack_size;
621 }
622}
623
Damienff8ed772013-10-08 22:18:32 +0100624/*
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200625STATIC void emit_pre_raw(emit_t *emit, int stack_size_delta) {
Damien13ed3a62013-10-08 09:05:10 +0100626 adjust_stack(emit, stack_size_delta);
627 emit->last_emit_was_return_value = false;
628}
Damienff8ed772013-10-08 22:18:32 +0100629*/
Damien13ed3a62013-10-08 09:05:10 +0100630
Damienff8ed772013-10-08 22:18:32 +0100631// this must be called at start of emit functions
Damien Georgece8f07a2014-03-27 23:30:26 +0000632STATIC void emit_native_pre(emit_t *emit) {
Damienff8ed772013-10-08 22:18:32 +0100633 emit->last_emit_was_return_value = false;
634 // settle the stack
635 /*
636 if (regs_needed != 0) {
637 for (int i = 0; i < emit->stack_size; i++) {
638 switch (emit->stack_info[i].kind) {
639 case STACK_VALUE:
640 break;
641
642 case STACK_REG:
643 // TODO only push reg if in regs_needed
644 emit->stack_info[i].kind = STACK_VALUE;
Damien Georgec90f59e2014-09-06 23:06:36 +0100645 ASM_MOV_REG_TO_LOCAL(emit->as, emit->stack_info[i].u_reg, emit->stack_start + i);
Damienff8ed772013-10-08 22:18:32 +0100646 break;
647
648 case STACK_IMM:
649 // don't think we ever need to push imms for settling
650 //ASM_MOV_IMM_TO_LOCAL(emit->last_imm, emit->stack_start + i);
651 break;
652 }
653 }
654 }
655 */
Damien13ed3a62013-10-08 09:05:10 +0100656}
657
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200658STATIC vtype_kind_t peek_vtype(emit_t *emit) {
Damienff8ed772013-10-08 22:18:32 +0100659 return emit->stack_info[emit->stack_size - 1].vtype;
660}
Damien13ed3a62013-10-08 09:05:10 +0100661
Damiend2755ec2013-10-16 23:58:48 +0100662// pos=1 is TOS, pos=2 is next, etc
663// use pos=0 for no skipping
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200664STATIC void need_reg_single(emit_t *emit, int reg_needed, int skip_stack_pos) {
Damiend2755ec2013-10-16 23:58:48 +0100665 skip_stack_pos = emit->stack_size - skip_stack_pos;
Damienff8ed772013-10-08 22:18:32 +0100666 for (int i = 0; i < emit->stack_size; i++) {
Damiend2755ec2013-10-16 23:58:48 +0100667 if (i != skip_stack_pos) {
668 stack_info_t *si = &emit->stack_info[i];
669 if (si->kind == STACK_REG && si->u_reg == reg_needed) {
670 si->kind = STACK_VALUE;
Damien Georgec90f59e2014-09-06 23:06:36 +0100671 ASM_MOV_REG_TO_LOCAL(emit->as, si->u_reg, emit->stack_start + i);
Damiend2755ec2013-10-16 23:58:48 +0100672 }
Damienff8ed772013-10-08 22:18:32 +0100673 }
674 }
675}
Damien13ed3a62013-10-08 09:05:10 +0100676
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200677STATIC void need_reg_all(emit_t *emit) {
Damienff8ed772013-10-08 22:18:32 +0100678 for (int i = 0; i < emit->stack_size; i++) {
679 stack_info_t *si = &emit->stack_info[i];
680 if (si->kind == STACK_REG) {
681 si->kind = STACK_VALUE;
Damien Georgec90f59e2014-09-06 23:06:36 +0100682 ASM_MOV_REG_TO_LOCAL(emit->as, si->u_reg, emit->stack_start + i);
Damienff8ed772013-10-08 22:18:32 +0100683 }
Damien13ed3a62013-10-08 09:05:10 +0100684 }
685}
686
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200687STATIC void need_stack_settled(emit_t *emit) {
Damiend2755ec2013-10-16 23:58:48 +0100688 for (int i = 0; i < emit->stack_size; i++) {
689 stack_info_t *si = &emit->stack_info[i];
690 if (si->kind == STACK_REG) {
691 si->kind = STACK_VALUE;
Damien Georgec90f59e2014-09-06 23:06:36 +0100692 ASM_MOV_REG_TO_LOCAL(emit->as, si->u_reg, emit->stack_start + i);
Damiend2755ec2013-10-16 23:58:48 +0100693 }
694 }
695 for (int i = 0; i < emit->stack_size; i++) {
696 stack_info_t *si = &emit->stack_info[i];
697 if (si->kind == STACK_IMM) {
Damien George02d95d72014-08-29 20:05:32 +0100698 si->kind = STACK_VALUE;
Damien Georgec90f59e2014-09-06 23:06:36 +0100699 ASM_MOV_IMM_TO_LOCAL_USING(emit->as, si->u_imm, emit->stack_start + i, REG_TEMP0);
Damiend2755ec2013-10-16 23:58:48 +0100700 }
701 }
702}
703
704// pos=1 is TOS, pos=2 is next, etc
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200705STATIC void emit_access_stack(emit_t *emit, int pos, vtype_kind_t *vtype, int reg_dest) {
Damiend2755ec2013-10-16 23:58:48 +0100706 need_reg_single(emit, reg_dest, pos);
707 stack_info_t *si = &emit->stack_info[emit->stack_size - pos];
Damienff8ed772013-10-08 22:18:32 +0100708 *vtype = si->vtype;
709 switch (si->kind) {
710 case STACK_VALUE:
Damien Georgec90f59e2014-09-06 23:06:36 +0100711 ASM_MOV_LOCAL_TO_REG(emit->as, emit->stack_start + emit->stack_size - pos, reg_dest);
Damien13ed3a62013-10-08 09:05:10 +0100712 break;
713
Damienff8ed772013-10-08 22:18:32 +0100714 case STACK_REG:
715 if (si->u_reg != reg_dest) {
Damien Georgec90f59e2014-09-06 23:06:36 +0100716 ASM_MOV_REG_TO_REG(emit->as, si->u_reg, reg_dest);
Damien13ed3a62013-10-08 09:05:10 +0100717 }
718 break;
719
Damienff8ed772013-10-08 22:18:32 +0100720 case STACK_IMM:
Damien Georgec90f59e2014-09-06 23:06:36 +0100721 ASM_MOV_IMM_TO_REG(emit->as, si->u_imm, reg_dest);
Damien13ed3a62013-10-08 09:05:10 +0100722 break;
723 }
Damien13ed3a62013-10-08 09:05:10 +0100724}
725
Damien Georgee6ce10a2014-09-06 18:38:20 +0100726STATIC void emit_pre_pop_discard(emit_t *emit) {
Damien Georgeccc85ea2014-05-10 13:40:46 +0100727 emit->last_emit_was_return_value = false;
728 adjust_stack(emit, -1);
729}
730
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200731STATIC void emit_pre_pop_reg(emit_t *emit, vtype_kind_t *vtype, int reg_dest) {
Damiend2755ec2013-10-16 23:58:48 +0100732 emit->last_emit_was_return_value = false;
733 emit_access_stack(emit, 1, vtype, reg_dest);
734 adjust_stack(emit, -1);
735}
736
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200737STATIC 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 +0100738 emit_pre_pop_reg(emit, vtypea, rega);
Damienff8ed772013-10-08 22:18:32 +0100739 emit_pre_pop_reg(emit, vtypeb, regb);
Damien13ed3a62013-10-08 09:05:10 +0100740}
741
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200742STATIC 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 +0100743 emit_pre_pop_reg(emit, vtypea, rega);
Damienff8ed772013-10-08 22:18:32 +0100744 emit_pre_pop_reg(emit, vtypeb, regb);
745 emit_pre_pop_reg(emit, vtypec, regc);
Damien13ed3a62013-10-08 09:05:10 +0100746}
747
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200748STATIC void emit_post(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +0100749}
750
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200751STATIC void emit_post_push_reg(emit_t *emit, vtype_kind_t vtype, int reg) {
Damienff8ed772013-10-08 22:18:32 +0100752 stack_info_t *si = &emit->stack_info[emit->stack_size];
753 si->vtype = vtype;
754 si->kind = STACK_REG;
755 si->u_reg = reg;
Damien13ed3a62013-10-08 09:05:10 +0100756 adjust_stack(emit, 1);
757}
758
Damien George40f3c022014-07-03 13:25:24 +0100759STATIC void emit_post_push_imm(emit_t *emit, vtype_kind_t vtype, mp_int_t imm) {
Damienff8ed772013-10-08 22:18:32 +0100760 stack_info_t *si = &emit->stack_info[emit->stack_size];
761 si->vtype = vtype;
762 si->kind = STACK_IMM;
763 si->u_imm = imm;
764 adjust_stack(emit, 1);
765}
766
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200767STATIC 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 +0100768 emit_post_push_reg(emit, vtypea, rega);
769 emit_post_push_reg(emit, vtypeb, regb);
770}
771
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200772STATIC 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 +0100773 emit_post_push_reg(emit, vtypea, rega);
774 emit_post_push_reg(emit, vtypeb, regb);
775 emit_post_push_reg(emit, vtypec, regc);
Damien13ed3a62013-10-08 09:05:10 +0100776}
777
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200778STATIC 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 +0100779 emit_post_push_reg(emit, vtypea, rega);
780 emit_post_push_reg(emit, vtypeb, regb);
781 emit_post_push_reg(emit, vtypec, regc);
782 emit_post_push_reg(emit, vtyped, regd);
Damien13ed3a62013-10-08 09:05:10 +0100783}
784
Damien George7fe21912014-08-16 22:31:57 +0100785STATIC void emit_call(emit_t *emit, mp_fun_kind_t fun_kind) {
Damiend2755ec2013-10-16 23:58:48 +0100786 need_reg_all(emit);
Damien Georgec90f59e2014-09-06 23:06:36 +0100787 ASM_CALL_IND(emit->as, mp_fun_table[fun_kind], fun_kind);
Damien13ed3a62013-10-08 09:05:10 +0100788}
789
Damien George7fe21912014-08-16 22:31:57 +0100790STATIC 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 +0100791 need_reg_all(emit);
Damien Georgec90f59e2014-09-06 23:06:36 +0100792 ASM_MOV_IMM_TO_REG(emit->as, arg_val, arg_reg);
793 ASM_CALL_IND(emit->as, mp_fun_table[fun_kind], fun_kind);
Damien13ed3a62013-10-08 09:05:10 +0100794}
795
Damien George40f3c022014-07-03 13:25:24 +0100796// the first arg is stored in the code aligned on a mp_uint_t boundary
Damien George7fe21912014-08-16 22:31:57 +0100797STATIC 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 +0100798 need_reg_all(emit);
Damien Georgec90f59e2014-09-06 23:06:36 +0100799 ASM_MOV_ALIGNED_IMM_TO_REG(emit->as, arg_val, arg_reg);
800 ASM_CALL_IND(emit->as, mp_fun_table[fun_kind], fun_kind);
Damien Georgea32c1e42014-05-07 18:30:52 +0100801}
802
Damien George7fe21912014-08-16 22:31:57 +0100803STATIC 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 +0000804 need_reg_all(emit);
Damien Georgec90f59e2014-09-06 23:06:36 +0100805 ASM_MOV_IMM_TO_REG(emit->as, arg_val1, arg_reg1);
806 ASM_MOV_IMM_TO_REG(emit->as, arg_val2, arg_reg2);
807 ASM_CALL_IND(emit->as, mp_fun_table[fun_kind], fun_kind);
Damien Georgecd82e022014-02-02 13:11:48 +0000808}
809
Damien George40f3c022014-07-03 13:25:24 +0100810// the first arg is stored in the code aligned on a mp_uint_t boundary
Damien George7fe21912014-08-16 22:31:57 +0100811STATIC 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 +0100812 need_reg_all(emit);
Damien Georgec90f59e2014-09-06 23:06:36 +0100813 ASM_MOV_ALIGNED_IMM_TO_REG(emit->as, arg_val1, arg_reg1);
814 ASM_MOV_IMM_TO_REG(emit->as, arg_val2, arg_reg2);
815 ASM_MOV_IMM_TO_REG(emit->as, arg_val3, arg_reg3);
816 ASM_CALL_IND(emit->as, mp_fun_table[fun_kind], fun_kind);
Damien Georgecdd96df2014-04-06 12:58:40 +0100817}
818
Damien George86de21b2014-08-16 22:06:11 +0100819// vtype of all n_pop objects is VTYPE_PYOBJ
820// Will convert any items that are not VTYPE_PYOBJ to this type and put them back on the stack.
821// If any conversions of non-immediate values are needed, then it uses REG_ARG_1, REG_ARG_2 and REG_RET.
822// Otherwise, it does not use any temporary registers (but may use reg_dest before loading it with stack pointer).
823STATIC void emit_get_stack_pointer_to_reg_for_pop(emit_t *emit, mp_uint_t reg_dest, mp_uint_t n_pop) {
824 need_reg_all(emit);
Damien13ed3a62013-10-08 09:05:10 +0100825
Damien George86de21b2014-08-16 22:06:11 +0100826 // First, store any immediate values to their respective place on the stack.
827 for (mp_uint_t i = 0; i < n_pop; i++) {
828 stack_info_t *si = &emit->stack_info[emit->stack_size - 1 - i];
829 // must push any imm's to stack
830 // must convert them to VTYPE_PYOBJ for viper code
831 if (si->kind == STACK_IMM) {
832 si->kind = STACK_VALUE;
833 switch (si->vtype) {
834 case VTYPE_PYOBJ:
Damien Georgec90f59e2014-09-06 23:06:36 +0100835 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 +0100836 break;
837 case VTYPE_BOOL:
838 if (si->u_imm == 0) {
Damien Georgec90f59e2014-09-06 23:06:36 +0100839 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 +0100840 } else {
Damien Georgec90f59e2014-09-06 23:06:36 +0100841 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 +0100842 }
843 si->vtype = VTYPE_PYOBJ;
844 break;
845 case VTYPE_INT:
846 case VTYPE_UINT:
Damien Georgec90f59e2014-09-06 23:06:36 +0100847 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 +0100848 si->vtype = VTYPE_PYOBJ;
849 break;
850 default:
851 // not handled
852 assert(0);
853 }
854 }
855
856 // verify that this value is on the stack
857 assert(si->kind == STACK_VALUE);
Damien13ed3a62013-10-08 09:05:10 +0100858 }
Damien George86de21b2014-08-16 22:06:11 +0100859
860 // Second, convert any non-VTYPE_PYOBJ to that type.
861 for (mp_uint_t i = 0; i < n_pop; i++) {
862 stack_info_t *si = &emit->stack_info[emit->stack_size - 1 - i];
863 if (si->vtype != VTYPE_PYOBJ) {
864 mp_uint_t local_num = emit->stack_start + emit->stack_size - 1 - i;
Damien Georgec90f59e2014-09-06 23:06:36 +0100865 ASM_MOV_LOCAL_TO_REG(emit->as, local_num, REG_ARG_1);
Damien George7fe21912014-08-16 22:31:57 +0100866 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 +0100867 ASM_MOV_REG_TO_LOCAL(emit->as, REG_RET, local_num);
Damien George86de21b2014-08-16 22:06:11 +0100868 si->vtype = VTYPE_PYOBJ;
869 }
870 }
871
872 // Adujust the stack for a pop of n_pop items, and load the stack pointer into reg_dest.
873 adjust_stack(emit, -n_pop);
Damien Georgec90f59e2014-09-06 23:06:36 +0100874 ASM_MOV_LOCAL_ADDR_TO_REG(emit->as, emit->stack_start + emit->stack_size, reg_dest);
Damien George86de21b2014-08-16 22:06:11 +0100875}
876
877// vtype of all n_push objects is VTYPE_PYOBJ
878STATIC void emit_get_stack_pointer_to_reg_for_push(emit_t *emit, mp_uint_t reg_dest, mp_uint_t n_push) {
879 need_reg_all(emit);
880 for (mp_uint_t i = 0; i < n_push; i++) {
881 emit->stack_info[emit->stack_size + i].kind = STACK_VALUE;
882 emit->stack_info[emit->stack_size + i].vtype = VTYPE_PYOBJ;
883 }
Damien Georgec90f59e2014-09-06 23:06:36 +0100884 ASM_MOV_LOCAL_ADDR_TO_REG(emit->as, emit->stack_start + emit->stack_size, reg_dest);
Damien George86de21b2014-08-16 22:06:11 +0100885 adjust_stack(emit, n_push);
886}
887
888STATIC void emit_native_load_id(emit_t *emit, qstr qstr) {
889 emit_common_load_id(emit, &EXPORT_FUN(method_table), emit->scope, qstr);
Damien13ed3a62013-10-08 09:05:10 +0100890}
891
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200892STATIC void emit_native_store_id(emit_t *emit, qstr qstr) {
Damien13ed3a62013-10-08 09:05:10 +0100893 emit_common_store_id(emit, &EXPORT_FUN(method_table), emit->scope, qstr);
894}
895
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200896STATIC void emit_native_delete_id(emit_t *emit, qstr qstr) {
Damien13ed3a62013-10-08 09:05:10 +0100897 emit_common_delete_id(emit, &EXPORT_FUN(method_table), emit->scope, qstr);
898}
899
Damien George6f355fd2014-04-10 14:11:31 +0100900STATIC void emit_native_label_assign(emit_t *emit, uint l) {
Damien Georgece8f07a2014-03-27 23:30:26 +0000901 emit_native_pre(emit);
Damiend2755ec2013-10-16 23:58:48 +0100902 // need to commit stack because we can jump here from elsewhere
903 need_stack_settled(emit);
Damien Georgec90f59e2014-09-06 23:06:36 +0100904 ASM_LABEL_ASSIGN(emit->as, l);
Damien6ba13142013-11-02 20:34:54 +0000905 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +0100906}
907
Damien Georgecdd96df2014-04-06 12:58:40 +0100908STATIC void emit_native_import_name(emit_t *emit, qstr qst) {
909 DEBUG_printf("import_name %s\n", qstr_str(qst));
910 vtype_kind_t vtype_fromlist;
911 vtype_kind_t vtype_level;
912 emit_pre_pop_reg_reg(emit, &vtype_fromlist, REG_ARG_2, &vtype_level, REG_ARG_3); // arg2 = fromlist, arg3 = level
913 assert(vtype_fromlist == VTYPE_PYOBJ);
914 assert(vtype_level == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +0100915 emit_call_with_imm_arg(emit, MP_F_IMPORT_NAME, qst, REG_ARG_1); // arg1 = import name
Damien Georgecdd96df2014-04-06 12:58:40 +0100916 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
Damien13ed3a62013-10-08 09:05:10 +0100917}
918
Damien Georgecdd96df2014-04-06 12:58:40 +0100919STATIC void emit_native_import_from(emit_t *emit, qstr qst) {
920 DEBUG_printf("import_from %s\n", qstr_str(qst));
921 emit_native_pre(emit);
922 vtype_kind_t vtype_module;
923 emit_access_stack(emit, 1, &vtype_module, REG_ARG_1); // arg1 = module
924 assert(vtype_module == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +0100925 emit_call_with_imm_arg(emit, MP_F_IMPORT_FROM, qst, REG_ARG_2); // arg2 = import name
Damien Georgecdd96df2014-04-06 12:58:40 +0100926 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
Damien13ed3a62013-10-08 09:05:10 +0100927}
928
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200929STATIC void emit_native_import_star(emit_t *emit) {
Damien Georgecdd96df2014-04-06 12:58:40 +0100930 DEBUG_printf("import_star\n");
931 vtype_kind_t vtype_module;
932 emit_pre_pop_reg(emit, &vtype_module, REG_ARG_1); // arg1 = module
933 assert(vtype_module == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +0100934 emit_call(emit, MP_F_IMPORT_ALL);
Damien Georgecdd96df2014-04-06 12:58:40 +0100935 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +0100936}
937
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200938STATIC void emit_native_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
Damien Georgecdd96df2014-04-06 12:58:40 +0100939 DEBUG_printf("load_const_tok %d\n", tok);
Damien Georgece8f07a2014-03-27 23:30:26 +0000940 emit_native_pre(emit);
Damien13ed3a62013-10-08 09:05:10 +0100941 int vtype;
Damien George40f3c022014-07-03 13:25:24 +0100942 mp_uint_t val;
Damien13ed3a62013-10-08 09:05:10 +0100943 if (emit->do_viper_types) {
944 switch (tok) {
Damiend99b0522013-12-21 18:17:45 +0000945 case MP_TOKEN_KW_NONE: vtype = VTYPE_PTR_NONE; val = 0; break;
946 case MP_TOKEN_KW_FALSE: vtype = VTYPE_BOOL; val = 0; break;
947 case MP_TOKEN_KW_TRUE: vtype = VTYPE_BOOL; val = 1; break;
Damien13ed3a62013-10-08 09:05:10 +0100948 default: assert(0); vtype = 0; val = 0; // shouldn't happen
949 }
950 } else {
951 vtype = VTYPE_PYOBJ;
952 switch (tok) {
Damien George40f3c022014-07-03 13:25:24 +0100953 case MP_TOKEN_KW_NONE: val = (mp_uint_t)mp_const_none; break;
954 case MP_TOKEN_KW_FALSE: val = (mp_uint_t)mp_const_false; break;
955 case MP_TOKEN_KW_TRUE: val = (mp_uint_t)mp_const_true; break;
Damien13ed3a62013-10-08 09:05:10 +0100956 default: assert(0); vtype = 0; val = 0; // shouldn't happen
957 }
958 }
959 emit_post_push_imm(emit, vtype, val);
960}
961
Damien George40f3c022014-07-03 13:25:24 +0100962STATIC void emit_native_load_const_small_int(emit_t *emit, mp_int_t arg) {
Damien Georgecdd96df2014-04-06 12:58:40 +0100963 DEBUG_printf("load_const_small_int %d\n", arg);
Damien Georgece8f07a2014-03-27 23:30:26 +0000964 emit_native_pre(emit);
Damien13ed3a62013-10-08 09:05:10 +0100965 if (emit->do_viper_types) {
966 emit_post_push_imm(emit, VTYPE_INT, arg);
967 } else {
968 emit_post_push_imm(emit, VTYPE_PYOBJ, (arg << 1) | 1);
969 }
970}
971
Damien Georgecdd96df2014-04-06 12:58:40 +0100972STATIC void emit_native_load_const_int(emit_t *emit, qstr qst) {
973 DEBUG_printf("load_const_int %s\n", qstr_str(st));
974 // for viper: load integer, check fits in 32 bits
975 emit_native_pre(emit);
Damien George7fe21912014-08-16 22:31:57 +0100976 emit_call_with_imm_arg(emit, MP_F_LOAD_CONST_INT, qst, REG_ARG_1);
Damien Georgecdd96df2014-04-06 12:58:40 +0100977 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
Damien13ed3a62013-10-08 09:05:10 +0100978}
979
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200980STATIC void emit_native_load_const_dec(emit_t *emit, qstr qstr) {
Damien6ba13142013-11-02 20:34:54 +0000981 // for viper, a float/complex is just a Python object
Damien Georgece8f07a2014-03-27 23:30:26 +0000982 emit_native_pre(emit);
Damien George7fe21912014-08-16 22:31:57 +0100983 emit_call_with_imm_arg(emit, MP_F_LOAD_CONST_DEC, qstr, REG_ARG_1);
Damien6ba13142013-11-02 20:34:54 +0000984 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
Damien13ed3a62013-10-08 09:05:10 +0100985}
986
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200987STATIC void emit_native_load_const_str(emit_t *emit, qstr qstr, bool bytes) {
Damien Georgece8f07a2014-03-27 23:30:26 +0000988 emit_native_pre(emit);
Damien13ed3a62013-10-08 09:05:10 +0100989 if (emit->do_viper_types) {
990 // not implemented properly
991 // load a pointer to the asciiz string?
992 assert(0);
Damien George40f3c022014-07-03 13:25:24 +0100993 emit_post_push_imm(emit, VTYPE_PTR, (mp_uint_t)qstr_str(qstr));
Damien13ed3a62013-10-08 09:05:10 +0100994 } else {
Damien Georgeb601d952014-06-30 05:17:25 +0100995 if (bytes) {
Damien George7fe21912014-08-16 22:31:57 +0100996 emit_call_with_imm_arg(emit, MP_F_LOAD_CONST_BYTES, qstr, REG_ARG_1);
Damien Georgeb601d952014-06-30 05:17:25 +0100997 } else {
Damien George7fe21912014-08-16 22:31:57 +0100998 emit_call_with_imm_arg(emit, MP_F_LOAD_CONST_STR, qstr, REG_ARG_1);
Damien Georgeb601d952014-06-30 05:17:25 +0100999 }
Damien13ed3a62013-10-08 09:05:10 +01001000 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1001 }
1002}
1003
Damien George3558f622014-04-20 17:50:40 +01001004STATIC void emit_native_load_null(emit_t *emit) {
1005 emit_native_pre(emit);
1006 emit_post_push_imm(emit, VTYPE_PYOBJ, 0);
1007}
1008
Damien George2bf7c092014-04-09 15:26:46 +01001009STATIC void emit_native_load_fast(emit_t *emit, qstr qstr, uint id_flags, int local_num) {
Damien13ed3a62013-10-08 09:05:10 +01001010 vtype_kind_t vtype = emit->local_vtype[local_num];
1011 if (vtype == VTYPE_UNBOUND) {
1012 printf("ViperTypeError: local %s used before type known\n", qstr_str(qstr));
1013 }
Damien Georgece8f07a2014-03-27 23:30:26 +00001014 emit_native_pre(emit);
Damien3ef4abb2013-10-12 16:53:13 +01001015#if N_X64
Damien13ed3a62013-10-08 09:05:10 +01001016 if (local_num == 0) {
1017 emit_post_push_reg(emit, vtype, REG_LOCAL_1);
1018 } else {
Damiend2755ec2013-10-16 23:58:48 +01001019 need_reg_single(emit, REG_RAX, 0);
Damien Georged509ac22014-05-07 23:27:45 +01001020 asm_x64_mov_local_to_r64(emit->as, local_num - REG_LOCAL_NUM, REG_RAX);
Damien13ed3a62013-10-08 09:05:10 +01001021 emit_post_push_reg(emit, vtype, REG_RAX);
1022 }
Damien Georgec90f59e2014-09-06 23:06:36 +01001023#elif N_X86
1024 if (local_num == 0) {
1025 emit_post_push_reg(emit, vtype, REG_LOCAL_1);
1026 } else {
1027 need_reg_single(emit, REG_EAX, 0);
1028 asm_x86_mov_local_to_r32(emit->as, local_num - REG_LOCAL_NUM, REG_EAX);
1029 emit_post_push_reg(emit, vtype, REG_EAX);
1030 }
Damien3ef4abb2013-10-12 16:53:13 +01001031#elif N_THUMB
Damien13ed3a62013-10-08 09:05:10 +01001032 if (local_num == 0) {
1033 emit_post_push_reg(emit, vtype, REG_LOCAL_1);
1034 } else if (local_num == 1) {
1035 emit_post_push_reg(emit, vtype, REG_LOCAL_2);
1036 } else if (local_num == 2) {
1037 emit_post_push_reg(emit, vtype, REG_LOCAL_3);
1038 } else {
Damiend2755ec2013-10-16 23:58:48 +01001039 need_reg_single(emit, REG_R0, 0);
Damien Georged509ac22014-05-07 23:27:45 +01001040 asm_thumb_mov_reg_local(emit->as, REG_R0, local_num - REG_LOCAL_NUM);
Damien13ed3a62013-10-08 09:05:10 +01001041 emit_post_push_reg(emit, vtype, REG_R0);
1042 }
Fabian Vogtfe3d16e2014-08-16 22:55:53 +02001043#elif N_ARM
1044 if (local_num == 0) {
1045 emit_post_push_reg(emit, vtype, REG_LOCAL_1);
1046 } else if (local_num == 1) {
1047 emit_post_push_reg(emit, vtype, REG_LOCAL_2);
1048 } else if (local_num == 2) {
1049 emit_post_push_reg(emit, vtype, REG_LOCAL_3);
1050 } else {
1051 need_reg_single(emit, REG_R0, 0);
1052 asm_arm_mov_reg_local(emit->as, REG_R0, local_num - REG_LOCAL_NUM);
1053 emit_post_push_reg(emit, vtype, REG_R0);
1054 }
Damien Georgec90f59e2014-09-06 23:06:36 +01001055#else
1056 #error not implemented
Damien13ed3a62013-10-08 09:05:10 +01001057#endif
1058}
1059
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001060STATIC void emit_native_load_deref(emit_t *emit, qstr qstr, int local_num) {
Damien9ecbcff2013-12-11 00:41:43 +00001061 // not implemented
1062 // in principle could support this quite easily (ldr r0, [r0, #0]) and then get closed over variables!
1063 assert(0);
1064}
1065
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001066STATIC void emit_native_load_name(emit_t *emit, qstr qstr) {
Damien Georgece8f07a2014-03-27 23:30:26 +00001067 emit_native_pre(emit);
Damien George7fe21912014-08-16 22:31:57 +01001068 emit_call_with_imm_arg(emit, MP_F_LOAD_NAME, qstr, REG_ARG_1);
Damien13ed3a62013-10-08 09:05:10 +01001069 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1070}
1071
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001072STATIC void emit_native_load_global(emit_t *emit, qstr qstr) {
Damien Georgece8f07a2014-03-27 23:30:26 +00001073 emit_native_pre(emit);
Damien George7fe21912014-08-16 22:31:57 +01001074 emit_call_with_imm_arg(emit, MP_F_LOAD_GLOBAL, qstr, REG_ARG_1);
Damien13ed3a62013-10-08 09:05:10 +01001075 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1076}
1077
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001078STATIC void emit_native_load_attr(emit_t *emit, qstr qstr) {
Damien13ed3a62013-10-08 09:05:10 +01001079 // depends on type of subject:
1080 // - integer, function, pointer to integers: error
1081 // - pointer to structure: get member, quite easy
Damien Georged17926d2014-03-30 13:35:08 +01001082 // - Python object: call mp_load_attr, and needs to be typed to convert result
Damien13ed3a62013-10-08 09:05:10 +01001083 vtype_kind_t vtype_base;
1084 emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base
1085 assert(vtype_base == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001086 emit_call_with_imm_arg(emit, MP_F_LOAD_ATTR, qstr, REG_ARG_2); // arg2 = attribute name
Damien13ed3a62013-10-08 09:05:10 +01001087 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1088}
1089
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001090STATIC void emit_native_load_method(emit_t *emit, qstr qstr) {
Damien13ed3a62013-10-08 09:05:10 +01001091 vtype_kind_t vtype_base;
1092 emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base
1093 assert(vtype_base == VTYPE_PYOBJ);
1094 emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, 2); // arg3 = dest ptr
Damien George7fe21912014-08-16 22:31:57 +01001095 emit_call_with_imm_arg(emit, MP_F_LOAD_METHOD, qstr, REG_ARG_2); // arg2 = method name
Damien13ed3a62013-10-08 09:05:10 +01001096}
1097
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001098STATIC void emit_native_load_build_class(emit_t *emit) {
Damien Georgece8f07a2014-03-27 23:30:26 +00001099 emit_native_pre(emit);
Damien George7fe21912014-08-16 22:31:57 +01001100 emit_call(emit, MP_F_LOAD_BUILD_CLASS);
Damien7f5dacf2013-10-10 11:24:39 +01001101 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
Damien13ed3a62013-10-08 09:05:10 +01001102}
1103
Damien George729f7b42014-04-17 22:10:53 +01001104STATIC void emit_native_load_subscr(emit_t *emit) {
1105 vtype_kind_t vtype_lhs, vtype_rhs;
1106 emit_pre_pop_reg_reg(emit, &vtype_rhs, REG_ARG_2, &vtype_lhs, REG_ARG_1);
1107 if (vtype_lhs == VTYPE_PYOBJ && vtype_rhs == VTYPE_PYOBJ) {
Damien George7fe21912014-08-16 22:31:57 +01001108 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 +01001109 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1110 } else {
1111 printf("ViperTypeError: can't do subscr of types %d and %d\n", vtype_lhs, vtype_rhs);
Damien George729f7b42014-04-17 22:10:53 +01001112 }
1113}
1114
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001115STATIC void emit_native_store_fast(emit_t *emit, qstr qstr, int local_num) {
Damien13ed3a62013-10-08 09:05:10 +01001116 vtype_kind_t vtype;
Damien3ef4abb2013-10-12 16:53:13 +01001117#if N_X64
Damien13ed3a62013-10-08 09:05:10 +01001118 if (local_num == 0) {
1119 emit_pre_pop_reg(emit, &vtype, REG_LOCAL_1);
1120 } else {
1121 emit_pre_pop_reg(emit, &vtype, REG_RAX);
Damien Georged509ac22014-05-07 23:27:45 +01001122 asm_x64_mov_r64_to_local(emit->as, REG_RAX, local_num - REG_LOCAL_NUM);
Damien13ed3a62013-10-08 09:05:10 +01001123 }
Damien Georgec90f59e2014-09-06 23:06:36 +01001124#elif N_X86
1125 if (local_num == 0) {
1126 emit_pre_pop_reg(emit, &vtype, REG_LOCAL_1);
1127 } else {
1128 emit_pre_pop_reg(emit, &vtype, REG_EAX);
1129 asm_x86_mov_r32_to_local(emit->as, REG_EAX, local_num - REG_LOCAL_NUM);
1130 }
Damien3ef4abb2013-10-12 16:53:13 +01001131#elif N_THUMB
Damien13ed3a62013-10-08 09:05:10 +01001132 if (local_num == 0) {
1133 emit_pre_pop_reg(emit, &vtype, REG_LOCAL_1);
1134 } else if (local_num == 1) {
1135 emit_pre_pop_reg(emit, &vtype, REG_LOCAL_2);
1136 } else if (local_num == 2) {
1137 emit_pre_pop_reg(emit, &vtype, REG_LOCAL_3);
1138 } else {
1139 emit_pre_pop_reg(emit, &vtype, REG_R0);
Damien Georged509ac22014-05-07 23:27:45 +01001140 asm_thumb_mov_local_reg(emit->as, local_num - REG_LOCAL_NUM, REG_R0);
Damien13ed3a62013-10-08 09:05:10 +01001141 }
Fabian Vogtfe3d16e2014-08-16 22:55:53 +02001142#elif N_ARM
1143 if (local_num == 0) {
1144 emit_pre_pop_reg(emit, &vtype, REG_LOCAL_1);
1145 } else if (local_num == 1) {
1146 emit_pre_pop_reg(emit, &vtype, REG_LOCAL_2);
1147 } else if (local_num == 2) {
1148 emit_pre_pop_reg(emit, &vtype, REG_LOCAL_3);
1149 } else {
1150 emit_pre_pop_reg(emit, &vtype, REG_R0);
1151 asm_arm_mov_local_reg(emit->as, local_num - REG_LOCAL_NUM, REG_R0);
1152 }
Damien Georgec90f59e2014-09-06 23:06:36 +01001153#else
1154 #error not implemented
Damien13ed3a62013-10-08 09:05:10 +01001155#endif
1156
1157 emit_post(emit);
1158
1159 // check types
1160 if (emit->local_vtype[local_num] == VTYPE_UNBOUND) {
1161 // first time this local is assigned, so give it a type of the object stored in it
1162 emit->local_vtype[local_num] = vtype;
1163 } else if (emit->local_vtype[local_num] != vtype) {
1164 // type of local is not the same as object stored in it
1165 printf("ViperTypeError: type mismatch, local %s has type %d but source object has type %d\n", qstr_str(qstr), emit->local_vtype[local_num], vtype);
1166 }
1167}
1168
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001169STATIC void emit_native_store_deref(emit_t *emit, qstr qstr, int local_num) {
Damien9ecbcff2013-12-11 00:41:43 +00001170 // not implemented
1171 assert(0);
1172}
1173
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001174STATIC void emit_native_store_name(emit_t *emit, qstr qstr) {
Damien Georged17926d2014-03-30 13:35:08 +01001175 // mp_store_name, but needs conversion of object (maybe have mp_viper_store_name(obj, type))
Damien13ed3a62013-10-08 09:05:10 +01001176 vtype_kind_t vtype;
1177 emit_pre_pop_reg(emit, &vtype, REG_ARG_2);
1178 assert(vtype == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001179 emit_call_with_imm_arg(emit, MP_F_STORE_NAME, qstr, REG_ARG_1); // arg1 = name
Damien13ed3a62013-10-08 09:05:10 +01001180 emit_post(emit);
1181}
1182
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001183STATIC void emit_native_store_global(emit_t *emit, qstr qstr) {
Damien Georgee6c0dff2014-08-15 23:47:59 +01001184 vtype_kind_t vtype = peek_vtype(emit);
1185 if (vtype == VTYPE_PYOBJ) {
1186 emit_pre_pop_reg(emit, &vtype, REG_ARG_2);
1187 } else {
1188 emit_pre_pop_reg(emit, &vtype, REG_ARG_1);
Damien George7fe21912014-08-16 22:31:57 +01001189 emit_call_with_imm_arg(emit, MP_F_CONVERT_NATIVE_TO_OBJ, vtype, REG_ARG_2); // arg2 = type
Damien Georgec90f59e2014-09-06 23:06:36 +01001190 ASM_MOV_REG_TO_REG(emit->as, REG_RET, REG_ARG_2);
Damien Georgee6c0dff2014-08-15 23:47:59 +01001191 }
Damien George7fe21912014-08-16 22:31:57 +01001192 emit_call_with_imm_arg(emit, MP_F_STORE_GLOBAL, qstr, REG_ARG_1); // arg1 = name
Damien Georgee6c0dff2014-08-15 23:47:59 +01001193 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001194}
1195
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001196STATIC void emit_native_store_attr(emit_t *emit, qstr qstr) {
Damien7f5dacf2013-10-10 11:24:39 +01001197 vtype_kind_t vtype_base, vtype_val;
1198 emit_pre_pop_reg_reg(emit, &vtype_base, REG_ARG_1, &vtype_val, REG_ARG_3); // arg1 = base, arg3 = value
1199 assert(vtype_base == VTYPE_PYOBJ);
1200 assert(vtype_val == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001201 emit_call_with_imm_arg(emit, MP_F_STORE_ATTR, qstr, REG_ARG_2); // arg2 = attribute name
Damien7f5dacf2013-10-10 11:24:39 +01001202 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001203}
1204
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001205STATIC void emit_native_store_subscr(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +01001206 // depends on type of subject:
1207 // - integer, function, pointer to structure: error
1208 // - pointer to integers: store as per array
1209 // - Python object: call runtime with converted object or type info
1210 vtype_kind_t vtype_index, vtype_base, vtype_value;
1211 emit_pre_pop_reg_reg_reg(emit, &vtype_index, REG_ARG_2, &vtype_base, REG_ARG_1, &vtype_value, REG_ARG_3); // index, base, value to store
1212 assert(vtype_index == VTYPE_PYOBJ);
1213 assert(vtype_base == VTYPE_PYOBJ);
1214 assert(vtype_value == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001215 emit_call(emit, MP_F_OBJ_SUBSCR);
Damien13ed3a62013-10-08 09:05:10 +01001216}
1217
Damien Georgee6ce10a2014-09-06 18:38:20 +01001218STATIC void emit_native_delete_fast(emit_t *emit, qstr qst, int local_num) {
1219 // TODO implement me!
Damien13ed3a62013-10-08 09:05:10 +01001220 // could support for Python types, just set to None (so GC can reclaim it)
Damien13ed3a62013-10-08 09:05:10 +01001221}
1222
Damien Georgee6ce10a2014-09-06 18:38:20 +01001223STATIC void emit_native_delete_deref(emit_t *emit, qstr qst, int local_num) {
1224 // TODO implement me!
Damien9ecbcff2013-12-11 00:41:43 +00001225}
1226
Damien Georgee6ce10a2014-09-06 18:38:20 +01001227STATIC void emit_native_delete_name(emit_t *emit, qstr qst) {
1228 emit_native_pre(emit);
1229 emit_call_with_imm_arg(emit, MP_F_DELETE_NAME, qst, REG_ARG_1);
1230 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001231}
1232
Damien Georgee6ce10a2014-09-06 18:38:20 +01001233STATIC void emit_native_delete_global(emit_t *emit, qstr qst) {
1234 emit_native_pre(emit);
1235 emit_call_with_imm_arg(emit, MP_F_DELETE_GLOBAL, qst, REG_ARG_1);
1236 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001237}
1238
Damien Georgee6ce10a2014-09-06 18:38:20 +01001239STATIC void emit_native_delete_attr(emit_t *emit, qstr qst) {
Damien George780e54c2014-06-22 18:35:04 +01001240 vtype_kind_t vtype_base;
1241 emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base
1242 assert(vtype_base == VTYPE_PYOBJ);
Damien Georgee6ce10a2014-09-06 18:38:20 +01001243 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 +01001244 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001245}
1246
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001247STATIC void emit_native_delete_subscr(emit_t *emit) {
Damien George729f7b42014-04-17 22:10:53 +01001248 vtype_kind_t vtype_index, vtype_base;
1249 emit_pre_pop_reg_reg(emit, &vtype_index, REG_ARG_2, &vtype_base, REG_ARG_1); // index, base
1250 assert(vtype_index == VTYPE_PYOBJ);
1251 assert(vtype_base == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001252 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 +01001253}
1254
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001255STATIC void emit_native_dup_top(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +01001256 vtype_kind_t vtype;
1257 emit_pre_pop_reg(emit, &vtype, REG_TEMP0);
1258 emit_post_push_reg_reg(emit, vtype, REG_TEMP0, vtype, REG_TEMP0);
1259}
1260
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001261STATIC void emit_native_dup_top_two(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +01001262 vtype_kind_t vtype0, vtype1;
1263 emit_pre_pop_reg_reg(emit, &vtype0, REG_TEMP0, &vtype1, REG_TEMP1);
1264 emit_post_push_reg_reg_reg_reg(emit, vtype1, REG_TEMP1, vtype0, REG_TEMP0, vtype1, REG_TEMP1, vtype0, REG_TEMP0);
1265}
1266
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001267STATIC void emit_native_pop_top(emit_t *emit) {
Damien Georgee6ce10a2014-09-06 18:38:20 +01001268 emit_pre_pop_discard(emit);
Damien13ed3a62013-10-08 09:05:10 +01001269 emit_post(emit);
1270}
1271
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001272STATIC void emit_native_rot_two(emit_t *emit) {
Damienff8ed772013-10-08 22:18:32 +01001273 vtype_kind_t vtype0, vtype1;
1274 emit_pre_pop_reg_reg(emit, &vtype0, REG_TEMP0, &vtype1, REG_TEMP1);
1275 emit_post_push_reg_reg(emit, vtype0, REG_TEMP0, vtype1, REG_TEMP1);
Damien13ed3a62013-10-08 09:05:10 +01001276}
1277
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001278STATIC void emit_native_rot_three(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +01001279 vtype_kind_t vtype0, vtype1, vtype2;
1280 emit_pre_pop_reg_reg_reg(emit, &vtype0, REG_TEMP0, &vtype1, REG_TEMP1, &vtype2, REG_TEMP2);
1281 emit_post_push_reg_reg_reg(emit, vtype0, REG_TEMP0, vtype2, REG_TEMP2, vtype1, REG_TEMP1);
1282}
1283
Damien George6f355fd2014-04-10 14:11:31 +01001284STATIC void emit_native_jump(emit_t *emit, uint label) {
Damien Georgece8f07a2014-03-27 23:30:26 +00001285 emit_native_pre(emit);
Damien Georgea32c1e42014-05-07 18:30:52 +01001286 // need to commit stack because we are jumping elsewhere
1287 need_stack_settled(emit);
Damien Georgec90f59e2014-09-06 23:06:36 +01001288 ASM_JUMP(emit->as, label);
Damien13ed3a62013-10-08 09:05:10 +01001289 emit_post(emit);
1290}
1291
Damien Georgea32c1e42014-05-07 18:30:52 +01001292STATIC void emit_native_jump_helper(emit_t *emit, uint label, bool pop) {
Damien13ed3a62013-10-08 09:05:10 +01001293 vtype_kind_t vtype = peek_vtype(emit);
1294 if (vtype == VTYPE_BOOL) {
1295 emit_pre_pop_reg(emit, &vtype, REG_RET);
Damien Georgea32c1e42014-05-07 18:30:52 +01001296 if (!pop) {
1297 adjust_stack(emit, 1);
1298 }
Damien13ed3a62013-10-08 09:05:10 +01001299 } else if (vtype == VTYPE_PYOBJ) {
1300 emit_pre_pop_reg(emit, &vtype, REG_ARG_1);
Damien Georgea32c1e42014-05-07 18:30:52 +01001301 if (!pop) {
Damien George02d95d72014-08-29 20:05:32 +01001302 adjust_stack(emit, 1);
Damien Georgea32c1e42014-05-07 18:30:52 +01001303 }
Damien George02d95d72014-08-29 20:05:32 +01001304 emit_call(emit, MP_F_OBJ_IS_TRUE);
Damien13ed3a62013-10-08 09:05:10 +01001305 } else {
1306 printf("ViperTypeError: expecting a bool or pyobj, got %d\n", vtype);
1307 assert(0);
1308 }
Damien Georgea32c1e42014-05-07 18:30:52 +01001309 // need to commit stack because we may jump elsewhere
1310 need_stack_settled(emit);
Damien13ed3a62013-10-08 09:05:10 +01001311}
1312
Damien George6f355fd2014-04-10 14:11:31 +01001313STATIC void emit_native_pop_jump_if_true(emit_t *emit, uint label) {
Damien Georgea32c1e42014-05-07 18:30:52 +01001314 emit_native_jump_helper(emit, label, true);
Damien Georgec90f59e2014-09-06 23:06:36 +01001315 ASM_JUMP_IF_REG_NONZERO(emit->as, REG_RET, label);
Damien1a6633a2013-11-03 13:58:19 +00001316 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001317}
Damien1a6633a2013-11-03 13:58:19 +00001318
Damien Georgea32c1e42014-05-07 18:30:52 +01001319STATIC void emit_native_pop_jump_if_false(emit_t *emit, uint label) {
1320 emit_native_jump_helper(emit, label, true);
Damien Georgec90f59e2014-09-06 23:06:36 +01001321 ASM_JUMP_IF_REG_ZERO(emit->as, REG_RET, label);
Damien Georgea32c1e42014-05-07 18:30:52 +01001322 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001323}
Damien Georgea32c1e42014-05-07 18:30:52 +01001324
1325STATIC void emit_native_jump_if_true_or_pop(emit_t *emit, uint label) {
1326 emit_native_jump_helper(emit, label, false);
Damien Georgec90f59e2014-09-06 23:06:36 +01001327 ASM_JUMP_IF_REG_NONZERO(emit->as, REG_RET, label);
Damien Georgea32c1e42014-05-07 18:30:52 +01001328 adjust_stack(emit, -1);
1329 emit_post(emit);
1330}
1331
Damien George6f355fd2014-04-10 14:11:31 +01001332STATIC void emit_native_jump_if_false_or_pop(emit_t *emit, uint label) {
Damien Georgea32c1e42014-05-07 18:30:52 +01001333 emit_native_jump_helper(emit, label, false);
Damien Georgec90f59e2014-09-06 23:06:36 +01001334 ASM_JUMP_IF_REG_ZERO(emit->as, REG_RET, label);
Damien Georgea32c1e42014-05-07 18:30:52 +01001335 adjust_stack(emit, -1);
1336 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001337}
1338
Damien George6f355fd2014-04-10 14:11:31 +01001339STATIC void emit_native_break_loop(emit_t *emit, uint label, int except_depth) {
Damien George25c84642014-05-30 15:20:41 +01001340 emit_native_jump(emit, label & ~MP_EMIT_BREAK_FROM_FOR); // TODO properly
Damien13ed3a62013-10-08 09:05:10 +01001341}
Damien Georgea32c1e42014-05-07 18:30:52 +01001342
Damien George6f355fd2014-04-10 14:11:31 +01001343STATIC void emit_native_continue_loop(emit_t *emit, uint label, int except_depth) {
Damien Georgea32c1e42014-05-07 18:30:52 +01001344 emit_native_jump(emit, label); // TODO properly
Damien13ed3a62013-10-08 09:05:10 +01001345}
Damien Georgea32c1e42014-05-07 18:30:52 +01001346
Damien George6f355fd2014-04-10 14:11:31 +01001347STATIC void emit_native_setup_with(emit_t *emit, uint label) {
Damien13ed3a62013-10-08 09:05:10 +01001348 // not supported, or could be with runtime call
1349 assert(0);
1350}
Damien Georgeb601d952014-06-30 05:17:25 +01001351
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001352STATIC void emit_native_with_cleanup(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +01001353 assert(0);
1354}
Damien Georgeb601d952014-06-30 05:17:25 +01001355
Damien George6f355fd2014-04-10 14:11:31 +01001356STATIC void emit_native_setup_except(emit_t *emit, uint label) {
Damien Georgeb601d952014-06-30 05:17:25 +01001357 emit_native_pre(emit);
1358 // need to commit stack because we may jump elsewhere
1359 need_stack_settled(emit);
Damien George40f3c022014-07-03 13:25:24 +01001360 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 +01001361 emit_call(emit, MP_F_NLR_PUSH);
Damien Georgec90f59e2014-09-06 23:06:36 +01001362 ASM_JUMP_IF_REG_NONZERO(emit->as, REG_RET, label);
Damien Georgeb601d952014-06-30 05:17:25 +01001363 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001364}
Damien Georgeb601d952014-06-30 05:17:25 +01001365
Damien George6f355fd2014-04-10 14:11:31 +01001366STATIC void emit_native_setup_finally(emit_t *emit, uint label) {
Damien Georgee6ce10a2014-09-06 18:38:20 +01001367 emit_native_setup_except(emit, label);
Damien13ed3a62013-10-08 09:05:10 +01001368}
Damien Georgeb601d952014-06-30 05:17:25 +01001369
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001370STATIC void emit_native_end_finally(emit_t *emit) {
Damien Georgee6ce10a2014-09-06 18:38:20 +01001371 emit_pre_pop_discard(emit);
1372 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001373}
Damiend2755ec2013-10-16 23:58:48 +01001374
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001375STATIC void emit_native_get_iter(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +01001376 // perhaps the difficult one, as we want to rewrite for loops using native code
1377 // in cases where we iterate over a Python object, can we use normal runtime calls?
Damiend2755ec2013-10-16 23:58:48 +01001378
1379 vtype_kind_t vtype;
1380 emit_pre_pop_reg(emit, &vtype, REG_ARG_1);
1381 assert(vtype == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001382 emit_call(emit, MP_F_GETITER);
Damiend2755ec2013-10-16 23:58:48 +01001383 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
Damien13ed3a62013-10-08 09:05:10 +01001384}
Damiend2755ec2013-10-16 23:58:48 +01001385
Damien George6f355fd2014-04-10 14:11:31 +01001386STATIC void emit_native_for_iter(emit_t *emit, uint label) {
Damien Georgece8f07a2014-03-27 23:30:26 +00001387 emit_native_pre(emit);
Damiend2755ec2013-10-16 23:58:48 +01001388 vtype_kind_t vtype;
1389 emit_access_stack(emit, 1, &vtype, REG_ARG_1);
1390 assert(vtype == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001391 emit_call(emit, MP_F_ITERNEXT);
Damien Georgec90f59e2014-09-06 23:06:36 +01001392 ASM_MOV_IMM_TO_REG(emit->as, (mp_uint_t)MP_OBJ_STOP_ITERATION, REG_TEMP1);
1393 ASM_JUMP_IF_REG_EQ(emit->as, REG_RET, REG_TEMP1, label);
Damiend2755ec2013-10-16 23:58:48 +01001394 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1395}
1396
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001397STATIC void emit_native_for_iter_end(emit_t *emit) {
Damiend2755ec2013-10-16 23:58:48 +01001398 // adjust stack counter (we get here from for_iter ending, which popped the value for us)
Damien Georgece8f07a2014-03-27 23:30:26 +00001399 emit_native_pre(emit);
Damiend2755ec2013-10-16 23:58:48 +01001400 adjust_stack(emit, -1);
1401 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001402}
1403
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001404STATIC void emit_native_pop_block(emit_t *emit) {
Damien Georgece8f07a2014-03-27 23:30:26 +00001405 emit_native_pre(emit);
Damien George7fe21912014-08-16 22:31:57 +01001406 emit_call(emit, MP_F_NLR_POP);
Damien George40f3c022014-07-03 13:25:24 +01001407 adjust_stack(emit, -(mp_int_t)(sizeof(nlr_buf_t) / sizeof(mp_uint_t)));
Damien13ed3a62013-10-08 09:05:10 +01001408 emit_post(emit);
1409}
1410
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001411STATIC void emit_native_pop_except(emit_t *emit) {
Damien Georgeb601d952014-06-30 05:17:25 +01001412 /*
1413 emit_native_pre(emit);
Damien George7fe21912014-08-16 22:31:57 +01001414 emit_call(emit, MP_F_NLR_POP);
Damien George40f3c022014-07-03 13:25:24 +01001415 adjust_stack(emit, -(mp_int_t)(sizeof(nlr_buf_t) / sizeof(mp_uint_t)));
Damien Georgeb601d952014-06-30 05:17:25 +01001416 emit_post(emit);
1417 */
Damien13ed3a62013-10-08 09:05:10 +01001418}
1419
Damien Georged17926d2014-03-30 13:35:08 +01001420STATIC void emit_native_unary_op(emit_t *emit, mp_unary_op_t op) {
Damien Georgeb601d952014-06-30 05:17:25 +01001421 if (op == MP_UNARY_OP_NOT) {
1422 // we need to synthesise this operation
1423 assert(0);
1424 } else {
1425 vtype_kind_t vtype;
1426 emit_pre_pop_reg(emit, &vtype, REG_ARG_2);
1427 assert(vtype == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001428 emit_call_with_imm_arg(emit, MP_F_UNARY_OP, op, REG_ARG_1);
Damien Georgeb601d952014-06-30 05:17:25 +01001429 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1430 }
Damien13ed3a62013-10-08 09:05:10 +01001431}
1432
Damien Georged17926d2014-03-30 13:35:08 +01001433STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) {
Damien13ed3a62013-10-08 09:05:10 +01001434 vtype_kind_t vtype_lhs, vtype_rhs;
1435 emit_pre_pop_reg_reg(emit, &vtype_rhs, REG_ARG_3, &vtype_lhs, REG_ARG_2);
1436 if (vtype_lhs == VTYPE_INT && vtype_rhs == VTYPE_INT) {
Damien Georged17926d2014-03-30 13:35:08 +01001437 if (op == MP_BINARY_OP_ADD || op == MP_BINARY_OP_INPLACE_ADD) {
Damien3ef4abb2013-10-12 16:53:13 +01001438#if N_X64
Damien Georgebc1d3692014-01-11 09:47:06 +00001439 asm_x64_add_r64_to_r64(emit->as, REG_ARG_3, REG_ARG_2);
Damien Georgec90f59e2014-09-06 23:06:36 +01001440#elif N_X86
1441 asm_x86_add_r32_to_r32(emit->as, REG_ARG_3, REG_ARG_2);
Damien3ef4abb2013-10-12 16:53:13 +01001442#elif N_THUMB
Damien Georgea26dc502014-04-12 17:54:52 +01001443 asm_thumb_add_rlo_rlo_rlo(emit->as, REG_ARG_2, REG_ARG_2, REG_ARG_3);
Fabian Vogtfe3d16e2014-08-16 22:55:53 +02001444#elif N_ARM
1445 asm_arm_add_reg(emit->as, REG_ARG_2, REG_ARG_2, REG_ARG_3);
Damien Georgec90f59e2014-09-06 23:06:36 +01001446#else
1447 #error not implemented
Damien13ed3a62013-10-08 09:05:10 +01001448#endif
Damien Georgebc1d3692014-01-11 09:47:06 +00001449 emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);
Damien Georged17926d2014-03-30 13:35:08 +01001450 } else if (op == MP_BINARY_OP_LESS) {
Damien Georgebc1d3692014-01-11 09:47:06 +00001451#if N_X64
1452 asm_x64_xor_r64_to_r64(emit->as, REG_RET, REG_RET);
1453 asm_x64_cmp_r64_with_r64(emit->as, REG_ARG_3, REG_ARG_2);
Damien Georgec90f59e2014-09-06 23:06:36 +01001454 asm_x64_setcc_r8(emit->as, ASM_X64_CC_JL, REG_RET);
1455#elif N_X86
1456 asm_x86_xor_r32_to_r32(emit->as, REG_RET, REG_RET);
1457 asm_x86_cmp_r32_with_r32(emit->as, REG_ARG_3, REG_ARG_2);
1458 asm_x86_setcc_r8(emit->as, ASM_X86_CC_JL, REG_RET);
Damien Georgebc1d3692014-01-11 09:47:06 +00001459#elif N_THUMB
Damien George87210872014-04-13 00:30:32 +01001460 asm_thumb_cmp_rlo_rlo(emit->as, REG_ARG_2, REG_ARG_3);
Damien Georgebc1d3692014-01-11 09:47:06 +00001461 asm_thumb_ite_ge(emit->as);
Damien George87210872014-04-13 00:30:32 +01001462 asm_thumb_mov_rlo_i8(emit->as, REG_RET, 0); // if r0 >= r1
1463 asm_thumb_mov_rlo_i8(emit->as, REG_RET, 1); // if r0 < r1
Fabian Vogtfe3d16e2014-08-16 22:55:53 +02001464#elif N_ARM
1465 asm_arm_less_op(emit->as, REG_ARG_2, REG_ARG_3);
Damien Georgec90f59e2014-09-06 23:06:36 +01001466#else
1467 #error not implemented
Damien Georgebc1d3692014-01-11 09:47:06 +00001468#endif
1469 emit_post_push_reg(emit, VTYPE_BOOL, REG_RET);
1470 } else {
1471 // TODO other ops not yet implemented
1472 assert(0);
1473 }
Damien13ed3a62013-10-08 09:05:10 +01001474 } else if (vtype_lhs == VTYPE_PYOBJ && vtype_rhs == VTYPE_PYOBJ) {
Damien George7fe21912014-08-16 22:31:57 +01001475 emit_call_with_imm_arg(emit, MP_F_BINARY_OP, op, REG_ARG_1);
Damien13ed3a62013-10-08 09:05:10 +01001476 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1477 } else {
1478 printf("ViperTypeError: can't do binary op between types %d and %d\n", vtype_lhs, vtype_rhs);
Damien Georgea5190a72014-08-15 22:39:08 +01001479 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
Damien13ed3a62013-10-08 09:05:10 +01001480 }
1481}
1482
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001483STATIC void emit_native_build_tuple(emit_t *emit, int n_args) {
Damiend2755ec2013-10-16 23:58:48 +01001484 // for viper: call runtime, with types of args
1485 // if wrapped in byte_array, or something, allocates memory and fills it
Damien Georgece8f07a2014-03-27 23:30:26 +00001486 emit_native_pre(emit);
Damien Georgecd82e022014-02-02 13:11:48 +00001487 emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, n_args); // pointer to items
Damien George7fe21912014-08-16 22:31:57 +01001488 emit_call_with_imm_arg(emit, MP_F_BUILD_TUPLE, n_args, REG_ARG_1);
Damiend2755ec2013-10-16 23:58:48 +01001489 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new tuple
Damien13ed3a62013-10-08 09:05:10 +01001490}
1491
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001492STATIC void emit_native_build_list(emit_t *emit, int n_args) {
Damien Georgece8f07a2014-03-27 23:30:26 +00001493 emit_native_pre(emit);
Damien Georgecd82e022014-02-02 13:11:48 +00001494 emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, n_args); // pointer to items
Damien George7fe21912014-08-16 22:31:57 +01001495 emit_call_with_imm_arg(emit, MP_F_BUILD_LIST, n_args, REG_ARG_1);
Damien13ed3a62013-10-08 09:05:10 +01001496 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new list
1497}
1498
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001499STATIC void emit_native_list_append(emit_t *emit, int list_index) {
Damiend2755ec2013-10-16 23:58:48 +01001500 // only used in list comprehension
1501 vtype_kind_t vtype_list, vtype_item;
1502 emit_pre_pop_reg(emit, &vtype_item, REG_ARG_2);
1503 emit_access_stack(emit, list_index, &vtype_list, REG_ARG_1);
1504 assert(vtype_list == VTYPE_PYOBJ);
1505 assert(vtype_item == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001506 emit_call(emit, MP_F_LIST_APPEND);
Damiend2755ec2013-10-16 23:58:48 +01001507 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001508}
1509
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001510STATIC void emit_native_build_map(emit_t *emit, int n_args) {
Damien Georgece8f07a2014-03-27 23:30:26 +00001511 emit_native_pre(emit);
Damien George7fe21912014-08-16 22:31:57 +01001512 emit_call_with_imm_arg(emit, MP_F_BUILD_MAP, n_args, REG_ARG_1);
Damien13ed3a62013-10-08 09:05:10 +01001513 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new map
1514}
1515
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001516STATIC void emit_native_store_map(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +01001517 vtype_kind_t vtype_key, vtype_value, vtype_map;
1518 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
1519 assert(vtype_key == VTYPE_PYOBJ);
1520 assert(vtype_value == VTYPE_PYOBJ);
1521 assert(vtype_map == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001522 emit_call(emit, MP_F_STORE_MAP);
Damien13ed3a62013-10-08 09:05:10 +01001523 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // map
1524}
1525
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001526STATIC void emit_native_map_add(emit_t *emit, int map_index) {
Damiend2755ec2013-10-16 23:58:48 +01001527 // only used in list comprehension
1528 vtype_kind_t vtype_map, vtype_key, vtype_value;
1529 emit_pre_pop_reg_reg(emit, &vtype_key, REG_ARG_2, &vtype_value, REG_ARG_3);
1530 emit_access_stack(emit, map_index, &vtype_map, REG_ARG_1);
1531 assert(vtype_map == VTYPE_PYOBJ);
1532 assert(vtype_key == VTYPE_PYOBJ);
1533 assert(vtype_value == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001534 emit_call(emit, MP_F_STORE_MAP);
Damiend2755ec2013-10-16 23:58:48 +01001535 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001536}
1537
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001538STATIC void emit_native_build_set(emit_t *emit, int n_args) {
Damien Georgece8f07a2014-03-27 23:30:26 +00001539 emit_native_pre(emit);
Damien Georgecd82e022014-02-02 13:11:48 +00001540 emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, n_args); // pointer to items
Damien George7fe21912014-08-16 22:31:57 +01001541 emit_call_with_imm_arg(emit, MP_F_BUILD_SET, n_args, REG_ARG_1);
Damien13ed3a62013-10-08 09:05:10 +01001542 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new set
1543}
1544
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001545STATIC void emit_native_set_add(emit_t *emit, int set_index) {
Damiend2755ec2013-10-16 23:58:48 +01001546 // only used in set comprehension
1547 vtype_kind_t vtype_set, vtype_item;
1548 emit_pre_pop_reg(emit, &vtype_item, REG_ARG_2);
1549 emit_access_stack(emit, set_index, &vtype_set, REG_ARG_1);
1550 assert(vtype_set == VTYPE_PYOBJ);
1551 assert(vtype_item == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001552 emit_call(emit, MP_F_STORE_SET);
Damiend2755ec2013-10-16 23:58:48 +01001553 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001554}
Damiend2755ec2013-10-16 23:58:48 +01001555
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001556STATIC void emit_native_build_slice(emit_t *emit, int n_args) {
Damien Georgecdd96df2014-04-06 12:58:40 +01001557 DEBUG_printf("build_slice %d\n", n_args);
Damien Georgeb601d952014-06-30 05:17:25 +01001558 if (n_args == 2) {
1559 vtype_kind_t vtype_start, vtype_stop;
1560 emit_pre_pop_reg_reg(emit, &vtype_stop, REG_ARG_2, &vtype_start, REG_ARG_1); // arg1 = start, arg2 = stop
1561 assert(vtype_start == VTYPE_PYOBJ);
1562 assert(vtype_stop == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001563 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 +01001564 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1565 } else {
1566 assert(n_args == 3);
1567 vtype_kind_t vtype_start, vtype_stop, vtype_step;
1568 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
1569 assert(vtype_start == VTYPE_PYOBJ);
1570 assert(vtype_stop == VTYPE_PYOBJ);
1571 assert(vtype_step == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001572 emit_call(emit, MP_F_NEW_SLICE);
Damien Georgeb601d952014-06-30 05:17:25 +01001573 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1574 }
Damien13ed3a62013-10-08 09:05:10 +01001575}
Damien Georgecdd96df2014-04-06 12:58:40 +01001576
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001577STATIC void emit_native_unpack_sequence(emit_t *emit, int n_args) {
Damien Georgecdd96df2014-04-06 12:58:40 +01001578 DEBUG_printf("unpack_sequence %d\n", n_args);
1579 vtype_kind_t vtype_base;
1580 emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = seq
1581 assert(vtype_base == VTYPE_PYOBJ);
1582 emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, n_args); // arg3 = dest ptr
Damien George7fe21912014-08-16 22:31:57 +01001583 emit_call_with_imm_arg(emit, MP_F_UNPACK_SEQUENCE, n_args, REG_ARG_2); // arg2 = n_args
Damien13ed3a62013-10-08 09:05:10 +01001584}
Damien Georgecdd96df2014-04-06 12:58:40 +01001585
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001586STATIC void emit_native_unpack_ex(emit_t *emit, int n_left, int n_right) {
Damien Georgea32c1e42014-05-07 18:30:52 +01001587 DEBUG_printf("unpack_ex %d %d\n", n_left, n_right);
1588 vtype_kind_t vtype_base;
1589 emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = seq
1590 assert(vtype_base == VTYPE_PYOBJ);
Damien Georgeb601d952014-06-30 05:17:25 +01001591 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 +01001592 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 +01001593}
1594
Damien George30565092014-03-31 11:30:17 +01001595STATIC void emit_native_make_function(emit_t *emit, scope_t *scope, uint n_pos_defaults, uint n_kw_defaults) {
Damien13ed3a62013-10-08 09:05:10 +01001596 // 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 +00001597 emit_native_pre(emit);
Damien Georgea32c1e42014-05-07 18:30:52 +01001598 if (n_pos_defaults == 0 && n_kw_defaults == 0) {
Damien George7fe21912014-08-16 22:31:57 +01001599 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 +01001600 } else {
1601 vtype_kind_t vtype_def_tuple, vtype_def_dict;
1602 emit_pre_pop_reg_reg(emit, &vtype_def_dict, REG_ARG_3, &vtype_def_tuple, REG_ARG_2);
1603 assert(vtype_def_tuple == VTYPE_PYOBJ);
1604 assert(vtype_def_dict == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001605 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 +01001606 }
Damien13ed3a62013-10-08 09:05:10 +01001607 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1608}
1609
Damien George3558f622014-04-20 17:50:40 +01001610STATIC void emit_native_make_closure(emit_t *emit, scope_t *scope, uint n_closed_over, uint n_pos_defaults, uint n_kw_defaults) {
Damien13ed3a62013-10-08 09:05:10 +01001611 assert(0);
1612}
1613
Damien George922ddd62014-04-09 12:43:17 +01001614STATIC void emit_native_call_function(emit_t *emit, int n_positional, int n_keyword, uint star_flags) {
Damien13ed3a62013-10-08 09:05:10 +01001615 // call special viper runtime routine with type info for args, and wanted type info for return
Damien George922ddd62014-04-09 12:43:17 +01001616 assert(!star_flags);
Damien Georgecd82e022014-02-02 13:11:48 +00001617
1618 /* we no longer have these _n specific call_function's
1619 * they anyway push args into an array
1620 * and they would take too much room in the native dispatch table
Damien13ed3a62013-10-08 09:05:10 +01001621 if (n_positional == 0) {
1622 vtype_kind_t vtype_fun;
1623 emit_pre_pop_reg(emit, &vtype_fun, REG_ARG_1); // the function
1624 assert(vtype_fun == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001625 emit_call(emit, MP_F_CALL_FUNCTION_0);
Damien13ed3a62013-10-08 09:05:10 +01001626 } else if (n_positional == 1) {
1627 vtype_kind_t vtype_fun, vtype_arg1;
1628 emit_pre_pop_reg_reg(emit, &vtype_arg1, REG_ARG_2, &vtype_fun, REG_ARG_1); // the single argument, the function
1629 assert(vtype_fun == VTYPE_PYOBJ);
1630 assert(vtype_arg1 == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001631 emit_call(emit, MP_F_CALL_FUNCTION_1);
Damien13ed3a62013-10-08 09:05:10 +01001632 } else if (n_positional == 2) {
1633 vtype_kind_t vtype_fun, vtype_arg1, vtype_arg2;
1634 emit_pre_pop_reg_reg_reg(emit, &vtype_arg2, REG_ARG_3, &vtype_arg1, REG_ARG_2, &vtype_fun, REG_ARG_1); // the second argument, the first argument, the function
1635 assert(vtype_fun == VTYPE_PYOBJ);
1636 assert(vtype_arg1 == VTYPE_PYOBJ);
1637 assert(vtype_arg2 == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001638 emit_call(emit, MP_F_CALL_FUNCTION_2);
Damien13ed3a62013-10-08 09:05:10 +01001639 } else {
Damieneb19efb2013-10-10 22:06:54 +01001640 */
Damien Georgecd82e022014-02-02 13:11:48 +00001641
Damien Georgece8f07a2014-03-27 23:30:26 +00001642 emit_native_pre(emit);
Damien Georgecdd96df2014-04-06 12:58:40 +01001643 if (n_positional != 0 || n_keyword != 0) {
1644 emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_positional + 2 * n_keyword); // pointer to args
Damien Georgecd82e022014-02-02 13:11:48 +00001645 }
1646 vtype_kind_t vtype_fun;
1647 emit_pre_pop_reg(emit, &vtype_fun, REG_ARG_1); // the function
1648 assert(vtype_fun == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001649 emit_call_with_imm_arg(emit, MP_F_NATIVE_CALL_FUNCTION_N_KW, n_positional | (n_keyword << 8), REG_ARG_2);
Damien13ed3a62013-10-08 09:05:10 +01001650 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1651}
1652
Damien George922ddd62014-04-09 12:43:17 +01001653STATIC void emit_native_call_method(emit_t *emit, int n_positional, int n_keyword, uint star_flags) {
1654 assert(!star_flags);
Damien Georgecd82e022014-02-02 13:11:48 +00001655
Damieneb19efb2013-10-10 22:06:54 +01001656 /*
Damien13ed3a62013-10-08 09:05:10 +01001657 if (n_positional == 0) {
1658 vtype_kind_t vtype_meth, vtype_self;
1659 emit_pre_pop_reg_reg(emit, &vtype_self, REG_ARG_2, &vtype_meth, REG_ARG_1); // the self object (or NULL), the method
1660 assert(vtype_meth == VTYPE_PYOBJ);
1661 assert(vtype_self == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001662 emit_call(emit, MP_F_CALL_METHOD_1);
Damien13ed3a62013-10-08 09:05:10 +01001663 } else if (n_positional == 1) {
1664 vtype_kind_t vtype_meth, vtype_self, vtype_arg1;
1665 emit_pre_pop_reg_reg_reg(emit, &vtype_arg1, REG_ARG_3, &vtype_self, REG_ARG_2, &vtype_meth, REG_ARG_1); // the first argument, the self object (or NULL), the method
1666 assert(vtype_meth == VTYPE_PYOBJ);
1667 assert(vtype_self == VTYPE_PYOBJ);
1668 assert(vtype_arg1 == VTYPE_PYOBJ);
Damien George7fe21912014-08-16 22:31:57 +01001669 emit_call(emit, MP_F_CALL_METHOD_2);
Damien13ed3a62013-10-08 09:05:10 +01001670 } else {
Damieneb19efb2013-10-10 22:06:54 +01001671 */
Damien Georgecd82e022014-02-02 13:11:48 +00001672
Damien Georgece8f07a2014-03-27 23:30:26 +00001673 emit_native_pre(emit);
Damien Georgecdd96df2014-04-06 12:58:40 +01001674 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 +01001675 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 +01001676 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1677}
1678
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001679STATIC void emit_native_return_value(emit_t *emit) {
Damien Georgecdd96df2014-04-06 12:58:40 +01001680 DEBUG_printf("return_value\n");
Damien13ed3a62013-10-08 09:05:10 +01001681 vtype_kind_t vtype;
1682 emit_pre_pop_reg(emit, &vtype, REG_RET);
1683 if (emit->do_viper_types) {
Damien Georgee6c0dff2014-08-15 23:47:59 +01001684 if (vtype == VTYPE_PTR_NONE) {
1685 if (emit->return_vtype == VTYPE_PYOBJ) {
Damien Georgec90f59e2014-09-06 23:06:36 +01001686 ASM_MOV_IMM_TO_REG(emit->as, (mp_uint_t)mp_const_none, REG_RET);
Damien Georgee6c0dff2014-08-15 23:47:59 +01001687 }
1688 } else if (vtype != emit->return_vtype) {
Damien George2ac4af62014-08-15 16:45:41 +01001689 printf("ViperTypeError: incompatible return type\n");
1690 }
Damien13ed3a62013-10-08 09:05:10 +01001691 } else {
1692 assert(vtype == VTYPE_PYOBJ);
1693 }
1694 emit->last_emit_was_return_value = true;
Damien Georgec90f59e2014-09-06 23:06:36 +01001695 //ASM_BREAK_POINT(emit->as); // to insert a break-point for debugging
1696 ASM_EXIT(emit->as);
Damien13ed3a62013-10-08 09:05:10 +01001697}
1698
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001699STATIC void emit_native_raise_varargs(emit_t *emit, int n_args) {
Damien Georgeb601d952014-06-30 05:17:25 +01001700 assert(n_args == 1);
Damien George86de21b2014-08-16 22:06:11 +01001701 vtype_kind_t vtype_exc;
1702 emit_pre_pop_reg(emit, &vtype_exc, REG_ARG_1); // arg1 = object to raise
1703 if (vtype_exc != VTYPE_PYOBJ) {
1704 printf("ViperTypeError: must raise an object\n");
1705 }
1706 // 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 +01001707 emit_call(emit, MP_F_NATIVE_RAISE);
Damien13ed3a62013-10-08 09:05:10 +01001708}
Damien Georgeb601d952014-06-30 05:17:25 +01001709
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001710STATIC void emit_native_yield_value(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +01001711 // not supported (for now)
1712 assert(0);
1713}
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001714STATIC void emit_native_yield_from(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +01001715 // not supported (for now)
1716 assert(0);
1717}
1718
Damien Georgeb601d952014-06-30 05:17:25 +01001719STATIC void emit_native_start_except_handler(emit_t *emit) {
1720 // This instruction follows an nlr_pop, so the stack counter is back to zero, when really
1721 // it should be up by a whole nlr_buf_t. We then want to pop the nlr_buf_t here, but save
1722 // the first 2 elements, so we can get the thrown value.
1723 adjust_stack(emit, 2);
1724 vtype_kind_t vtype_nlr;
1725 emit_pre_pop_reg(emit, &vtype_nlr, REG_ARG_1); // get the thrown value
Damien Georgee6ce10a2014-09-06 18:38:20 +01001726 emit_pre_pop_discard(emit); // discard the linked-list pointer in the nlr_buf
Damien Georgeb601d952014-06-30 05:17:25 +01001727 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
1728}
1729
1730STATIC void emit_native_end_except_handler(emit_t *emit) {
Damien Georgee6ce10a2014-09-06 18:38:20 +01001731 adjust_stack(emit, -2);
Damien Georgeb601d952014-06-30 05:17:25 +01001732}
1733
Damien13ed3a62013-10-08 09:05:10 +01001734const emit_method_table_t EXPORT_FUN(method_table) = {
Damien George2ac4af62014-08-15 16:45:41 +01001735 emit_native_set_native_type,
Damien13ed3a62013-10-08 09:05:10 +01001736 emit_native_start_pass,
1737 emit_native_end_pass,
1738 emit_native_last_emit_was_return_value,
Damien Georged66ae182014-04-10 17:28:54 +00001739 emit_native_adjust_stack_size,
Damien George08335002014-01-18 23:24:36 +00001740 emit_native_set_source_line,
Damien13ed3a62013-10-08 09:05:10 +01001741
1742 emit_native_load_id,
1743 emit_native_store_id,
1744 emit_native_delete_id,
1745
1746 emit_native_label_assign,
1747 emit_native_import_name,
1748 emit_native_import_from,
1749 emit_native_import_star,
1750 emit_native_load_const_tok,
1751 emit_native_load_const_small_int,
1752 emit_native_load_const_int,
1753 emit_native_load_const_dec,
Damien13ed3a62013-10-08 09:05:10 +01001754 emit_native_load_const_str,
Damien George3558f622014-04-20 17:50:40 +01001755 emit_native_load_null,
Damien13ed3a62013-10-08 09:05:10 +01001756 emit_native_load_fast,
Damien13ed3a62013-10-08 09:05:10 +01001757 emit_native_load_deref,
Damien9ecbcff2013-12-11 00:41:43 +00001758 emit_native_load_name,
1759 emit_native_load_global,
Damien13ed3a62013-10-08 09:05:10 +01001760 emit_native_load_attr,
1761 emit_native_load_method,
1762 emit_native_load_build_class,
Damien George729f7b42014-04-17 22:10:53 +01001763 emit_native_load_subscr,
Damien13ed3a62013-10-08 09:05:10 +01001764 emit_native_store_fast,
Damien9ecbcff2013-12-11 00:41:43 +00001765 emit_native_store_deref,
Damien13ed3a62013-10-08 09:05:10 +01001766 emit_native_store_name,
1767 emit_native_store_global,
Damien13ed3a62013-10-08 09:05:10 +01001768 emit_native_store_attr,
Damien13ed3a62013-10-08 09:05:10 +01001769 emit_native_store_subscr,
Damien13ed3a62013-10-08 09:05:10 +01001770 emit_native_delete_fast,
Damien9ecbcff2013-12-11 00:41:43 +00001771 emit_native_delete_deref,
Damien13ed3a62013-10-08 09:05:10 +01001772 emit_native_delete_name,
1773 emit_native_delete_global,
Damien13ed3a62013-10-08 09:05:10 +01001774 emit_native_delete_attr,
1775 emit_native_delete_subscr,
1776 emit_native_dup_top,
1777 emit_native_dup_top_two,
1778 emit_native_pop_top,
1779 emit_native_rot_two,
1780 emit_native_rot_three,
1781 emit_native_jump,
1782 emit_native_pop_jump_if_true,
1783 emit_native_pop_jump_if_false,
1784 emit_native_jump_if_true_or_pop,
1785 emit_native_jump_if_false_or_pop,
Damien13ed3a62013-10-08 09:05:10 +01001786 emit_native_break_loop,
1787 emit_native_continue_loop,
1788 emit_native_setup_with,
1789 emit_native_with_cleanup,
1790 emit_native_setup_except,
1791 emit_native_setup_finally,
1792 emit_native_end_finally,
1793 emit_native_get_iter,
1794 emit_native_for_iter,
1795 emit_native_for_iter_end,
1796 emit_native_pop_block,
1797 emit_native_pop_except,
1798 emit_native_unary_op,
1799 emit_native_binary_op,
Damien13ed3a62013-10-08 09:05:10 +01001800 emit_native_build_tuple,
1801 emit_native_build_list,
1802 emit_native_list_append,
1803 emit_native_build_map,
1804 emit_native_store_map,
1805 emit_native_map_add,
1806 emit_native_build_set,
1807 emit_native_set_add,
1808 emit_native_build_slice,
1809 emit_native_unpack_sequence,
1810 emit_native_unpack_ex,
1811 emit_native_make_function,
1812 emit_native_make_closure,
1813 emit_native_call_function,
1814 emit_native_call_method,
1815 emit_native_return_value,
1816 emit_native_raise_varargs,
1817 emit_native_yield_value,
1818 emit_native_yield_from,
Damien Georgeb601d952014-06-30 05:17:25 +01001819
1820 emit_native_start_except_handler,
1821 emit_native_end_except_handler,
Damien13ed3a62013-10-08 09:05:10 +01001822};
1823
Damien Georgec90f59e2014-09-06 23:06:36 +01001824#endif