blob: 4966e37e301b4fe6fd37ad347eda6cdecbe59b37 [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 Georgee67ed5d2014-01-04 13:55:24 +000072#if (MICROPY_EMIT_X64 && N_X64) || (MICROPY_EMIT_THUMB && N_THUMB)
Damien13ed3a62013-10-08 09:05:10 +010073
Damien3ef4abb2013-10-12 16:53:13 +010074#if N_X64
Damien13ed3a62013-10-08 09:05:10 +010075
76// x64 specific stuff
77
78#include "asmx64.h"
79
80#define REG_LOCAL_1 (REG_RBX)
81#define REG_LOCAL_NUM (1)
82
83#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)
88#define ASM_MOV_REG_TO_LOCAL(reg, local_num) asm_x64_mov_r64_to_local(emit->as, (reg), (local_num))
89#define ASM_MOV_IMM_TO_REG(imm, reg) asm_x64_mov_i64_to_r64_optimised(emit->as, (imm), (reg))
Damien George36db6bc2014-05-07 17:24:22 +010090#define ASM_MOV_ALIGNED_IMM_TO_REG(imm, reg) asm_x64_mov_i64_to_r64_aligned(emit->as, (imm), (reg))
Damieneb19efb2013-10-10 22:06:54 +010091#define ASM_MOV_IMM_TO_LOCAL_USING(imm, local_num, reg_temp) do { asm_x64_mov_i64_to_r64_optimised(emit->as, (imm), (reg_temp)); asm_x64_mov_r64_to_local(emit->as, (reg_temp), (local_num)); } while (false)
Damien13ed3a62013-10-08 09:05:10 +010092#define ASM_MOV_LOCAL_TO_REG(local_num, reg) asm_x64_mov_local_to_r64(emit->as, (local_num), (reg))
93#define ASM_MOV_REG_TO_REG(reg_src, reg_dest) asm_x64_mov_r64_to_r64(emit->as, (reg_src), (reg_dest))
94#define ASM_MOV_LOCAL_ADDR_TO_REG(local_num, reg) asm_x64_mov_local_addr_to_r64(emit->as, (local_num), (reg))
95
Damien3ef4abb2013-10-12 16:53:13 +010096#elif N_THUMB
Damien13ed3a62013-10-08 09:05:10 +010097
98// thumb specific stuff
99
100#include "asmthumb.h"
101
102#define REG_LOCAL_1 (REG_R4)
103#define REG_LOCAL_2 (REG_R5)
104#define REG_LOCAL_3 (REG_R6)
105#define REG_LOCAL_NUM (3)
106
107#define EXPORT_FUN(name) emit_native_thumb_##name
108
109#define REG_TEMP0 (REG_R0)
110#define REG_TEMP1 (REG_R1)
111#define REG_TEMP2 (REG_R2)
112#define ASM_MOV_REG_TO_LOCAL(reg, local_num) asm_thumb_mov_local_reg(emit->as, (local_num), (reg))
113#define ASM_MOV_IMM_TO_REG(imm, reg) asm_thumb_mov_reg_i32_optimised(emit->as, (reg), (imm))
Damien George36db6bc2014-05-07 17:24:22 +0100114#define ASM_MOV_ALIGNED_IMM_TO_REG(imm, reg) asm_thumb_mov_reg_i32_aligned(emit->as, (reg), (imm))
Damieneb19efb2013-10-10 22:06:54 +0100115#define ASM_MOV_IMM_TO_LOCAL_USING(imm, local_num, reg_temp) do { asm_thumb_mov_reg_i32_optimised(emit->as, (reg_temp), (imm)); asm_thumb_mov_local_reg(emit->as, (local_num), (reg_temp)); } while (false)
Damien13ed3a62013-10-08 09:05:10 +0100116#define ASM_MOV_LOCAL_TO_REG(local_num, reg) asm_thumb_mov_reg_local(emit->as, (reg), (local_num))
117#define ASM_MOV_REG_TO_REG(reg_src, reg_dest) asm_thumb_mov_reg_reg(emit->as, (reg_dest), (reg_src))
118#define ASM_MOV_LOCAL_ADDR_TO_REG(local_num, reg) asm_thumb_mov_reg_local_addr(emit->as, (reg), (local_num))
119
120#endif
121
122typedef enum {
Damienff8ed772013-10-08 22:18:32 +0100123 STACK_VALUE,
124 STACK_REG,
125 STACK_IMM,
126} stack_info_kind_t;
Damien13ed3a62013-10-08 09:05:10 +0100127
128typedef enum {
Damien George2ac4af62014-08-15 16:45:41 +0100129 VTYPE_PYOBJ = MP_NATIVE_TYPE_OBJ,
130 VTYPE_BOOL = MP_NATIVE_TYPE_BOOL,
131 VTYPE_INT = MP_NATIVE_TYPE_INT,
132 VTYPE_UINT = MP_NATIVE_TYPE_UINT,
Damien13ed3a62013-10-08 09:05:10 +0100133 VTYPE_UNBOUND,
Damien13ed3a62013-10-08 09:05:10 +0100134 VTYPE_PTR,
135 VTYPE_PTR_NONE,
136 VTYPE_BUILTIN_V_INT,
137} vtype_kind_t;
138
Damienff8ed772013-10-08 22:18:32 +0100139typedef struct _stack_info_t {
140 vtype_kind_t vtype;
141 stack_info_kind_t kind;
142 union {
143 int u_reg;
Damien George40f3c022014-07-03 13:25:24 +0100144 mp_int_t u_imm;
Damienff8ed772013-10-08 22:18:32 +0100145 };
146} stack_info_t;
147
Damien13ed3a62013-10-08 09:05:10 +0100148struct _emit_t {
149 int pass;
150
151 bool do_viper_types;
Damienff8ed772013-10-08 22:18:32 +0100152
Damien George2ac4af62014-08-15 16:45:41 +0100153 vtype_kind_t return_vtype;
154
Damien George36db6bc2014-05-07 17:24:22 +0100155 uint local_vtype_alloc;
Damien13ed3a62013-10-08 09:05:10 +0100156 vtype_kind_t *local_vtype;
Damienff8ed772013-10-08 22:18:32 +0100157
Damien George36db6bc2014-05-07 17:24:22 +0100158 uint stack_info_alloc;
Damienff8ed772013-10-08 22:18:32 +0100159 stack_info_t *stack_info;
160
Damien13ed3a62013-10-08 09:05:10 +0100161 int stack_start;
162 int stack_size;
163
164 bool last_emit_was_return_value;
165
Damien13ed3a62013-10-08 09:05:10 +0100166 scope_t *scope;
167
Damien3ef4abb2013-10-12 16:53:13 +0100168#if N_X64
Damien13ed3a62013-10-08 09:05:10 +0100169 asm_x64_t *as;
Damien3ef4abb2013-10-12 16:53:13 +0100170#elif N_THUMB
Damien13ed3a62013-10-08 09:05:10 +0100171 asm_thumb_t *as;
172#endif
173};
174
175emit_t *EXPORT_FUN(new)(uint max_num_labels) {
Damien George36db6bc2014-05-07 17:24:22 +0100176 emit_t *emit = m_new0(emit_t, 1);
Damien3ef4abb2013-10-12 16:53:13 +0100177#if N_X64
Damien13ed3a62013-10-08 09:05:10 +0100178 emit->as = asm_x64_new(max_num_labels);
Damien3ef4abb2013-10-12 16:53:13 +0100179#elif N_THUMB
Damien13ed3a62013-10-08 09:05:10 +0100180 emit->as = asm_thumb_new(max_num_labels);
181#endif
182 return emit;
183}
184
Damien George41d02b62014-01-24 22:42:28 +0000185void EXPORT_FUN(free)(emit_t *emit) {
Paul Sokolovskyf46d87a2014-01-24 16:20:11 +0200186#if N_X64
187 asm_x64_free(emit->as, false);
188#elif N_THUMB
189 asm_thumb_free(emit->as, false);
190#endif
Damien George36db6bc2014-05-07 17:24:22 +0100191 m_del(vtype_kind_t, emit->local_vtype, emit->local_vtype_alloc);
192 m_del(stack_info_t, emit->stack_info, emit->stack_info_alloc);
Paul Sokolovskyf46d87a2014-01-24 16:20:11 +0200193 m_del_obj(emit_t, emit);
194}
195
Damien George2ac4af62014-08-15 16:45:41 +0100196STATIC void emit_native_set_native_type(emit_t *emit, mp_uint_t op, mp_uint_t arg1, qstr arg2) {
197 switch (op) {
198 case MP_EMIT_NATIVE_TYPE_ENABLE:
199 emit->do_viper_types = arg1;
200 break;
201
202 default: {
203 vtype_kind_t type;
204 switch (arg2) {
205 case MP_QSTR_object: type = VTYPE_PYOBJ; break;
206 case MP_QSTR_bool: type = VTYPE_BOOL; break;
207 case MP_QSTR_int: type = VTYPE_INT; break;
208 case MP_QSTR_uint: type = VTYPE_UINT; break;
209 default: printf("ViperTypeError: unknown type %s\n", qstr_str(arg2)); return;
210 }
211 if (op == MP_EMIT_NATIVE_TYPE_RETURN) {
212 emit->return_vtype = type;
213 } else {
214 assert(arg1 < emit->local_vtype_alloc);
215 emit->local_vtype[arg1] = type;
216 }
217 break;
218 }
219 }
Damien13ed3a62013-10-08 09:05:10 +0100220}
221
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200222STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
Damien13ed3a62013-10-08 09:05:10 +0100223 emit->pass = pass;
224 emit->stack_start = 0;
225 emit->stack_size = 0;
226 emit->last_emit_was_return_value = false;
Damien13ed3a62013-10-08 09:05:10 +0100227 emit->scope = scope;
228
Damien George36db6bc2014-05-07 17:24:22 +0100229 // allocate memory for keeping track of the types of locals
230 if (emit->local_vtype_alloc < scope->num_locals) {
231 emit->local_vtype = m_renew(vtype_kind_t, emit->local_vtype, emit->local_vtype_alloc, scope->num_locals);
232 emit->local_vtype_alloc = scope->num_locals;
Damienff8ed772013-10-08 22:18:32 +0100233 }
Damien George36db6bc2014-05-07 17:24:22 +0100234
235 // allocate memory for keeping track of the objects on the stack
236 // XXX don't know stack size on entry, and it should be maximum over all scopes
Damienff8ed772013-10-08 22:18:32 +0100237 if (emit->stack_info == NULL) {
Damien George36db6bc2014-05-07 17:24:22 +0100238 emit->stack_info_alloc = scope->stack_size + 50;
Damienff8ed772013-10-08 22:18:32 +0100239 emit->stack_info = m_new(stack_info_t, emit->stack_info_alloc);
Damien13ed3a62013-10-08 09:05:10 +0100240 }
241
Damien George2ac4af62014-08-15 16:45:41 +0100242 // set default type for return and arguments
243 emit->return_vtype = VTYPE_PYOBJ;
Damien Georgea5190a72014-08-15 22:39:08 +0100244 for (mp_uint_t i = 0; i < emit->scope->num_pos_args; i++) {
Damien George2ac4af62014-08-15 16:45:41 +0100245 emit->local_vtype[i] = VTYPE_PYOBJ;
246 }
Damien Georgea5190a72014-08-15 22:39:08 +0100247
248 // local variables begin unbound, and have unknown type
249 for (mp_uint_t i = emit->scope->num_pos_args; i < emit->local_vtype_alloc; i++) {
250 emit->local_vtype[i] = VTYPE_UNBOUND;
251 }
252
253 // values on stack begin unbound
254 for (mp_uint_t i = 0; i < emit->stack_info_alloc; i++) {
Damien George2ac4af62014-08-15 16:45:41 +0100255 emit->stack_info[i].kind = STACK_VALUE;
Damien Georgea5190a72014-08-15 22:39:08 +0100256 emit->stack_info[i].vtype = VTYPE_UNBOUND;
Damien13ed3a62013-10-08 09:05:10 +0100257 }
258
Damien3ef4abb2013-10-12 16:53:13 +0100259#if N_X64
Damien George36db6bc2014-05-07 17:24:22 +0100260 asm_x64_start_pass(emit->as, pass == MP_PASS_EMIT ? ASM_X64_PASS_EMIT : ASM_X64_PASS_COMPUTE);
Damien3ef4abb2013-10-12 16:53:13 +0100261#elif N_THUMB
Damien George36db6bc2014-05-07 17:24:22 +0100262 asm_thumb_start_pass(emit->as, pass == MP_PASS_EMIT ? ASM_THUMB_PASS_EMIT : ASM_THUMB_PASS_COMPUTE);
Damien13ed3a62013-10-08 09:05:10 +0100263#endif
264
265 // entry to function
266 int num_locals = 0;
Damien George36db6bc2014-05-07 17:24:22 +0100267 if (pass > MP_PASS_SCOPE) {
Damien13ed3a62013-10-08 09:05:10 +0100268 num_locals = scope->num_locals - REG_LOCAL_NUM;
269 if (num_locals < 0) {
270 num_locals = 0;
271 }
272 emit->stack_start = num_locals;
273 num_locals += scope->stack_size;
274 }
Damien3ef4abb2013-10-12 16:53:13 +0100275#if N_X64
Damien13ed3a62013-10-08 09:05:10 +0100276 asm_x64_entry(emit->as, num_locals);
Damien3ef4abb2013-10-12 16:53:13 +0100277#elif N_THUMB
Damien13ed3a62013-10-08 09:05:10 +0100278 asm_thumb_entry(emit->as, num_locals);
279#endif
280
281 // initialise locals from parameters
Damien3ef4abb2013-10-12 16:53:13 +0100282#if N_X64
Damien George2827d622014-04-27 15:50:52 +0100283 for (int i = 0; i < scope->num_pos_args; i++) {
Damien13ed3a62013-10-08 09:05:10 +0100284 if (i == 0) {
285 asm_x64_mov_r64_to_r64(emit->as, REG_ARG_1, REG_LOCAL_1);
286 } else if (i == 1) {
Damien Georged509ac22014-05-07 23:27:45 +0100287 asm_x64_mov_r64_to_local(emit->as, REG_ARG_2, i - REG_LOCAL_NUM);
Damien13ed3a62013-10-08 09:05:10 +0100288 } else if (i == 2) {
Damien Georged509ac22014-05-07 23:27:45 +0100289 asm_x64_mov_r64_to_local(emit->as, REG_ARG_3, i - REG_LOCAL_NUM);
Damien13ed3a62013-10-08 09:05:10 +0100290 } else {
291 // TODO not implemented
292 assert(0);
293 }
294 }
Damien3ef4abb2013-10-12 16:53:13 +0100295#elif N_THUMB
Damien George2827d622014-04-27 15:50:52 +0100296 for (int i = 0; i < scope->num_pos_args; i++) {
Damien13ed3a62013-10-08 09:05:10 +0100297 if (i == 0) {
298 asm_thumb_mov_reg_reg(emit->as, REG_LOCAL_1, REG_ARG_1);
299 } else if (i == 1) {
300 asm_thumb_mov_reg_reg(emit->as, REG_LOCAL_2, REG_ARG_2);
301 } else if (i == 2) {
302 asm_thumb_mov_reg_reg(emit->as, REG_LOCAL_3, REG_ARG_3);
303 } else if (i == 3) {
304 asm_thumb_mov_local_reg(emit->as, i - REG_LOCAL_NUM, REG_ARG_4);
305 } else {
306 // TODO not implemented
307 assert(0);
308 }
309 }
310
Damien George40f3c022014-07-03 13:25:24 +0100311 asm_thumb_mov_reg_i32(emit->as, REG_R7, (mp_uint_t)mp_fun_table);
Damien13ed3a62013-10-08 09:05:10 +0100312#endif
313}
314
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200315STATIC void emit_native_end_pass(emit_t *emit) {
Damien3ef4abb2013-10-12 16:53:13 +0100316#if N_X64
Damien13ed3a62013-10-08 09:05:10 +0100317 if (!emit->last_emit_was_return_value) {
318 asm_x64_exit(emit->as);
319 }
320 asm_x64_end_pass(emit->as);
Damien3ef4abb2013-10-12 16:53:13 +0100321#elif N_THUMB
Damien13ed3a62013-10-08 09:05:10 +0100322 if (!emit->last_emit_was_return_value) {
323 asm_thumb_exit(emit->as);
324 }
325 asm_thumb_end_pass(emit->as);
326#endif
327
328 // check stack is back to zero size
329 if (emit->stack_size != 0) {
330 printf("ERROR: stack size not back to zero; got %d\n", emit->stack_size);
331 }
332
Damien George36db6bc2014-05-07 17:24:22 +0100333 if (emit->pass == MP_PASS_EMIT) {
Damien3ef4abb2013-10-12 16:53:13 +0100334#if N_X64
Damiend99b0522013-12-21 18:17:45 +0000335 void *f = asm_x64_get_code(emit->as);
Damien George2ac4af62014-08-15 16:45:41 +0100336 mp_uint_t f_len = asm_x64_get_code_size(emit->as);
Damien3ef4abb2013-10-12 16:53:13 +0100337#elif N_THUMB
Damiend99b0522013-12-21 18:17:45 +0000338 void *f = asm_thumb_get_code(emit->as);
Damien George2ac4af62014-08-15 16:45:41 +0100339 mp_uint_t f_len = asm_thumb_get_code_size(emit->as);
Damien13ed3a62013-10-08 09:05:10 +0100340#endif
Damien George2ac4af62014-08-15 16:45:41 +0100341
342 // compute type signature
343 // TODO check that viper types here convert correctly to valid types for emit glue
344 mp_uint_t type_sig = emit->return_vtype & 3;
345 for (mp_uint_t i = 0; i < emit->scope->num_pos_args; i++) {
346 type_sig |= (emit->local_vtype[i] & 3) << (i * 2 + 2);
347 }
348
349 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 +0100350 }
351}
352
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200353STATIC bool emit_native_last_emit_was_return_value(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +0100354 return emit->last_emit_was_return_value;
355}
356
Damien Georged66ae182014-04-10 17:28:54 +0000357STATIC void emit_native_adjust_stack_size(emit_t *emit, int delta) {
358 emit->stack_size += delta;
Damien13ed3a62013-10-08 09:05:10 +0100359}
360
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200361STATIC void emit_native_set_source_line(emit_t *emit, int source_line) {
Damien George08335002014-01-18 23:24:36 +0000362}
363
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200364STATIC void adjust_stack(emit_t *emit, int stack_size_delta) {
Damien Georgecdd96df2014-04-06 12:58:40 +0100365 DEBUG_printf("adjust stack: stack:%d + delta:%d\n", emit->stack_size, stack_size_delta);
Damien George78035b92014-04-09 12:27:39 +0100366 assert((int)emit->stack_size + stack_size_delta >= 0);
Damien13ed3a62013-10-08 09:05:10 +0100367 emit->stack_size += stack_size_delta;
Damien George36db6bc2014-05-07 17:24:22 +0100368 if (emit->pass > MP_PASS_SCOPE && emit->stack_size > emit->scope->stack_size) {
Damien13ed3a62013-10-08 09:05:10 +0100369 emit->scope->stack_size = emit->stack_size;
370 }
371}
372
Damienff8ed772013-10-08 22:18:32 +0100373/*
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200374STATIC void emit_pre_raw(emit_t *emit, int stack_size_delta) {
Damien13ed3a62013-10-08 09:05:10 +0100375 adjust_stack(emit, stack_size_delta);
376 emit->last_emit_was_return_value = false;
377}
Damienff8ed772013-10-08 22:18:32 +0100378*/
Damien13ed3a62013-10-08 09:05:10 +0100379
Damienff8ed772013-10-08 22:18:32 +0100380// this must be called at start of emit functions
Damien Georgece8f07a2014-03-27 23:30:26 +0000381STATIC void emit_native_pre(emit_t *emit) {
Damienff8ed772013-10-08 22:18:32 +0100382 emit->last_emit_was_return_value = false;
383 // settle the stack
384 /*
385 if (regs_needed != 0) {
386 for (int i = 0; i < emit->stack_size; i++) {
387 switch (emit->stack_info[i].kind) {
388 case STACK_VALUE:
389 break;
390
391 case STACK_REG:
392 // TODO only push reg if in regs_needed
393 emit->stack_info[i].kind = STACK_VALUE;
394 ASM_MOV_REG_TO_LOCAL(emit->stack_info[i].u_reg, emit->stack_start + i);
395 break;
396
397 case STACK_IMM:
398 // don't think we ever need to push imms for settling
399 //ASM_MOV_IMM_TO_LOCAL(emit->last_imm, emit->stack_start + i);
400 break;
401 }
402 }
403 }
404 */
Damien13ed3a62013-10-08 09:05:10 +0100405}
406
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200407STATIC vtype_kind_t peek_vtype(emit_t *emit) {
Damienff8ed772013-10-08 22:18:32 +0100408 return emit->stack_info[emit->stack_size - 1].vtype;
409}
Damien13ed3a62013-10-08 09:05:10 +0100410
Damiend2755ec2013-10-16 23:58:48 +0100411// pos=1 is TOS, pos=2 is next, etc
412// use pos=0 for no skipping
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200413STATIC void need_reg_single(emit_t *emit, int reg_needed, int skip_stack_pos) {
Damiend2755ec2013-10-16 23:58:48 +0100414 skip_stack_pos = emit->stack_size - skip_stack_pos;
Damienff8ed772013-10-08 22:18:32 +0100415 for (int i = 0; i < emit->stack_size; i++) {
Damiend2755ec2013-10-16 23:58:48 +0100416 if (i != skip_stack_pos) {
417 stack_info_t *si = &emit->stack_info[i];
418 if (si->kind == STACK_REG && si->u_reg == reg_needed) {
419 si->kind = STACK_VALUE;
420 ASM_MOV_REG_TO_LOCAL(si->u_reg, emit->stack_start + i);
421 }
Damienff8ed772013-10-08 22:18:32 +0100422 }
423 }
424}
Damien13ed3a62013-10-08 09:05:10 +0100425
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200426STATIC void need_reg_all(emit_t *emit) {
Damienff8ed772013-10-08 22:18:32 +0100427 for (int i = 0; i < emit->stack_size; i++) {
428 stack_info_t *si = &emit->stack_info[i];
429 if (si->kind == STACK_REG) {
430 si->kind = STACK_VALUE;
431 ASM_MOV_REG_TO_LOCAL(si->u_reg, emit->stack_start + i);
432 }
Damien13ed3a62013-10-08 09:05:10 +0100433 }
434}
435
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200436STATIC void need_stack_settled(emit_t *emit) {
Damiend2755ec2013-10-16 23:58:48 +0100437 for (int i = 0; i < emit->stack_size; i++) {
438 stack_info_t *si = &emit->stack_info[i];
439 if (si->kind == STACK_REG) {
440 si->kind = STACK_VALUE;
441 ASM_MOV_REG_TO_LOCAL(si->u_reg, emit->stack_start + i);
442 }
443 }
444 for (int i = 0; i < emit->stack_size; i++) {
445 stack_info_t *si = &emit->stack_info[i];
446 if (si->kind == STACK_IMM) {
447 ASM_MOV_IMM_TO_LOCAL_USING(si->u_imm, emit->stack_start + i, REG_TEMP0);
448 }
449 }
450}
451
452// pos=1 is TOS, pos=2 is next, etc
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200453STATIC void emit_access_stack(emit_t *emit, int pos, vtype_kind_t *vtype, int reg_dest) {
Damiend2755ec2013-10-16 23:58:48 +0100454 need_reg_single(emit, reg_dest, pos);
455 stack_info_t *si = &emit->stack_info[emit->stack_size - pos];
Damienff8ed772013-10-08 22:18:32 +0100456 *vtype = si->vtype;
457 switch (si->kind) {
458 case STACK_VALUE:
Damiend2755ec2013-10-16 23:58:48 +0100459 ASM_MOV_LOCAL_TO_REG(emit->stack_start + emit->stack_size - pos, reg_dest);
Damien13ed3a62013-10-08 09:05:10 +0100460 break;
461
Damienff8ed772013-10-08 22:18:32 +0100462 case STACK_REG:
463 if (si->u_reg != reg_dest) {
464 ASM_MOV_REG_TO_REG(si->u_reg, reg_dest);
Damien13ed3a62013-10-08 09:05:10 +0100465 }
466 break;
467
Damienff8ed772013-10-08 22:18:32 +0100468 case STACK_IMM:
469 ASM_MOV_IMM_TO_REG(si->u_imm, reg_dest);
Damien13ed3a62013-10-08 09:05:10 +0100470 break;
471 }
Damien13ed3a62013-10-08 09:05:10 +0100472}
473
Damien Georgeccc85ea2014-05-10 13:40:46 +0100474STATIC void emit_pre_pop_discard(emit_t *emit, vtype_kind_t *vtype) {
475 emit->last_emit_was_return_value = false;
476 adjust_stack(emit, -1);
477}
478
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200479STATIC void emit_pre_pop_reg(emit_t *emit, vtype_kind_t *vtype, int reg_dest) {
Damiend2755ec2013-10-16 23:58:48 +0100480 emit->last_emit_was_return_value = false;
481 emit_access_stack(emit, 1, vtype, reg_dest);
482 adjust_stack(emit, -1);
483}
484
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200485STATIC 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 +0100486 emit_pre_pop_reg(emit, vtypea, rega);
Damienff8ed772013-10-08 22:18:32 +0100487 emit_pre_pop_reg(emit, vtypeb, regb);
Damien13ed3a62013-10-08 09:05:10 +0100488}
489
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200490STATIC 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 +0100491 emit_pre_pop_reg(emit, vtypea, rega);
Damienff8ed772013-10-08 22:18:32 +0100492 emit_pre_pop_reg(emit, vtypeb, regb);
493 emit_pre_pop_reg(emit, vtypec, regc);
Damien13ed3a62013-10-08 09:05:10 +0100494}
495
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200496STATIC void emit_post(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +0100497}
498
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200499STATIC void emit_post_push_reg(emit_t *emit, vtype_kind_t vtype, int reg) {
Damienff8ed772013-10-08 22:18:32 +0100500 stack_info_t *si = &emit->stack_info[emit->stack_size];
501 si->vtype = vtype;
502 si->kind = STACK_REG;
503 si->u_reg = reg;
Damien13ed3a62013-10-08 09:05:10 +0100504 adjust_stack(emit, 1);
505}
506
Damien George40f3c022014-07-03 13:25:24 +0100507STATIC void emit_post_push_imm(emit_t *emit, vtype_kind_t vtype, mp_int_t imm) {
Damienff8ed772013-10-08 22:18:32 +0100508 stack_info_t *si = &emit->stack_info[emit->stack_size];
509 si->vtype = vtype;
510 si->kind = STACK_IMM;
511 si->u_imm = imm;
512 adjust_stack(emit, 1);
513}
514
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200515STATIC 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 +0100516 emit_post_push_reg(emit, vtypea, rega);
517 emit_post_push_reg(emit, vtypeb, regb);
518}
519
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200520STATIC 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 +0100521 emit_post_push_reg(emit, vtypea, rega);
522 emit_post_push_reg(emit, vtypeb, regb);
523 emit_post_push_reg(emit, vtypec, regc);
Damien13ed3a62013-10-08 09:05:10 +0100524}
525
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200526STATIC 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 +0100527 emit_post_push_reg(emit, vtypea, rega);
528 emit_post_push_reg(emit, vtypeb, regb);
529 emit_post_push_reg(emit, vtypec, regc);
530 emit_post_push_reg(emit, vtyped, regd);
Damien13ed3a62013-10-08 09:05:10 +0100531}
532
533// vtype of all n_pop objects is VTYPE_PYOBJ
Damieneb19efb2013-10-10 22:06:54 +0100534// does not use any temporary registers (but may use reg_dest before loading it with stack pointer)
Damien6d4f3462013-11-16 20:44:39 +0000535// TODO this needs some thinking for viper code
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200536STATIC void emit_get_stack_pointer_to_reg_for_pop(emit_t *emit, int reg_dest, int n_pop) {
Damieneb19efb2013-10-10 22:06:54 +0100537 need_reg_all(emit);
Damienff8ed772013-10-08 22:18:32 +0100538 for (int i = 0; i < n_pop; i++) {
Damieneb19efb2013-10-10 22:06:54 +0100539 stack_info_t *si = &emit->stack_info[emit->stack_size - 1 - i];
540 // must push any imm's to stack
Damien6d4f3462013-11-16 20:44:39 +0000541 // must convert them to VTYPE_PYOBJ for viper code
Damieneb19efb2013-10-10 22:06:54 +0100542 if (si->kind == STACK_IMM) {
543 si->kind = STACK_VALUE;
Damien6d4f3462013-11-16 20:44:39 +0000544 switch (si->vtype) {
545 case VTYPE_PYOBJ:
546 ASM_MOV_IMM_TO_LOCAL_USING(si->u_imm, emit->stack_start + emit->stack_size - 1 - i, reg_dest);
547 break;
548 case VTYPE_BOOL:
549 si->vtype = VTYPE_PYOBJ;
550 if (si->u_imm == 0) {
Damien George40f3c022014-07-03 13:25:24 +0100551 ASM_MOV_IMM_TO_LOCAL_USING((mp_uint_t)mp_const_false, emit->stack_start + emit->stack_size - 1 - i, reg_dest);
Damien6d4f3462013-11-16 20:44:39 +0000552 } else {
Damien George40f3c022014-07-03 13:25:24 +0100553 ASM_MOV_IMM_TO_LOCAL_USING((mp_uint_t)mp_const_true, emit->stack_start + emit->stack_size - 1 - i, reg_dest);
Damien6d4f3462013-11-16 20:44:39 +0000554 }
555 break;
556 case VTYPE_INT:
557 si->vtype = VTYPE_PYOBJ;
558 ASM_MOV_IMM_TO_LOCAL_USING((si->u_imm << 1) | 1, emit->stack_start + emit->stack_size - 1 - i, reg_dest);
559 break;
560 default:
561 // not handled
562 assert(0);
563 }
Damieneb19efb2013-10-10 22:06:54 +0100564 }
565 assert(si->kind == STACK_VALUE);
566 assert(si->vtype == VTYPE_PYOBJ);
Damienff8ed772013-10-08 22:18:32 +0100567 }
Damien13ed3a62013-10-08 09:05:10 +0100568 adjust_stack(emit, -n_pop);
Damien Georgecd82e022014-02-02 13:11:48 +0000569 ASM_MOV_LOCAL_ADDR_TO_REG(emit->stack_start + emit->stack_size, reg_dest);
Damien13ed3a62013-10-08 09:05:10 +0100570}
571
572// vtype of all n_push objects is VTYPE_PYOBJ
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200573STATIC void emit_get_stack_pointer_to_reg_for_push(emit_t *emit, int reg_dest, int n_push) {
Damieneb19efb2013-10-10 22:06:54 +0100574 need_reg_all(emit);
Damien13ed3a62013-10-08 09:05:10 +0100575 for (int i = 0; i < n_push; i++) {
Damien7f5dacf2013-10-10 11:24:39 +0100576 emit->stack_info[emit->stack_size + i].kind = STACK_VALUE;
Damienff8ed772013-10-08 22:18:32 +0100577 emit->stack_info[emit->stack_size + i].vtype = VTYPE_PYOBJ;
Damien13ed3a62013-10-08 09:05:10 +0100578 }
Damien Georgecd82e022014-02-02 13:11:48 +0000579 ASM_MOV_LOCAL_ADDR_TO_REG(emit->stack_start + emit->stack_size, reg_dest);
Damien13ed3a62013-10-08 09:05:10 +0100580 adjust_stack(emit, n_push);
581}
582
Damien Georged17926d2014-03-30 13:35:08 +0100583STATIC void emit_call(emit_t *emit, mp_fun_kind_t fun_kind, void *fun) {
Damiend2755ec2013-10-16 23:58:48 +0100584 need_reg_all(emit);
Damien3ef4abb2013-10-12 16:53:13 +0100585#if N_X64
Damien13ed3a62013-10-08 09:05:10 +0100586 asm_x64_call_ind(emit->as, fun, REG_RAX);
Damien3ef4abb2013-10-12 16:53:13 +0100587#elif N_THUMB
Damien Georged17926d2014-03-30 13:35:08 +0100588 asm_thumb_bl_ind(emit->as, mp_fun_table[fun_kind], fun_kind, REG_R3);
Damien13ed3a62013-10-08 09:05:10 +0100589#endif
590}
591
Damien George40f3c022014-07-03 13:25:24 +0100592STATIC void emit_call_with_imm_arg(emit_t *emit, mp_fun_kind_t fun_kind, void *fun, mp_int_t arg_val, int arg_reg) {
Damieneb19efb2013-10-10 22:06:54 +0100593 need_reg_all(emit);
Damien13ed3a62013-10-08 09:05:10 +0100594 ASM_MOV_IMM_TO_REG(arg_val, arg_reg);
Damiend2755ec2013-10-16 23:58:48 +0100595#if N_X64
596 asm_x64_call_ind(emit->as, fun, REG_RAX);
597#elif N_THUMB
Damien Georged17926d2014-03-30 13:35:08 +0100598 asm_thumb_bl_ind(emit->as, mp_fun_table[fun_kind], fun_kind, REG_R3);
Damiend2755ec2013-10-16 23:58:48 +0100599#endif
Damien13ed3a62013-10-08 09:05:10 +0100600}
601
Damien George40f3c022014-07-03 13:25:24 +0100602// the first arg is stored in the code aligned on a mp_uint_t boundary
603STATIC void emit_call_with_imm_arg_aligned(emit_t *emit, mp_fun_kind_t fun_kind, void *fun, mp_int_t arg_val, int arg_reg) {
Damien Georgea32c1e42014-05-07 18:30:52 +0100604 need_reg_all(emit);
605 ASM_MOV_ALIGNED_IMM_TO_REG(arg_val, arg_reg);
606#if N_X64
607 asm_x64_call_ind(emit->as, fun, REG_RAX);
608#elif N_THUMB
609 asm_thumb_bl_ind(emit->as, mp_fun_table[fun_kind], fun_kind, REG_R3);
610#endif
611}
612
Damien George40f3c022014-07-03 13:25:24 +0100613STATIC void emit_call_with_2_imm_args(emit_t *emit, mp_fun_kind_t fun_kind, void *fun, mp_int_t arg_val1, int arg_reg1, mp_int_t arg_val2, int arg_reg2) {
Damien Georgecd82e022014-02-02 13:11:48 +0000614 need_reg_all(emit);
615 ASM_MOV_IMM_TO_REG(arg_val1, arg_reg1);
616 ASM_MOV_IMM_TO_REG(arg_val2, arg_reg2);
617#if N_X64
618 asm_x64_call_ind(emit->as, fun, REG_RAX);
619#elif N_THUMB
Damien Georged17926d2014-03-30 13:35:08 +0100620 asm_thumb_bl_ind(emit->as, mp_fun_table[fun_kind], fun_kind, REG_R3);
Damien Georgecd82e022014-02-02 13:11:48 +0000621#endif
622}
623
Damien George40f3c022014-07-03 13:25:24 +0100624// the first arg is stored in the code aligned on a mp_uint_t boundary
625STATIC void emit_call_with_3_imm_args_and_first_aligned(emit_t *emit, mp_fun_kind_t fun_kind, void *fun, 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 +0100626 need_reg_all(emit);
Damien George36db6bc2014-05-07 17:24:22 +0100627 ASM_MOV_ALIGNED_IMM_TO_REG(arg_val1, arg_reg1);
Damien Georgecdd96df2014-04-06 12:58:40 +0100628 ASM_MOV_IMM_TO_REG(arg_val2, arg_reg2);
629 ASM_MOV_IMM_TO_REG(arg_val3, arg_reg3);
630#if N_X64
631 asm_x64_call_ind(emit->as, fun, REG_RAX);
632#elif N_THUMB
633 asm_thumb_bl_ind(emit->as, mp_fun_table[fun_kind], fun_kind, REG_R3);
634#endif
635}
636
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200637STATIC void emit_native_load_id(emit_t *emit, qstr qstr) {
Damien13ed3a62013-10-08 09:05:10 +0100638 // check for built-ins
639 if (strcmp(qstr_str(qstr), "v_int") == 0) {
Damienff8ed772013-10-08 22:18:32 +0100640 assert(0);
Damien Georgece8f07a2014-03-27 23:30:26 +0000641 emit_native_pre(emit);
Damien13ed3a62013-10-08 09:05:10 +0100642 //emit_post_push_blank(emit, VTYPE_BUILTIN_V_INT);
643
644 // not a built-in, so do usual thing
645 } else {
646 emit_common_load_id(emit, &EXPORT_FUN(method_table), emit->scope, qstr);
647 }
648}
649
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200650STATIC void emit_native_store_id(emit_t *emit, qstr qstr) {
Damien13ed3a62013-10-08 09:05:10 +0100651 // TODO check for built-ins and disallow
652 emit_common_store_id(emit, &EXPORT_FUN(method_table), emit->scope, qstr);
653}
654
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200655STATIC void emit_native_delete_id(emit_t *emit, qstr qstr) {
Damien13ed3a62013-10-08 09:05:10 +0100656 // TODO check for built-ins and disallow
657 emit_common_delete_id(emit, &EXPORT_FUN(method_table), emit->scope, qstr);
658}
659
Damien George6f355fd2014-04-10 14:11:31 +0100660STATIC void emit_native_label_assign(emit_t *emit, uint l) {
Damien Georgece8f07a2014-03-27 23:30:26 +0000661 emit_native_pre(emit);
Damiend2755ec2013-10-16 23:58:48 +0100662 // need to commit stack because we can jump here from elsewhere
663 need_stack_settled(emit);
Damien3ef4abb2013-10-12 16:53:13 +0100664#if N_X64
Damien13ed3a62013-10-08 09:05:10 +0100665 asm_x64_label_assign(emit->as, l);
Damien3ef4abb2013-10-12 16:53:13 +0100666#elif N_THUMB
Damien13ed3a62013-10-08 09:05:10 +0100667 asm_thumb_label_assign(emit->as, l);
668#endif
Damien6ba13142013-11-02 20:34:54 +0000669 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +0100670}
671
Damien Georgecdd96df2014-04-06 12:58:40 +0100672STATIC void emit_native_import_name(emit_t *emit, qstr qst) {
673 DEBUG_printf("import_name %s\n", qstr_str(qst));
674 vtype_kind_t vtype_fromlist;
675 vtype_kind_t vtype_level;
676 emit_pre_pop_reg_reg(emit, &vtype_fromlist, REG_ARG_2, &vtype_level, REG_ARG_3); // arg2 = fromlist, arg3 = level
677 assert(vtype_fromlist == VTYPE_PYOBJ);
678 assert(vtype_level == VTYPE_PYOBJ);
679 emit_call_with_imm_arg(emit, MP_F_IMPORT_NAME, mp_import_name, qst, REG_ARG_1); // arg1 = import name
680 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
Damien13ed3a62013-10-08 09:05:10 +0100681}
682
Damien Georgecdd96df2014-04-06 12:58:40 +0100683STATIC void emit_native_import_from(emit_t *emit, qstr qst) {
684 DEBUG_printf("import_from %s\n", qstr_str(qst));
685 emit_native_pre(emit);
686 vtype_kind_t vtype_module;
687 emit_access_stack(emit, 1, &vtype_module, REG_ARG_1); // arg1 = module
688 assert(vtype_module == VTYPE_PYOBJ);
689 emit_call_with_imm_arg(emit, MP_F_IMPORT_FROM, mp_import_from, qst, REG_ARG_2); // arg2 = import name
690 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
Damien13ed3a62013-10-08 09:05:10 +0100691}
692
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200693STATIC void emit_native_import_star(emit_t *emit) {
Damien Georgecdd96df2014-04-06 12:58:40 +0100694 DEBUG_printf("import_star\n");
695 vtype_kind_t vtype_module;
696 emit_pre_pop_reg(emit, &vtype_module, REG_ARG_1); // arg1 = module
697 assert(vtype_module == VTYPE_PYOBJ);
698 emit_call(emit, MP_F_IMPORT_ALL, mp_import_all);
699 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +0100700}
701
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200702STATIC void emit_native_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
Damien Georgecdd96df2014-04-06 12:58:40 +0100703 DEBUG_printf("load_const_tok %d\n", tok);
Damien Georgece8f07a2014-03-27 23:30:26 +0000704 emit_native_pre(emit);
Damien13ed3a62013-10-08 09:05:10 +0100705 int vtype;
Damien George40f3c022014-07-03 13:25:24 +0100706 mp_uint_t val;
Damien13ed3a62013-10-08 09:05:10 +0100707 if (emit->do_viper_types) {
708 switch (tok) {
Damiend99b0522013-12-21 18:17:45 +0000709 case MP_TOKEN_KW_NONE: vtype = VTYPE_PTR_NONE; val = 0; break;
710 case MP_TOKEN_KW_FALSE: vtype = VTYPE_BOOL; val = 0; break;
711 case MP_TOKEN_KW_TRUE: vtype = VTYPE_BOOL; val = 1; break;
Damien13ed3a62013-10-08 09:05:10 +0100712 default: assert(0); vtype = 0; val = 0; // shouldn't happen
713 }
714 } else {
715 vtype = VTYPE_PYOBJ;
716 switch (tok) {
Damien George40f3c022014-07-03 13:25:24 +0100717 case MP_TOKEN_KW_NONE: val = (mp_uint_t)mp_const_none; break;
718 case MP_TOKEN_KW_FALSE: val = (mp_uint_t)mp_const_false; break;
719 case MP_TOKEN_KW_TRUE: val = (mp_uint_t)mp_const_true; break;
Damien13ed3a62013-10-08 09:05:10 +0100720 default: assert(0); vtype = 0; val = 0; // shouldn't happen
721 }
722 }
723 emit_post_push_imm(emit, vtype, val);
724}
725
Damien George40f3c022014-07-03 13:25:24 +0100726STATIC void emit_native_load_const_small_int(emit_t *emit, mp_int_t arg) {
Damien Georgecdd96df2014-04-06 12:58:40 +0100727 DEBUG_printf("load_const_small_int %d\n", arg);
Damien Georgece8f07a2014-03-27 23:30:26 +0000728 emit_native_pre(emit);
Damien13ed3a62013-10-08 09:05:10 +0100729 if (emit->do_viper_types) {
730 emit_post_push_imm(emit, VTYPE_INT, arg);
731 } else {
732 emit_post_push_imm(emit, VTYPE_PYOBJ, (arg << 1) | 1);
733 }
734}
735
Damien Georgecdd96df2014-04-06 12:58:40 +0100736STATIC void emit_native_load_const_int(emit_t *emit, qstr qst) {
737 DEBUG_printf("load_const_int %s\n", qstr_str(st));
738 // for viper: load integer, check fits in 32 bits
739 emit_native_pre(emit);
Damien George503d6112014-05-28 14:07:21 +0100740 emit_call_with_imm_arg(emit, MP_F_LOAD_CONST_INT, mp_load_const_int, qst, REG_ARG_1);
Damien Georgecdd96df2014-04-06 12:58:40 +0100741 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
Damien13ed3a62013-10-08 09:05:10 +0100742}
743
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200744STATIC void emit_native_load_const_dec(emit_t *emit, qstr qstr) {
Damien6ba13142013-11-02 20:34:54 +0000745 // for viper, a float/complex is just a Python object
Damien Georgece8f07a2014-03-27 23:30:26 +0000746 emit_native_pre(emit);
Damien Georged17926d2014-03-30 13:35:08 +0100747 emit_call_with_imm_arg(emit, MP_F_LOAD_CONST_DEC, mp_load_const_dec, qstr, REG_ARG_1);
Damien6ba13142013-11-02 20:34:54 +0000748 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
Damien13ed3a62013-10-08 09:05:10 +0100749}
750
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200751STATIC void emit_native_load_const_str(emit_t *emit, qstr qstr, bool bytes) {
Damien Georgece8f07a2014-03-27 23:30:26 +0000752 emit_native_pre(emit);
Damien13ed3a62013-10-08 09:05:10 +0100753 if (emit->do_viper_types) {
754 // not implemented properly
755 // load a pointer to the asciiz string?
756 assert(0);
Damien George40f3c022014-07-03 13:25:24 +0100757 emit_post_push_imm(emit, VTYPE_PTR, (mp_uint_t)qstr_str(qstr));
Damien13ed3a62013-10-08 09:05:10 +0100758 } else {
Damien Georgeb601d952014-06-30 05:17:25 +0100759 if (bytes) {
760 emit_call_with_imm_arg(emit, 0, mp_load_const_bytes, qstr, REG_ARG_1); // TODO need to add function to runtime table
761 } else {
762 emit_call_with_imm_arg(emit, MP_F_LOAD_CONST_STR, mp_load_const_str, qstr, REG_ARG_1);
763 }
Damien13ed3a62013-10-08 09:05:10 +0100764 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
765 }
766}
767
Damien George3558f622014-04-20 17:50:40 +0100768STATIC void emit_native_load_null(emit_t *emit) {
769 emit_native_pre(emit);
770 emit_post_push_imm(emit, VTYPE_PYOBJ, 0);
771}
772
Damien George2bf7c092014-04-09 15:26:46 +0100773STATIC void emit_native_load_fast(emit_t *emit, qstr qstr, uint id_flags, int local_num) {
Damien13ed3a62013-10-08 09:05:10 +0100774 vtype_kind_t vtype = emit->local_vtype[local_num];
775 if (vtype == VTYPE_UNBOUND) {
776 printf("ViperTypeError: local %s used before type known\n", qstr_str(qstr));
777 }
Damien Georgece8f07a2014-03-27 23:30:26 +0000778 emit_native_pre(emit);
Damien3ef4abb2013-10-12 16:53:13 +0100779#if N_X64
Damien13ed3a62013-10-08 09:05:10 +0100780 if (local_num == 0) {
781 emit_post_push_reg(emit, vtype, REG_LOCAL_1);
782 } else {
Damiend2755ec2013-10-16 23:58:48 +0100783 need_reg_single(emit, REG_RAX, 0);
Damien Georged509ac22014-05-07 23:27:45 +0100784 asm_x64_mov_local_to_r64(emit->as, local_num - REG_LOCAL_NUM, REG_RAX);
Damien13ed3a62013-10-08 09:05:10 +0100785 emit_post_push_reg(emit, vtype, REG_RAX);
786 }
Damien3ef4abb2013-10-12 16:53:13 +0100787#elif N_THUMB
Damien13ed3a62013-10-08 09:05:10 +0100788 if (local_num == 0) {
789 emit_post_push_reg(emit, vtype, REG_LOCAL_1);
790 } else if (local_num == 1) {
791 emit_post_push_reg(emit, vtype, REG_LOCAL_2);
792 } else if (local_num == 2) {
793 emit_post_push_reg(emit, vtype, REG_LOCAL_3);
794 } else {
Damiend2755ec2013-10-16 23:58:48 +0100795 need_reg_single(emit, REG_R0, 0);
Damien Georged509ac22014-05-07 23:27:45 +0100796 asm_thumb_mov_reg_local(emit->as, REG_R0, local_num - REG_LOCAL_NUM);
Damien13ed3a62013-10-08 09:05:10 +0100797 emit_post_push_reg(emit, vtype, REG_R0);
798 }
799#endif
800}
801
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200802STATIC void emit_native_load_deref(emit_t *emit, qstr qstr, int local_num) {
Damien9ecbcff2013-12-11 00:41:43 +0000803 // not implemented
804 // in principle could support this quite easily (ldr r0, [r0, #0]) and then get closed over variables!
805 assert(0);
806}
807
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200808STATIC void emit_native_load_name(emit_t *emit, qstr qstr) {
Damien Georgece8f07a2014-03-27 23:30:26 +0000809 emit_native_pre(emit);
Damien Georged17926d2014-03-30 13:35:08 +0100810 emit_call_with_imm_arg(emit, MP_F_LOAD_NAME, mp_load_name, qstr, REG_ARG_1);
Damien13ed3a62013-10-08 09:05:10 +0100811 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
812}
813
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200814STATIC void emit_native_load_global(emit_t *emit, qstr qstr) {
Damien Georgece8f07a2014-03-27 23:30:26 +0000815 emit_native_pre(emit);
Damien Georged17926d2014-03-30 13:35:08 +0100816 emit_call_with_imm_arg(emit, MP_F_LOAD_GLOBAL, mp_load_global, qstr, REG_ARG_1);
Damien13ed3a62013-10-08 09:05:10 +0100817 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
818}
819
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200820STATIC void emit_native_load_attr(emit_t *emit, qstr qstr) {
Damien13ed3a62013-10-08 09:05:10 +0100821 // depends on type of subject:
822 // - integer, function, pointer to integers: error
823 // - pointer to structure: get member, quite easy
Damien Georged17926d2014-03-30 13:35:08 +0100824 // - Python object: call mp_load_attr, and needs to be typed to convert result
Damien13ed3a62013-10-08 09:05:10 +0100825 vtype_kind_t vtype_base;
826 emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base
827 assert(vtype_base == VTYPE_PYOBJ);
Damien Georged17926d2014-03-30 13:35:08 +0100828 emit_call_with_imm_arg(emit, MP_F_LOAD_ATTR, mp_load_attr, qstr, REG_ARG_2); // arg2 = attribute name
Damien13ed3a62013-10-08 09:05:10 +0100829 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
830}
831
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200832STATIC void emit_native_load_method(emit_t *emit, qstr qstr) {
Damien13ed3a62013-10-08 09:05:10 +0100833 vtype_kind_t vtype_base;
834 emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base
835 assert(vtype_base == VTYPE_PYOBJ);
836 emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, 2); // arg3 = dest ptr
Damien Georged17926d2014-03-30 13:35:08 +0100837 emit_call_with_imm_arg(emit, MP_F_LOAD_METHOD, mp_load_method, qstr, REG_ARG_2); // arg2 = method name
Damien13ed3a62013-10-08 09:05:10 +0100838}
839
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200840STATIC void emit_native_load_build_class(emit_t *emit) {
Damien Georgece8f07a2014-03-27 23:30:26 +0000841 emit_native_pre(emit);
Damien Georged17926d2014-03-30 13:35:08 +0100842 emit_call(emit, MP_F_LOAD_BUILD_CLASS, mp_load_build_class);
Damien7f5dacf2013-10-10 11:24:39 +0100843 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
Damien13ed3a62013-10-08 09:05:10 +0100844}
845
Damien George729f7b42014-04-17 22:10:53 +0100846STATIC void emit_native_load_subscr(emit_t *emit) {
847 vtype_kind_t vtype_lhs, vtype_rhs;
848 emit_pre_pop_reg_reg(emit, &vtype_rhs, REG_ARG_2, &vtype_lhs, REG_ARG_1);
849 if (vtype_lhs == VTYPE_PYOBJ && vtype_rhs == VTYPE_PYOBJ) {
Damien George40f3c022014-07-03 13:25:24 +0100850 emit_call_with_imm_arg(emit, MP_F_OBJ_SUBSCR, mp_obj_subscr, (mp_uint_t)MP_OBJ_SENTINEL, REG_ARG_3);
Damien George729f7b42014-04-17 22:10:53 +0100851 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
852 } else {
853 printf("ViperTypeError: can't do subscr of types %d and %d\n", vtype_lhs, vtype_rhs);
Damien George729f7b42014-04-17 22:10:53 +0100854 }
855}
856
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200857STATIC void emit_native_store_fast(emit_t *emit, qstr qstr, int local_num) {
Damien13ed3a62013-10-08 09:05:10 +0100858 vtype_kind_t vtype;
Damien3ef4abb2013-10-12 16:53:13 +0100859#if N_X64
Damien13ed3a62013-10-08 09:05:10 +0100860 if (local_num == 0) {
861 emit_pre_pop_reg(emit, &vtype, REG_LOCAL_1);
862 } else {
863 emit_pre_pop_reg(emit, &vtype, REG_RAX);
Damien Georged509ac22014-05-07 23:27:45 +0100864 asm_x64_mov_r64_to_local(emit->as, REG_RAX, local_num - REG_LOCAL_NUM);
Damien13ed3a62013-10-08 09:05:10 +0100865 }
Damien3ef4abb2013-10-12 16:53:13 +0100866#elif N_THUMB
Damien13ed3a62013-10-08 09:05:10 +0100867 if (local_num == 0) {
868 emit_pre_pop_reg(emit, &vtype, REG_LOCAL_1);
869 } else if (local_num == 1) {
870 emit_pre_pop_reg(emit, &vtype, REG_LOCAL_2);
871 } else if (local_num == 2) {
872 emit_pre_pop_reg(emit, &vtype, REG_LOCAL_3);
873 } else {
874 emit_pre_pop_reg(emit, &vtype, REG_R0);
Damien Georged509ac22014-05-07 23:27:45 +0100875 asm_thumb_mov_local_reg(emit->as, local_num - REG_LOCAL_NUM, REG_R0);
Damien13ed3a62013-10-08 09:05:10 +0100876 }
877#endif
878
879 emit_post(emit);
880
881 // check types
882 if (emit->local_vtype[local_num] == VTYPE_UNBOUND) {
883 // first time this local is assigned, so give it a type of the object stored in it
884 emit->local_vtype[local_num] = vtype;
885 } else if (emit->local_vtype[local_num] != vtype) {
886 // type of local is not the same as object stored in it
887 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);
888 }
889}
890
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200891STATIC void emit_native_store_deref(emit_t *emit, qstr qstr, int local_num) {
Damien9ecbcff2013-12-11 00:41:43 +0000892 // not implemented
893 assert(0);
894}
895
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200896STATIC void emit_native_store_name(emit_t *emit, qstr qstr) {
Damien Georged17926d2014-03-30 13:35:08 +0100897 // mp_store_name, but needs conversion of object (maybe have mp_viper_store_name(obj, type))
Damien13ed3a62013-10-08 09:05:10 +0100898 vtype_kind_t vtype;
899 emit_pre_pop_reg(emit, &vtype, REG_ARG_2);
900 assert(vtype == VTYPE_PYOBJ);
Damien Georged17926d2014-03-30 13:35:08 +0100901 emit_call_with_imm_arg(emit, MP_F_STORE_NAME, mp_store_name, qstr, REG_ARG_1); // arg1 = name
Damien13ed3a62013-10-08 09:05:10 +0100902 emit_post(emit);
903}
904
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200905STATIC void emit_native_store_global(emit_t *emit, qstr qstr) {
Damien Georgee6c0dff2014-08-15 23:47:59 +0100906 vtype_kind_t vtype = peek_vtype(emit);
907 if (vtype == VTYPE_PYOBJ) {
908 emit_pre_pop_reg(emit, &vtype, REG_ARG_2);
909 } else {
910 emit_pre_pop_reg(emit, &vtype, REG_ARG_1);
911 emit_call_with_imm_arg(emit, MP_F_CONVERT_NATIVE_TO_OBJ, mp_convert_native_to_obj, vtype, REG_ARG_2); // arg2 = type
912 ASM_MOV_REG_TO_REG(REG_RET, REG_ARG_2);
913 }
914 emit_call_with_imm_arg(emit, MP_F_STORE_GLOBAL, mp_store_global, qstr, REG_ARG_1); // arg1 = name
915 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +0100916}
917
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200918STATIC void emit_native_store_attr(emit_t *emit, qstr qstr) {
Damien7f5dacf2013-10-10 11:24:39 +0100919 vtype_kind_t vtype_base, vtype_val;
920 emit_pre_pop_reg_reg(emit, &vtype_base, REG_ARG_1, &vtype_val, REG_ARG_3); // arg1 = base, arg3 = value
921 assert(vtype_base == VTYPE_PYOBJ);
922 assert(vtype_val == VTYPE_PYOBJ);
Damien Georged17926d2014-03-30 13:35:08 +0100923 emit_call_with_imm_arg(emit, MP_F_STORE_ATTR, mp_store_attr, qstr, REG_ARG_2); // arg2 = attribute name
Damien7f5dacf2013-10-10 11:24:39 +0100924 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +0100925}
926
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200927STATIC void emit_native_store_subscr(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +0100928 // depends on type of subject:
929 // - integer, function, pointer to structure: error
930 // - pointer to integers: store as per array
931 // - Python object: call runtime with converted object or type info
932 vtype_kind_t vtype_index, vtype_base, vtype_value;
933 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
934 assert(vtype_index == VTYPE_PYOBJ);
935 assert(vtype_base == VTYPE_PYOBJ);
936 assert(vtype_value == VTYPE_PYOBJ);
Damien George729f7b42014-04-17 22:10:53 +0100937 emit_call(emit, MP_F_OBJ_SUBSCR, mp_obj_subscr);
Damien13ed3a62013-10-08 09:05:10 +0100938}
939
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200940STATIC void emit_native_delete_fast(emit_t *emit, qstr qstr, int local_num) {
Damien13ed3a62013-10-08 09:05:10 +0100941 // not implemented
942 // could support for Python types, just set to None (so GC can reclaim it)
943 assert(0);
944}
945
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200946STATIC void emit_native_delete_deref(emit_t *emit, qstr qstr, int local_num) {
Damien9ecbcff2013-12-11 00:41:43 +0000947 // not supported
948 assert(0);
949}
950
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200951STATIC void emit_native_delete_name(emit_t *emit, qstr qstr) {
Damien13ed3a62013-10-08 09:05:10 +0100952 // not implemented
Damien Georged17926d2014-03-30 13:35:08 +0100953 // use mp_delete_name
Damien13ed3a62013-10-08 09:05:10 +0100954 assert(0);
955}
956
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200957STATIC void emit_native_delete_global(emit_t *emit, qstr qstr) {
Damien13ed3a62013-10-08 09:05:10 +0100958 // not implemented
Damien Georged17926d2014-03-30 13:35:08 +0100959 // use mp_delete_global
Damien13ed3a62013-10-08 09:05:10 +0100960 assert(0);
961}
962
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200963STATIC void emit_native_delete_attr(emit_t *emit, qstr qstr) {
Damien George780e54c2014-06-22 18:35:04 +0100964 vtype_kind_t vtype_base;
965 emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base
966 assert(vtype_base == VTYPE_PYOBJ);
Damien George40f3c022014-07-03 13:25:24 +0100967 emit_call_with_2_imm_args(emit, MP_F_STORE_ATTR, mp_store_attr, qstr, 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 +0100968 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +0100969}
970
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200971STATIC void emit_native_delete_subscr(emit_t *emit) {
Damien George729f7b42014-04-17 22:10:53 +0100972 vtype_kind_t vtype_index, vtype_base;
973 emit_pre_pop_reg_reg(emit, &vtype_index, REG_ARG_2, &vtype_base, REG_ARG_1); // index, base
974 assert(vtype_index == VTYPE_PYOBJ);
975 assert(vtype_base == VTYPE_PYOBJ);
Damien George40f3c022014-07-03 13:25:24 +0100976 emit_call_with_imm_arg(emit, MP_F_OBJ_SUBSCR, mp_obj_subscr, (mp_uint_t)MP_OBJ_NULL, REG_ARG_3);
Damien13ed3a62013-10-08 09:05:10 +0100977}
978
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200979STATIC void emit_native_dup_top(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +0100980 vtype_kind_t vtype;
981 emit_pre_pop_reg(emit, &vtype, REG_TEMP0);
982 emit_post_push_reg_reg(emit, vtype, REG_TEMP0, vtype, REG_TEMP0);
983}
984
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200985STATIC void emit_native_dup_top_two(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +0100986 vtype_kind_t vtype0, vtype1;
987 emit_pre_pop_reg_reg(emit, &vtype0, REG_TEMP0, &vtype1, REG_TEMP1);
988 emit_post_push_reg_reg_reg_reg(emit, vtype1, REG_TEMP1, vtype0, REG_TEMP0, vtype1, REG_TEMP1, vtype0, REG_TEMP0);
989}
990
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200991STATIC void emit_native_pop_top(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +0100992 vtype_kind_t vtype;
Damien Georgeccc85ea2014-05-10 13:40:46 +0100993 emit_pre_pop_discard(emit, &vtype);
Damien13ed3a62013-10-08 09:05:10 +0100994 emit_post(emit);
995}
996
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200997STATIC void emit_native_rot_two(emit_t *emit) {
Damienff8ed772013-10-08 22:18:32 +0100998 vtype_kind_t vtype0, vtype1;
999 emit_pre_pop_reg_reg(emit, &vtype0, REG_TEMP0, &vtype1, REG_TEMP1);
1000 emit_post_push_reg_reg(emit, vtype0, REG_TEMP0, vtype1, REG_TEMP1);
Damien13ed3a62013-10-08 09:05:10 +01001001}
1002
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001003STATIC void emit_native_rot_three(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +01001004 vtype_kind_t vtype0, vtype1, vtype2;
1005 emit_pre_pop_reg_reg_reg(emit, &vtype0, REG_TEMP0, &vtype1, REG_TEMP1, &vtype2, REG_TEMP2);
1006 emit_post_push_reg_reg_reg(emit, vtype0, REG_TEMP0, vtype2, REG_TEMP2, vtype1, REG_TEMP1);
1007}
1008
Damien George6f355fd2014-04-10 14:11:31 +01001009STATIC void emit_native_jump(emit_t *emit, uint label) {
Damien Georgece8f07a2014-03-27 23:30:26 +00001010 emit_native_pre(emit);
Damien Georgea32c1e42014-05-07 18:30:52 +01001011 // need to commit stack because we are jumping elsewhere
1012 need_stack_settled(emit);
Damien3ef4abb2013-10-12 16:53:13 +01001013#if N_X64
Damien13ed3a62013-10-08 09:05:10 +01001014 asm_x64_jmp_label(emit->as, label);
Damien3ef4abb2013-10-12 16:53:13 +01001015#elif N_THUMB
Damien13ed3a62013-10-08 09:05:10 +01001016 asm_thumb_b_label(emit->as, label);
1017#endif
1018 emit_post(emit);
1019}
1020
Damien Georgea32c1e42014-05-07 18:30:52 +01001021STATIC void emit_native_jump_helper(emit_t *emit, uint label, bool pop) {
Damien13ed3a62013-10-08 09:05:10 +01001022 vtype_kind_t vtype = peek_vtype(emit);
1023 if (vtype == VTYPE_BOOL) {
1024 emit_pre_pop_reg(emit, &vtype, REG_RET);
Damien Georgea32c1e42014-05-07 18:30:52 +01001025 if (!pop) {
1026 adjust_stack(emit, 1);
1027 }
Damien13ed3a62013-10-08 09:05:10 +01001028 } else if (vtype == VTYPE_PYOBJ) {
1029 emit_pre_pop_reg(emit, &vtype, REG_ARG_1);
Damien Georged17926d2014-03-30 13:35:08 +01001030 emit_call(emit, MP_F_OBJ_IS_TRUE, mp_obj_is_true);
Damien Georgea32c1e42014-05-07 18:30:52 +01001031 if (!pop) {
1032 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1033 }
Damien13ed3a62013-10-08 09:05:10 +01001034 } else {
1035 printf("ViperTypeError: expecting a bool or pyobj, got %d\n", vtype);
1036 assert(0);
1037 }
Damien Georgea32c1e42014-05-07 18:30:52 +01001038 // need to commit stack because we may jump elsewhere
1039 need_stack_settled(emit);
Damien13ed3a62013-10-08 09:05:10 +01001040}
1041
Damien George6f355fd2014-04-10 14:11:31 +01001042STATIC void emit_native_pop_jump_if_true(emit_t *emit, uint label) {
Damien Georgea32c1e42014-05-07 18:30:52 +01001043 emit_native_jump_helper(emit, label, true);
Damien1a6633a2013-11-03 13:58:19 +00001044#if N_X64
1045 asm_x64_test_r8_with_r8(emit->as, REG_RET, REG_RET);
1046 asm_x64_jcc_label(emit->as, JCC_JNZ, label);
1047#elif N_THUMB
1048 asm_thumb_cmp_rlo_i8(emit->as, REG_RET, 0);
1049 asm_thumb_bcc_label(emit->as, THUMB_CC_NE, label);
1050#endif
1051 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001052}
Damien1a6633a2013-11-03 13:58:19 +00001053
Damien Georgea32c1e42014-05-07 18:30:52 +01001054STATIC void emit_native_pop_jump_if_false(emit_t *emit, uint label) {
1055 emit_native_jump_helper(emit, label, true);
1056#if N_X64
1057 asm_x64_test_r8_with_r8(emit->as, REG_RET, REG_RET);
1058 asm_x64_jcc_label(emit->as, JCC_JZ, label);
1059#elif N_THUMB
1060 asm_thumb_cmp_rlo_i8(emit->as, REG_RET, 0);
1061 asm_thumb_bcc_label(emit->as, THUMB_CC_EQ, label);
1062#endif
1063 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001064}
Damien Georgea32c1e42014-05-07 18:30:52 +01001065
1066STATIC void emit_native_jump_if_true_or_pop(emit_t *emit, uint label) {
1067 emit_native_jump_helper(emit, label, false);
1068#if N_X64
1069 asm_x64_test_r8_with_r8(emit->as, REG_RET, REG_RET);
1070 asm_x64_jcc_label(emit->as, JCC_JNZ, label);
1071#elif N_THUMB
1072 asm_thumb_cmp_rlo_i8(emit->as, REG_RET, 0);
1073 asm_thumb_bcc_label(emit->as, THUMB_CC_NE, label);
1074#endif
1075 adjust_stack(emit, -1);
1076 emit_post(emit);
1077}
1078
Damien George6f355fd2014-04-10 14:11:31 +01001079STATIC void emit_native_jump_if_false_or_pop(emit_t *emit, uint label) {
Damien Georgea32c1e42014-05-07 18:30:52 +01001080 emit_native_jump_helper(emit, label, false);
1081#if N_X64
1082 asm_x64_test_r8_with_r8(emit->as, REG_RET, REG_RET);
1083 asm_x64_jcc_label(emit->as, JCC_JZ, label);
1084#elif N_THUMB
1085 asm_thumb_cmp_rlo_i8(emit->as, REG_RET, 0);
1086 asm_thumb_bcc_label(emit->as, THUMB_CC_EQ, label);
1087#endif
1088 adjust_stack(emit, -1);
1089 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001090}
1091
Damien George6f355fd2014-04-10 14:11:31 +01001092STATIC void emit_native_break_loop(emit_t *emit, uint label, int except_depth) {
Damien George25c84642014-05-30 15:20:41 +01001093 emit_native_jump(emit, label & ~MP_EMIT_BREAK_FROM_FOR); // TODO properly
Damien13ed3a62013-10-08 09:05:10 +01001094}
Damien Georgea32c1e42014-05-07 18:30:52 +01001095
Damien George6f355fd2014-04-10 14:11:31 +01001096STATIC void emit_native_continue_loop(emit_t *emit, uint label, int except_depth) {
Damien Georgea32c1e42014-05-07 18:30:52 +01001097 emit_native_jump(emit, label); // TODO properly
Damien13ed3a62013-10-08 09:05:10 +01001098}
Damien Georgea32c1e42014-05-07 18:30:52 +01001099
Damien George6f355fd2014-04-10 14:11:31 +01001100STATIC void emit_native_setup_with(emit_t *emit, uint label) {
Damien13ed3a62013-10-08 09:05:10 +01001101 // not supported, or could be with runtime call
1102 assert(0);
1103}
Damien Georgeb601d952014-06-30 05:17:25 +01001104
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001105STATIC void emit_native_with_cleanup(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +01001106 assert(0);
1107}
Damien Georgeb601d952014-06-30 05:17:25 +01001108
Damien George6f355fd2014-04-10 14:11:31 +01001109STATIC void emit_native_setup_except(emit_t *emit, uint label) {
Damien Georgeb601d952014-06-30 05:17:25 +01001110 emit_native_pre(emit);
1111 // need to commit stack because we may jump elsewhere
1112 need_stack_settled(emit);
Damien George40f3c022014-07-03 13:25:24 +01001113 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 Georgeb601d952014-06-30 05:17:25 +01001114 emit_call(emit, 0, nlr_push); // TODO need to add function to runtime table
1115#if N_X64
1116 asm_x64_test_r8_with_r8(emit->as, REG_RET, REG_RET);
1117 asm_x64_jcc_label(emit->as, JCC_JNZ, label);
1118#elif N_THUMB
1119 asm_thumb_cmp_rlo_i8(emit->as, REG_RET, 0);
1120 asm_thumb_bcc_label(emit->as, THUMB_CC_NE, label);
1121#endif
1122 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001123}
Damien Georgeb601d952014-06-30 05:17:25 +01001124
Damien George6f355fd2014-04-10 14:11:31 +01001125STATIC void emit_native_setup_finally(emit_t *emit, uint label) {
Damien13ed3a62013-10-08 09:05:10 +01001126 assert(0);
1127}
Damien Georgeb601d952014-06-30 05:17:25 +01001128
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001129STATIC void emit_native_end_finally(emit_t *emit) {
Damien Georgeb601d952014-06-30 05:17:25 +01001130 //assert(0);
Damien13ed3a62013-10-08 09:05:10 +01001131}
Damiend2755ec2013-10-16 23:58:48 +01001132
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001133STATIC void emit_native_get_iter(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +01001134 // perhaps the difficult one, as we want to rewrite for loops using native code
1135 // in cases where we iterate over a Python object, can we use normal runtime calls?
Damiend2755ec2013-10-16 23:58:48 +01001136
1137 vtype_kind_t vtype;
1138 emit_pre_pop_reg(emit, &vtype, REG_ARG_1);
1139 assert(vtype == VTYPE_PYOBJ);
Damien Georged17926d2014-03-30 13:35:08 +01001140 emit_call(emit, MP_F_GETITER, mp_getiter);
Damiend2755ec2013-10-16 23:58:48 +01001141 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
Damien13ed3a62013-10-08 09:05:10 +01001142}
Damiend2755ec2013-10-16 23:58:48 +01001143
Damien George6f355fd2014-04-10 14:11:31 +01001144STATIC void emit_native_for_iter(emit_t *emit, uint label) {
Damien Georgece8f07a2014-03-27 23:30:26 +00001145 emit_native_pre(emit);
Damiend2755ec2013-10-16 23:58:48 +01001146 vtype_kind_t vtype;
1147 emit_access_stack(emit, 1, &vtype, REG_ARG_1);
1148 assert(vtype == VTYPE_PYOBJ);
Damien Georged17926d2014-03-30 13:35:08 +01001149 emit_call(emit, MP_F_ITERNEXT, mp_iternext);
Damien George40f3c022014-07-03 13:25:24 +01001150 ASM_MOV_IMM_TO_REG((mp_uint_t)MP_OBJ_STOP_ITERATION, REG_TEMP1);
Damiend2755ec2013-10-16 23:58:48 +01001151#if N_X64
1152 asm_x64_cmp_r64_with_r64(emit->as, REG_RET, REG_TEMP1);
1153 asm_x64_jcc_label(emit->as, JCC_JE, label);
1154#elif N_THUMB
Damien George87210872014-04-13 00:30:32 +01001155 asm_thumb_cmp_rlo_rlo(emit->as, REG_RET, REG_TEMP1);
Damien9b9e9962013-11-03 14:25:43 +00001156 asm_thumb_bcc_label(emit->as, THUMB_CC_EQ, label);
Damiend2755ec2013-10-16 23:58:48 +01001157#endif
1158 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1159}
1160
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001161STATIC void emit_native_for_iter_end(emit_t *emit) {
Damiend2755ec2013-10-16 23:58:48 +01001162 // adjust stack counter (we get here from for_iter ending, which popped the value for us)
Damien Georgece8f07a2014-03-27 23:30:26 +00001163 emit_native_pre(emit);
Damiend2755ec2013-10-16 23:58:48 +01001164 adjust_stack(emit, -1);
1165 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001166}
1167
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001168STATIC void emit_native_pop_block(emit_t *emit) {
Damien Georgece8f07a2014-03-27 23:30:26 +00001169 emit_native_pre(emit);
Damien Georgeb601d952014-06-30 05:17:25 +01001170 emit_call(emit, 0, nlr_pop); // TODO need to add function to runtime table
Damien George40f3c022014-07-03 13:25:24 +01001171 adjust_stack(emit, -(mp_int_t)(sizeof(nlr_buf_t) / sizeof(mp_uint_t)));
Damien13ed3a62013-10-08 09:05:10 +01001172 emit_post(emit);
1173}
1174
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001175STATIC void emit_native_pop_except(emit_t *emit) {
Damien Georgeb601d952014-06-30 05:17:25 +01001176 /*
1177 emit_native_pre(emit);
1178 emit_call(emit, 0, nlr_pop); // TODO need to add function to runtime table
Damien George40f3c022014-07-03 13:25:24 +01001179 adjust_stack(emit, -(mp_int_t)(sizeof(nlr_buf_t) / sizeof(mp_uint_t)));
Damien Georgeb601d952014-06-30 05:17:25 +01001180 emit_post(emit);
1181 */
Damien13ed3a62013-10-08 09:05:10 +01001182}
1183
Damien Georged17926d2014-03-30 13:35:08 +01001184STATIC void emit_native_unary_op(emit_t *emit, mp_unary_op_t op) {
Damien Georgeb601d952014-06-30 05:17:25 +01001185 if (op == MP_UNARY_OP_NOT) {
1186 // we need to synthesise this operation
1187 assert(0);
1188 } else {
1189 vtype_kind_t vtype;
1190 emit_pre_pop_reg(emit, &vtype, REG_ARG_2);
1191 assert(vtype == VTYPE_PYOBJ);
1192 emit_call_with_imm_arg(emit, MP_F_UNARY_OP, mp_unary_op, op, REG_ARG_1);
1193 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1194 }
Damien13ed3a62013-10-08 09:05:10 +01001195}
1196
Damien Georged17926d2014-03-30 13:35:08 +01001197STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) {
Damien13ed3a62013-10-08 09:05:10 +01001198 vtype_kind_t vtype_lhs, vtype_rhs;
1199 emit_pre_pop_reg_reg(emit, &vtype_rhs, REG_ARG_3, &vtype_lhs, REG_ARG_2);
1200 if (vtype_lhs == VTYPE_INT && vtype_rhs == VTYPE_INT) {
Damien Georged17926d2014-03-30 13:35:08 +01001201 if (op == MP_BINARY_OP_ADD || op == MP_BINARY_OP_INPLACE_ADD) {
Damien3ef4abb2013-10-12 16:53:13 +01001202#if N_X64
Damien Georgebc1d3692014-01-11 09:47:06 +00001203 asm_x64_add_r64_to_r64(emit->as, REG_ARG_3, REG_ARG_2);
Damien3ef4abb2013-10-12 16:53:13 +01001204#elif N_THUMB
Damien Georgea26dc502014-04-12 17:54:52 +01001205 asm_thumb_add_rlo_rlo_rlo(emit->as, REG_ARG_2, REG_ARG_2, REG_ARG_3);
Damien13ed3a62013-10-08 09:05:10 +01001206#endif
Damien Georgebc1d3692014-01-11 09:47:06 +00001207 emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);
Damien Georged17926d2014-03-30 13:35:08 +01001208 } else if (op == MP_BINARY_OP_LESS) {
Damien Georgebc1d3692014-01-11 09:47:06 +00001209#if N_X64
1210 asm_x64_xor_r64_to_r64(emit->as, REG_RET, REG_RET);
1211 asm_x64_cmp_r64_with_r64(emit->as, REG_ARG_3, REG_ARG_2);
1212 asm_x64_setcc_r8(emit->as, JCC_JL, REG_RET);
1213#elif N_THUMB
Damien George87210872014-04-13 00:30:32 +01001214 asm_thumb_cmp_rlo_rlo(emit->as, REG_ARG_2, REG_ARG_3);
Damien Georgebc1d3692014-01-11 09:47:06 +00001215 asm_thumb_ite_ge(emit->as);
Damien George87210872014-04-13 00:30:32 +01001216 asm_thumb_mov_rlo_i8(emit->as, REG_RET, 0); // if r0 >= r1
1217 asm_thumb_mov_rlo_i8(emit->as, REG_RET, 1); // if r0 < r1
Damien Georgebc1d3692014-01-11 09:47:06 +00001218#endif
1219 emit_post_push_reg(emit, VTYPE_BOOL, REG_RET);
1220 } else {
1221 // TODO other ops not yet implemented
1222 assert(0);
1223 }
Damien13ed3a62013-10-08 09:05:10 +01001224 } else if (vtype_lhs == VTYPE_PYOBJ && vtype_rhs == VTYPE_PYOBJ) {
Damien Georged17926d2014-03-30 13:35:08 +01001225 emit_call_with_imm_arg(emit, MP_F_BINARY_OP, mp_binary_op, op, REG_ARG_1);
Damien13ed3a62013-10-08 09:05:10 +01001226 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1227 } else {
1228 printf("ViperTypeError: can't do binary op between types %d and %d\n", vtype_lhs, vtype_rhs);
Damien Georgea5190a72014-08-15 22:39:08 +01001229 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
Damien13ed3a62013-10-08 09:05:10 +01001230 }
1231}
1232
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001233STATIC void emit_native_build_tuple(emit_t *emit, int n_args) {
Damiend2755ec2013-10-16 23:58:48 +01001234 // for viper: call runtime, with types of args
1235 // if wrapped in byte_array, or something, allocates memory and fills it
Damien Georgece8f07a2014-03-27 23:30:26 +00001236 emit_native_pre(emit);
Damien Georgecd82e022014-02-02 13:11:48 +00001237 emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, n_args); // pointer to items
Damien George15d18062014-03-31 16:28:13 +01001238 emit_call_with_imm_arg(emit, MP_F_BUILD_TUPLE, mp_obj_new_tuple, n_args, REG_ARG_1);
Damiend2755ec2013-10-16 23:58:48 +01001239 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new tuple
Damien13ed3a62013-10-08 09:05:10 +01001240}
1241
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001242STATIC void emit_native_build_list(emit_t *emit, int n_args) {
Damien Georgece8f07a2014-03-27 23:30:26 +00001243 emit_native_pre(emit);
Damien Georgecd82e022014-02-02 13:11:48 +00001244 emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, n_args); // pointer to items
Damien George15d18062014-03-31 16:28:13 +01001245 emit_call_with_imm_arg(emit, MP_F_BUILD_LIST, mp_obj_new_list, n_args, REG_ARG_1);
Damien13ed3a62013-10-08 09:05:10 +01001246 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new list
1247}
1248
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001249STATIC void emit_native_list_append(emit_t *emit, int list_index) {
Damiend2755ec2013-10-16 23:58:48 +01001250 // only used in list comprehension
1251 vtype_kind_t vtype_list, vtype_item;
1252 emit_pre_pop_reg(emit, &vtype_item, REG_ARG_2);
1253 emit_access_stack(emit, list_index, &vtype_list, REG_ARG_1);
1254 assert(vtype_list == VTYPE_PYOBJ);
1255 assert(vtype_item == VTYPE_PYOBJ);
Damien George15d18062014-03-31 16:28:13 +01001256 emit_call(emit, MP_F_LIST_APPEND, mp_obj_list_append);
Damiend2755ec2013-10-16 23:58:48 +01001257 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001258}
1259
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001260STATIC void emit_native_build_map(emit_t *emit, int n_args) {
Damien Georgece8f07a2014-03-27 23:30:26 +00001261 emit_native_pre(emit);
Damien George15d18062014-03-31 16:28:13 +01001262 emit_call_with_imm_arg(emit, MP_F_BUILD_MAP, mp_obj_new_dict, n_args, REG_ARG_1);
Damien13ed3a62013-10-08 09:05:10 +01001263 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new map
1264}
1265
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001266STATIC void emit_native_store_map(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +01001267 vtype_kind_t vtype_key, vtype_value, vtype_map;
1268 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
1269 assert(vtype_key == VTYPE_PYOBJ);
1270 assert(vtype_value == VTYPE_PYOBJ);
1271 assert(vtype_map == VTYPE_PYOBJ);
Damien George15d18062014-03-31 16:28:13 +01001272 emit_call(emit, MP_F_STORE_MAP, mp_obj_dict_store);
Damien13ed3a62013-10-08 09:05:10 +01001273 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // map
1274}
1275
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001276STATIC void emit_native_map_add(emit_t *emit, int map_index) {
Damiend2755ec2013-10-16 23:58:48 +01001277 // only used in list comprehension
1278 vtype_kind_t vtype_map, vtype_key, vtype_value;
1279 emit_pre_pop_reg_reg(emit, &vtype_key, REG_ARG_2, &vtype_value, REG_ARG_3);
1280 emit_access_stack(emit, map_index, &vtype_map, REG_ARG_1);
1281 assert(vtype_map == VTYPE_PYOBJ);
1282 assert(vtype_key == VTYPE_PYOBJ);
1283 assert(vtype_value == VTYPE_PYOBJ);
Damien George15d18062014-03-31 16:28:13 +01001284 emit_call(emit, MP_F_STORE_MAP, mp_obj_dict_store);
Damiend2755ec2013-10-16 23:58:48 +01001285 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001286}
1287
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001288STATIC void emit_native_build_set(emit_t *emit, int n_args) {
Damien Georgece8f07a2014-03-27 23:30:26 +00001289 emit_native_pre(emit);
Damien Georgecd82e022014-02-02 13:11:48 +00001290 emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, n_args); // pointer to items
Damien George15d18062014-03-31 16:28:13 +01001291 emit_call_with_imm_arg(emit, MP_F_BUILD_SET, mp_obj_new_set, n_args, REG_ARG_1);
Damien13ed3a62013-10-08 09:05:10 +01001292 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new set
1293}
1294
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001295STATIC void emit_native_set_add(emit_t *emit, int set_index) {
Damiend2755ec2013-10-16 23:58:48 +01001296 // only used in set comprehension
1297 vtype_kind_t vtype_set, vtype_item;
1298 emit_pre_pop_reg(emit, &vtype_item, REG_ARG_2);
1299 emit_access_stack(emit, set_index, &vtype_set, REG_ARG_1);
1300 assert(vtype_set == VTYPE_PYOBJ);
1301 assert(vtype_item == VTYPE_PYOBJ);
Damien George15d18062014-03-31 16:28:13 +01001302 emit_call(emit, MP_F_STORE_SET, mp_obj_set_store);
Damiend2755ec2013-10-16 23:58:48 +01001303 emit_post(emit);
Damien13ed3a62013-10-08 09:05:10 +01001304}
Damiend2755ec2013-10-16 23:58:48 +01001305
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001306STATIC void emit_native_build_slice(emit_t *emit, int n_args) {
Damien Georgecdd96df2014-04-06 12:58:40 +01001307 DEBUG_printf("build_slice %d\n", n_args);
Damien Georgeb601d952014-06-30 05:17:25 +01001308 if (n_args == 2) {
1309 vtype_kind_t vtype_start, vtype_stop;
1310 emit_pre_pop_reg_reg(emit, &vtype_stop, REG_ARG_2, &vtype_start, REG_ARG_1); // arg1 = start, arg2 = stop
1311 assert(vtype_start == VTYPE_PYOBJ);
1312 assert(vtype_stop == VTYPE_PYOBJ);
Damien George40f3c022014-07-03 13:25:24 +01001313 emit_call_with_imm_arg(emit, MP_F_NEW_SLICE, mp_obj_new_slice, (mp_uint_t)mp_const_none, REG_ARG_3); // arg3 = step
Damien Georgeb601d952014-06-30 05:17:25 +01001314 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1315 } else {
1316 assert(n_args == 3);
1317 vtype_kind_t vtype_start, vtype_stop, vtype_step;
1318 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
1319 assert(vtype_start == VTYPE_PYOBJ);
1320 assert(vtype_stop == VTYPE_PYOBJ);
1321 assert(vtype_step == VTYPE_PYOBJ);
1322 emit_call(emit, MP_F_NEW_SLICE, mp_obj_new_slice);
1323 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1324 }
Damien13ed3a62013-10-08 09:05:10 +01001325}
Damien Georgecdd96df2014-04-06 12:58:40 +01001326
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001327STATIC void emit_native_unpack_sequence(emit_t *emit, int n_args) {
Damien Georgecdd96df2014-04-06 12:58:40 +01001328 DEBUG_printf("unpack_sequence %d\n", n_args);
1329 vtype_kind_t vtype_base;
1330 emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = seq
1331 assert(vtype_base == VTYPE_PYOBJ);
1332 emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, n_args); // arg3 = dest ptr
1333 emit_call_with_imm_arg(emit, MP_F_UNPACK_SEQUENCE, mp_unpack_sequence, n_args, REG_ARG_2); // arg2 = n_args
Damien13ed3a62013-10-08 09:05:10 +01001334}
Damien Georgecdd96df2014-04-06 12:58:40 +01001335
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001336STATIC void emit_native_unpack_ex(emit_t *emit, int n_left, int n_right) {
Damien Georgea32c1e42014-05-07 18:30:52 +01001337 DEBUG_printf("unpack_ex %d %d\n", n_left, n_right);
1338 vtype_kind_t vtype_base;
1339 emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = seq
1340 assert(vtype_base == VTYPE_PYOBJ);
Damien Georgeb601d952014-06-30 05:17:25 +01001341 emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, n_left + n_right + 1); // arg3 = dest ptr
1342 emit_call_with_imm_arg(emit, MP_F_UNPACK_EX, mp_unpack_ex, n_left | (n_right << 8), REG_ARG_2); // arg2 = n_left + n_right
Damien13ed3a62013-10-08 09:05:10 +01001343}
1344
Damien George30565092014-03-31 11:30:17 +01001345STATIC 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 +01001346 // 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 +00001347 emit_native_pre(emit);
Damien Georgea32c1e42014-05-07 18:30:52 +01001348 if (n_pos_defaults == 0 && n_kw_defaults == 0) {
Damien George40f3c022014-07-03 13:25:24 +01001349 emit_call_with_3_imm_args_and_first_aligned(emit, MP_F_MAKE_FUNCTION_FROM_RAW_CODE, mp_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 +01001350 } else {
1351 vtype_kind_t vtype_def_tuple, vtype_def_dict;
1352 emit_pre_pop_reg_reg(emit, &vtype_def_dict, REG_ARG_3, &vtype_def_tuple, REG_ARG_2);
1353 assert(vtype_def_tuple == VTYPE_PYOBJ);
1354 assert(vtype_def_dict == VTYPE_PYOBJ);
Damien George40f3c022014-07-03 13:25:24 +01001355 emit_call_with_imm_arg_aligned(emit, MP_F_MAKE_FUNCTION_FROM_RAW_CODE, mp_make_function_from_raw_code, (mp_uint_t)scope->raw_code, REG_ARG_1);
Damien Georgea32c1e42014-05-07 18:30:52 +01001356 }
Damien13ed3a62013-10-08 09:05:10 +01001357 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1358}
1359
Damien George3558f622014-04-20 17:50:40 +01001360STATIC 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 +01001361 assert(0);
1362}
1363
Damien George922ddd62014-04-09 12:43:17 +01001364STATIC void emit_native_call_function(emit_t *emit, int n_positional, int n_keyword, uint star_flags) {
Damien13ed3a62013-10-08 09:05:10 +01001365 // call special viper runtime routine with type info for args, and wanted type info for return
Damien George922ddd62014-04-09 12:43:17 +01001366 assert(!star_flags);
Damien Georgecd82e022014-02-02 13:11:48 +00001367
1368 /* we no longer have these _n specific call_function's
1369 * they anyway push args into an array
1370 * and they would take too much room in the native dispatch table
Damien13ed3a62013-10-08 09:05:10 +01001371 if (n_positional == 0) {
1372 vtype_kind_t vtype_fun;
1373 emit_pre_pop_reg(emit, &vtype_fun, REG_ARG_1); // the function
1374 assert(vtype_fun == VTYPE_PYOBJ);
Damien Georged17926d2014-03-30 13:35:08 +01001375 emit_call(emit, MP_F_CALL_FUNCTION_0, mp_call_function_0);
Damien13ed3a62013-10-08 09:05:10 +01001376 } else if (n_positional == 1) {
1377 vtype_kind_t vtype_fun, vtype_arg1;
1378 emit_pre_pop_reg_reg(emit, &vtype_arg1, REG_ARG_2, &vtype_fun, REG_ARG_1); // the single argument, the function
1379 assert(vtype_fun == VTYPE_PYOBJ);
1380 assert(vtype_arg1 == VTYPE_PYOBJ);
Damien Georged17926d2014-03-30 13:35:08 +01001381 emit_call(emit, MP_F_CALL_FUNCTION_1, mp_call_function_1);
Damien13ed3a62013-10-08 09:05:10 +01001382 } else if (n_positional == 2) {
1383 vtype_kind_t vtype_fun, vtype_arg1, vtype_arg2;
1384 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
1385 assert(vtype_fun == VTYPE_PYOBJ);
1386 assert(vtype_arg1 == VTYPE_PYOBJ);
1387 assert(vtype_arg2 == VTYPE_PYOBJ);
Damien Georged17926d2014-03-30 13:35:08 +01001388 emit_call(emit, MP_F_CALL_FUNCTION_2, mp_call_function_2);
Damien13ed3a62013-10-08 09:05:10 +01001389 } else {
Damieneb19efb2013-10-10 22:06:54 +01001390 */
Damien Georgecd82e022014-02-02 13:11:48 +00001391
Damien Georgece8f07a2014-03-27 23:30:26 +00001392 emit_native_pre(emit);
Damien Georgecdd96df2014-04-06 12:58:40 +01001393 if (n_positional != 0 || n_keyword != 0) {
1394 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 +00001395 }
1396 vtype_kind_t vtype_fun;
1397 emit_pre_pop_reg(emit, &vtype_fun, REG_ARG_1); // the function
1398 assert(vtype_fun == VTYPE_PYOBJ);
Damien Georgecdd96df2014-04-06 12:58:40 +01001399 emit_call_with_imm_arg(emit, MP_F_CALL_FUNCTION_N_KW_FOR_NATIVE, mp_call_function_n_kw_for_native, n_positional | (n_keyword << 8), REG_ARG_2);
Damien13ed3a62013-10-08 09:05:10 +01001400 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1401}
1402
Damien George922ddd62014-04-09 12:43:17 +01001403STATIC void emit_native_call_method(emit_t *emit, int n_positional, int n_keyword, uint star_flags) {
1404 assert(!star_flags);
Damien Georgecd82e022014-02-02 13:11:48 +00001405
Damieneb19efb2013-10-10 22:06:54 +01001406 /*
Damien13ed3a62013-10-08 09:05:10 +01001407 if (n_positional == 0) {
1408 vtype_kind_t vtype_meth, vtype_self;
1409 emit_pre_pop_reg_reg(emit, &vtype_self, REG_ARG_2, &vtype_meth, REG_ARG_1); // the self object (or NULL), the method
1410 assert(vtype_meth == VTYPE_PYOBJ);
1411 assert(vtype_self == VTYPE_PYOBJ);
Damien Georged17926d2014-03-30 13:35:08 +01001412 emit_call(emit, MP_F_CALL_METHOD_1, mp_call_method_1);
Damien13ed3a62013-10-08 09:05:10 +01001413 } else if (n_positional == 1) {
1414 vtype_kind_t vtype_meth, vtype_self, vtype_arg1;
1415 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
1416 assert(vtype_meth == VTYPE_PYOBJ);
1417 assert(vtype_self == VTYPE_PYOBJ);
1418 assert(vtype_arg1 == VTYPE_PYOBJ);
Damien Georged17926d2014-03-30 13:35:08 +01001419 emit_call(emit, MP_F_CALL_METHOD_2, mp_call_method_2);
Damien13ed3a62013-10-08 09:05:10 +01001420 } else {
Damieneb19efb2013-10-10 22:06:54 +01001421 */
Damien Georgecd82e022014-02-02 13:11:48 +00001422
Damien Georgece8f07a2014-03-27 23:30:26 +00001423 emit_native_pre(emit);
Damien Georgecdd96df2014-04-06 12:58:40 +01001424 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 Georged17926d2014-03-30 13:35:08 +01001425 emit_call_with_2_imm_args(emit, MP_F_CALL_METHOD_N_KW, mp_call_method_n_kw, n_positional, REG_ARG_1, n_keyword, REG_ARG_2);
Damien13ed3a62013-10-08 09:05:10 +01001426 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1427}
1428
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001429STATIC void emit_native_return_value(emit_t *emit) {
Damien Georgecdd96df2014-04-06 12:58:40 +01001430 DEBUG_printf("return_value\n");
Damien13ed3a62013-10-08 09:05:10 +01001431 vtype_kind_t vtype;
1432 emit_pre_pop_reg(emit, &vtype, REG_RET);
1433 if (emit->do_viper_types) {
Damien Georgee6c0dff2014-08-15 23:47:59 +01001434 if (vtype == VTYPE_PTR_NONE) {
1435 if (emit->return_vtype == VTYPE_PYOBJ) {
1436 ASM_MOV_IMM_TO_REG((mp_uint_t)mp_const_none, REG_RET);
1437 }
1438 } else if (vtype != emit->return_vtype) {
Damien George2ac4af62014-08-15 16:45:41 +01001439 printf("ViperTypeError: incompatible return type\n");
1440 }
Damien13ed3a62013-10-08 09:05:10 +01001441 } else {
1442 assert(vtype == VTYPE_PYOBJ);
1443 }
1444 emit->last_emit_was_return_value = true;
Damien3ef4abb2013-10-12 16:53:13 +01001445#if N_X64
Damien13ed3a62013-10-08 09:05:10 +01001446 //asm_x64_call_ind(emit->as, 0, REG_RAX); to seg fault for debugging with gdb
1447 asm_x64_exit(emit->as);
Damien3ef4abb2013-10-12 16:53:13 +01001448#elif N_THUMB
Damien13ed3a62013-10-08 09:05:10 +01001449 //asm_thumb_call_ind(emit->as, 0, REG_R0); to seg fault for debugging with gdb
1450 asm_thumb_exit(emit->as);
1451#endif
1452}
1453
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001454STATIC void emit_native_raise_varargs(emit_t *emit, int n_args) {
Damien Georgeb601d952014-06-30 05:17:25 +01001455 assert(n_args == 1);
1456 vtype_kind_t vtype_err;
1457 emit_pre_pop_reg(emit, &vtype_err, REG_ARG_1); // arg1 = object to raise
1458 assert(vtype_err == VTYPE_PYOBJ);
1459 emit_call(emit, 0, mp_make_raise_obj); // TODO need to add function to runtime table
1460 emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1461 emit_pre_pop_reg(emit, &vtype_err, REG_ARG_1);
1462 emit_call(emit, 0, nlr_jump); // TODO need to add function to runtime table
Damien13ed3a62013-10-08 09:05:10 +01001463}
Damien Georgeb601d952014-06-30 05:17:25 +01001464
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001465STATIC void emit_native_yield_value(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +01001466 // not supported (for now)
1467 assert(0);
1468}
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02001469STATIC void emit_native_yield_from(emit_t *emit) {
Damien13ed3a62013-10-08 09:05:10 +01001470 // not supported (for now)
1471 assert(0);
1472}
1473
Damien Georgeb601d952014-06-30 05:17:25 +01001474STATIC void emit_native_start_except_handler(emit_t *emit) {
1475 // This instruction follows an nlr_pop, so the stack counter is back to zero, when really
1476 // it should be up by a whole nlr_buf_t. We then want to pop the nlr_buf_t here, but save
1477 // the first 2 elements, so we can get the thrown value.
1478 adjust_stack(emit, 2);
1479 vtype_kind_t vtype_nlr;
1480 emit_pre_pop_reg(emit, &vtype_nlr, REG_ARG_1); // get the thrown value
1481 emit_pre_pop_discard(emit, &vtype_nlr); // discard the linked-list pointer in the nlr_buf
1482 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
1483}
1484
1485STATIC void emit_native_end_except_handler(emit_t *emit) {
1486 adjust_stack(emit, -3); // stack adjust (not sure why it's this much...)
1487}
1488
Damien13ed3a62013-10-08 09:05:10 +01001489const emit_method_table_t EXPORT_FUN(method_table) = {
Damien George2ac4af62014-08-15 16:45:41 +01001490 emit_native_set_native_type,
Damien13ed3a62013-10-08 09:05:10 +01001491 emit_native_start_pass,
1492 emit_native_end_pass,
1493 emit_native_last_emit_was_return_value,
Damien Georged66ae182014-04-10 17:28:54 +00001494 emit_native_adjust_stack_size,
Damien George08335002014-01-18 23:24:36 +00001495 emit_native_set_source_line,
Damien13ed3a62013-10-08 09:05:10 +01001496
1497 emit_native_load_id,
1498 emit_native_store_id,
1499 emit_native_delete_id,
1500
1501 emit_native_label_assign,
1502 emit_native_import_name,
1503 emit_native_import_from,
1504 emit_native_import_star,
1505 emit_native_load_const_tok,
1506 emit_native_load_const_small_int,
1507 emit_native_load_const_int,
1508 emit_native_load_const_dec,
Damien13ed3a62013-10-08 09:05:10 +01001509 emit_native_load_const_str,
Damien George3558f622014-04-20 17:50:40 +01001510 emit_native_load_null,
Damien13ed3a62013-10-08 09:05:10 +01001511 emit_native_load_fast,
Damien13ed3a62013-10-08 09:05:10 +01001512 emit_native_load_deref,
Damien9ecbcff2013-12-11 00:41:43 +00001513 emit_native_load_name,
1514 emit_native_load_global,
Damien13ed3a62013-10-08 09:05:10 +01001515 emit_native_load_attr,
1516 emit_native_load_method,
1517 emit_native_load_build_class,
Damien George729f7b42014-04-17 22:10:53 +01001518 emit_native_load_subscr,
Damien13ed3a62013-10-08 09:05:10 +01001519 emit_native_store_fast,
Damien9ecbcff2013-12-11 00:41:43 +00001520 emit_native_store_deref,
Damien13ed3a62013-10-08 09:05:10 +01001521 emit_native_store_name,
1522 emit_native_store_global,
Damien13ed3a62013-10-08 09:05:10 +01001523 emit_native_store_attr,
Damien13ed3a62013-10-08 09:05:10 +01001524 emit_native_store_subscr,
Damien13ed3a62013-10-08 09:05:10 +01001525 emit_native_delete_fast,
Damien9ecbcff2013-12-11 00:41:43 +00001526 emit_native_delete_deref,
Damien13ed3a62013-10-08 09:05:10 +01001527 emit_native_delete_name,
1528 emit_native_delete_global,
Damien13ed3a62013-10-08 09:05:10 +01001529 emit_native_delete_attr,
1530 emit_native_delete_subscr,
1531 emit_native_dup_top,
1532 emit_native_dup_top_two,
1533 emit_native_pop_top,
1534 emit_native_rot_two,
1535 emit_native_rot_three,
1536 emit_native_jump,
1537 emit_native_pop_jump_if_true,
1538 emit_native_pop_jump_if_false,
1539 emit_native_jump_if_true_or_pop,
1540 emit_native_jump_if_false_or_pop,
Damien13ed3a62013-10-08 09:05:10 +01001541 emit_native_break_loop,
1542 emit_native_continue_loop,
1543 emit_native_setup_with,
1544 emit_native_with_cleanup,
1545 emit_native_setup_except,
1546 emit_native_setup_finally,
1547 emit_native_end_finally,
1548 emit_native_get_iter,
1549 emit_native_for_iter,
1550 emit_native_for_iter_end,
1551 emit_native_pop_block,
1552 emit_native_pop_except,
1553 emit_native_unary_op,
1554 emit_native_binary_op,
Damien13ed3a62013-10-08 09:05:10 +01001555 emit_native_build_tuple,
1556 emit_native_build_list,
1557 emit_native_list_append,
1558 emit_native_build_map,
1559 emit_native_store_map,
1560 emit_native_map_add,
1561 emit_native_build_set,
1562 emit_native_set_add,
1563 emit_native_build_slice,
1564 emit_native_unpack_sequence,
1565 emit_native_unpack_ex,
1566 emit_native_make_function,
1567 emit_native_make_closure,
1568 emit_native_call_function,
1569 emit_native_call_method,
1570 emit_native_return_value,
1571 emit_native_raise_varargs,
1572 emit_native_yield_value,
1573 emit_native_yield_from,
Damien Georgeb601d952014-06-30 05:17:25 +01001574
1575 emit_native_start_except_handler,
1576 emit_native_end_except_handler,
Damien13ed3a62013-10-08 09:05:10 +01001577};
1578
Damien Georgee67ed5d2014-01-04 13:55:24 +00001579#endif // (MICROPY_EMIT_X64 && N_X64) || (MICROPY_EMIT_THUMB && N_THUMB)