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) 2013, 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 : : #ifndef MICROPY_INCLUDED_PY_BC_H
28 : : #define MICROPY_INCLUDED_PY_BC_H
29 : :
30 : : #include "py/runtime.h"
31 : :
32 : : // bytecode layout:
33 : : //
34 : : // func signature : var uint
35 : : // contains six values interleaved bit-wise as: xSSSSEAA [xFSSKAED repeated]
36 : : // x = extension another byte follows
37 : : // S = n_state - 1 number of entries in Python value stack
38 : : // E = n_exc_stack number of entries in exception stack
39 : : // F = scope_flags four bits of flags, MP_SCOPE_FLAG_xxx
40 : : // A = n_pos_args number of arguments this function takes
41 : : // K = n_kwonly_args number of keyword-only arguments this function takes
42 : : // D = n_def_pos_args number of default positional arguments
43 : : //
44 : : // prelude size : var uint
45 : : // contains two values interleaved bit-wise as: xIIIIIIC repeated
46 : : // x = extension another byte follows
47 : : // I = n_info number of bytes in source info section (always > 0)
48 : : // C = n_cells number of bytes/cells in closure section
49 : : //
50 : : // source info section:
51 : : // simple_name : var qstr always exists
52 : : // argname0 : var qstr
53 : : // ... : var qstr
54 : : // argnameN : var qstr N = num_pos_args + num_kwonly_args - 1
55 : : // <line number info>
56 : : //
57 : : // closure section:
58 : : // local_num0 : byte
59 : : // ... : byte
60 : : // local_numN : byte N = n_cells-1
61 : : //
62 : : // <bytecode>
63 : : //
64 : : //
65 : : // constant table layout:
66 : : //
67 : : // const0 : obj
68 : : // constN : obj
69 : :
70 : : #define MP_ENCODE_UINT_MAX_BYTES ((MP_BYTES_PER_OBJ_WORD * 8 + 6) / 7)
71 : :
72 : : #define MP_BC_PRELUDE_SIG_ENCODE(S, E, scope, out_byte, out_env) \
73 : : do { \
74 : : /*// Get values to store in prelude */ \
75 : : size_t F = scope->scope_flags & MP_SCOPE_FLAG_ALL_SIG; \
76 : : size_t A = scope->num_pos_args; \
77 : : size_t K = scope->num_kwonly_args; \
78 : : size_t D = scope->num_def_pos_args; \
79 : : \
80 : : /* Adjust S to shrink range, to compress better */ \
81 : : S -= 1; \
82 : : \
83 : : /* Encode prelude */ \
84 : : /* xSSSSEAA */ \
85 : : uint8_t z = (S & 0xf) << 3 | (E & 1) << 2 | (A & 3); \
86 : : S >>= 4; \
87 : : E >>= 1; \
88 : : A >>= 2; \
89 : : while (S | E | F | A | K | D) { \
90 : : out_byte(out_env, 0x80 | z); \
91 : : /* xFSSKAED */ \
92 : : z = (F & 1) << 6 | (S & 3) << 4 | (K & 1) << 3 \
93 : : | (A & 1) << 2 | (E & 1) << 1 | (D & 1); \
94 : : S >>= 2; \
95 : : E >>= 1; \
96 : : F >>= 1; \
97 : : A >>= 1; \
98 : : K >>= 1; \
99 : : D >>= 1; \
100 : : } \
101 : : out_byte(out_env, z); \
102 : : } while (0)
103 : :
104 : : #define MP_BC_PRELUDE_SIG_DECODE_INTO(ip, S, E, F, A, K, D) \
105 : : do { \
106 : : uint8_t z = *(ip)++; \
107 : : /* xSSSSEAA */ \
108 : : S = (z >> 3) & 0xf; \
109 : : E = (z >> 2) & 0x1; \
110 : : F = 0; \
111 : : A = z & 0x3; \
112 : : K = 0; \
113 : : D = 0; \
114 : : for (unsigned n = 0; z & 0x80; ++n) { \
115 : : z = *(ip)++; \
116 : : /* xFSSKAED */ \
117 : : S |= (z & 0x30) << (2 * n); \
118 : : E |= (z & 0x02) << n; \
119 : : F |= ((z & 0x40) >> 6) << n; \
120 : : A |= (z & 0x4) << n; \
121 : : K |= ((z & 0x08) >> 3) << n; \
122 : : D |= (z & 0x1) << n; \
123 : : } \
124 : : S += 1; \
125 : : } while (0)
126 : :
127 : : #define MP_BC_PRELUDE_SIG_DECODE(ip) \
128 : : size_t n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args; \
129 : : MP_BC_PRELUDE_SIG_DECODE_INTO(ip, n_state, n_exc_stack, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args); \
130 : : (void)n_state; (void)n_exc_stack; (void)scope_flags; \
131 : : (void)n_pos_args; (void)n_kwonly_args; (void)n_def_pos_args
132 : :
133 : : #define MP_BC_PRELUDE_SIZE_ENCODE(I, C, out_byte, out_env) \
134 : : do { \
135 : : /* Encode bit-wise as: xIIIIIIC */ \
136 : : uint8_t z = 0; \
137 : : do { \
138 : : z = (I & 0x3f) << 1 | (C & 1); \
139 : : C >>= 1; \
140 : : I >>= 6; \
141 : : if (C | I) { \
142 : : z |= 0x80; \
143 : : } \
144 : : out_byte(out_env, z); \
145 : : } while (C | I); \
146 : : } while (0)
147 : :
148 : : #define MP_BC_PRELUDE_SIZE_DECODE_INTO(ip, I, C) \
149 : : do { \
150 : : uint8_t z; \
151 : : C = 0; \
152 : : I = 0; \
153 : : for (unsigned n = 0;; ++n) { \
154 : : z = *(ip)++; \
155 : : /* xIIIIIIC */ \
156 : : C |= (z & 1) << n; \
157 : : I |= ((z & 0x7e) >> 1) << (6 * n); \
158 : : if (!(z & 0x80)) { \
159 : : break; \
160 : : } \
161 : : } \
162 : : } while (0)
163 : :
164 : : #define MP_BC_PRELUDE_SIZE_DECODE(ip) \
165 : : size_t n_info, n_cell; \
166 : : MP_BC_PRELUDE_SIZE_DECODE_INTO(ip, n_info, n_cell); \
167 : : (void)n_info; (void)n_cell
168 : :
169 : : // Sentinel value for mp_code_state_t.exc_sp_idx
170 : : #define MP_CODE_STATE_EXC_SP_IDX_SENTINEL ((uint16_t)-1)
171 : :
172 : : // To convert mp_code_state_t.exc_sp_idx to/from a pointer to mp_exc_stack_t
173 : : #define MP_CODE_STATE_EXC_SP_IDX_FROM_PTR(exc_stack, exc_sp) ((exc_sp) + 1 - (exc_stack))
174 : : #define MP_CODE_STATE_EXC_SP_IDX_TO_PTR(exc_stack, exc_sp_idx) ((exc_stack) + (exc_sp_idx) - 1)
175 : :
176 : : typedef struct _mp_bytecode_prelude_t {
177 : : uint n_state;
178 : : uint n_exc_stack;
179 : : uint scope_flags;
180 : : uint n_pos_args;
181 : : uint n_kwonly_args;
182 : : uint n_def_pos_args;
183 : : qstr qstr_block_name_idx;
184 : : const byte *line_info;
185 : : const byte *line_info_top;
186 : : const byte *opcodes;
187 : : } mp_bytecode_prelude_t;
188 : :
189 : : // Exception stack entry
190 : : typedef struct _mp_exc_stack_t {
191 : : const byte *handler;
192 : : // bit 0 is currently unused
193 : : // bit 1 is whether the opcode was SETUP_WITH or SETUP_FINALLY
194 : : mp_obj_t *val_sp;
195 : : // Saved exception
196 : : mp_obj_base_t *prev_exc;
197 : : } mp_exc_stack_t;
198 : :
199 : : // Constants associated with a module, to interface bytecode with runtime.
200 : : typedef struct _mp_module_constants_t {
201 : : #if MICROPY_EMIT_BYTECODE_USES_QSTR_TABLE
202 : : qstr_short_t *qstr_table;
203 : : #else
204 : : qstr source_file;
205 : : #endif
206 : : mp_obj_t *obj_table;
207 : : } mp_module_constants_t;
208 : :
209 : : // State associated with a module.
210 : : typedef struct _mp_module_context_t {
211 : : mp_obj_module_t module;
212 : : mp_module_constants_t constants;
213 : : } mp_module_context_t;
214 : :
215 : : // Outer level struct defining a compiled module.
216 : : typedef struct _mp_compiled_module_t {
217 : : mp_module_context_t *context;
218 : : const struct _mp_raw_code_t *rc;
219 : : #if MICROPY_PERSISTENT_CODE_SAVE
220 : : bool has_native;
221 : : size_t n_qstr;
222 : : size_t n_obj;
223 : : #endif
224 : : } mp_compiled_module_t;
225 : :
226 : : // Outer level struct defining a frozen module.
227 : : typedef struct _mp_frozen_module_t {
228 : : const mp_module_constants_t constants;
229 : : const void *proto_fun;
230 : : } mp_frozen_module_t;
231 : :
232 : : // State for an executing function.
233 : : typedef struct _mp_code_state_t {
234 : : // The fun_bc entry points to the underlying function object that is being executed.
235 : : // It is needed to access the start of bytecode and the const_table.
236 : : // It is also needed to prevent the GC from reclaiming the bytecode during execution,
237 : : // because the ip pointer below will always point to the interior of the bytecode.
238 : : struct _mp_obj_fun_bc_t *fun_bc;
239 : : const byte *ip;
240 : : mp_obj_t *sp;
241 : : uint16_t n_state;
242 : : uint16_t exc_sp_idx;
243 : : mp_obj_dict_t *old_globals;
244 : : #if MICROPY_STACKLESS
245 : : struct _mp_code_state_t *prev;
246 : : #endif
247 : : #if MICROPY_PY_SYS_SETTRACE
248 : : struct _mp_code_state_t *prev_state;
249 : : struct _mp_obj_frame_t *frame;
250 : : #endif
251 : : // Variable-length
252 : : mp_obj_t state[0];
253 : : // Variable-length, never accessed by name, only as (void*)(state + n_state)
254 : : // mp_exc_stack_t exc_state[0];
255 : : } mp_code_state_t;
256 : :
257 : : // State for an executing native function (based on mp_code_state_t).
258 : : typedef struct _mp_code_state_native_t {
259 : : struct _mp_obj_fun_bc_t *fun_bc;
260 : : const byte *ip;
261 : : mp_obj_t *sp;
262 : : uint16_t n_state;
263 : : uint16_t exc_sp_idx;
264 : : mp_obj_dict_t *old_globals;
265 : : mp_obj_t state[0];
266 : : } mp_code_state_native_t;
267 : :
268 : : // Allocator may return NULL, in which case data is not stored (can be used to compute size).
269 : : typedef uint8_t *(*mp_encode_uint_allocator_t)(void *env, size_t nbytes);
270 : :
271 : : void mp_encode_uint(void *env, mp_encode_uint_allocator_t allocator, mp_uint_t val);
272 : : mp_uint_t mp_decode_uint(const byte **ptr);
273 : : mp_uint_t mp_decode_uint_value(const byte *ptr);
274 : : const byte *mp_decode_uint_skip(const byte *ptr);
275 : :
276 : : mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state,
277 : : #ifndef __cplusplus
278 : : volatile
279 : : #endif
280 : : mp_obj_t inject_exc);
281 : : mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t func, size_t n_args, size_t n_kw, const mp_obj_t *args);
282 : : void mp_setup_code_state(mp_code_state_t *code_state, size_t n_args, size_t n_kw, const mp_obj_t *args);
283 : : void mp_setup_code_state_native(mp_code_state_native_t *code_state, size_t n_args, size_t n_kw, const mp_obj_t *args);
284 : : void mp_bytecode_print(const mp_print_t *print, const struct _mp_raw_code_t *rc, size_t fun_data_len, const mp_module_constants_t *cm);
285 : : void mp_bytecode_print2(const mp_print_t *print, const byte *ip, size_t len, struct _mp_raw_code_t *const *child_table, const mp_module_constants_t *cm);
286 : : const byte *mp_bytecode_print_str(const mp_print_t *print, const byte *ip_start, const byte *ip, struct _mp_raw_code_t *const *child_table, const mp_module_constants_t *cm);
287 : : #define mp_bytecode_print_inst(print, code, x_table) mp_bytecode_print2(print, code, 1, x_table)
288 : :
289 : : // Helper macros to access pointer with least significant bits holding flags
290 : : #define MP_TAGPTR_PTR(x) ((void *)((uintptr_t)(x) & ~((uintptr_t)3)))
291 : : #define MP_TAGPTR_TAG0(x) ((uintptr_t)(x) & 1)
292 : : #define MP_TAGPTR_TAG1(x) ((uintptr_t)(x) & 2)
293 : : #define MP_TAGPTR_MAKE(ptr, tag) ((void *)((uintptr_t)(ptr) | (tag)))
294 : :
295 : 4925 : static inline void mp_module_context_alloc_tables(mp_module_context_t *context, size_t n_qstr, size_t n_obj) {
296 : : #if MICROPY_EMIT_BYTECODE_USES_QSTR_TABLE
297 : 4925 : size_t nq = (n_qstr * sizeof(qstr_short_t) + sizeof(mp_uint_t) - 1) / sizeof(mp_uint_t);
298 : 4925 : size_t no = n_obj;
299 : 4925 : mp_uint_t *mem = m_new(mp_uint_t, nq + no);
300 : 4925 : context->constants.qstr_table = (qstr_short_t *)mem;
301 : 4925 : context->constants.obj_table = (mp_obj_t *)(mem + nq);
302 : : #else
303 : : if (n_obj == 0) {
304 : : context->constants.obj_table = NULL;
305 : : } else {
306 : : context->constants.obj_table = m_new(mp_obj_t, n_obj);
307 : : }
308 : : #endif
309 : 4925 : }
310 : :
311 : 159413 : static inline size_t mp_bytecode_get_source_line(const byte *line_info, const byte *line_info_top, size_t bc_offset) {
312 : 159413 : size_t source_line = 1;
313 [ + + ]: 1133405 : while (line_info < line_info_top) {
314 : 984211 : size_t c = *line_info;
315 : 984211 : size_t b, l;
316 [ + + ]: 984211 : if ((c & 0x80) == 0) {
317 : : // 0b0LLBBBBB encoding
318 : 827084 : b = c & 0x1f;
319 : 827084 : l = c >> 5;
320 : 827084 : line_info += 1;
321 : : } else {
322 : : // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte)
323 : 157127 : b = c & 0xf;
324 : 157127 : l = ((c << 4) & 0x700) | line_info[1];
325 : 157127 : line_info += 2;
326 : : }
327 [ + + ]: 984211 : if (bc_offset >= b) {
328 : 973992 : bc_offset -= b;
329 : 973992 : source_line += l;
330 : : } else {
331 : : // found source line corresponding to bytecode offset
332 : : break;
333 : : }
334 : : }
335 : 159413 : return source_line;
336 : : }
337 : :
338 : : #endif // MICROPY_INCLUDED_PY_BC_H
|