blob: 07de08fc3678c8fbfba54ab5cfde1c40e8c271d6 [file] [log] [blame]
Damien Georgeb534e1b2014-09-04 14:44:01 +01001/*
2 * This file is part of the Micro Python project, http://micropython.org/
3 *
4 * The MIT License (MIT)
5 *
6 * Copyright (c) 2014 Damien P. George
7 * Copyright (c) 2014 Paul Sokolovsky
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 */
27
28#include <stdbool.h>
29#include <string.h>
30#include <assert.h>
31
Damien George51dfcb42015-01-01 20:27:54 +000032#include "py/nlr.h"
33#include "py/objfun.h"
Damien George3a3db4d2015-10-22 23:45:37 +010034#include "py/runtime0.h"
Damien Georged8c834c2015-11-02 21:55:42 +000035#include "py/bc0.h"
Damien George51dfcb42015-01-01 20:27:54 +000036#include "py/bc.h"
Damien Georgeb534e1b2014-09-04 14:44:01 +010037
38#if 0 // print debugging info
39#define DEBUG_PRINT (1)
40#else // don't print debugging info
Damien George7860c2a2014-11-05 21:16:41 +000041#define DEBUG_PRINT (0)
Damien Georgeb534e1b2014-09-04 14:44:01 +010042#define DEBUG_printf(...) (void)0
43#endif
44
45mp_uint_t mp_decode_uint(const byte **ptr) {
46 mp_uint_t unum = 0;
47 byte val;
48 const byte *p = *ptr;
49 do {
50 val = *p++;
51 unum = (unum << 7) | (val & 0x7f);
52 } while ((val & 0x80) != 0);
53 *ptr = p;
54 return unum;
55}
56
Damien George1d899e12015-12-17 12:33:42 +000057STATIC NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, size_t expected, size_t given) {
Damien Georgeb534e1b2014-09-04 14:44:01 +010058#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE
Damien George7f233842015-01-01 15:33:50 +000059 // generic message, used also for other argument issues
Damien George3a2171e2015-09-04 16:53:46 +010060 (void)f;
61 (void)expected;
62 (void)given;
Damien George7f233842015-01-01 15:33:50 +000063 mp_arg_error_terse_mismatch();
Damien Georgeb534e1b2014-09-04 14:44:01 +010064#elif MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_NORMAL
Damien George3a2171e2015-09-04 16:53:46 +010065 (void)f;
Damien Georgeb534e1b2014-09-04 14:44:01 +010066 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
67 "function takes %d positional arguments but %d were given", expected, given));
68#elif MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED
69 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
Damien George044c4732015-04-11 13:03:37 +010070 "%q() takes %d positional arguments but %d were given",
Damien George999cedb2015-11-27 17:01:44 +000071 mp_obj_fun_get_name(MP_OBJ_FROM_PTR(f)), expected, given));
Damien Georgeb534e1b2014-09-04 14:44:01 +010072#endif
73}
74
75#if DEBUG_PRINT
Damien George1d899e12015-12-17 12:33:42 +000076STATIC void dump_args(const mp_obj_t *a, size_t sz) {
Damien Georgeb534e1b2014-09-04 14:44:01 +010077 DEBUG_printf("%p: ", a);
Damien George1d899e12015-12-17 12:33:42 +000078 for (size_t i = 0; i < sz; i++) {
Damien Georgeb534e1b2014-09-04 14:44:01 +010079 DEBUG_printf("%p ", a[i]);
80 }
81 DEBUG_printf("\n");
82}
83#else
84#define dump_args(...) (void)0
85#endif
86
Damien George99886182015-04-06 22:38:53 +010087// On entry code_state should be allocated somewhere (stack/heap) and
88// contain the following valid entries:
Damien George99886182015-04-06 22:38:53 +010089// - code_state->ip should contain the offset in bytes from the start of
Damien George9b7f5832015-03-18 17:47:47 +000090// the bytecode chunk to just after n_state and n_exc_stack
Damien George99886182015-04-06 22:38:53 +010091// - code_state->n_state should be set to the state size (locals plus stack)
Damien George581a59a2016-08-27 23:21:00 +100092void mp_setup_code_state(mp_code_state_t *code_state, mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) {
Damien Georgeb534e1b2014-09-04 14:44:01 +010093 // This function is pretty complicated. It's main aim is to be efficient in speed and RAM
94 // usage for the common case of positional only args.
Damien George1d899e12015-12-17 12:33:42 +000095 size_t n_state = code_state->n_state;
Damien Georgeb534e1b2014-09-04 14:44:01 +010096
Damien George9b7f5832015-03-18 17:47:47 +000097 // ip comes in as an offset into bytecode, so turn it into a true pointer
Damien George999cedb2015-11-27 17:01:44 +000098 code_state->ip = self->bytecode + (size_t)code_state->ip;
Damien George9b7f5832015-03-18 17:47:47 +000099
Damien George713ea182015-10-23 01:23:11 +0100100 // store pointer to constant table
101 code_state->const_table = self->const_table;
102
Paul Sokolovsky20397572015-03-28 01:14:44 +0200103 #if MICROPY_STACKLESS
104 code_state->prev = NULL;
105 #endif
Damien George9b7f5832015-03-18 17:47:47 +0000106
Damien George3a3db4d2015-10-22 23:45:37 +0100107 // get params
Damien George1d899e12015-12-17 12:33:42 +0000108 size_t scope_flags = *code_state->ip++;
109 size_t n_pos_args = *code_state->ip++;
110 size_t n_kwonly_args = *code_state->ip++;
111 size_t n_def_pos_args = *code_state->ip++;
Damien George3a3db4d2015-10-22 23:45:37 +0100112
Damien Georgeb534e1b2014-09-04 14:44:01 +0100113 code_state->sp = &code_state->state[0] - 1;
114 code_state->exc_sp = (mp_exc_stack_t*)(code_state->state + n_state) - 1;
115
116 // zero out the local stack to begin with
117 memset(code_state->state, 0, n_state * sizeof(*code_state->state));
118
119 const mp_obj_t *kwargs = args + n_args;
120
121 // var_pos_kw_args points to the stack where the var-args tuple, and var-kw dict, should go (if they are needed)
Damien George3a3db4d2015-10-22 23:45:37 +0100122 mp_obj_t *var_pos_kw_args = &code_state->state[n_state - 1 - n_pos_args - n_kwonly_args];
Damien Georgeb534e1b2014-09-04 14:44:01 +0100123
124 // check positional arguments
125
Damien George3a3db4d2015-10-22 23:45:37 +0100126 if (n_args > n_pos_args) {
Damien Georgeb534e1b2014-09-04 14:44:01 +0100127 // given more than enough arguments
Damien George3a3db4d2015-10-22 23:45:37 +0100128 if ((scope_flags & MP_SCOPE_FLAG_VARARGS) == 0) {
129 fun_pos_args_mismatch(self, n_pos_args, n_args);
Damien Georgeb534e1b2014-09-04 14:44:01 +0100130 }
131 // put extra arguments in varargs tuple
Damien George3a3db4d2015-10-22 23:45:37 +0100132 *var_pos_kw_args-- = mp_obj_new_tuple(n_args - n_pos_args, args + n_pos_args);
133 n_args = n_pos_args;
Damien Georgeb534e1b2014-09-04 14:44:01 +0100134 } else {
Damien George3a3db4d2015-10-22 23:45:37 +0100135 if ((scope_flags & MP_SCOPE_FLAG_VARARGS) != 0) {
Damien Georgeb534e1b2014-09-04 14:44:01 +0100136 DEBUG_printf("passing empty tuple as *args\n");
137 *var_pos_kw_args-- = mp_const_empty_tuple;
138 }
139 // Apply processing and check below only if we don't have kwargs,
140 // otherwise, kw handling code below has own extensive checks.
Damien George3a3db4d2015-10-22 23:45:37 +0100141 if (n_kw == 0 && (scope_flags & MP_SCOPE_FLAG_DEFKWARGS) == 0) {
Damien George1d899e12015-12-17 12:33:42 +0000142 if (n_args >= (size_t)(n_pos_args - n_def_pos_args)) {
Damien Georgeb534e1b2014-09-04 14:44:01 +0100143 // given enough arguments, but may need to use some default arguments
Damien George1d899e12015-12-17 12:33:42 +0000144 for (size_t i = n_args; i < n_pos_args; i++) {
Damien George3a3db4d2015-10-22 23:45:37 +0100145 code_state->state[n_state - 1 - i] = self->extra_args[i - (n_pos_args - n_def_pos_args)];
Damien Georgeb534e1b2014-09-04 14:44:01 +0100146 }
147 } else {
Damien George3a3db4d2015-10-22 23:45:37 +0100148 fun_pos_args_mismatch(self, n_pos_args - n_def_pos_args, n_args);
Damien Georgeb534e1b2014-09-04 14:44:01 +0100149 }
150 }
151 }
152
153 // copy positional args into state
Damien George1d899e12015-12-17 12:33:42 +0000154 for (size_t i = 0; i < n_args; i++) {
Damien Georgeb534e1b2014-09-04 14:44:01 +0100155 code_state->state[n_state - 1 - i] = args[i];
156 }
157
158 // check keyword arguments
159
Damien George3a3db4d2015-10-22 23:45:37 +0100160 if (n_kw != 0 || (scope_flags & MP_SCOPE_FLAG_DEFKWARGS) != 0) {
Damien Georgeb534e1b2014-09-04 14:44:01 +0100161 DEBUG_printf("Initial args: ");
Damien George3a3db4d2015-10-22 23:45:37 +0100162 dump_args(code_state->state + n_state - n_pos_args - n_kwonly_args, n_pos_args + n_kwonly_args);
Damien Georgeb534e1b2014-09-04 14:44:01 +0100163
164 mp_obj_t dict = MP_OBJ_NULL;
Damien George3a3db4d2015-10-22 23:45:37 +0100165 if ((scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) != 0) {
Damien Georgeb534e1b2014-09-04 14:44:01 +0100166 dict = mp_obj_new_dict(n_kw); // TODO: better go conservative with 0?
167 *var_pos_kw_args = dict;
168 }
169
Damien George9b7f5832015-03-18 17:47:47 +0000170 // get pointer to arg_names array
Damien George713ea182015-10-23 01:23:11 +0100171 const mp_obj_t *arg_names = (const mp_obj_t*)code_state->const_table;
Damien George1084b0f2014-10-25 15:07:02 +0100172
Damien George1d899e12015-12-17 12:33:42 +0000173 for (size_t i = 0; i < n_kw; i++) {
Damien Georgefea40ad2016-04-21 16:51:36 +0100174 // the keys in kwargs are expected to be qstr objects
Damien George1084b0f2014-10-25 15:07:02 +0100175 mp_obj_t wanted_arg_name = kwargs[2 * i];
Damien George1d899e12015-12-17 12:33:42 +0000176 for (size_t j = 0; j < n_pos_args + n_kwonly_args; j++) {
Damien George1084b0f2014-10-25 15:07:02 +0100177 if (wanted_arg_name == arg_names[j]) {
Damien Georgeb534e1b2014-09-04 14:44:01 +0100178 if (code_state->state[n_state - 1 - j] != MP_OBJ_NULL) {
179 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
Damien George044c4732015-04-11 13:03:37 +0100180 "function got multiple values for argument '%q'", MP_OBJ_QSTR_VALUE(wanted_arg_name)));
Damien Georgeb534e1b2014-09-04 14:44:01 +0100181 }
182 code_state->state[n_state - 1 - j] = kwargs[2 * i + 1];
183 goto continue2;
184 }
185 }
186 // Didn't find name match with positional args
Damien George3a3db4d2015-10-22 23:45:37 +0100187 if ((scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) == 0) {
Damien George7d0d7212016-10-17 12:17:37 +1100188 mp_raise_msg(&mp_type_TypeError, "function does not take keyword arguments");
Damien Georgeb534e1b2014-09-04 14:44:01 +0100189 }
190 mp_obj_dict_store(dict, kwargs[2 * i], kwargs[2 * i + 1]);
191continue2:;
192 }
193
194 DEBUG_printf("Args with kws flattened: ");
Damien George3a3db4d2015-10-22 23:45:37 +0100195 dump_args(code_state->state + n_state - n_pos_args - n_kwonly_args, n_pos_args + n_kwonly_args);
Damien Georgeb534e1b2014-09-04 14:44:01 +0100196
197 // fill in defaults for positional args
Damien George3a3db4d2015-10-22 23:45:37 +0100198 mp_obj_t *d = &code_state->state[n_state - n_pos_args];
199 mp_obj_t *s = &self->extra_args[n_def_pos_args - 1];
Damien George1d899e12015-12-17 12:33:42 +0000200 for (size_t i = n_def_pos_args; i > 0; i--, d++, s--) {
Damien Georgeb534e1b2014-09-04 14:44:01 +0100201 if (*d == MP_OBJ_NULL) {
202 *d = *s;
203 }
204 }
205
206 DEBUG_printf("Args after filling default positional: ");
Damien George3a3db4d2015-10-22 23:45:37 +0100207 dump_args(code_state->state + n_state - n_pos_args - n_kwonly_args, n_pos_args + n_kwonly_args);
Damien Georgeb534e1b2014-09-04 14:44:01 +0100208
209 // Check that all mandatory positional args are specified
210 while (d < &code_state->state[n_state]) {
211 if (*d++ == MP_OBJ_NULL) {
212 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
213 "function missing required positional argument #%d", &code_state->state[n_state] - d));
214 }
215 }
216
217 // Check that all mandatory keyword args are specified
218 // Fill in default kw args if we have them
Damien George1d899e12015-12-17 12:33:42 +0000219 for (size_t i = 0; i < n_kwonly_args; i++) {
Damien George3a3db4d2015-10-22 23:45:37 +0100220 if (code_state->state[n_state - 1 - n_pos_args - i] == MP_OBJ_NULL) {
Damien Georgeb534e1b2014-09-04 14:44:01 +0100221 mp_map_elem_t *elem = NULL;
Damien George3a3db4d2015-10-22 23:45:37 +0100222 if ((scope_flags & MP_SCOPE_FLAG_DEFKWARGS) != 0) {
Damien George999cedb2015-11-27 17:01:44 +0000223 elem = mp_map_lookup(&((mp_obj_dict_t*)MP_OBJ_TO_PTR(self->extra_args[n_def_pos_args]))->map, arg_names[n_pos_args + i], MP_MAP_LOOKUP);
Damien Georgeb534e1b2014-09-04 14:44:01 +0100224 }
225 if (elem != NULL) {
Damien George3a3db4d2015-10-22 23:45:37 +0100226 code_state->state[n_state - 1 - n_pos_args - i] = elem->value;
Damien Georgeb534e1b2014-09-04 14:44:01 +0100227 } else {
228 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
Damien George3a3db4d2015-10-22 23:45:37 +0100229 "function missing required keyword argument '%q'", MP_OBJ_QSTR_VALUE(arg_names[n_pos_args + i])));
Damien Georgeb534e1b2014-09-04 14:44:01 +0100230 }
231 }
232 }
233
234 } else {
235 // no keyword arguments given
Damien George3a3db4d2015-10-22 23:45:37 +0100236 if (n_kwonly_args != 0) {
Damien George7d0d7212016-10-17 12:17:37 +1100237 mp_raise_msg(&mp_type_TypeError, "function missing keyword-only argument");
Damien Georgeb534e1b2014-09-04 14:44:01 +0100238 }
Damien George3a3db4d2015-10-22 23:45:37 +0100239 if ((scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) != 0) {
Damien Georgeb534e1b2014-09-04 14:44:01 +0100240 *var_pos_kw_args = mp_obj_new_dict(0);
241 }
242 }
243
Damien George9b7f5832015-03-18 17:47:47 +0000244 // get the ip and skip argument names
245 const byte *ip = code_state->ip;
Damien George9b7f5832015-03-18 17:47:47 +0000246
247 // store pointer to code_info and jump over it
248 {
249 code_state->code_info = ip;
250 const byte *ip2 = ip;
Damien George1d899e12015-12-17 12:33:42 +0000251 size_t code_info_size = mp_decode_uint(&ip2);
Damien George9b7f5832015-03-18 17:47:47 +0000252 ip += code_info_size;
253 }
254
Damien Georgeb534e1b2014-09-04 14:44:01 +0100255 // bytecode prelude: initialise closed over variables
Damien George1d899e12015-12-17 12:33:42 +0000256 size_t local_num;
Damien Georgec9aa1882015-04-07 00:08:17 +0100257 while ((local_num = *ip++) != 255) {
258 code_state->state[n_state - 1 - local_num] =
259 mp_obj_new_cell(code_state->state[n_state - 1 - local_num]);
Damien Georgeb534e1b2014-09-04 14:44:01 +0100260 }
261
262 // now that we skipped over the prelude, set the ip for the VM
263 code_state->ip = ip;
264
Damien George3a3db4d2015-10-22 23:45:37 +0100265 DEBUG_printf("Calling: n_pos_args=%d, n_kwonly_args=%d\n", n_pos_args, n_kwonly_args);
266 dump_args(code_state->state + n_state - n_pos_args - n_kwonly_args, n_pos_args + n_kwonly_args);
Damien Georgeb534e1b2014-09-04 14:44:01 +0100267 dump_args(code_state->state, n_state);
268}
Damien Georged8c834c2015-11-02 21:55:42 +0000269
270#if MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE
271
272// The following table encodes the number of bytes that a specific opcode
273// takes up. There are 3 special opcodes that always have an extra byte:
274// MP_BC_MAKE_CLOSURE
275// MP_BC_MAKE_CLOSURE_DEFARGS
276// MP_BC_RAISE_VARARGS
277// There are 4 special opcodes that have an extra byte only when
278// MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE is enabled:
279// MP_BC_LOAD_NAME
280// MP_BC_LOAD_GLOBAL
281// MP_BC_LOAD_ATTR
282// MP_BC_STORE_ATTR
283#define OC4(a, b, c, d) (a | (b << 2) | (c << 4) | (d << 6))
284#define U (0) // undefined opcode
285#define B (MP_OPCODE_BYTE) // single byte
286#define Q (MP_OPCODE_QSTR) // single byte plus 2-byte qstr
287#define V (MP_OPCODE_VAR_UINT) // single byte plus variable encoded unsigned int
288#define O (MP_OPCODE_OFFSET) // single byte plus 2-byte bytecode offset
289STATIC const byte opcode_format_table[64] = {
290 OC4(U, U, U, U), // 0x00-0x03
291 OC4(U, U, U, U), // 0x04-0x07
292 OC4(U, U, U, U), // 0x08-0x0b
293 OC4(U, U, U, U), // 0x0c-0x0f
294 OC4(B, B, B, U), // 0x10-0x13
295 OC4(V, U, Q, V), // 0x14-0x17
296 OC4(B, U, V, V), // 0x18-0x1b
297 OC4(Q, Q, Q, Q), // 0x1c-0x1f
298 OC4(B, B, V, V), // 0x20-0x23
299 OC4(Q, Q, Q, B), // 0x24-0x27
300 OC4(V, V, Q, Q), // 0x28-0x2b
301 OC4(U, U, U, U), // 0x2c-0x2f
302 OC4(B, B, B, B), // 0x30-0x33
303 OC4(B, O, O, O), // 0x34-0x37
304 OC4(O, O, U, U), // 0x38-0x3b
305 OC4(U, O, B, O), // 0x3c-0x3f
306 OC4(O, B, B, O), // 0x40-0x43
Damien George7b05b1b2016-01-28 16:11:41 +0000307 OC4(B, B, O, U), // 0x44-0x47
Damien Georged8c834c2015-11-02 21:55:42 +0000308 OC4(U, U, U, U), // 0x48-0x4b
309 OC4(U, U, U, U), // 0x4c-0x4f
Damien George7df92912016-09-23 12:48:57 +1000310 OC4(V, V, U, V), // 0x50-0x53
311 OC4(B, U, V, V), // 0x54-0x57
Damien Georged8c834c2015-11-02 21:55:42 +0000312 OC4(V, V, V, B), // 0x58-0x5b
313 OC4(B, B, B, U), // 0x5c-0x5f
314 OC4(V, V, V, V), // 0x60-0x63
315 OC4(V, V, V, V), // 0x64-0x67
316 OC4(Q, Q, B, U), // 0x68-0x6b
317 OC4(U, U, U, U), // 0x6c-0x6f
318
319 OC4(B, B, B, B), // 0x70-0x73
320 OC4(B, B, B, B), // 0x74-0x77
321 OC4(B, B, B, B), // 0x78-0x7b
322 OC4(B, B, B, B), // 0x7c-0x7f
323 OC4(B, B, B, B), // 0x80-0x83
324 OC4(B, B, B, B), // 0x84-0x87
325 OC4(B, B, B, B), // 0x88-0x8b
326 OC4(B, B, B, B), // 0x8c-0x8f
327 OC4(B, B, B, B), // 0x90-0x93
328 OC4(B, B, B, B), // 0x94-0x97
329 OC4(B, B, B, B), // 0x98-0x9b
330 OC4(B, B, B, B), // 0x9c-0x9f
331 OC4(B, B, B, B), // 0xa0-0xa3
332 OC4(B, B, B, B), // 0xa4-0xa7
333 OC4(B, B, B, B), // 0xa8-0xab
334 OC4(B, B, B, B), // 0xac-0xaf
335
336 OC4(B, B, B, B), // 0xb0-0xb3
337 OC4(B, B, B, B), // 0xb4-0xb7
338 OC4(B, B, B, B), // 0xb8-0xbb
339 OC4(B, B, B, B), // 0xbc-0xbf
340
341 OC4(B, B, B, B), // 0xc0-0xc3
342 OC4(B, B, B, B), // 0xc4-0xc7
343 OC4(B, B, B, B), // 0xc8-0xcb
344 OC4(B, B, B, B), // 0xcc-0xcf
345
346 OC4(B, B, B, B), // 0xd0-0xd3
347 OC4(B, B, B, B), // 0xd4-0xd7
348 OC4(B, B, B, B), // 0xd8-0xdb
349 OC4(B, B, B, B), // 0xdc-0xdf
350
351 OC4(B, B, B, B), // 0xe0-0xe3
352 OC4(B, B, B, B), // 0xe4-0xe7
353 OC4(B, B, B, B), // 0xe8-0xeb
354 OC4(B, B, B, B), // 0xec-0xef
355
356 OC4(B, B, B, B), // 0xf0-0xf3
357 OC4(B, B, B, B), // 0xf4-0xf7
Damien George7b05b1b2016-01-28 16:11:41 +0000358 OC4(B, B, B, U), // 0xf8-0xfb
Damien Georged8c834c2015-11-02 21:55:42 +0000359 OC4(U, U, U, U), // 0xfc-0xff
360};
361#undef OC4
362#undef U
363#undef B
364#undef Q
365#undef V
366#undef O
367
368uint mp_opcode_format(const byte *ip, size_t *opcode_size) {
369 uint f = (opcode_format_table[*ip >> 2] >> (2 * (*ip & 3))) & 3;
370 const byte *ip_start = ip;
371 if (f == MP_OPCODE_QSTR) {
372 ip += 3;
373 } else {
374 int extra_byte = (
375 *ip == MP_BC_RAISE_VARARGS
376 || *ip == MP_BC_MAKE_CLOSURE
377 || *ip == MP_BC_MAKE_CLOSURE_DEFARGS
378 #if MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
379 || *ip == MP_BC_LOAD_NAME
380 || *ip == MP_BC_LOAD_GLOBAL
381 || *ip == MP_BC_LOAD_ATTR
382 || *ip == MP_BC_STORE_ATTR
383 #endif
384 );
385 ip += 1;
386 if (f == MP_OPCODE_VAR_UINT) {
387 while ((*ip++ & 0x80) != 0) {
388 }
389 } else if (f == MP_OPCODE_OFFSET) {
390 ip += 2;
391 }
392 ip += extra_byte;
393 }
394 *opcode_size = ip - ip_start;
395 return f;
396}
397
398#endif // MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE