LCOV - code coverage report
Current view: top level - py - bc.h (source / functions) Hit Total Coverage
Test: unix_coverage_v1.24.0-148-g136058496.info Lines: 23 23 100.0 %
Date: 2024-12-20 19:05:39 Functions: 1 1 100.0 %
Branches: 6 6 100.0 %

           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                 :       4929 : 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                 :       4929 :     size_t nq = (n_qstr * sizeof(qstr_short_t) + sizeof(mp_uint_t) - 1) / sizeof(mp_uint_t);
     298                 :       4929 :     size_t no = n_obj;
     299                 :       4929 :     mp_uint_t *mem = m_new(mp_uint_t, nq + no);
     300                 :       4929 :     context->constants.qstr_table = (qstr_short_t *)mem;
     301                 :       4929 :     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                 :       4929 : }
     310                 :            : 
     311                 :     154333 : static inline size_t mp_bytecode_get_source_line(const byte *line_info, const byte *line_info_top, size_t bc_offset) {
     312                 :     154333 :     size_t source_line = 1;
     313         [ +  + ]:    1098480 :     while (line_info < line_info_top) {
     314                 :     954133 :         size_t c = *line_info;
     315                 :     954133 :         size_t b, l;
     316         [ +  + ]:     954133 :         if ((c & 0x80) == 0) {
     317                 :            :             // 0b0LLBBBBB encoding
     318                 :     802080 :             b = c & 0x1f;
     319                 :     802080 :             l = c >> 5;
     320                 :     802080 :             line_info += 1;
     321                 :            :         } else {
     322                 :            :             // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte)
     323                 :     152053 :             b = c & 0xf;
     324                 :     152053 :             l = ((c << 4) & 0x700) | line_info[1];
     325                 :     152053 :             line_info += 2;
     326                 :            :         }
     327         [ +  + ]:     954133 :         if (bc_offset >= b) {
     328                 :     944147 :             bc_offset -= b;
     329                 :     944147 :             source_line += l;
     330                 :            :         } else {
     331                 :            :             // found source line corresponding to bytecode offset
     332                 :            :             break;
     333                 :            :         }
     334                 :            :     }
     335                 :     154333 :     return source_line;
     336                 :            : }
     337                 :            : 
     338                 :            : #endif // MICROPY_INCLUDED_PY_BC_H

Generated by: LCOV version 1.15-5-g462f71d