blob: e63c2fcda683498c4ff37851d707623d123076f6 [file] [log] [blame]
Damien George110ba352014-08-28 23:37:02 +01001/*
Alexander Steffen55f33242017-06-30 09:22:17 +02002 * This file is part of the MicroPython project, http://micropython.org/
Damien George110ba352014-08-28 23:37:02 +01003 *
4 * The MIT License (MIT)
5 *
6 * Copyright (c) 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
27#include <stdio.h>
28#include <string.h>
29#include <assert.h>
30
Damien George51dfcb42015-01-01 20:27:54 +000031#include "py/runtime.h"
Damien Georgea3afa8c2017-10-11 18:54:34 +110032#include "py/smallint.h"
Damien George51dfcb42015-01-01 20:27:54 +000033#include "py/emitglue.h"
Damien George99886182015-04-06 22:38:53 +010034#include "py/bc.h"
Damien George110ba352014-08-28 23:37:02 +010035
Stefan Naumannace9fb52017-07-24 18:55:14 +020036#if MICROPY_DEBUG_VERBOSE // print debugging info
Damien George110ba352014-08-28 23:37:02 +010037#define DEBUG_printf DEBUG_printf
38#else // don't print debugging info
39#define DEBUG_printf(...) (void)0
40#endif
41
Damien George8f54c082016-01-15 15:20:43 +000042#if MICROPY_EMIT_NATIVE
43
Alexander Steffen55f33242017-06-30 09:22:17 +020044// convert a MicroPython object to a valid native value based on type
Damien George110ba352014-08-28 23:37:02 +010045mp_uint_t mp_convert_obj_to_native(mp_obj_t obj, mp_uint_t type) {
46 DEBUG_printf("mp_convert_obj_to_native(%p, " UINT_FMT ")\n", obj, type);
Damien George5f3e0052016-02-02 23:16:05 +000047 switch (type & 0xf) {
Damien George110ba352014-08-28 23:37:02 +010048 case MP_NATIVE_TYPE_OBJ: return (mp_uint_t)obj;
49 case MP_NATIVE_TYPE_BOOL:
Damien George5f3e0052016-02-02 23:16:05 +000050 case MP_NATIVE_TYPE_INT:
51 case MP_NATIVE_TYPE_UINT: return mp_obj_get_int_truncated(obj);
Damien George3e02b1d2016-02-09 13:29:20 +000052 default: { // cast obj to a pointer
Damien Georgee9dac3b2014-09-29 22:10:41 +010053 mp_buffer_info_t bufinfo;
Damien George3e02b1d2016-02-09 13:29:20 +000054 if (mp_get_buffer(obj, &bufinfo, MP_BUFFER_RW)) {
55 return (mp_uint_t)bufinfo.buf;
56 } else {
57 // assume obj is an integer that represents an address
58 return mp_obj_get_int_truncated(obj);
59 }
Damien Georgee9dac3b2014-09-29 22:10:41 +010060 }
Damien George110ba352014-08-28 23:37:02 +010061 }
62}
63
Damien George8f54c082016-01-15 15:20:43 +000064#endif
65
Damien Georgead297a12016-12-09 13:17:49 +110066#if MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_ASM
Damien George8f54c082016-01-15 15:20:43 +000067
Alexander Steffen55f33242017-06-30 09:22:17 +020068// convert a native value to a MicroPython object based on type
Damien George110ba352014-08-28 23:37:02 +010069mp_obj_t mp_convert_native_to_obj(mp_uint_t val, mp_uint_t type) {
70 DEBUG_printf("mp_convert_native_to_obj(" UINT_FMT ", " UINT_FMT ")\n", val, type);
Damien George5f3e0052016-02-02 23:16:05 +000071 switch (type & 0xf) {
Damien George110ba352014-08-28 23:37:02 +010072 case MP_NATIVE_TYPE_OBJ: return (mp_obj_t)val;
Paul Sokolovsky1b586f32015-10-11 12:09:43 +030073 case MP_NATIVE_TYPE_BOOL: return mp_obj_new_bool(val);
Damien George110ba352014-08-28 23:37:02 +010074 case MP_NATIVE_TYPE_INT: return mp_obj_new_int(val);
75 case MP_NATIVE_TYPE_UINT: return mp_obj_new_int_from_uint(val);
Damien George5f3e0052016-02-02 23:16:05 +000076 default: // a pointer
77 // we return just the value of the pointer as an integer
78 return mp_obj_new_int_from_uint(val);
Damien George110ba352014-08-28 23:37:02 +010079 }
80}
81
Damien George8f54c082016-01-15 15:20:43 +000082#endif
83
84#if MICROPY_EMIT_NATIVE
85
Damien George110ba352014-08-28 23:37:02 +010086// wrapper that accepts n_args and n_kw in one argument
87// (native emitter can only pass at most 3 arguments to a function)
Damien George4e3bac22017-02-16 15:32:34 +110088mp_obj_t mp_native_call_function_n_kw(mp_obj_t fun_in, size_t n_args_kw, const mp_obj_t *args) {
Damien George110ba352014-08-28 23:37:02 +010089 return mp_call_function_n_kw(fun_in, n_args_kw & 0xff, (n_args_kw >> 8) & 0xff, args);
90}
91
92// wrapper that makes raise obj and raises it
Damien Georgeb6e6b522015-01-21 17:00:01 +000093// END_FINALLY opcode requires that we don't raise if o==None
94void mp_native_raise(mp_obj_t o) {
95 if (o != mp_const_none) {
96 nlr_raise(mp_make_raise_obj(o));
97 }
Damien George110ba352014-08-28 23:37:02 +010098}
99
Damien George088740e2017-01-17 15:27:37 +1100100// wrapper that handles iterator buffer
101STATIC mp_obj_t mp_native_getiter(mp_obj_t obj, mp_obj_iter_buf_t *iter) {
102 if (iter == NULL) {
103 return mp_getiter(obj, NULL);
104 } else {
105 obj = mp_getiter(obj, iter);
106 if (obj != MP_OBJ_FROM_PTR(iter)) {
107 // Iterator didn't use the stack so indicate that with MP_OBJ_NULL.
108 iter->base.type = MP_OBJ_NULL;
109 iter->buf[0] = obj;
110 }
111 return NULL;
112 }
113}
114
115// wrapper that handles iterator buffer
116STATIC mp_obj_t mp_native_iternext(mp_obj_iter_buf_t *iter) {
117 mp_obj_t obj;
118 if (iter->base.type == MP_OBJ_NULL) {
119 obj = iter->buf[0];
120 } else {
121 obj = MP_OBJ_FROM_PTR(iter);
122 }
123 return mp_iternext(obj);
124}
125
Damien George110ba352014-08-28 23:37:02 +0100126// these must correspond to the respective enum in runtime0.h
127void *const mp_fun_table[MP_F_NUMBER_OF] = {
128 mp_convert_obj_to_native,
129 mp_convert_native_to_obj,
Damien George110ba352014-08-28 23:37:02 +0100130 mp_load_name,
131 mp_load_global,
132 mp_load_build_class,
133 mp_load_attr,
134 mp_load_method,
Damien Georgedd11af22017-04-19 09:45:59 +1000135 mp_load_super_method,
Damien George110ba352014-08-28 23:37:02 +0100136 mp_store_name,
137 mp_store_global,
138 mp_store_attr,
139 mp_obj_subscr,
140 mp_obj_is_true,
141 mp_unary_op,
142 mp_binary_op,
143 mp_obj_new_tuple,
144 mp_obj_new_list,
145 mp_obj_list_append,
146 mp_obj_new_dict,
147 mp_obj_dict_store,
148#if MICROPY_PY_BUILTINS_SET
149 mp_obj_new_set,
150 mp_obj_set_store,
151#endif
152 mp_make_function_from_raw_code,
153 mp_native_call_function_n_kw,
154 mp_call_method_n_kw,
Damien George78772ad2015-04-06 22:48:21 +0100155 mp_call_method_n_kw_var,
Damien George088740e2017-01-17 15:27:37 +1100156 mp_native_getiter,
157 mp_native_iternext,
Damien George110ba352014-08-28 23:37:02 +0100158 nlr_push,
159 nlr_pop,
160 mp_native_raise,
161 mp_import_name,
162 mp_import_from,
163 mp_import_all,
164#if MICROPY_PY_BUILTINS_SLICE
165 mp_obj_new_slice,
166#endif
167 mp_unpack_sequence,
168 mp_unpack_ex,
Damien Georgee6ce10a2014-09-06 18:38:20 +0100169 mp_delete_name,
170 mp_delete_global,
Damien George4cd9ced2015-01-15 14:41:41 +0000171 mp_obj_new_cell,
172 mp_make_closure_from_raw_code,
Damien George99886182015-04-06 22:38:53 +0100173 mp_setup_code_state,
Damien Georgea3afa8c2017-10-11 18:54:34 +1100174 mp_small_int_floor_divide,
175 mp_small_int_modulo,
Damien George110ba352014-08-28 23:37:02 +0100176};
177
178/*
179void mp_f_vector(mp_fun_kind_t fun_kind) {
180 (mp_f_table[fun_kind])();
181}
182*/
183
184#endif // MICROPY_EMIT_NATIVE