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 *
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 <assert.h>
29
30#include "py/bc0.h"
31#include "py/bc.h"
32
33#if MICROPY_DEBUG_PRINTERS
34
35#define DECODE_UINT { \
36 unum = 0; \
37 do { \
38 unum = (unum << 7) + (*ip & 0x7f); \
39 } while ((*ip++ & 0x80) != 0); \
40}
41#define DECODE_ULABEL do { unum = (ip[0] | (ip[1] << 8)); ip += 2; } while (0)
42#define DECODE_SLABEL do { unum = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2; } while (0)
43
44#if MICROPY_PERSISTENT_CODE
45
46#define DECODE_QSTR \
47 qst = ip[0] | ip[1] << 8; \
48 ip += 2;
49#define DECODE_PTR \
50 DECODE_UINT; \
51 unum = mp_showbc_const_table[unum]
52#define DECODE_OBJ \
53 DECODE_UINT; \
54 unum = mp_showbc_const_table[unum]
55
56#else
57
58#define DECODE_QSTR { \
59 qst = 0; \
60 do { \
61 qst = (qst << 7) + (*ip & 0x7f); \
62 } while ((*ip++ & 0x80) != 0); \
63}
64#define DECODE_PTR do { \
65 ip = (byte *)MP_ALIGN(ip, sizeof(void *)); \
66 unum = (uintptr_t)*(void **)ip; \
67 ip += sizeof(void *); \
68} while (0)
69#define DECODE_OBJ do { \
70 ip = (byte *)MP_ALIGN(ip, sizeof(mp_obj_t)); \
71 unum = (mp_uint_t)*(mp_obj_t *)ip; \
72 ip += sizeof(mp_obj_t); \
73} while (0)
74
75#endif
76
77const byte *mp_showbc_code_start;
78const mp_uint_t *mp_showbc_const_table;
79
80void mp_bytecode_print(const mp_print_t *print, const void *descr, const byte *ip, mp_uint_t len, const mp_uint_t *const_table) {
81 mp_showbc_code_start = ip;
82
83 // Decode prelude
84 MP_BC_PRELUDE_SIG_DECODE(ip);
85 MP_BC_PRELUDE_SIZE_DECODE(ip);
86 const byte *code_info = ip;
87
88 #if MICROPY_PERSISTENT_CODE
89 qstr block_name = code_info[0] | (code_info[1] << 8);
90 qstr source_file = code_info[2] | (code_info[3] << 8);
91 code_info += 4;
92 #else
93 qstr block_name = mp_decode_uint(&code_info);
94 qstr source_file = mp_decode_uint(&code_info);
95 #endif
96 mp_printf(print, "File %s, code block '%s' (descriptor: %p, bytecode @%p " UINT_FMT " bytes)\n",
97 qstr_str(source_file), qstr_str(block_name), descr, mp_showbc_code_start, len);
98
99 // raw bytecode dump
100 size_t prelude_size = ip - mp_showbc_code_start + n_info + n_cell;
101 mp_printf(print, "Raw bytecode (code_info_size=" UINT_FMT ", bytecode_size=" UINT_FMT "):\n",
102 prelude_size, len - prelude_size);
103 for (mp_uint_t i = 0; i < len; i++) {
104 if (i > 0 && i % 16 == 0) {
105 mp_printf(print, "\n");
106 }
107 mp_printf(print, " %02x", mp_showbc_code_start[i]);
108 }
109 mp_printf(print, "\n");
110
111 // bytecode prelude: arg names (as qstr objects)
112 mp_printf(print, "arg names:");
113 for (mp_uint_t i = 0; i < n_pos_args + n_kwonly_args; i++) {
114 mp_printf(print, " %s", qstr_str(MP_OBJ_QSTR_VALUE(const_table[i])));
115 }
116 mp_printf(print, "\n");
117
118 mp_printf(print, "(N_STATE %u)\n", (unsigned)n_state);
119 mp_printf(print, "(N_EXC_STACK %u)\n", (unsigned)n_exc_stack);
120
121 // skip over code_info
122 ip += n_info;
123
124 // bytecode prelude: initialise closed over variables
125 for (size_t i = 0; i < n_cell; ++i) {
126 uint local_num = *ip++;
127 mp_printf(print, "(INIT_CELL %u)\n", local_num);
128 }
129
130 // print out line number info
131 {
132 mp_int_t bc = 0;
133 mp_uint_t source_line = 1;
134 mp_printf(print, " bc=" INT_FMT " line=" UINT_FMT "\n", bc, source_line);
135 for (const byte *ci = code_info; *ci;) {
136 if ((ci[0] & 0x80) == 0) {
137 // 0b0LLBBBBB encoding
138 bc += ci[0] & 0x1f;
139 source_line += ci[0] >> 5;
140 ci += 1;
141 } else {
142 // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte)
143 bc += ci[0] & 0xf;
144 source_line += ((ci[0] << 4) & 0x700) | ci[1];
145 ci += 2;
146 }
147 mp_printf(print, " bc=" INT_FMT " line=" UINT_FMT "\n", bc, source_line);
148 }
149 }
150 mp_bytecode_print2(print, ip, len - prelude_size, const_table);
151}
152
153const byte *mp_bytecode_print_str(const mp_print_t *print, const byte *ip) {
154 mp_uint_t unum;
155 qstr qst;
156
157 switch (*ip++) {
158 case MP_BC_LOAD_CONST_FALSE:
159 mp_printf(print, "LOAD_CONST_FALSE");
160 break;
161
162 case MP_BC_LOAD_CONST_NONE:
163 mp_printf(print, "LOAD_CONST_NONE");
164 break;
165
166 case MP_BC_LOAD_CONST_TRUE:
167 mp_printf(print, "LOAD_CONST_TRUE");
168 break;
169
170 case MP_BC_LOAD_CONST_SMALL_INT: {
171 mp_int_t num = 0;
172 if ((ip[0] & 0x40) != 0) {
173 // Number is negative
174 num--;
175 }
176 do {
177 num = (num << 7) | (*ip & 0x7f);
178 } while ((*ip++ & 0x80) != 0);
179 mp_printf(print, "LOAD_CONST_SMALL_INT " INT_FMT, num);
180 break;
181 }
182
183 case MP_BC_LOAD_CONST_STRING:
184 DECODE_QSTR;
185 mp_printf(print, "LOAD_CONST_STRING '%s'", qstr_str(qst));
186 break;
187
188 case MP_BC_LOAD_CONST_OBJ:
189 DECODE_OBJ;
190 mp_printf(print, "LOAD_CONST_OBJ %p=", MP_OBJ_TO_PTR(unum));
191 mp_obj_print_helper(print, (mp_obj_t)unum, PRINT_REPR);
192 break;
193
194 case MP_BC_LOAD_NULL:
195 mp_printf(print, "LOAD_NULL");
196 break;
197
198 case MP_BC_LOAD_FAST_N:
199 DECODE_UINT;
200 mp_printf(print, "LOAD_FAST_N " UINT_FMT, unum);
201 break;
202
203 case MP_BC_LOAD_DEREF:
204 DECODE_UINT;
205 mp_printf(print, "LOAD_DEREF " UINT_FMT, unum);
206 break;
207
208 case MP_BC_LOAD_NAME:
209 DECODE_QSTR;
210 mp_printf(print, "LOAD_NAME %s", qstr_str(qst));
211 if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) {
212 mp_printf(print, " (cache=%u)", *ip++);
213 }
214 break;
215
216 case MP_BC_LOAD_GLOBAL:
217 DECODE_QSTR;
218 mp_printf(print, "LOAD_GLOBAL %s", qstr_str(qst));
219 if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) {
220 mp_printf(print, " (cache=%u)", *ip++);
221 }
222 break;
223
224 case MP_BC_LOAD_ATTR:
225 DECODE_QSTR;
226 mp_printf(print, "LOAD_ATTR %s", qstr_str(qst));
227 if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) {
228 mp_printf(print, " (cache=%u)", *ip++);
229 }
230 break;
231
232 case MP_BC_LOAD_METHOD:
233 DECODE_QSTR;
234 mp_printf(print, "LOAD_METHOD %s", qstr_str(qst));
235 break;
236
237 case MP_BC_LOAD_SUPER_METHOD:
238 DECODE_QSTR;
239 mp_printf(print, "LOAD_SUPER_METHOD %s", qstr_str(qst));
240 break;
241
242 case MP_BC_LOAD_BUILD_CLASS:
243 mp_printf(print, "LOAD_BUILD_CLASS");
244 break;
245
246 case MP_BC_LOAD_SUBSCR:
247 mp_printf(print, "LOAD_SUBSCR");
248 break;
249
250 case MP_BC_STORE_FAST_N:
251 DECODE_UINT;
252 mp_printf(print, "STORE_FAST_N " UINT_FMT, unum);
253 break;
254
255 case MP_BC_STORE_DEREF:
256 DECODE_UINT;
257 mp_printf(print, "STORE_DEREF " UINT_FMT, unum);
258 break;
259
260 case MP_BC_STORE_NAME:
261 DECODE_QSTR;
262 mp_printf(print, "STORE_NAME %s", qstr_str(qst));
263 break;
264
265 case MP_BC_STORE_GLOBAL:
266 DECODE_QSTR;
267 mp_printf(print, "STORE_GLOBAL %s", qstr_str(qst));
268 break;
269
270 case MP_BC_STORE_ATTR:
271 DECODE_QSTR;
272 mp_printf(print, "STORE_ATTR %s", qstr_str(qst));
273 if (MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) {
274 mp_printf(print, " (cache=%u)", *ip++);
275 }
276 break;
277
278 case MP_BC_STORE_SUBSCR:
279 mp_printf(print, "STORE_SUBSCR");
280 break;
281
282 case MP_BC_DELETE_FAST:
283 DECODE_UINT;
284 mp_printf(print, "DELETE_FAST " UINT_FMT, unum);
285 break;
286
287 case MP_BC_DELETE_DEREF:
288 DECODE_UINT;
289 mp_printf(print, "DELETE_DEREF " UINT_FMT, unum);
290 break;
291
292 case MP_BC_DELETE_NAME:
293 DECODE_QSTR;
294 mp_printf(print, "DELETE_NAME %s", qstr_str(qst));
295 break;
296
297 case MP_BC_DELETE_GLOBAL:
298 DECODE_QSTR;
299 mp_printf(print, "DELETE_GLOBAL %s", qstr_str(qst));
300 break;
301
302 case MP_BC_DUP_TOP:
303 mp_printf(print, "DUP_TOP");
304 break;
305
306 case MP_BC_DUP_TOP_TWO:
307 mp_printf(print, "DUP_TOP_TWO");
308 break;
309
310 case MP_BC_POP_TOP:
311 mp_printf(print, "POP_TOP");
312 break;
313
314 case MP_BC_ROT_TWO:
315 mp_printf(print, "ROT_TWO");
316 break;
317
318 case MP_BC_ROT_THREE:
319 mp_printf(print, "ROT_THREE");
320 break;
321
322 case MP_BC_JUMP:
323 DECODE_SLABEL;
324 mp_printf(print, "JUMP " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));
325 break;
326
327 case MP_BC_POP_JUMP_IF_TRUE:
328 DECODE_SLABEL;
329 mp_printf(print, "POP_JUMP_IF_TRUE " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));
330 break;
331
332 case MP_BC_POP_JUMP_IF_FALSE:
333 DECODE_SLABEL;
334 mp_printf(print, "POP_JUMP_IF_FALSE " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));
335 break;
336
337 case MP_BC_JUMP_IF_TRUE_OR_POP:
338 DECODE_SLABEL;
339 mp_printf(print, "JUMP_IF_TRUE_OR_POP " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));
340 break;
341
342 case MP_BC_JUMP_IF_FALSE_OR_POP:
343 DECODE_SLABEL;
344 mp_printf(print, "JUMP_IF_FALSE_OR_POP " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));
345 break;
346
347 case MP_BC_SETUP_WITH:
348 DECODE_ULABEL; // loop-like labels are always forward
349 mp_printf(print, "SETUP_WITH " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));
350 break;
351
352 case MP_BC_WITH_CLEANUP:
353 mp_printf(print, "WITH_CLEANUP");
354 break;
355
356 case MP_BC_UNWIND_JUMP:
357 DECODE_SLABEL;
358 mp_printf(print, "UNWIND_JUMP " UINT_FMT " %d", (mp_uint_t)(ip + unum - mp_showbc_code_start), *ip);
359 ip += 1;
360 break;
361
362 case MP_BC_SETUP_EXCEPT:
363 DECODE_ULABEL; // except labels are always forward
364 mp_printf(print, "SETUP_EXCEPT " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));
365 break;
366
367 case MP_BC_SETUP_FINALLY:
368 DECODE_ULABEL; // except labels are always forward
369 mp_printf(print, "SETUP_FINALLY " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));
370 break;
371
372 case MP_BC_END_FINALLY:
373 // if TOS is an exception, reraises the exception (3 values on TOS)
374 // if TOS is an integer, does something else
375 // if TOS is None, just pops it and continues
376 // else error
377 mp_printf(print, "END_FINALLY");
378 break;
379
380 case MP_BC_GET_ITER:
381 mp_printf(print, "GET_ITER");
382 break;
383
384 case MP_BC_GET_ITER_STACK:
385 mp_printf(print, "GET_ITER_STACK");
386 break;
387
388 case MP_BC_FOR_ITER:
389 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
390 mp_printf(print, "FOR_ITER " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));
391 break;
392
393 case MP_BC_POP_EXCEPT_JUMP:
394 DECODE_ULABEL; // these labels are always forward
395 mp_printf(print, "POP_EXCEPT_JUMP " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));
396 break;
397
398 case MP_BC_BUILD_TUPLE:
399 DECODE_UINT;
400 mp_printf(print, "BUILD_TUPLE " UINT_FMT, unum);
401 break;
402
403 case MP_BC_BUILD_LIST:
404 DECODE_UINT;
405 mp_printf(print, "BUILD_LIST " UINT_FMT, unum);
406 break;
407
408 case MP_BC_BUILD_MAP:
409 DECODE_UINT;
410 mp_printf(print, "BUILD_MAP " UINT_FMT, unum);
411 break;
412
413 case MP_BC_STORE_MAP:
414 mp_printf(print, "STORE_MAP");
415 break;
416
417 case MP_BC_BUILD_SET:
418 DECODE_UINT;
419 mp_printf(print, "BUILD_SET " UINT_FMT, unum);
420 break;
421
422 #if MICROPY_PY_BUILTINS_SLICE
423 case MP_BC_BUILD_SLICE:
424 DECODE_UINT;
425 mp_printf(print, "BUILD_SLICE " UINT_FMT, unum);
426 break;
427 #endif
428
429 case MP_BC_STORE_COMP:
430 DECODE_UINT;
431 mp_printf(print, "STORE_COMP " UINT_FMT, unum);
432 break;
433
434 case MP_BC_UNPACK_SEQUENCE:
435 DECODE_UINT;
436 mp_printf(print, "UNPACK_SEQUENCE " UINT_FMT, unum);
437 break;
438
439 case MP_BC_UNPACK_EX:
440 DECODE_UINT;
441 mp_printf(print, "UNPACK_EX " UINT_FMT, unum);
442 break;
443
444 case MP_BC_MAKE_FUNCTION:
445 DECODE_PTR;
446 mp_printf(print, "MAKE_FUNCTION %p", (void *)(uintptr_t)unum);
447 break;
448
449 case MP_BC_MAKE_FUNCTION_DEFARGS:
450 DECODE_PTR;
451 mp_printf(print, "MAKE_FUNCTION_DEFARGS %p", (void *)(uintptr_t)unum);
452 break;
453
454 case MP_BC_MAKE_CLOSURE: {
455 DECODE_PTR;
456 mp_uint_t n_closed_over = *ip++;
457 mp_printf(print, "MAKE_CLOSURE %p " UINT_FMT, (void *)(uintptr_t)unum, n_closed_over);
458 break;
459 }
460
461 case MP_BC_MAKE_CLOSURE_DEFARGS: {
462 DECODE_PTR;
463 mp_uint_t n_closed_over = *ip++;
464 mp_printf(print, "MAKE_CLOSURE_DEFARGS %p " UINT_FMT, (void *)(uintptr_t)unum, n_closed_over);
465 break;
466 }
467
468 case MP_BC_CALL_FUNCTION:
469 DECODE_UINT;
470 mp_printf(print, "CALL_FUNCTION n=" UINT_FMT " nkw=" UINT_FMT, unum & 0xff, (unum >> 8) & 0xff);
471 break;
472
473 case MP_BC_CALL_FUNCTION_VAR_KW:
474 DECODE_UINT;
475 mp_printf(print, "CALL_FUNCTION_VAR_KW n=" UINT_FMT " nkw=" UINT_FMT, unum & 0xff, (unum >> 8) & 0xff);
476 break;
477
478 case MP_BC_CALL_METHOD:
479 DECODE_UINT;
480 mp_printf(print, "CALL_METHOD n=" UINT_FMT " nkw=" UINT_FMT, unum & 0xff, (unum >> 8) & 0xff);
481 break;
482
483 case MP_BC_CALL_METHOD_VAR_KW:
484 DECODE_UINT;
485 mp_printf(print, "CALL_METHOD_VAR_KW n=" UINT_FMT " nkw=" UINT_FMT, unum & 0xff, (unum >> 8) & 0xff);
486 break;
487
488 case MP_BC_RETURN_VALUE:
489 mp_printf(print, "RETURN_VALUE");
490 break;
491
492 case MP_BC_RAISE_LAST:
493 mp_printf(print, "RAISE_LAST");
494 break;
495
496 case MP_BC_RAISE_OBJ:
497 mp_printf(print, "RAISE_OBJ");
498 break;
499
500 case MP_BC_RAISE_FROM:
501 mp_printf(print, "RAISE_FROM");
502 break;
503
504 case MP_BC_YIELD_VALUE:
505 mp_printf(print, "YIELD_VALUE");
506 break;
507
508 case MP_BC_YIELD_FROM:
509 mp_printf(print, "YIELD_FROM");
510 break;
511
512 case MP_BC_IMPORT_NAME:
513 DECODE_QSTR;
514 mp_printf(print, "IMPORT_NAME '%s'", qstr_str(qst));
515 break;
516
517 case MP_BC_IMPORT_FROM:
518 DECODE_QSTR;
519 mp_printf(print, "IMPORT_FROM '%s'", qstr_str(qst));
520 break;
521
522 case MP_BC_IMPORT_STAR:
523 mp_printf(print, "IMPORT_STAR");
524 break;
525
526 default:
527 if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + 64) {
528 mp_printf(print, "LOAD_CONST_SMALL_INT " INT_FMT, (mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16);
529 } else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + 16) {
530 mp_printf(print, "LOAD_FAST " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_LOAD_FAST_MULTI);
531 } else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) {
532 mp_printf(print, "STORE_FAST " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_STORE_FAST_MULTI);
533 } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_NUM_BYTECODE) {
534 mp_printf(print, "UNARY_OP " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_UNARY_OP_MULTI);
535 } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + MP_BINARY_OP_NUM_BYTECODE) {
536 mp_uint_t op = ip[-1] - MP_BC_BINARY_OP_MULTI;
537 mp_printf(print, "BINARY_OP " UINT_FMT " %s", op, qstr_str(mp_binary_op_method_name[op]));
538 } else {
539 mp_printf(print, "code %p, byte code 0x%02x not implemented\n", ip - 1, ip[-1]);
540 assert(0);
541 return ip;
542 }
543 break;
544 }
545
546 return ip;
547}
548
549void mp_bytecode_print2(const mp_print_t *print, const byte *ip, size_t len, const mp_uint_t *const_table) {
550 mp_showbc_code_start = ip;
551 mp_showbc_const_table = const_table;
552 while (ip < len + mp_showbc_code_start) {
553 mp_printf(print, "%02u ", (uint)(ip - mp_showbc_code_start));
554 ip = mp_bytecode_print_str(print, ip);
555 mp_printf(print, "\n");
556 }
557}
558
559#endif // MICROPY_DEBUG_PRINTERS
560