Branch data Line data Source code
1 : : /*
2 : : * This file is part of the MicroPython project, http://micropython.org/
3 : : *
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 <stdarg.h>
28 : : #include <stdio.h>
29 : : #include <string.h>
30 : : #include <assert.h>
31 : :
32 : : #include "py/binary.h"
33 : : #include "py/runtime.h"
34 : : #include "py/smallint.h"
35 : : #include "py/nativeglue.h"
36 : : #include "py/gc.h"
37 : :
38 : : #if MICROPY_DEBUG_VERBOSE // print debugging info
39 : : #define DEBUG_printf DEBUG_printf
40 : : #else // don't print debugging info
41 : : #define DEBUG_printf(...) (void)0
42 : : #endif
43 : :
44 : : #if MICROPY_EMIT_NATIVE
45 : :
46 : 1162 : int mp_native_type_from_qstr(qstr qst) {
47 [ + + + + : 1162 : switch (qst) {
+ + + +
+ ]
48 : : case MP_QSTR_object:
49 : : return MP_NATIVE_TYPE_OBJ;
50 : 16 : case MP_QSTR_bool:
51 : 16 : return MP_NATIVE_TYPE_BOOL;
52 : 318 : case MP_QSTR_int:
53 : 318 : return MP_NATIVE_TYPE_INT;
54 : 70 : case MP_QSTR_uint:
55 : 70 : return MP_NATIVE_TYPE_UINT;
56 : 24 : case MP_QSTR_ptr:
57 : 24 : return MP_NATIVE_TYPE_PTR;
58 : 42 : case MP_QSTR_ptr8:
59 : 42 : return MP_NATIVE_TYPE_PTR8;
60 : 28 : case MP_QSTR_ptr16:
61 : 28 : return MP_NATIVE_TYPE_PTR16;
62 : 36 : case MP_QSTR_ptr32:
63 : 36 : return MP_NATIVE_TYPE_PTR32;
64 : 620 : default:
65 : 620 : return -1;
66 : : }
67 : : }
68 : :
69 : : // convert a MicroPython object to a valid native value based on type
70 : 1580 : mp_uint_t mp_native_from_obj(mp_obj_t obj, mp_uint_t type) {
71 : 1580 : DEBUG_printf("mp_native_from_obj(%p, " UINT_FMT ")\n", obj, type);
72 [ - + + + ]: 1580 : switch (type & 0xf) {
73 : 0 : case MP_NATIVE_TYPE_OBJ:
74 : 0 : return (mp_uint_t)obj;
75 : 32 : case MP_NATIVE_TYPE_BOOL:
76 : 32 : return mp_obj_is_true(obj);
77 : 1412 : case MP_NATIVE_TYPE_INT:
78 : : case MP_NATIVE_TYPE_UINT:
79 : 1412 : return mp_obj_get_int_truncated(obj);
80 : 136 : default: { // cast obj to a pointer
81 : 136 : mp_buffer_info_t bufinfo;
82 [ + + ]: 136 : if (mp_get_buffer(obj, &bufinfo, MP_BUFFER_READ)) {
83 : 128 : return (mp_uint_t)bufinfo.buf;
84 : : } else {
85 : : // assume obj is an integer that represents an address
86 : 8 : return mp_obj_get_int_truncated(obj);
87 : : }
88 : : }
89 : : }
90 : : }
91 : :
92 : : #endif
93 : :
94 : : #if MICROPY_EMIT_MACHINE_CODE
95 : :
96 : : // convert a native value to a MicroPython object based on type
97 : 1240 : mp_obj_t mp_native_to_obj(mp_uint_t val, mp_uint_t type) {
98 : 1240 : DEBUG_printf("mp_native_to_obj(" UINT_FMT ", " UINT_FMT ")\n", val, type);
99 [ - + + + : 1240 : switch (type & 0xf) {
- + ]
100 : 0 : case MP_NATIVE_TYPE_OBJ:
101 : 0 : return (mp_obj_t)val;
102 : 104 : case MP_NATIVE_TYPE_BOOL:
103 [ + + ]: 104 : return mp_obj_new_bool(val);
104 : 960 : case MP_NATIVE_TYPE_INT:
105 : 960 : return mp_obj_new_int(val);
106 : 172 : case MP_NATIVE_TYPE_UINT:
107 : 172 : return mp_obj_new_int_from_uint(val);
108 : 0 : case MP_NATIVE_TYPE_QSTR:
109 : 0 : return MP_OBJ_NEW_QSTR(val);
110 : 4 : default: // a pointer
111 : : // we return just the value of the pointer as an integer
112 : 4 : return mp_obj_new_int_from_uint(val);
113 : : }
114 : : }
115 : :
116 : : #endif
117 : :
118 : : #if MICROPY_EMIT_NATIVE && !MICROPY_DYNAMIC_COMPILER
119 : :
120 : : #if !MICROPY_PY_BUILTINS_SET
121 : : mp_obj_t mp_obj_new_set(size_t n_args, mp_obj_t *items) {
122 : : (void)n_args;
123 : : (void)items;
124 : : mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("set unsupported"));
125 : : }
126 : :
127 : : void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item) {
128 : : (void)self_in;
129 : : (void)item;
130 : : mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("set unsupported"));
131 : : }
132 : : #endif
133 : :
134 : : #if !MICROPY_PY_BUILTINS_SLICE
135 : : mp_obj_t mp_obj_new_slice(mp_obj_t ostart, mp_obj_t ostop, mp_obj_t ostep) {
136 : : (void)ostart;
137 : : (void)ostop;
138 : : (void)ostep;
139 : : mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("slice unsupported"));
140 : : }
141 : : #endif
142 : :
143 : 1354079 : static mp_obj_dict_t *mp_native_swap_globals(mp_obj_dict_t *new_globals) {
144 [ + + ]: 1354079 : if (new_globals == NULL) {
145 : : // Globals were the originally the same so don't restore them
146 : : return NULL;
147 : : }
148 : 1352280 : mp_obj_dict_t *old_globals = mp_globals_get();
149 [ + + ]: 1352280 : if (old_globals == new_globals) {
150 : : // Don't set globals if they are the same, and return NULL to indicate this
151 : : return NULL;
152 : : }
153 : 995228 : mp_globals_set(new_globals);
154 : 995228 : return old_globals;
155 : : }
156 : :
157 : : // wrapper that accepts n_args and n_kw in one argument
158 : : // (native emitter can only pass at most 3 arguments to a function)
159 : 1558121 : static mp_obj_t mp_native_call_function_n_kw(mp_obj_t fun_in, size_t n_args_kw, const mp_obj_t *args) {
160 : 1558121 : return mp_call_function_n_kw(fun_in, n_args_kw & 0xff, (n_args_kw >> 8) & 0xff, args);
161 : : }
162 : :
163 : : // wrapper that makes raise obj and raises it
164 : : // END_FINALLY opcode requires that we don't raise if o==None
165 : 347056 : static void mp_native_raise(mp_obj_t o) {
166 [ + + ]: 347056 : if (o != MP_OBJ_NULL && o != mp_const_none) {
167 : 332156 : nlr_raise(mp_make_raise_obj(o));
168 : : }
169 : 14900 : }
170 : :
171 : : // wrapper that handles iterator buffer
172 : 337778 : static mp_obj_t mp_native_getiter(mp_obj_t obj, mp_obj_iter_buf_t *iter) {
173 [ + + ]: 337778 : if (iter == NULL) {
174 : 166542 : return mp_getiter(obj, NULL);
175 : : } else {
176 : 171236 : obj = mp_getiter(obj, iter);
177 [ + + ]: 171232 : if (obj != MP_OBJ_FROM_PTR(iter)) {
178 : : // Iterator didn't use the stack so indicate that with MP_OBJ_NULL.
179 : 169079 : iter->base.type = MP_OBJ_NULL;
180 : 169079 : iter->buf[0] = obj;
181 : : }
182 : 171232 : return NULL;
183 : : }
184 : : }
185 : :
186 : : // wrapper that handles iterator buffer
187 : 211888 : static mp_obj_t mp_native_iternext(mp_obj_iter_buf_t *iter) {
188 : 211888 : mp_obj_t obj;
189 [ + + ]: 211888 : if (iter->base.type == MP_OBJ_NULL) {
190 : 197144 : obj = iter->buf[0];
191 : : } else {
192 : : obj = MP_OBJ_FROM_PTR(iter);
193 : : }
194 : 211888 : return mp_iternext(obj);
195 : : }
196 : :
197 : 332477 : static bool mp_native_yield_from(mp_obj_t gen, mp_obj_t send_value, mp_obj_t *ret_value) {
198 : 332477 : mp_vm_return_kind_t ret_kind;
199 : 332477 : nlr_buf_t nlr_buf;
200 : 332477 : mp_obj_t throw_value = *ret_value;
201 [ + + ]: 332477 : if (nlr_push(&nlr_buf) == 0) {
202 [ + + ]: 332477 : if (throw_value != MP_OBJ_NULL) {
203 : 103 : send_value = MP_OBJ_NULL;
204 : : }
205 : 332477 : ret_kind = mp_resume(gen, send_value, throw_value, ret_value);
206 : 166721 : nlr_pop();
207 : : } else {
208 : 165756 : ret_kind = MP_VM_RETURN_EXCEPTION;
209 : 165756 : *ret_value = nlr_buf.ret_val;
210 : : }
211 : :
212 [ + + ]: 332477 : if (ret_kind == MP_VM_RETURN_YIELD) {
213 : : return true;
214 [ + + ]: 166353 : } else if (ret_kind == MP_VM_RETURN_NORMAL) {
215 [ - + ]: 295 : if (*ret_value == MP_OBJ_STOP_ITERATION) {
216 : 0 : *ret_value = mp_const_none;
217 : : }
218 : : } else {
219 [ - + ]: 166058 : assert(ret_kind == MP_VM_RETURN_EXCEPTION);
220 [ + + ]: 166058 : if (!mp_obj_exception_match(*ret_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {
221 : 329 : nlr_raise(*ret_value);
222 : : }
223 : 165729 : *ret_value = mp_obj_exception_get_value(*ret_value);
224 : : }
225 : :
226 [ + + + + ]: 166024 : if (throw_value != MP_OBJ_NULL && mp_obj_exception_match(throw_value, MP_OBJ_FROM_PTR(&mp_type_GeneratorExit))) {
227 : 4 : nlr_raise(mp_make_raise_obj(throw_value));
228 : : }
229 : :
230 : : return false;
231 : : }
232 : :
233 : : #if !MICROPY_PY_BUILTINS_FLOAT
234 : :
235 : : static mp_obj_t mp_obj_new_float_from_f(float f) {
236 : : (void)f;
237 : : mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("float unsupported"));
238 : : }
239 : :
240 : : static mp_obj_t mp_obj_new_float_from_d(double d) {
241 : : (void)d;
242 : : mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("float unsupported"));
243 : : }
244 : :
245 : : static float mp_obj_get_float_to_f(mp_obj_t o) {
246 : : (void)o;
247 : : mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("float unsupported"));
248 : : }
249 : :
250 : : static double mp_obj_get_float_to_d(mp_obj_t o) {
251 : : (void)o;
252 : : mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("float unsupported"));
253 : : }
254 : :
255 : : #endif
256 : :
257 : : // these must correspond to the respective enum in nativeglue.h
258 : : const mp_fun_table_t mp_fun_table = {
259 : : mp_const_none,
260 : : mp_const_false,
261 : : mp_const_true,
262 : : mp_native_from_obj,
263 : : mp_native_to_obj,
264 : : mp_native_swap_globals,
265 : : mp_load_name,
266 : : mp_load_global,
267 : : mp_load_build_class,
268 : : mp_load_attr,
269 : : mp_load_method,
270 : : mp_load_super_method,
271 : : mp_store_name,
272 : : mp_store_global,
273 : : mp_store_attr,
274 : : mp_obj_subscr,
275 : : mp_obj_is_true,
276 : : mp_unary_op,
277 : : mp_binary_op,
278 : : mp_obj_new_tuple,
279 : : mp_obj_new_list,
280 : : mp_obj_new_dict,
281 : : mp_obj_new_set,
282 : : mp_obj_set_store,
283 : : mp_obj_list_append,
284 : : mp_obj_dict_store,
285 : : mp_make_function_from_proto_fun,
286 : : mp_native_call_function_n_kw,
287 : : mp_call_method_n_kw,
288 : : mp_call_method_n_kw_var,
289 : : mp_native_getiter,
290 : : mp_native_iternext,
291 : : #if MICROPY_NLR_SETJMP
292 : : nlr_push_tail,
293 : : #else
294 : : nlr_push,
295 : : #endif
296 : : nlr_pop,
297 : : mp_native_raise,
298 : : mp_import_name,
299 : : mp_import_from,
300 : : mp_import_all,
301 : : mp_obj_new_slice,
302 : : mp_unpack_sequence,
303 : : mp_unpack_ex,
304 : : mp_delete_name,
305 : : mp_delete_global,
306 : : mp_obj_new_closure,
307 : : mp_arg_check_num_sig,
308 : : mp_setup_code_state_native,
309 : : mp_small_int_floor_divide,
310 : : mp_small_int_modulo,
311 : : mp_native_yield_from,
312 : : #if MICROPY_NLR_SETJMP
313 : : setjmp,
314 : : #else
315 : : NULL,
316 : : #endif
317 : : // Additional entries for dynamic runtime, starts at index 50
318 : : memset,
319 : : memmove,
320 : : gc_realloc,
321 : : mp_printf,
322 : : mp_vprintf,
323 : : mp_raise_msg,
324 : : mp_obj_get_type,
325 : : mp_obj_new_str,
326 : : mp_obj_new_bytes,
327 : : mp_obj_new_bytearray_by_ref,
328 : : mp_obj_new_float_from_f,
329 : : mp_obj_new_float_from_d,
330 : : mp_obj_get_float_to_f,
331 : : mp_obj_get_float_to_d,
332 : : mp_load_method_maybe,
333 : : mp_get_buffer,
334 : : mp_get_stream_raise,
335 : : mp_arg_parse_all,
336 : : mp_arg_parse_all_kw_array,
337 : : mp_binary_get_size,
338 : : mp_binary_get_val_array,
339 : : mp_binary_set_val_array,
340 : : &mp_plat_print,
341 : : &mp_type_type,
342 : : &mp_type_str,
343 : : &mp_type_list,
344 : : &mp_type_dict,
345 : : &mp_type_fun_builtin_0,
346 : : &mp_type_fun_builtin_1,
347 : : &mp_type_fun_builtin_2,
348 : : &mp_type_fun_builtin_3,
349 : : &mp_type_fun_builtin_var,
350 : : &mp_type_Exception,
351 : : &mp_stream_read_obj,
352 : : &mp_stream_readinto_obj,
353 : : &mp_stream_unbuffered_readline_obj,
354 : : &mp_stream_write_obj,
355 : : };
356 : :
357 : : #elif MICROPY_EMIT_NATIVE && MICROPY_DYNAMIC_COMPILER
358 : :
359 : : const int mp_fun_table;
360 : :
361 : : #endif // MICROPY_EMIT_NATIVE
|