LCOV - code coverage report
Current view: top level - py - emitglue.c (source / functions) Hit Total Coverage
Test: unix_coverage_v1.19.1-724-gfb7d21153.info Lines: 46 46 100.0 %
Date: 2022-12-01 09:37:31 Functions: 5 5 100.0 %
Branches: 29 44 65.9 %

           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                 :            :  *
       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                 :            : // This code glues the code emitters to the runtime.
      28                 :            : 
      29                 :            : #include <stdint.h>
      30                 :            : #include <stdio.h>
      31                 :            : #include <string.h>
      32                 :            : #include <assert.h>
      33                 :            : 
      34                 :            : #include "py/emitglue.h"
      35                 :            : #include "py/runtime0.h"
      36                 :            : #include "py/bc.h"
      37                 :            : #include "py/objfun.h"
      38                 :            : #include "py/profile.h"
      39                 :            : 
      40                 :            : #if MICROPY_DEBUG_VERBOSE // print debugging info
      41                 :            : #define DEBUG_PRINT (1)
      42                 :            : #define WRITE_CODE (1)
      43                 :            : #define DEBUG_printf DEBUG_printf
      44                 :            : #define DEBUG_OP_printf(...) DEBUG_printf(__VA_ARGS__)
      45                 :            : #else // don't print debugging info
      46                 :            : #define DEBUG_printf(...) (void)0
      47                 :            : #define DEBUG_OP_printf(...) (void)0
      48                 :            : #endif
      49                 :            : 
      50                 :            : #if MICROPY_DEBUG_PRINTERS
      51                 :            : mp_uint_t mp_verbose_flag = 0;
      52                 :            : #endif
      53                 :            : 
      54                 :      12898 : mp_raw_code_t *mp_emit_glue_new_raw_code(void) {
      55                 :      12898 :     mp_raw_code_t *rc = m_new0(mp_raw_code_t, 1);
      56                 :      12898 :     rc->kind = MP_CODE_RESERVED;
      57                 :            :     #if MICROPY_PY_SYS_SETTRACE
      58                 :            :     rc->line_of_definition = 0;
      59                 :            :     #endif
      60                 :      12898 :     return rc;
      61                 :            : }
      62                 :            : 
      63                 :       6650 : void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code,
      64                 :            :     #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS
      65                 :            :     size_t len,
      66                 :            :     #endif
      67                 :            :     mp_raw_code_t **children,
      68                 :            :     #if MICROPY_PERSISTENT_CODE_SAVE
      69                 :            :     size_t n_children,
      70                 :            :     #endif
      71                 :            :     mp_uint_t scope_flags) {
      72                 :            : 
      73                 :       6650 :     rc->kind = MP_CODE_BYTECODE;
      74                 :       6650 :     rc->scope_flags = scope_flags;
      75                 :       6650 :     rc->fun_data = code;
      76                 :            :     #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS
      77                 :       6650 :     rc->fun_data_len = len;
      78                 :            :     #endif
      79                 :       6650 :     rc->children = children;
      80                 :            : 
      81                 :            :     #if MICROPY_PERSISTENT_CODE_SAVE
      82                 :            :     rc->n_children = n_children;
      83                 :            :     #endif
      84                 :            : 
      85                 :            :     #if MICROPY_PY_SYS_SETTRACE
      86                 :            :     mp_bytecode_prelude_t *prelude = &rc->prelude;
      87                 :            :     mp_prof_extract_prelude(code, prelude);
      88                 :            :     #endif
      89                 :            : 
      90                 :            :     #ifdef DEBUG_PRINT
      91                 :            :     #if !(MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS)
      92                 :            :     const size_t len = 0;
      93                 :            :     #endif
      94                 :            :     DEBUG_printf("assign byte code: code=%p len=" UINT_FMT " flags=%x\n", code, len, (uint)scope_flags);
      95                 :            :     #endif
      96                 :       6650 : }
      97                 :            : 
      98                 :            : #if MICROPY_EMIT_MACHINE_CODE
      99                 :       5852 : void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void *fun_data, mp_uint_t fun_len,
     100                 :            :     mp_raw_code_t **children,
     101                 :            :     #if MICROPY_PERSISTENT_CODE_SAVE
     102                 :            :     size_t n_children,
     103                 :            :     uint16_t prelude_offset,
     104                 :            :     #endif
     105                 :            :     mp_uint_t scope_flags, mp_uint_t n_pos_args, mp_uint_t type_sig) {
     106                 :            : 
     107         [ -  + ]:       5852 :     assert(kind == MP_CODE_NATIVE_PY || kind == MP_CODE_NATIVE_VIPER || kind == MP_CODE_NATIVE_ASM);
     108                 :            : 
     109                 :            :     // Some architectures require flushing/invalidation of the I/D caches,
     110                 :            :     // so that the generated native code which was created in data RAM will
     111                 :            :     // be available for execution from instruction RAM.
     112                 :            :     #if MICROPY_EMIT_THUMB || MICROPY_EMIT_INLINE_THUMB
     113                 :            :     #if __ICACHE_PRESENT == 1
     114                 :            :     // Flush D-cache, so the code emitted is stored in RAM.
     115                 :            :     MP_HAL_CLEAN_DCACHE(fun_data, fun_len);
     116                 :            :     // Invalidate I-cache, so the newly-created code is reloaded from RAM.
     117                 :            :     SCB_InvalidateICache();
     118                 :            :     #endif
     119                 :            :     #elif MICROPY_EMIT_ARM
     120                 :            :     #if (defined(__linux__) && defined(__GNUC__)) || __ARM_ARCH == 7
     121                 :            :     __builtin___clear_cache(fun_data, (uint8_t *)fun_data + fun_len);
     122                 :            :     #elif defined(__arm__)
     123                 :            :     // Flush I-cache and D-cache.
     124                 :            :     asm volatile (
     125                 :            :         "0:"
     126                 :            :         "mrc p15, 0, r15, c7, c10, 3\n" // test and clean D-cache
     127                 :            :         "bne 0b\n"
     128                 :            :         "mov r0, #0\n"
     129                 :            :         "mcr p15, 0, r0, c7, c7, 0\n" // invalidate I-cache and D-cache
     130                 :            :         : : : "r0", "cc");
     131                 :            :     #endif
     132                 :            :     #endif
     133                 :            : 
     134                 :       5852 :     rc->kind = kind;
     135                 :       5852 :     rc->scope_flags = scope_flags;
     136                 :       5852 :     rc->fun_data = fun_data;
     137                 :            : 
     138                 :            :     #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS
     139                 :       5852 :     rc->fun_data_len = fun_len;
     140                 :            :     #endif
     141                 :       5852 :     rc->children = children;
     142                 :            : 
     143                 :            :     #if MICROPY_PERSISTENT_CODE_SAVE
     144                 :            :     rc->n_children = n_children;
     145                 :            :     rc->prelude_offset = prelude_offset;
     146                 :            :     #endif
     147                 :            : 
     148                 :            :     // These two entries are only needed for MP_CODE_NATIVE_ASM.
     149                 :       5852 :     rc->n_pos_args = n_pos_args;
     150                 :       5852 :     rc->type_sig = type_sig;
     151                 :            : 
     152                 :            :     #ifdef DEBUG_PRINT
     153                 :            :     DEBUG_printf("assign native: kind=%d fun=%p len=" UINT_FMT " n_pos_args=" UINT_FMT " flags=%x\n", kind, fun_data, fun_len, n_pos_args, (uint)scope_flags);
     154                 :            :     for (mp_uint_t i = 0; i < fun_len; i++) {
     155                 :            :         if (i > 0 && i % 16 == 0) {
     156                 :            :             DEBUG_printf("\n");
     157                 :            :         }
     158                 :            :         DEBUG_printf(" %02x", ((byte *)fun_data)[i]);
     159                 :            :     }
     160                 :            :     DEBUG_printf("\n");
     161                 :            : 
     162                 :            :     #ifdef WRITE_CODE
     163                 :            :     FILE *fp_write_code = fopen("out-code", "wb");
     164                 :            :     fwrite(fun_data, fun_len, 1, fp_write_code);
     165                 :            :     fclose(fp_write_code);
     166                 :            :     #endif
     167                 :            :     #else
     168                 :       5852 :     (void)fun_len;
     169                 :            :     #endif
     170                 :       5852 : }
     171                 :            : #endif
     172                 :            : 
     173                 :      17349 : mp_obj_t mp_make_function_from_raw_code(const mp_raw_code_t *rc, const mp_module_context_t *context, const mp_obj_t *def_args) {
     174                 :      17349 :     DEBUG_OP_printf("make_function_from_raw_code %p\n", rc);
     175         [ -  + ]:      17349 :     assert(rc != NULL);
     176                 :            : 
     177                 :            :     // def_args must be MP_OBJ_NULL or a tuple
     178   [ +  +  +  +  :      17349 :     assert(def_args == NULL || def_args[0] == MP_OBJ_NULL || mp_obj_is_type(def_args[0], &mp_type_tuple));
          -  +  -  +  -  
          +  -  +  +  -  
                   -  + ]
     179                 :            : 
     180                 :            :     // def_kw_args must be MP_OBJ_NULL or a dict
     181   [ +  +  -  +  :        320 :     assert(def_args == NULL || def_args[1] == MP_OBJ_NULL || mp_obj_is_type(def_args[1], &mp_type_dict));
          -  +  -  +  -  
             +  +  -  -  
                      + ]
     182                 :            : 
     183                 :            :     // make the function, depending on the raw code kind
     184                 :      17349 :     mp_obj_t fun;
     185         [ +  + ]:      17349 :     switch (rc->kind) {
     186                 :            :         #if MICROPY_EMIT_NATIVE
     187                 :       8267 :         case MP_CODE_NATIVE_PY:
     188                 :            :         case MP_CODE_NATIVE_VIPER:
     189                 :       8267 :             fun = mp_obj_new_fun_native(def_args, rc->fun_data, context, rc->children);
     190                 :            :             // Check for a generator function, and if so change the type of the object
     191         [ +  + ]:       8267 :             if ((rc->scope_flags & MP_SCOPE_FLAG_GENERATOR) != 0) {
     192                 :        452 :                 ((mp_obj_base_t *)MP_OBJ_TO_PTR(fun))->type = &mp_type_native_gen_wrap;
     193                 :            :             }
     194                 :            :             break;
     195                 :            :         #endif
     196                 :            :         #if MICROPY_EMIT_INLINE_ASM
     197                 :            :         case MP_CODE_NATIVE_ASM:
     198                 :            :             fun = mp_obj_new_fun_asm(rc->n_pos_args, rc->fun_data, rc->type_sig);
     199                 :            :             break;
     200                 :            :         #endif
     201                 :       9082 :         default:
     202                 :            :             // rc->kind should always be set and BYTECODE is the only remaining case
     203         [ -  + ]:       9082 :             assert(rc->kind == MP_CODE_BYTECODE);
     204                 :       9082 :             fun = mp_obj_new_fun_bc(def_args, rc->fun_data, context, rc->children);
     205                 :            :             // check for generator functions and if so change the type of the object
     206         [ +  + ]:       9082 :             if ((rc->scope_flags & MP_SCOPE_FLAG_GENERATOR) != 0) {
     207                 :        552 :                 ((mp_obj_base_t *)MP_OBJ_TO_PTR(fun))->type = &mp_type_gen_wrap;
     208                 :            :             }
     209                 :            : 
     210                 :            :             #if MICROPY_PY_SYS_SETTRACE
     211                 :            :             mp_obj_fun_bc_t *self_fun = (mp_obj_fun_bc_t *)MP_OBJ_TO_PTR(fun);
     212                 :            :             self_fun->rc = rc;
     213                 :            :             #endif
     214                 :            : 
     215                 :            :             break;
     216                 :            :     }
     217                 :            : 
     218                 :      17349 :     return fun;
     219                 :            : }
     220                 :            : 
     221                 :       2418 : mp_obj_t mp_make_closure_from_raw_code(const mp_raw_code_t *rc, const mp_module_context_t *context, mp_uint_t n_closed_over, const mp_obj_t *args) {
     222                 :       2418 :     DEBUG_OP_printf("make_closure_from_raw_code %p " UINT_FMT " %p\n", rc, n_closed_over, args);
     223                 :            :     // make function object
     224                 :       2418 :     mp_obj_t ffun;
     225         [ +  + ]:       2418 :     if (n_closed_over & 0x100) {
     226                 :            :         // default positional and keyword args given
     227                 :          2 :         ffun = mp_make_function_from_raw_code(rc, context, args);
     228                 :            :     } else {
     229                 :            :         // default positional and keyword args not given
     230                 :       2416 :         ffun = mp_make_function_from_raw_code(rc, context, NULL);
     231                 :            :     }
     232                 :            :     // wrap function in closure object
     233                 :       2418 :     return mp_obj_new_closure(ffun, n_closed_over & 0xff, args + ((n_closed_over >> 7) & 2));
     234                 :            : }

Generated by: LCOV version 1.15-5-g462f71d