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 
77 const byte *mp_showbc_code_start;
78 const mp_uint_t *mp_showbc_const_table;
79 
mp_bytecode_print(const mp_print_t * print,const void * descr,const byte * ip,mp_uint_t len,const mp_uint_t * const_table)80 void 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 
mp_bytecode_print_str(const mp_print_t * print,const byte * ip)153 const 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 = ((mp_uint_t)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 
mp_bytecode_print2(const mp_print_t * print,const byte * ip,size_t len,const mp_uint_t * const_table)549 void 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