From aca9d5bc40c33ac0da25c94bf650ea4783cdb7a8 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sat, 8 May 2021 17:40:01 -0500 Subject: [PATCH] Fix up all natmod examples * modframebuf: _mp_framebuf_p_t is not "really" a protocol, but the QSTR assignment caused problems when building as a dynamic module * modure: str_index_to_ptr is not in the natmod API, disable URE match spans when dynamic. mp_obj_len() is a bugfix, we should throw here if the object is not string-like * moduzlib: Correct paths to uzlib headers & sources. this relative path (from moduzlib.c to the referenced file) works in all cases, the other only worked from ports/PORTNAME. * dynruntime: Handle 2-arg m_malloc, assert_native_inited, add a micropythonish mp_arg_check_num_mp, fix mp_raise_msg to use dumb strings, add mp_raise_arg1 * nativeglue: ad assert_native_inited * translate: MP_ERROR_TEXT evaluates to its argument for DYNRUNTIME * mpy-tool: A straggling magic number change * mpy_ld: Have to renumber manually after dynruntime change * import_mpy_native_gc.py: Update copy of features0 baked into this test --- examples/natmod/.gitignore | 1 + examples/natmod/btree/Makefile | 37 ++++++ examples/natmod/btree/btree_c.c | 147 ++++++++++++++++++++++ examples/natmod/btree/btree_py.py | 3 + examples/natmod/features1/Makefile | 14 +++ examples/natmod/features1/features1.c | 106 ++++++++++++++++ examples/natmod/features2/Makefile | 14 +++ examples/natmod/features2/main.c | 83 ++++++++++++ examples/natmod/features2/prod.c | 9 ++ examples/natmod/features2/prod.h | 1 + examples/natmod/features2/test.py | 29 +++++ examples/natmod/framebuf/Makefile | 13 ++ examples/natmod/framebuf/framebuf.c | 49 ++++++++ examples/natmod/uheapq/Makefile | 13 ++ examples/natmod/uheapq/uheapq.c | 16 +++ examples/natmod/urandom/Makefile | 13 ++ examples/natmod/urandom/urandom.c | 33 +++++ examples/natmod/ure/Makefile | 13 ++ examples/natmod/ure/ure.c | 78 ++++++++++++ examples/natmod/uzlib/Makefile | 13 ++ examples/natmod/uzlib/uzlib.c | 35 ++++++ extmod/modframebuf.c | 19 +-- extmod/modure.c | 5 +- extmod/moduzlib.c | 14 +-- py/dynruntime.h | 19 ++- py/nativeglue.c | 2 + py/nativeglue.h | 1 + py/runtime.h | 2 + supervisor/shared/translate.h | 4 + tests/micropython/import_mpy_native_gc.py | 4 +- tools/mpy-tool.py | 2 +- tools/mpy_ld.py | 10 +- 32 files changed, 770 insertions(+), 32 deletions(-) create mode 100644 examples/natmod/.gitignore create mode 100644 examples/natmod/btree/Makefile create mode 100644 examples/natmod/btree/btree_c.c create mode 100644 examples/natmod/btree/btree_py.py create mode 100644 examples/natmod/features1/Makefile create mode 100644 examples/natmod/features1/features1.c create mode 100644 examples/natmod/features2/Makefile create mode 100644 examples/natmod/features2/main.c create mode 100644 examples/natmod/features2/prod.c create mode 100644 examples/natmod/features2/prod.h create mode 100644 examples/natmod/features2/test.py create mode 100644 examples/natmod/framebuf/Makefile create mode 100644 examples/natmod/framebuf/framebuf.c create mode 100644 examples/natmod/uheapq/Makefile create mode 100644 examples/natmod/uheapq/uheapq.c create mode 100644 examples/natmod/urandom/Makefile create mode 100644 examples/natmod/urandom/urandom.c create mode 100644 examples/natmod/ure/Makefile create mode 100644 examples/natmod/ure/ure.c create mode 100644 examples/natmod/uzlib/Makefile create mode 100644 examples/natmod/uzlib/uzlib.c diff --git a/examples/natmod/.gitignore b/examples/natmod/.gitignore new file mode 100644 index 0000000000..4815d20f06 --- /dev/null +++ b/examples/natmod/.gitignore @@ -0,0 +1 @@ +*.mpy diff --git a/examples/natmod/btree/Makefile b/examples/natmod/btree/Makefile new file mode 100644 index 0000000000..d795102b4a --- /dev/null +++ b/examples/natmod/btree/Makefile @@ -0,0 +1,37 @@ +# Location of top-level MicroPython directory +MPY_DIR = ../../.. + +# Name of module (different to built-in btree so it can coexist) +MOD = btree_$(ARCH) + +# Source files (.c or .py) +SRC = btree_c.c btree_py.py + +# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) +ARCH = x64 + +BTREE_DIR = $(MPY_DIR)/lib/berkeley-db-1.xx +BTREE_DEFS = -D__DBINTERFACE_PRIVATE=1 -Dmpool_error="(void)" -Dabort=abort_ "-Dvirt_fd_t=void*" $(BTREE_DEFS_EXTRA) +CFLAGS += -I$(BTREE_DIR)/PORT/include +CFLAGS += -Wno-old-style-definition -Wno-sign-compare -Wno-unused-parameter $(BTREE_DEFS) + +SRC += $(addprefix $(realpath $(BTREE_DIR))/,\ + btree/bt_close.c \ + btree/bt_conv.c \ + btree/bt_delete.c \ + btree/bt_get.c \ + btree/bt_open.c \ + btree/bt_overflow.c \ + btree/bt_page.c \ + btree/bt_put.c \ + btree/bt_search.c \ + btree/bt_seq.c \ + btree/bt_split.c \ + btree/bt_utils.c \ + mpool/mpool.c \ + ) + +include $(MPY_DIR)/py/dynruntime.mk + +# btree needs gnu99 defined +CFLAGS += -std=gnu99 diff --git a/examples/natmod/btree/btree_c.c b/examples/natmod/btree/btree_c.c new file mode 100644 index 0000000000..a58a38e11e --- /dev/null +++ b/examples/natmod/btree/btree_c.c @@ -0,0 +1,147 @@ +#define MICROPY_PY_BTREE (1) + +#include "py/dynruntime.h" + +#include + +#if !defined(__linux__) +void *memcpy(void *dst, const void *src, size_t n) { + return mp_fun_table.memmove_(dst, src, n); +} +void *memset(void *s, int c, size_t n) { + return mp_fun_table.memset_(s, c, n); +} +#endif + +void *memmove(void *dest, const void *src, size_t n) { + return mp_fun_table.memmove_(dest, src, n); +} + +void *malloc(size_t n) { + void *ptr = m_malloc(n, false); + return ptr; +} +void *realloc(void *ptr, size_t n) { + mp_printf(&mp_plat_print, "UNDEF %d\n", __LINE__); + return NULL; +} +void *calloc(size_t n, size_t m) { + void *ptr = m_malloc(n * m, false); + // memory already cleared by conservative GC + return ptr; +} + +void free(void *ptr) { + m_free(ptr); +} + +void abort_(void) { + nlr_raise(mp_obj_new_exception(mp_load_global(MP_QSTR_RuntimeError))); +} + +int native_errno; +#if defined(__linux__) +int *__errno_location (void) +#else +int *__errno (void) +#endif +{ + return &native_errno; +} + +ssize_t mp_stream_posix_write(void *stream, const void *buf, size_t len) { + mp_obj_base_t* o = stream; + const mp_stream_p_t *stream_p = o->type->protocol; + mp_uint_t out_sz = stream_p->write(MP_OBJ_FROM_PTR(stream), buf, len, &native_errno); + if (out_sz == MP_STREAM_ERROR) { + return -1; + } else { + return out_sz; + } +} + +ssize_t mp_stream_posix_read(void *stream, void *buf, size_t len) { + mp_obj_base_t* o = stream; + const mp_stream_p_t *stream_p = o->type->protocol; + mp_uint_t out_sz = stream_p->read(MP_OBJ_FROM_PTR(stream), buf, len, &native_errno); + if (out_sz == MP_STREAM_ERROR) { + return -1; + } else { + return out_sz; + } +} + +off_t mp_stream_posix_lseek(void *stream, off_t offset, int whence) { + const mp_obj_base_t* o = stream; + const mp_stream_p_t *stream_p = o->type->protocol; + struct mp_stream_seek_t seek_s; + seek_s.offset = offset; + seek_s.whence = whence; + mp_uint_t res = stream_p->ioctl(MP_OBJ_FROM_PTR(stream), MP_STREAM_SEEK, (mp_uint_t)(uintptr_t)&seek_s, &native_errno); + if (res == MP_STREAM_ERROR) { + return -1; + } + return seek_s.offset; +} + +int mp_stream_posix_fsync(void *stream) { + mp_obj_base_t* o = stream; + const mp_stream_p_t *stream_p = o->type->protocol; + mp_uint_t res = stream_p->ioctl(MP_OBJ_FROM_PTR(stream), MP_STREAM_FLUSH, 0, &native_errno); + if (res == MP_STREAM_ERROR) { + return -1; + } + return res; +} + +mp_obj_type_t btree_type; + +#include "extmod/modbtree.c" + +mp_map_elem_t btree_locals_dict_table[8]; +STATIC MP_DEFINE_CONST_DICT(btree_locals_dict, btree_locals_dict_table); + +STATIC mp_obj_t btree_open(size_t n_args, const mp_obj_t *args) { + // Make sure we got a stream object + mp_get_stream_raise(args[0], MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL); + + BTREEINFO openinfo = {0}; + openinfo.flags = mp_obj_get_int(args[1]); + openinfo.cachesize = mp_obj_get_int(args[2]); + openinfo.psize = mp_obj_get_int(args[3]); + openinfo.minkeypage = mp_obj_get_int(args[4]); + DB *db = __bt_open(MP_OBJ_TO_PTR(args[0]), &btree_stream_fvtable, &openinfo, 0); + if (db == NULL) { + mp_raise_OSError(native_errno); + } + + return MP_OBJ_FROM_PTR(btree_new(db, args[0])); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_open_obj, 5, 5, btree_open); + +mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { + MP_DYNRUNTIME_INIT_ENTRY + + btree_type.base.type = (void*)&mp_fun_table.type_type; + btree_type.name = MP_QSTR_btree; + btree_type.print = btree_print; + btree_type.getiter = btree_getiter; + btree_type.iternext = btree_iternext; + btree_type.binary_op = btree_binary_op; + btree_type.subscr = btree_subscr; + btree_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_close), MP_OBJ_FROM_PTR(&btree_close_obj) }; + btree_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_flush), MP_OBJ_FROM_PTR(&btree_flush_obj) }; + btree_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_get), MP_OBJ_FROM_PTR(&btree_get_obj) }; + btree_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_put), MP_OBJ_FROM_PTR(&btree_put_obj) }; + btree_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_seq), MP_OBJ_FROM_PTR(&btree_seq_obj) }; + btree_locals_dict_table[5] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_keys), MP_OBJ_FROM_PTR(&btree_keys_obj) }; + btree_locals_dict_table[6] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_values), MP_OBJ_FROM_PTR(&btree_values_obj) }; + btree_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_items), MP_OBJ_FROM_PTR(&btree_items_obj) }; + btree_type.locals_dict = (void*)&btree_locals_dict; + + mp_store_global(MP_QSTR__open, MP_OBJ_FROM_PTR(&btree_open_obj)); + mp_store_global(MP_QSTR_INCL, MP_OBJ_NEW_SMALL_INT(FLAG_END_KEY_INCL)); + mp_store_global(MP_QSTR_DESC, MP_OBJ_NEW_SMALL_INT(FLAG_DESC)); + + MP_DYNRUNTIME_INIT_EXIT +} diff --git a/examples/natmod/btree/btree_py.py b/examples/natmod/btree/btree_py.py new file mode 100644 index 0000000000..bd53c084a1 --- /dev/null +++ b/examples/natmod/btree/btree_py.py @@ -0,0 +1,3 @@ +# Implemented in Python to support keyword arguments +def open(stream, *, flags=0, cachesize=0, pagesize=0, minkeypage=0): + return _open(stream, flags, cachesize, pagesize, minkeypage) diff --git a/examples/natmod/features1/Makefile b/examples/natmod/features1/Makefile new file mode 100644 index 0000000000..010640daf9 --- /dev/null +++ b/examples/natmod/features1/Makefile @@ -0,0 +1,14 @@ +# Location of top-level MicroPython directory +MPY_DIR = ../../.. + +# Name of module +MOD = features1 + +# Source files (.c or .py) +SRC = features1.c + +# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) +ARCH = x64 + +# Include to get the rules for compiling and linking the module +include $(MPY_DIR)/py/dynruntime.mk diff --git a/examples/natmod/features1/features1.c b/examples/natmod/features1/features1.c new file mode 100644 index 0000000000..f865f1887c --- /dev/null +++ b/examples/natmod/features1/features1.c @@ -0,0 +1,106 @@ +/* This example demonstrates the following features in a native module: + - defining simple functions exposed to Python + - defining local, helper C functions + - defining constant integers and strings exposed to Python + - getting and creating integer objects + - creating Python lists + - raising exceptions + - allocating memory + - BSS and constant data (rodata) + - relocated pointers in rodata +*/ + +// Include the header file to get access to the MicroPython API +#include "py/dynruntime.h" + +// BSS (zero) data +uint16_t data16[4]; + +// Constant data (rodata) +const uint8_t table8[] = { 0, 1, 1, 2, 3, 5, 8, 13 }; +const uint16_t table16[] = { 0x1000, 0x2000 }; + +// Constant data pointing to BSS/constant data +uint16_t *const table_ptr16a[] = { &data16[0], &data16[1], &data16[2], &data16[3] }; +const uint16_t *const table_ptr16b[] = { &table16[0], &table16[1] }; + +// A simple function that adds its 2 arguments (must be integers) +STATIC mp_obj_t add(mp_obj_t x_in, mp_obj_t y_in) { + mp_int_t x = mp_obj_get_int(x_in); + mp_int_t y = mp_obj_get_int(y_in); + return mp_obj_new_int(x + y); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_obj, add); + +// A local helper function (not exposed to Python) +STATIC mp_int_t fibonacci_helper(mp_int_t x) { + if (x < MP_ARRAY_SIZE(table8)) { + return table8[x]; + } else { + return fibonacci_helper(x - 1) + fibonacci_helper(x - 2); + } +} + +// A function which computes Fibonacci numbers +STATIC mp_obj_t fibonacci(mp_obj_t x_in) { + mp_int_t x = mp_obj_get_int(x_in); + if (x < 0) { + mp_raise_ValueError(MP_ERROR_TEXT("can't compute negative Fibonacci number")); + } + return mp_obj_new_int(fibonacci_helper(x)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(fibonacci_obj, fibonacci); + +// A function that accesses the BSS data +STATIC mp_obj_t access(size_t n_args, const mp_obj_t *args) { + if (n_args == 0) { + // Create a list holding all items from data16 + mp_obj_list_t *lst = MP_OBJ_TO_PTR(mp_obj_new_list(MP_ARRAY_SIZE(data16), NULL)); + for (int i = 0; i < MP_ARRAY_SIZE(data16); ++i) { + lst->items[i] = mp_obj_new_int(data16[i]); + } + return MP_OBJ_FROM_PTR(lst); + } else if (n_args == 1) { + // Get one item from data16 + mp_int_t idx = mp_obj_get_int(args[0]) & 3; + return mp_obj_new_int(data16[idx]); + } else { + // Set one item in data16 (via table_ptr16a) + mp_int_t idx = mp_obj_get_int(args[0]) & 3; + *table_ptr16a[idx] = mp_obj_get_int(args[1]); + return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(access_obj, 0, 2, access); + +// A function that allocates memory and creates a bytearray +STATIC mp_obj_t make_array(void) { + uint16_t *ptr = m_new(uint16_t, MP_ARRAY_SIZE(table_ptr16b)); + for (int i = 0; i < MP_ARRAY_SIZE(table_ptr16b); ++i) { + ptr[i] = *table_ptr16b[i]; + } + return mp_obj_new_bytearray_by_ref(sizeof(uint16_t) * MP_ARRAY_SIZE(table_ptr16b), ptr); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(make_array_obj, make_array); + +// This is the entry point and is called when the module is imported +mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { + // This must be first, it sets up the globals dict and other things + MP_DYNRUNTIME_INIT_ENTRY + + // Messages can be printed as usualy + mp_printf(&mp_plat_print, "initialising module self=%p\n", self); + + // Make the functions available in the module's namespace + mp_store_global(MP_QSTR_add, MP_OBJ_FROM_PTR(&add_obj)); + mp_store_global(MP_QSTR_fibonacci, MP_OBJ_FROM_PTR(&fibonacci_obj)); + mp_store_global(MP_QSTR_access, MP_OBJ_FROM_PTR(&access_obj)); + mp_store_global(MP_QSTR_make_array, MP_OBJ_FROM_PTR(&make_array_obj)); + + // Add some constants to the module's namespace + mp_store_global(MP_QSTR_VAL, MP_OBJ_NEW_SMALL_INT(42)); + mp_store_global(MP_QSTR_MSG, MP_OBJ_NEW_QSTR(MP_QSTR_HELLO_MICROPYTHON)); + + // This must be last, it restores the globals dict + MP_DYNRUNTIME_INIT_EXIT +} diff --git a/examples/natmod/features2/Makefile b/examples/natmod/features2/Makefile new file mode 100644 index 0000000000..4fd23c6879 --- /dev/null +++ b/examples/natmod/features2/Makefile @@ -0,0 +1,14 @@ +# Location of top-level MicroPython directory +MPY_DIR = ../../.. + +# Name of module +MOD = features2 + +# Source files (.c or .py) +SRC = main.c prod.c test.py + +# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) +ARCH = x64 + +# Include to get the rules for compiling and linking the module +include $(MPY_DIR)/py/dynruntime.mk diff --git a/examples/natmod/features2/main.c b/examples/natmod/features2/main.c new file mode 100644 index 0000000000..60c48b0f72 --- /dev/null +++ b/examples/natmod/features2/main.c @@ -0,0 +1,83 @@ +/* This example demonstrates the following features in a native module: + - using floats + - defining additional code in Python (see test.py) + - have extra C code in a separate file (see prod.c) +*/ + +// Include the header file to get access to the MicroPython API +#include "py/dynruntime.h" + +// Include the header for auxiliary C code for this module +#include "prod.h" + +// Automatically detect if this module should include double-precision code. +// If double precision is supported by the target architecture then it can +// be used in native module regardless of what float setting the target +// MicroPython runtime uses (being none, float or double). +#if defined(__i386__) || defined(__x86_64__) || (defined(__ARM_FP) && (__ARM_FP & 8)) +#define USE_DOUBLE 1 +#else +#define USE_DOUBLE 0 +#endif + +// A function that uses the default float type configured for the current target +// This default can be overridden by specifying MICROPY_FLOAT_IMPL at the make level +STATIC mp_obj_t add(mp_obj_t x, mp_obj_t y) { + return mp_obj_new_float(mp_obj_get_float(x) + mp_obj_get_float(y)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_obj, add); + +// A function that explicitly uses single precision floats +STATIC mp_obj_t add_f(mp_obj_t x, mp_obj_t y) { + return mp_obj_new_float_from_f(mp_obj_get_float_to_f(x) + mp_obj_get_float_to_f(y)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_f_obj, add_f); + +#if USE_DOUBLE +// A function that explicitly uses double precision floats +STATIC mp_obj_t add_d(mp_obj_t x, mp_obj_t y) { + return mp_obj_new_float_from_d(mp_obj_get_float_to_d(x) + mp_obj_get_float_to_d(y)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_d_obj, add_d); +#endif + +// A function that computes the product of floats in an array. +// This function uses the most general C argument interface, which is more difficult +// to use but has access to the globals dict of the module via self->globals. +STATIC mp_obj_t productf(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { + // Check number of arguments is valid + mp_arg_check_num_mp(n_args, n_kw, 1, 1, false); + + // Extract buffer pointer and verify typecode + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_RW); + if (bufinfo.typecode != 'f') { + mp_raise_ValueError(MP_ERROR_TEXT("expecting float array")); + } + + // Compute product, store result back in first element of array + float *ptr = bufinfo.buf; + float prod = prod_array(bufinfo.len / sizeof(*ptr), ptr); + ptr[0] = prod; + + return mp_const_none; +} + +// This is the entry point and is called when the module is imported +mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { + // This must be first, it sets up the globals dict and other things + MP_DYNRUNTIME_INIT_ENTRY + + // Make the functions available in the module's namespace + mp_store_global(MP_QSTR_add, MP_OBJ_FROM_PTR(&add_obj)); + mp_store_global(MP_QSTR_add_f, MP_OBJ_FROM_PTR(&add_f_obj)); + #if USE_DOUBLE + mp_store_global(MP_QSTR_add_d, MP_OBJ_FROM_PTR(&add_d_obj)); + #endif + + // The productf function uses the most general C argument interface + mp_store_global(MP_QSTR_productf, MP_DYNRUNTIME_MAKE_FUNCTION(productf)); + + // This must be last, it restores the globals dict + MP_DYNRUNTIME_INIT_EXIT +} diff --git a/examples/natmod/features2/prod.c b/examples/natmod/features2/prod.c new file mode 100644 index 0000000000..7791dcad1d --- /dev/null +++ b/examples/natmod/features2/prod.c @@ -0,0 +1,9 @@ +#include "prod.h" + +float prod_array(int n, float *ar) { + float ans = 1; + for (int i = 0; i < n; ++i) { + ans *= ar[i]; + } + return ans; +} diff --git a/examples/natmod/features2/prod.h b/examples/natmod/features2/prod.h new file mode 100644 index 0000000000..f27dd8d033 --- /dev/null +++ b/examples/natmod/features2/prod.h @@ -0,0 +1 @@ +float prod_array(int n, float *ar); diff --git a/examples/natmod/features2/test.py b/examples/natmod/features2/test.py new file mode 100644 index 0000000000..5ac80120d7 --- /dev/null +++ b/examples/natmod/features2/test.py @@ -0,0 +1,29 @@ +# This Python code will be merged with the C code in main.c + +import array + + +def isclose(a, b): + return abs(a - b) < 1e-3 + + +def test(): + tests = [ + isclose(add(0.1, 0.2), 0.3), + isclose(add_f(0.1, 0.2), 0.3), + ] + + ar = array.array("f", [1, 2, 3.5]) + productf(ar) + tests.append(isclose(ar[0], 7)) + + if "add_d" in globals(): + tests.append(isclose(add_d(0.1, 0.2), 0.3)) + + print(tests) + + if not all(tests): + raise SystemExit(1) + + +test() diff --git a/examples/natmod/framebuf/Makefile b/examples/natmod/framebuf/Makefile new file mode 100644 index 0000000000..2e2b815975 --- /dev/null +++ b/examples/natmod/framebuf/Makefile @@ -0,0 +1,13 @@ +# Location of top-level MicroPython directory +MPY_DIR = ../../.. + +# Name of module (different to built-in framebuf so it can coexist) +MOD = framebuf_$(ARCH) + +# Source files (.c or .py) +SRC = framebuf.c + +# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) +ARCH = x64 + +include $(MPY_DIR)/py/dynruntime.mk diff --git a/examples/natmod/framebuf/framebuf.c b/examples/natmod/framebuf/framebuf.c new file mode 100644 index 0000000000..8d488cffd6 --- /dev/null +++ b/examples/natmod/framebuf/framebuf.c @@ -0,0 +1,49 @@ +#define MICROPY_PY_FRAMEBUF (1) + +#include "py/dynruntime.h" + +#if !defined(__linux__) +void *memset(void *s, int c, size_t n) { + return mp_fun_table.memset_(s, c, n); +} +#endif + +mp_obj_type_t mp_type_framebuf; + +#include "extmod/modframebuf.c" + +mp_map_elem_t framebuf_locals_dict_table[10]; +STATIC MP_DEFINE_CONST_DICT(framebuf_locals_dict, framebuf_locals_dict_table); + +mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { + MP_DYNRUNTIME_INIT_ENTRY + + mp_type_framebuf.base.type = (void*)&mp_type_type; + mp_type_framebuf.name = MP_QSTR_FrameBuffer; + mp_type_framebuf.make_new = framebuf_make_new; + mp_type_framebuf.buffer_p.get_buffer = framebuf_get_buffer; + framebuf_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_fill), MP_OBJ_FROM_PTR(&framebuf_fill_obj) }; + framebuf_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_fill_rect), MP_OBJ_FROM_PTR(&framebuf_fill_rect_obj) }; + framebuf_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_pixel), MP_OBJ_FROM_PTR(&framebuf_pixel_obj) }; + framebuf_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_hline), MP_OBJ_FROM_PTR(&framebuf_hline_obj) }; + framebuf_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_vline), MP_OBJ_FROM_PTR(&framebuf_vline_obj) }; + framebuf_locals_dict_table[5] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_rect), MP_OBJ_FROM_PTR(&framebuf_rect_obj) }; + framebuf_locals_dict_table[6] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_line), MP_OBJ_FROM_PTR(&framebuf_line_obj) }; + framebuf_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_blit), MP_OBJ_FROM_PTR(&framebuf_blit_obj) }; + framebuf_locals_dict_table[8] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_scroll), MP_OBJ_FROM_PTR(&framebuf_scroll_obj) }; + framebuf_locals_dict_table[9] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_text), MP_OBJ_FROM_PTR(&framebuf_text_obj) }; + mp_type_framebuf.locals_dict = (void*)&framebuf_locals_dict; + + mp_store_global(MP_QSTR_FrameBuffer, MP_OBJ_FROM_PTR(&mp_type_framebuf)); + mp_store_global(MP_QSTR_FrameBuffer1, MP_OBJ_FROM_PTR(&legacy_framebuffer1_obj)); + mp_store_global(MP_QSTR_MVLSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MVLSB)); + mp_store_global(MP_QSTR_MONO_VLSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MVLSB)); + mp_store_global(MP_QSTR_RGB565, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_RGB565)); + mp_store_global(MP_QSTR_GS2_HMSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS2_HMSB)); + mp_store_global(MP_QSTR_GS4_HMSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS4_HMSB)); + mp_store_global(MP_QSTR_GS8, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS8)); + mp_store_global(MP_QSTR_MONO_HLSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MHLSB)); + mp_store_global(MP_QSTR_MONO_HMSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MHMSB)); + + MP_DYNRUNTIME_INIT_EXIT +} diff --git a/examples/natmod/uheapq/Makefile b/examples/natmod/uheapq/Makefile new file mode 100644 index 0000000000..55de3cc081 --- /dev/null +++ b/examples/natmod/uheapq/Makefile @@ -0,0 +1,13 @@ +# Location of top-level MicroPython directory +MPY_DIR = ../../.. + +# Name of module (different to built-in uheapq so it can coexist) +MOD = uheapq_$(ARCH) + +# Source files (.c or .py) +SRC = uheapq.c + +# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) +ARCH = x64 + +include $(MPY_DIR)/py/dynruntime.mk diff --git a/examples/natmod/uheapq/uheapq.c b/examples/natmod/uheapq/uheapq.c new file mode 100644 index 0000000000..9da6bb4ada --- /dev/null +++ b/examples/natmod/uheapq/uheapq.c @@ -0,0 +1,16 @@ +#define MICROPY_PY_UHEAPQ (1) + +#include "py/dynruntime.h" + +#include "extmod/moduheapq.c" + +mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { + MP_DYNRUNTIME_INIT_ENTRY + + mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_uheapq)); + mp_store_global(MP_QSTR_heappush, MP_OBJ_FROM_PTR(&mod_uheapq_heappush_obj)); + mp_store_global(MP_QSTR_heappop, MP_OBJ_FROM_PTR(&mod_uheapq_heappop_obj)); + mp_store_global(MP_QSTR_heapify, MP_OBJ_FROM_PTR(&mod_uheapq_heapify_obj)); + + MP_DYNRUNTIME_INIT_EXIT +} diff --git a/examples/natmod/urandom/Makefile b/examples/natmod/urandom/Makefile new file mode 100644 index 0000000000..3f018baaf7 --- /dev/null +++ b/examples/natmod/urandom/Makefile @@ -0,0 +1,13 @@ +# Location of top-level MicroPython directory +MPY_DIR = ../../.. + +# Name of module (different to built-in urandom so it can coexist) +MOD = urandom_$(ARCH) + +# Source files (.c or .py) +SRC = urandom.c + +# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) +ARCH = x64 + +include $(MPY_DIR)/py/dynruntime.mk diff --git a/examples/natmod/urandom/urandom.c b/examples/natmod/urandom/urandom.c new file mode 100644 index 0000000000..e1fed6a554 --- /dev/null +++ b/examples/natmod/urandom/urandom.c @@ -0,0 +1,33 @@ +#define MICROPY_PY_URANDOM (1) +#define MICROPY_PY_URANDOM_EXTRA_FUNCS (1) + +#include "py/dynruntime.h" + +// Dynamic native modules don't support a data section so these must go in the BSS +uint32_t yasmarang_pad, yasmarang_n, yasmarang_d; +uint8_t yasmarang_dat; + +#include "extmod/modurandom.c" + +mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { + MP_DYNRUNTIME_INIT_ENTRY + + yasmarang_pad = 0xeda4baba; + yasmarang_n = 69; + yasmarang_d = 233; + + mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_urandom)); + mp_store_global(MP_QSTR_getrandbits, MP_OBJ_FROM_PTR(&mod_urandom_getrandbits_obj)); + mp_store_global(MP_QSTR_seed, MP_OBJ_FROM_PTR(&mod_urandom_seed_obj)); + #if MICROPY_PY_URANDOM_EXTRA_FUNCS + mp_store_global(MP_QSTR_randrange, MP_OBJ_FROM_PTR(&mod_urandom_randrange_obj)); + mp_store_global(MP_QSTR_randint, MP_OBJ_FROM_PTR(&mod_urandom_randint_obj)); + mp_store_global(MP_QSTR_choice, MP_OBJ_FROM_PTR(&mod_urandom_choice_obj)); + #if MICROPY_PY_BUILTINS_FLOAT + mp_store_global(MP_QSTR_random, MP_OBJ_FROM_PTR(&mod_urandom_random_obj)); + mp_store_global(MP_QSTR_uniform, MP_OBJ_FROM_PTR(&mod_urandom_uniform_obj)); + #endif + #endif + + MP_DYNRUNTIME_INIT_EXIT +} diff --git a/examples/natmod/ure/Makefile b/examples/natmod/ure/Makefile new file mode 100644 index 0000000000..f5254298fd --- /dev/null +++ b/examples/natmod/ure/Makefile @@ -0,0 +1,13 @@ +# Location of top-level MicroPython directory +MPY_DIR = ../../.. + +# Name of module (different to built-in ure so it can coexist) +MOD = ure_$(ARCH) + +# Source files (.c or .py) +SRC = ure.c + +# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) +ARCH = x64 + +include $(MPY_DIR)/py/dynruntime.mk diff --git a/examples/natmod/ure/ure.c b/examples/natmod/ure/ure.c new file mode 100644 index 0000000000..175b93e395 --- /dev/null +++ b/examples/natmod/ure/ure.c @@ -0,0 +1,78 @@ +#define MICROPY_STACK_CHECK (1) +#define MICROPY_PY_URE (1) +#define MICROPY_PY_URE_MATCH_GROUPS (1) +#define MICROPY_PY_URE_MATCH_SPAN_START_END (1) +#define MICROPY_PY_URE_SUB (0) // requires vstr interface + +#include +#include "py/dynruntime.h" + +#define STACK_LIMIT (2048) + +const char *stack_top; + +void mp_stack_check(void) { + // Assumes descending stack on target + volatile char dummy; + if (stack_top - &dummy >= STACK_LIMIT) { + mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("maximum recursion depth exceeded")); + } +} + +#if !defined(__linux__) +void *memcpy(void *dst, const void *src, size_t n) { + return mp_fun_table.memmove_(dst, src, n); +} +void *memset(void *s, int c, size_t n) { + return mp_fun_table.memset_(s, c, n); +} +#endif + +void *memmove(void *dest, const void *src, size_t n) { + return mp_fun_table.memmove_(dest, src, n); +} + +mp_obj_type_t match_type; +mp_obj_type_t re_type; + +#include "extmod/modure.c" + +mp_map_elem_t match_locals_dict_table[5]; +STATIC MP_DEFINE_CONST_DICT(match_locals_dict, match_locals_dict_table); + +mp_map_elem_t re_locals_dict_table[3]; +STATIC MP_DEFINE_CONST_DICT(re_locals_dict, re_locals_dict_table); + +mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { + MP_DYNRUNTIME_INIT_ENTRY + + char dummy; + stack_top = &dummy; + + // Because MP_QSTR_start/end/split are static, xtensa and xtensawin will make a small data section + // to copy in this key/value pair if they are specified as a struct, so assign them separately. + + match_type.base.type = (void*)&mp_fun_table.type_type; + match_type.name = MP_QSTR_match; + match_type.print = match_print; + match_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_group), MP_OBJ_FROM_PTR(&match_group_obj) }; + match_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_groups), MP_OBJ_FROM_PTR(&match_groups_obj) }; + match_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_span), MP_OBJ_FROM_PTR(&match_span_obj) }; + match_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_start), MP_OBJ_FROM_PTR(&match_start_obj) }; + match_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_end), MP_OBJ_FROM_PTR(&match_end_obj) }; + match_type.locals_dict = (void*)&match_locals_dict; + + re_type.base.type = (void*)&mp_fun_table.type_type; + re_type.name = MP_QSTR_ure; + re_type.print = re_print; + re_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_match), MP_OBJ_FROM_PTR(&re_match_obj) }; + re_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_search), MP_OBJ_FROM_PTR(&re_search_obj) }; + re_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_split), MP_OBJ_FROM_PTR(&re_split_obj) }; + re_type.locals_dict = (void*)&re_locals_dict; + + mp_store_global(MP_QSTR_compile, MP_OBJ_FROM_PTR(&mod_re_compile_obj)); + mp_store_global(MP_QSTR_match, MP_OBJ_FROM_PTR(&re_match_obj)); + mp_store_global(MP_QSTR_search, MP_OBJ_FROM_PTR(&re_search_obj)); + + MP_DYNRUNTIME_INIT_EXIT +} diff --git a/examples/natmod/uzlib/Makefile b/examples/natmod/uzlib/Makefile new file mode 100644 index 0000000000..8761caf2dd --- /dev/null +++ b/examples/natmod/uzlib/Makefile @@ -0,0 +1,13 @@ +# Location of top-level MicroPython directory +MPY_DIR = ../../.. + +# Name of module (different to built-in uzlib so it can coexist) +MOD = uzlib_$(ARCH) + +# Source files (.c or .py) +SRC = uzlib.c + +# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) +ARCH = x64 + +include $(MPY_DIR)/py/dynruntime.mk diff --git a/examples/natmod/uzlib/uzlib.c b/examples/natmod/uzlib/uzlib.c new file mode 100644 index 0000000000..99b3691761 --- /dev/null +++ b/examples/natmod/uzlib/uzlib.c @@ -0,0 +1,35 @@ +#define MICROPY_PY_UZLIB (1) + +#include "py/dynruntime.h" + +#if !defined(__linux__) +void *memset(void *s, int c, size_t n) { + return mp_fun_table.memset_(s, c, n); +} +#endif + +mp_obj_type_t decompio_type; + +#include "extmod/moduzlib.c" + +mp_map_elem_t decompio_locals_dict_table[3]; +STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table); + +mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { + MP_DYNRUNTIME_INIT_ENTRY + + decompio_type.base.type = mp_fun_table.type_type; + decompio_type.name = MP_QSTR_DecompIO; + decompio_type.make_new = decompio_make_new; + decompio_type.protocol = &decompio_stream_p; + decompio_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_read), MP_OBJ_FROM_PTR(&mp_stream_read_obj) }; + decompio_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_OBJ_FROM_PTR(&mp_stream_readinto_obj) }; + decompio_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readline), MP_OBJ_FROM_PTR(&mp_stream_unbuffered_readline_obj) }; + decompio_type.locals_dict = (void*)&decompio_locals_dict; + + mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_uzlib)); + mp_store_global(MP_QSTR_decompress, MP_OBJ_FROM_PTR(&mod_uzlib_decompress_obj)); + mp_store_global(MP_QSTR_DecompIO, MP_OBJ_FROM_PTR(&decompio_type)); + + MP_DYNRUNTIME_INIT_EXIT +} diff --git a/extmod/modframebuf.c b/extmod/modframebuf.c index 8b9eec4fc9..6ec2c44fde 100644 --- a/extmod/modframebuf.c +++ b/extmod/modframebuf.c @@ -31,7 +31,6 @@ typedef uint32_t (*getpixel_t)(const mp_obj_framebuf_t *, int, int); typedef void (*fill_rect_t)(const mp_obj_framebuf_t *, int, int, int, int, uint32_t); typedef struct _mp_framebuf_p_t { - MP_PROTOCOL_HEAD setpixel_t setpixel; getpixel_t getpixel; fill_rect_t fill_rect; @@ -212,14 +211,14 @@ STATIC void gs8_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int } } -STATIC mp_framebuf_p_t formats[] = { - [FRAMEBUF_MVLSB] = {MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuf) mvlsb_setpixel, mvlsb_getpixel, mvlsb_fill_rect}, - [FRAMEBUF_RGB565] = {MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuf) rgb565_setpixel, rgb565_getpixel, rgb565_fill_rect}, - [FRAMEBUF_GS2_HMSB] = {MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuf) gs2_hmsb_setpixel, gs2_hmsb_getpixel, gs2_hmsb_fill_rect}, - [FRAMEBUF_GS4_HMSB] = {MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuf) gs4_hmsb_setpixel, gs4_hmsb_getpixel, gs4_hmsb_fill_rect}, - [FRAMEBUF_GS8] = {MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuf) gs8_setpixel, gs8_getpixel, gs8_fill_rect}, - [FRAMEBUF_MHLSB] = {MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuf) mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect}, - [FRAMEBUF_MHMSB] = {MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuf) mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect}, +STATIC const mp_framebuf_p_t formats[] = { + [FRAMEBUF_MVLSB] = {mvlsb_setpixel, mvlsb_getpixel, mvlsb_fill_rect}, + [FRAMEBUF_RGB565] = {rgb565_setpixel, rgb565_getpixel, rgb565_fill_rect}, + [FRAMEBUF_GS2_HMSB] = {gs2_hmsb_setpixel, gs2_hmsb_getpixel, gs2_hmsb_fill_rect}, + [FRAMEBUF_GS4_HMSB] = {gs4_hmsb_setpixel, gs4_hmsb_getpixel, gs4_hmsb_fill_rect}, + [FRAMEBUF_GS8] = {gs8_setpixel, gs8_getpixel, gs8_fill_rect}, + [FRAMEBUF_MHLSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect}, + [FRAMEBUF_MHMSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect}, }; static inline void setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { @@ -288,7 +287,9 @@ STATIC mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, cons return MP_OBJ_FROM_PTR(o); } +#if !(defined(MICROPY_ENABLE_DYNRUNTIME) && MICROPY_ENABLE_DYNRUNTIME) STATIC const mp_obj_type_t mp_type_framebuf; +#endif // Helper to ensure we have the native super class instead of a subclass. static mp_obj_framebuf_t *native_framebuf(mp_obj_t framebuf_obj) { diff --git a/extmod/modure.c b/extmod/modure.c index 7836140778..728d99701d 100644 --- a/extmod/modure.c +++ b/extmod/modure.c @@ -170,10 +170,11 @@ STATIC mp_obj_t ure_exec(bool is_anchored, uint n_args, const mp_obj_t *args) { size_t len; subj.begin = mp_obj_str_get_data(args[1], &len); subj.end = subj.begin + len; - #if MICROPY_PY_URE_MATCH_SPAN_START_END + #if MICROPY_PY_URE_MATCH_SPAN_START_END && !(defined(MICROPY_ENABLE_DYNRUNTIME) && MICROPY_ENABLE_DYNRUNTIME) + if (n_args > 2) { const mp_obj_type_t *self_type = mp_obj_get_type(args[1]); - mp_int_t str_len = MP_OBJ_SMALL_INT_VALUE(mp_obj_len_maybe(args[1])); + mp_int_t str_len = MP_OBJ_SMALL_INT_VALUE(mp_obj_len(args[1])); const byte *begin = (const byte *)subj.begin; int pos = mp_obj_get_int(args[2]); diff --git a/extmod/moduzlib.c b/extmod/moduzlib.c index e580075546..19fabc59a0 100644 --- a/extmod/moduzlib.c +++ b/extmod/moduzlib.c @@ -15,7 +15,7 @@ #if MICROPY_PY_UZLIB #define UZLIB_CONF_PARANOID_CHECKS (1) -#include "../../lib/uzlib/src/tinf.h" +#include "../lib/uzlib/src/tinf.h" #if 0 // print debugging info #define DEBUG_printf DEBUG_printf @@ -35,7 +35,7 @@ STATIC int read_src_stream(TINF_DATA *data) { p -= offsetof(mp_obj_decompio_t, decomp); mp_obj_decompio_t *self = (mp_obj_decompio_t *)p; - const mp_stream_p_t *stream = mp_get_stream(self->src_stream); + const mp_stream_p_t *stream = mp_get_stream_raise(self->src_stream, MP_STREAM_OP_READ); int err; byte c; mp_uint_t out_sz = stream->read(self->src_stream, &c, 1, &err); @@ -206,10 +206,10 @@ const mp_obj_module_t mp_module_uzlib = { // only if module is enabled by config setting. #pragma GCC diagnostic ignored "-Wsign-compare" -#include "../../lib/uzlib/src/tinflate.c" -#include "../../lib/uzlib/src/tinfzlib.c" -#include "../../lib/uzlib/src/tinfgzip.c" -#include "../../lib/uzlib/src/adler32.c" -#include "../../lib/uzlib/src/crc32.c" +#include "../lib/uzlib/src/tinflate.c" +#include "../lib/uzlib/src/tinfzlib.c" +#include "../lib/uzlib/src/tinfgzip.c" +#include "../lib/uzlib/src/adler32.c" +#include "../lib/uzlib/src/crc32.c" #endif // MICROPY_PY_UZLIB diff --git a/py/dynruntime.h b/py/dynruntime.h index 696746f751..215ffc5445 100644 --- a/py/dynruntime.h +++ b/py/dynruntime.h @@ -49,7 +49,7 @@ /******************************************************************************/ // Memory allocation -#define m_malloc(n) (m_malloc_dyn((n))) +#define m_malloc(n,_) (m_malloc_dyn((n))) #define m_free(ptr) (m_free_dyn((ptr))) #define m_realloc(ptr, new_num_bytes) (m_realloc_dyn((ptr), (new_num_bytes))) @@ -123,6 +123,8 @@ static inline void *m_realloc_dyn(void *ptr, size_t new_num_bytes) { #define mp_obj_subscr(base, index, val) (mp_fun_table.obj_subscr((base), (index), (val))) #define mp_obj_list_append(list, item) (mp_fun_table.list_append((list), (item))) +#define mp_obj_assert_native_inited(o) (mp_fun_table.assert_native_inited((o))) + static inline mp_obj_t mp_obj_new_str_of_type_dyn(const mp_obj_type_t *type, const byte *data, size_t len) { if (type == &mp_type_str) { return mp_obj_new_str((const char *)data, len); @@ -160,6 +162,7 @@ static inline mp_obj_t mp_obj_len_dyn(mp_obj_t o) { return mp_fun_table.call_function_n_kw(mp_fun_table.load_name(MP_QSTR_len), 1, &o); } + /******************************************************************************/ // General runtime functions @@ -175,7 +178,10 @@ static inline mp_obj_t mp_obj_len_dyn(mp_obj_t o) { #define mp_call_function_n_kw(fun, n_args, n_kw, args) \ (mp_fun_table.call_function_n_kw((fun), (n_args) | ((n_kw) << 8), args)) -#define mp_arg_check_num(n_args, n_kw, n_args_min, n_args_max, takes_kw) \ +#define mp_arg_check_num(n_args, kw_args, n_args_min, n_args_max, takes_kw) \ + (mp_fun_table.arg_check_num_sig((n_args), (kw_args) ? kw_args->used : 0, MP_OBJ_FUN_MAKE_SIG((n_args_min), (n_args_max), (takes_kw)))) + +#define mp_arg_check_num_mp(n_args, n_kw, n_args_min, n_args_max, takes_kw) \ (mp_fun_table.arg_check_num_sig((n_args), (n_kw), MP_OBJ_FUN_MAKE_SIG((n_args_min), (n_args_max), (takes_kw)))) #define MP_DYNRUNTIME_INIT_ENTRY \ @@ -200,7 +206,7 @@ static inline mp_obj_t mp_obj_len_dyn(mp_obj_t o) { #define mp_obj_new_exception_arg1(e_type, arg) (mp_obj_new_exception_arg1_dyn((e_type), (arg))) #define nlr_raise(o) (mp_raise_dyn(o)) -#define mp_raise_msg(type, msg) (mp_fun_table.raise_msg((type), (msg))) +#define mp_raise_msg(type, msg) (mp_fun_table.raise_msg_str((type), (msg))) #define mp_raise_OSError(er) (mp_raise_OSError_dyn(er)) #define mp_raise_NotImplementedError(msg) (mp_raise_msg(&mp_type_NotImplementedError, (msg))) #define mp_raise_TypeError(msg) (mp_raise_msg(&mp_type_TypeError, (msg))) @@ -217,6 +223,13 @@ static NORETURN inline void mp_raise_dyn(mp_obj_t o) { } } +static NORETURN inline void mp_raise_arg1(const mp_obj_type_t *exc_type, mp_obj_t arg) { + mp_fun_table.raise(mp_obj_new_exception_arg1_dyn(exc_type, arg)); + for (;;) { + } +} + + static inline void mp_raise_OSError_dyn(int er) { mp_obj_t args[1] = { MP_OBJ_NEW_SMALL_INT(er) }; nlr_raise(mp_call_function_n_kw(mp_load_global(MP_QSTR_OSError), 1, 0, &args[0])); diff --git a/py/nativeglue.c b/py/nativeglue.c index 0dfaa27d66..29ca77b39e 100644 --- a/py/nativeglue.c +++ b/py/nativeglue.c @@ -32,6 +32,7 @@ #include "py/runtime.h" #include "py/smallint.h" #include "py/nativeglue.h" +#include "py/objtype.h" #include "py/gc.h" #if MICROPY_DEBUG_VERBOSE // print debugging info @@ -328,6 +329,7 @@ const mp_fun_table_t mp_fun_table = { mp_obj_get_float_to_d, mp_get_buffer_raise, mp_get_stream_raise, + mp_obj_assert_native_inited, &mp_plat_print, &mp_type_type, &mp_type_str, diff --git a/py/nativeglue.h b/py/nativeglue.h index 51566907c8..e1f0be3f4f 100644 --- a/py/nativeglue.h +++ b/py/nativeglue.h @@ -156,6 +156,7 @@ typedef struct _mp_fun_table_t { double (*obj_get_float_to_d)(mp_obj_t o); void (*get_buffer_raise)(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags); const mp_stream_p_t *(*get_stream_raise)(mp_obj_t self_in, int flags); + void (*assert_native_inited)(mp_obj_t native_object); const mp_print_t *plat_print; const mp_obj_type_t *type_type; const mp_obj_type_t *type_str; diff --git a/py/runtime.h b/py/runtime.h index dcfd48e8ee..a8a3120eef 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -163,7 +163,9 @@ mp_obj_t mp_import_from(mp_obj_t module, qstr name); void mp_import_all(mp_obj_t module); #define mp_raise_type(exc_type) mp_raise_msg(exc_type, NULL) +#if !(defined(MICROPY_ENABLE_DYNRUNTIME) && MICROPY_ENABLE_DYNRUNTIME) NORETURN void mp_raise_arg1(const mp_obj_type_t *exc_type, mp_obj_t arg); +#endif NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, const compressed_string_t *msg); NORETURN void mp_raise_msg_varg(const mp_obj_type_t *exc_type, const compressed_string_t *fmt, ...); NORETURN void mp_raise_msg_vlist(const mp_obj_type_t *exc_type, const compressed_string_t *fmt, va_list argptr); diff --git a/supervisor/shared/translate.h b/supervisor/shared/translate.h index f6e3be8cfb..3096fc3e80 100644 --- a/supervisor/shared/translate.h +++ b/supervisor/shared/translate.h @@ -81,6 +81,10 @@ uint16_t decompress_length(const compressed_string_t *compressed); // Map MicroPython's error messages to our translations. +#if defined(MICROPY_ENABLE_DYNRUNTIME) && MICROPY_ENABLE_DYNRUNTIME +#define MP_ERROR_TEXT(x) (x) +#else #define MP_ERROR_TEXT(x) translate(x) +#endif #endif // MICROPY_INCLUDED_SUPERVISOR_TRANSLATE_H diff --git a/tests/micropython/import_mpy_native_gc.py b/tests/micropython/import_mpy_native_gc.py index 4ac983bd1b..9c00f7984d 100644 --- a/tests/micropython/import_mpy_native_gc.py +++ b/tests/micropython/import_mpy_native_gc.py @@ -49,9 +49,9 @@ class UserFS: # by the required value of sys.implementation.mpy. features0_file_contents = { # -march=x64 -mcache-lookup-bc - 0xB05: b'C\x05\x0b\x1f \x84b\xe9/\x00\x00\x00SH\x8b\x1ds\x00\x00\x00\xbe\x02\x00\x00\x00\xffS\x18\xbf\x01\x00\x00\x00H\x85\xc0u\x0cH\x8bC \xbe\x02\x00\x00\x00[\xff\xe0H\x0f\xaf\xf8H\xff\xc8\xeb\xe6ATUSH\x8b\x1dA\x00\x00\x00H\x8b\x7f\x08H\x8bk(\xff\xd5H\x8d5 \x00\x00\x00I\x89\xc4H\x8b\x05.\x00\x00\x00\x0f\xb78\xffShL\x89\xe7\xff\xd5H\x8b\x03[]A\\\xc3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x84@\x12factorial \x00\x00\r \x01"\x9f\x1c\x01\x1e\xff', + 0xB05: b'C\x05\x0b\x1f \x84b\xe9/\x00\x00\x00SH\x8b\x1ds\x00\x00\x00\xbe\x02\x00\x00\x00\xffS\x18\xbf\x01\x00\x00\x00H\x85\xc0u\x0cH\x8bC \xbe\x02\x00\x00\x00[\xff\xe0H\x0f\xaf\xf8H\xff\xc8\xeb\xe6ATUSH\x8b\x1dA\x00\x00\x00H\x8b\x7f\x08H\x8bk(\xff\xd5H\x8d5 \x00\x00\x00I\x89\xc4H\x8b\x05.\x00\x00\x00\x0f\xb78\xffShL\x89\xe7\xff\xd5H\x8b\x03[]A\\\xc3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x84@\x12factorial \x00\x00\r \x01"\xa1\x1c\x01\x1e\xff', # -march=armv7m - 0x1605: b"C\x05\x16\x1f \x84\x12\x1a\xe0\x00\x00\x13\xb5\nK\nJ{D\x9cX\x02!\xe3h\x98G\x03F\x01 3\xb9\x02!#i\x01\x93\x02\xb0\xbd\xe8\x10@\x18GXC\x01;\xf4\xe7\x00\xbfj\x00\x00\x00\x00\x00\x00\x00\xf8\xb5\tN\tK~D\xf4X@hgi\xb8G\x05F\x07K\x07I\xf2XyD\x10\x88ck\x98G(F\xb8G h\xf8\xbd6\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x01\x84\x00\x12factorial \x00\x00\r<\x01>\x9f8\x01:\xff", + 0x1605: b"C\x05\x16\x1f \x84\x12\x1a\xe0\x00\x00\x13\xb5\nK\nJ{D\x9cX\x02!\xe3h\x98G\x03F\x01 3\xb9\x02!#i\x01\x93\x02\xb0\xbd\xe8\x10@\x18GXC\x01;\xf4\xe7\x00\xbfj\x00\x00\x00\x00\x00\x00\x00\xf8\xb5\tN\tK~D\xf4X@hgi\xb8G\x05F\x07K\x07I\xf2XyD\x10\x88ck\x98G(F\xb8G h\xf8\xbd6\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x01\x84\x00\x12factorial \x00\x00\r<\x01>\xa18\x01:\xff", } # Populate other armv7m-derived archs based on armv7m. diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index 804e05b14f..88b3df5734 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -919,7 +919,7 @@ def merge_mpy(raw_codes, output_file): merged_mpy.extend(f.read()) else: header = bytearray(5) - header[0] = ord("M") + header[0] = ord("C") header[1] = config.MPY_VERSION header[2] = ( config.native_arch << 2 diff --git a/tools/mpy_ld.py b/tools/mpy_ld.py index 98aadcdf01..b125febd61 100755 --- a/tools/mpy_ld.py +++ b/tools/mpy_ld.py @@ -758,7 +758,7 @@ def link_objects(env, native_qstr_vals_len, native_qstr_objs_len): # Resolve unknown symbols mp_fun_table_sec = Section(".external.mp_fun_table", b"", 0) fun_table = { - key: 67 + idx + key: 68 + idx for idx, key in enumerate( [ "mp_type_type", @@ -908,13 +908,7 @@ def build_mpy(env, entry_offset, fmpy, native_qstr_vals, native_qstr_objs): # MPY: header out.write_bytes( bytearray( - [ - ord("C"), - MPY_VERSION, - env.arch.mpy_feature, - MP_SMALL_INT_BITS, - QSTR_WINDOW_SIZE, - ] + [ord("C"), MPY_VERSION, env.arch.mpy_feature, MP_SMALL_INT_BITS, QSTR_WINDOW_SIZE,] ) )