LCOV - code coverage report
Current view: top level - py - nativeglue.c (source / functions) Hit Total Coverage
Test: unix_coverage_v1.22.0-313-g628a37e6c.info Lines: 86 93 92.5 %
Date: 2024-03-28 12:42:09 Functions: 9 9 100.0 %
Branches: 48 53 90.6 %

           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) 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 <stdarg.h>
      28                 :            : #include <stdio.h>
      29                 :            : #include <string.h>
      30                 :            : #include <assert.h>
      31                 :            : 
      32                 :            : #include "py/binary.h"
      33                 :            : #include "py/runtime.h"
      34                 :            : #include "py/smallint.h"
      35                 :            : #include "py/nativeglue.h"
      36                 :            : #include "py/gc.h"
      37                 :            : 
      38                 :            : #if MICROPY_DEBUG_VERBOSE // print debugging info
      39                 :            : #define DEBUG_printf DEBUG_printf
      40                 :            : #else // don't print debugging info
      41                 :            : #define DEBUG_printf(...) (void)0
      42                 :            : #endif
      43                 :            : 
      44                 :            : #if MICROPY_EMIT_NATIVE
      45                 :            : 
      46                 :       1162 : int mp_native_type_from_qstr(qstr qst) {
      47   [ +  +  +  +  :       1162 :     switch (qst) {
             +  +  +  +  
                      + ]
      48                 :            :         case MP_QSTR_object:
      49                 :            :             return MP_NATIVE_TYPE_OBJ;
      50                 :         16 :         case MP_QSTR_bool:
      51                 :         16 :             return MP_NATIVE_TYPE_BOOL;
      52                 :        318 :         case MP_QSTR_int:
      53                 :        318 :             return MP_NATIVE_TYPE_INT;
      54                 :         70 :         case MP_QSTR_uint:
      55                 :         70 :             return MP_NATIVE_TYPE_UINT;
      56                 :         24 :         case MP_QSTR_ptr:
      57                 :         24 :             return MP_NATIVE_TYPE_PTR;
      58                 :         42 :         case MP_QSTR_ptr8:
      59                 :         42 :             return MP_NATIVE_TYPE_PTR8;
      60                 :         28 :         case MP_QSTR_ptr16:
      61                 :         28 :             return MP_NATIVE_TYPE_PTR16;
      62                 :         36 :         case MP_QSTR_ptr32:
      63                 :         36 :             return MP_NATIVE_TYPE_PTR32;
      64                 :        620 :         default:
      65                 :        620 :             return -1;
      66                 :            :     }
      67                 :            : }
      68                 :            : 
      69                 :            : // convert a MicroPython object to a valid native value based on type
      70                 :       1576 : mp_uint_t mp_native_from_obj(mp_obj_t obj, mp_uint_t type) {
      71                 :       1576 :     DEBUG_printf("mp_native_from_obj(%p, " UINT_FMT ")\n", obj, type);
      72   [ -  +  +  + ]:       1576 :     switch (type & 0xf) {
      73                 :          0 :         case MP_NATIVE_TYPE_OBJ:
      74                 :          0 :             return (mp_uint_t)obj;
      75                 :         32 :         case MP_NATIVE_TYPE_BOOL:
      76                 :         32 :             return mp_obj_is_true(obj);
      77                 :       1408 :         case MP_NATIVE_TYPE_INT:
      78                 :            :         case MP_NATIVE_TYPE_UINT:
      79                 :       1408 :             return mp_obj_get_int_truncated(obj);
      80                 :        136 :         default: { // cast obj to a pointer
      81                 :        136 :             mp_buffer_info_t bufinfo;
      82         [ +  + ]:        136 :             if (mp_get_buffer(obj, &bufinfo, MP_BUFFER_READ)) {
      83                 :        128 :                 return (mp_uint_t)bufinfo.buf;
      84                 :            :             } else {
      85                 :            :                 // assume obj is an integer that represents an address
      86                 :          8 :                 return mp_obj_get_int_truncated(obj);
      87                 :            :             }
      88                 :            :         }
      89                 :            :     }
      90                 :            : }
      91                 :            : 
      92                 :            : #endif
      93                 :            : 
      94                 :            : #if MICROPY_EMIT_MACHINE_CODE
      95                 :            : 
      96                 :            : // convert a native value to a MicroPython object based on type
      97                 :       1228 : mp_obj_t mp_native_to_obj(mp_uint_t val, mp_uint_t type) {
      98                 :       1228 :     DEBUG_printf("mp_native_to_obj(" UINT_FMT ", " UINT_FMT ")\n", val, type);
      99   [ -  +  +  +  :       1228 :     switch (type & 0xf) {
                   -  + ]
     100                 :          0 :         case MP_NATIVE_TYPE_OBJ:
     101                 :          0 :             return (mp_obj_t)val;
     102                 :        104 :         case MP_NATIVE_TYPE_BOOL:
     103         [ +  + ]:        104 :             return mp_obj_new_bool(val);
     104                 :        948 :         case MP_NATIVE_TYPE_INT:
     105                 :        948 :             return mp_obj_new_int(val);
     106                 :        172 :         case MP_NATIVE_TYPE_UINT:
     107                 :        172 :             return mp_obj_new_int_from_uint(val);
     108                 :          0 :         case MP_NATIVE_TYPE_QSTR:
     109                 :          0 :             return MP_OBJ_NEW_QSTR(val);
     110                 :          4 :         default: // a pointer
     111                 :            :             // we return just the value of the pointer as an integer
     112                 :          4 :             return mp_obj_new_int_from_uint(val);
     113                 :            :     }
     114                 :            : }
     115                 :            : 
     116                 :            : #endif
     117                 :            : 
     118                 :            : #if MICROPY_EMIT_NATIVE && !MICROPY_DYNAMIC_COMPILER
     119                 :            : 
     120                 :            : #if !MICROPY_PY_BUILTINS_SET
     121                 :            : mp_obj_t mp_obj_new_set(size_t n_args, mp_obj_t *items) {
     122                 :            :     (void)n_args;
     123                 :            :     (void)items;
     124                 :            :     mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("set unsupported"));
     125                 :            : }
     126                 :            : 
     127                 :            : void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item) {
     128                 :            :     (void)self_in;
     129                 :            :     (void)item;
     130                 :            :     mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("set unsupported"));
     131                 :            : }
     132                 :            : #endif
     133                 :            : 
     134                 :            : #if !MICROPY_PY_BUILTINS_SLICE
     135                 :            : mp_obj_t mp_obj_new_slice(mp_obj_t ostart, mp_obj_t ostop, mp_obj_t ostep) {
     136                 :            :     (void)ostart;
     137                 :            :     (void)ostop;
     138                 :            :     (void)ostep;
     139                 :            :     mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("slice unsupported"));
     140                 :            : }
     141                 :            : #endif
     142                 :            : 
     143                 :     620745 : static mp_obj_dict_t *mp_native_swap_globals(mp_obj_dict_t *new_globals) {
     144         [ +  + ]:     620745 :     if (new_globals == NULL) {
     145                 :            :         // Globals were the originally the same so don't restore them
     146                 :            :         return NULL;
     147                 :            :     }
     148                 :     619005 :     mp_obj_dict_t *old_globals = mp_globals_get();
     149         [ +  + ]:     619005 :     if (old_globals == new_globals) {
     150                 :            :         // Don't set globals if they are the same, and return NULL to indicate this
     151                 :            :         return NULL;
     152                 :            :     }
     153                 :     445640 :     mp_globals_set(new_globals);
     154                 :     445640 :     return old_globals;
     155                 :            : }
     156                 :            : 
     157                 :            : // wrapper that accepts n_args and n_kw in one argument
     158                 :            : // (native emitter can only pass at most 3 arguments to a function)
     159                 :     823366 : static mp_obj_t mp_native_call_function_n_kw(mp_obj_t fun_in, size_t n_args_kw, const mp_obj_t *args) {
     160                 :     823366 :     return mp_call_function_n_kw(fun_in, n_args_kw & 0xff, (n_args_kw >> 8) & 0xff, args);
     161                 :            : }
     162                 :            : 
     163                 :            : // wrapper that makes raise obj and raises it
     164                 :            : // END_FINALLY opcode requires that we don't raise if o==None
     165                 :     163423 : static void mp_native_raise(mp_obj_t o) {
     166         [ +  + ]:     163423 :     if (o != MP_OBJ_NULL && o != mp_const_none) {
     167                 :     148980 :         nlr_raise(mp_make_raise_obj(o));
     168                 :            :     }
     169                 :      14443 : }
     170                 :            : 
     171                 :            : // wrapper that handles iterator buffer
     172                 :     154326 : static mp_obj_t mp_native_getiter(mp_obj_t obj, mp_obj_iter_buf_t *iter) {
     173         [ +  + ]:     154326 :     if (iter == NULL) {
     174                 :      74821 :         return mp_getiter(obj, NULL);
     175                 :            :     } else {
     176                 :      79505 :         obj = mp_getiter(obj, iter);
     177         [ +  + ]:      79501 :         if (obj != MP_OBJ_FROM_PTR(iter)) {
     178                 :            :             // Iterator didn't use the stack so indicate that with MP_OBJ_NULL.
     179                 :      77352 :             iter->base.type = MP_OBJ_NULL;
     180                 :      77352 :             iter->buf[0] = obj;
     181                 :            :         }
     182                 :      79501 :         return NULL;
     183                 :            :     }
     184                 :            : }
     185                 :            : 
     186                 :            : // wrapper that handles iterator buffer
     187                 :     120075 : static mp_obj_t mp_native_iternext(mp_obj_iter_buf_t *iter) {
     188                 :     120075 :     mp_obj_t obj;
     189         [ +  + ]:     120075 :     if (iter->base.type == MP_OBJ_NULL) {
     190                 :     105387 :         obj = iter->buf[0];
     191                 :            :     } else {
     192                 :            :         obj = MP_OBJ_FROM_PTR(iter);
     193                 :            :     }
     194                 :     120075 :     return mp_iternext(obj);
     195                 :            : }
     196                 :            : 
     197                 :     149050 : static bool mp_native_yield_from(mp_obj_t gen, mp_obj_t send_value, mp_obj_t *ret_value) {
     198                 :     149050 :     mp_vm_return_kind_t ret_kind;
     199                 :     149050 :     nlr_buf_t nlr_buf;
     200                 :     149050 :     mp_obj_t throw_value = *ret_value;
     201         [ +  + ]:     149050 :     if (nlr_push(&nlr_buf) == 0) {
     202         [ +  + ]:     149050 :         if (throw_value != MP_OBJ_NULL) {
     203                 :         58 :             send_value = MP_OBJ_NULL;
     204                 :            :         }
     205                 :     149050 :         ret_kind = mp_resume(gen, send_value, throw_value, ret_value);
     206                 :      74862 :         nlr_pop();
     207                 :            :     } else {
     208                 :      74188 :         ret_kind = MP_VM_RETURN_EXCEPTION;
     209                 :      74188 :         *ret_value = nlr_buf.ret_val;
     210                 :            :     }
     211                 :            : 
     212         [ +  + ]:     149050 :     if (ret_kind == MP_VM_RETURN_YIELD) {
     213                 :            :         return true;
     214         [ +  + ]:      74634 :     } else if (ret_kind == MP_VM_RETURN_NORMAL) {
     215         [ -  + ]:        183 :         if (*ret_value == MP_OBJ_STOP_ITERATION) {
     216                 :          0 :             *ret_value = mp_const_none;
     217                 :            :         }
     218                 :            :     } else {
     219         [ -  + ]:      74451 :         assert(ret_kind == MP_VM_RETURN_EXCEPTION);
     220         [ +  + ]:      74451 :         if (!mp_obj_exception_match(*ret_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {
     221                 :        279 :             nlr_raise(*ret_value);
     222                 :            :         }
     223                 :      74172 :         *ret_value = mp_obj_exception_get_value(*ret_value);
     224                 :            :     }
     225                 :            : 
     226   [ +  +  +  + ]:      74355 :     if (throw_value != MP_OBJ_NULL && mp_obj_exception_match(throw_value, MP_OBJ_FROM_PTR(&mp_type_GeneratorExit))) {
     227                 :          4 :         nlr_raise(mp_make_raise_obj(throw_value));
     228                 :            :     }
     229                 :            : 
     230                 :            :     return false;
     231                 :            : }
     232                 :            : 
     233                 :            : #if !MICROPY_PY_BUILTINS_FLOAT
     234                 :            : 
     235                 :            : static mp_obj_t mp_obj_new_float_from_f(float f) {
     236                 :            :     (void)f;
     237                 :            :     mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("float unsupported"));
     238                 :            : }
     239                 :            : 
     240                 :            : static mp_obj_t mp_obj_new_float_from_d(double d) {
     241                 :            :     (void)d;
     242                 :            :     mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("float unsupported"));
     243                 :            : }
     244                 :            : 
     245                 :            : static float mp_obj_get_float_to_f(mp_obj_t o) {
     246                 :            :     (void)o;
     247                 :            :     mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("float unsupported"));
     248                 :            : }
     249                 :            : 
     250                 :            : static double mp_obj_get_float_to_d(mp_obj_t o) {
     251                 :            :     (void)o;
     252                 :            :     mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("float unsupported"));
     253                 :            : }
     254                 :            : 
     255                 :            : #endif
     256                 :            : 
     257                 :            : // these must correspond to the respective enum in nativeglue.h
     258                 :            : const mp_fun_table_t mp_fun_table = {
     259                 :            :     mp_const_none,
     260                 :            :     mp_const_false,
     261                 :            :     mp_const_true,
     262                 :            :     mp_native_from_obj,
     263                 :            :     mp_native_to_obj,
     264                 :            :     mp_native_swap_globals,
     265                 :            :     mp_load_name,
     266                 :            :     mp_load_global,
     267                 :            :     mp_load_build_class,
     268                 :            :     mp_load_attr,
     269                 :            :     mp_load_method,
     270                 :            :     mp_load_super_method,
     271                 :            :     mp_store_name,
     272                 :            :     mp_store_global,
     273                 :            :     mp_store_attr,
     274                 :            :     mp_obj_subscr,
     275                 :            :     mp_obj_is_true,
     276                 :            :     mp_unary_op,
     277                 :            :     mp_binary_op,
     278                 :            :     mp_obj_new_tuple,
     279                 :            :     mp_obj_new_list,
     280                 :            :     mp_obj_new_dict,
     281                 :            :     mp_obj_new_set,
     282                 :            :     mp_obj_set_store,
     283                 :            :     mp_obj_list_append,
     284                 :            :     mp_obj_dict_store,
     285                 :            :     mp_make_function_from_proto_fun,
     286                 :            :     mp_native_call_function_n_kw,
     287                 :            :     mp_call_method_n_kw,
     288                 :            :     mp_call_method_n_kw_var,
     289                 :            :     mp_native_getiter,
     290                 :            :     mp_native_iternext,
     291                 :            :     #if MICROPY_NLR_SETJMP
     292                 :            :     nlr_push_tail,
     293                 :            :     #else
     294                 :            :     nlr_push,
     295                 :            :     #endif
     296                 :            :     nlr_pop,
     297                 :            :     mp_native_raise,
     298                 :            :     mp_import_name,
     299                 :            :     mp_import_from,
     300                 :            :     mp_import_all,
     301                 :            :     mp_obj_new_slice,
     302                 :            :     mp_unpack_sequence,
     303                 :            :     mp_unpack_ex,
     304                 :            :     mp_delete_name,
     305                 :            :     mp_delete_global,
     306                 :            :     mp_obj_new_closure,
     307                 :            :     mp_arg_check_num_sig,
     308                 :            :     mp_setup_code_state_native,
     309                 :            :     mp_small_int_floor_divide,
     310                 :            :     mp_small_int_modulo,
     311                 :            :     mp_native_yield_from,
     312                 :            :     #if MICROPY_NLR_SETJMP
     313                 :            :     setjmp,
     314                 :            :     #else
     315                 :            :     NULL,
     316                 :            :     #endif
     317                 :            :     // Additional entries for dynamic runtime, starts at index 50
     318                 :            :     memset,
     319                 :            :     memmove,
     320                 :            :     gc_realloc,
     321                 :            :     mp_printf,
     322                 :            :     mp_vprintf,
     323                 :            :     mp_raise_msg,
     324                 :            :     mp_obj_get_type,
     325                 :            :     mp_obj_new_str,
     326                 :            :     mp_obj_new_bytes,
     327                 :            :     mp_obj_new_bytearray_by_ref,
     328                 :            :     mp_obj_new_float_from_f,
     329                 :            :     mp_obj_new_float_from_d,
     330                 :            :     mp_obj_get_float_to_f,
     331                 :            :     mp_obj_get_float_to_d,
     332                 :            :     mp_get_buffer,
     333                 :            :     mp_get_stream_raise,
     334                 :            :     mp_binary_get_size,
     335                 :            :     mp_binary_get_val_array,
     336                 :            :     mp_binary_set_val_array,
     337                 :            :     &mp_plat_print,
     338                 :            :     &mp_type_type,
     339                 :            :     &mp_type_str,
     340                 :            :     &mp_type_list,
     341                 :            :     &mp_type_dict,
     342                 :            :     &mp_type_fun_builtin_0,
     343                 :            :     &mp_type_fun_builtin_1,
     344                 :            :     &mp_type_fun_builtin_2,
     345                 :            :     &mp_type_fun_builtin_3,
     346                 :            :     &mp_type_fun_builtin_var,
     347                 :            :     &mp_stream_read_obj,
     348                 :            :     &mp_stream_readinto_obj,
     349                 :            :     &mp_stream_unbuffered_readline_obj,
     350                 :            :     &mp_stream_write_obj,
     351                 :            : };
     352                 :            : 
     353                 :            : #elif MICROPY_EMIT_NATIVE && MICROPY_DYNAMIC_COMPILER
     354                 :            : 
     355                 :            : const int mp_fun_table;
     356                 :            : 
     357                 :            : #endif // MICROPY_EMIT_NATIVE

Generated by: LCOV version 1.15-5-g462f71d