diff --git a/.github/workflows/code_formatting.yml b/.github/workflows/code_formatting.yml index 9f30f048cfdbe..1972bc6b376c5 100644 --- a/.github/workflows/code_formatting.yml +++ b/.github/workflows/code_formatting.yml @@ -3,7 +3,7 @@ name: Check code formatting on: [push, pull_request] concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} cancel-in-progress: true jobs: diff --git a/.github/workflows/ports_m68kmac.yml b/.github/workflows/ports_m68kmac.yml index eec7559865f75..15b76f2d082c4 100644 --- a/.github/workflows/ports_m68kmac.yml +++ b/.github/workflows/ports_m68kmac.yml @@ -8,7 +8,7 @@ on: - created concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} cancel-in-progress: true jobs: diff --git a/.github/workflows/ports_unix.yml b/.github/workflows/ports_unix.yml index 6d885e69d6457..9f5ec001ecbe9 100644 --- a/.github/workflows/ports_unix.yml +++ b/.github/workflows/ports_unix.yml @@ -16,57 +16,10 @@ on: - 'tests/**' concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} cancel-in-progress: true jobs: - minimal: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Build - run: source tools/ci.sh && ci_unix_minimal_build - - name: Run main test suite - run: source tools/ci.sh && ci_unix_minimal_run_tests - - name: Print failures - if: failure() - run: tests/run-tests.py --print-failures - - reproducible: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Build with reproducible date - run: source tools/ci.sh && ci_unix_minimal_build - env: - SOURCE_DATE_EPOCH: 1234567890 - - name: Check reproducible build date - run: echo | ports/unix/build-minimal/micropython -i | grep 'on 2009-02-13;' - - standard: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Build - run: source tools/ci.sh && ci_unix_standard_build - - name: Run main test suite - run: source tools/ci.sh && ci_unix_standard_run_tests - - name: Print failures - if: failure() - run: tests/run-tests.py --print-failures - - standard_v2: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Build - run: source tools/ci.sh && ci_unix_standard_v2_build - - name: Run main test suite - run: source tools/ci.sh && ci_unix_standard_v2_run_tests - - name: Print failures - if: failure() - run: tests/run-tests.py --print-failures - coverage: runs-on: ubuntu-latest steps: @@ -113,186 +66,3 @@ jobs: - name: Print failures if: failure() run: tests/run-tests.py --print-failures - - nanbox: - runs-on: ubuntu-22.04 # use 22.04 to get python2, and libffi-dev:i386 - steps: - - uses: actions/checkout@v4 - - name: Install packages - run: source tools/ci.sh && ci_unix_32bit_setup - - name: Build - run: source tools/ci.sh && ci_unix_nanbox_build - - name: Run main test suite - run: source tools/ci.sh && ci_unix_nanbox_run_tests - - name: Print failures - if: failure() - run: tests/run-tests.py --print-failures - - float: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Install packages - run: source tools/ci.sh && ci_unix_float_setup - - name: Build - run: source tools/ci.sh && ci_unix_float_build - - name: Run main test suite - run: source tools/ci.sh && ci_unix_float_run_tests - - name: Print failures - if: failure() - run: tests/run-tests.py --print-failures - - stackless_clang: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Install packages - run: source tools/ci.sh && ci_unix_clang_setup - - name: Build - run: source tools/ci.sh && ci_unix_stackless_clang_build - - name: Run main test suite - run: source tools/ci.sh && ci_unix_stackless_clang_run_tests - - name: Print failures - if: failure() - run: tests/run-tests.py --print-failures - - float_clang: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Install packages - run: source tools/ci.sh && ci_unix_clang_setup - - name: Build - run: source tools/ci.sh && ci_unix_float_clang_build - - name: Run main test suite - run: source tools/ci.sh && ci_unix_float_clang_run_tests - - name: Print failures - if: failure() - run: tests/run-tests.py --print-failures - - settrace_stackless: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - # Python 3.12 is the default for ubuntu-24.04, but that has compatibility issues with settrace tests. - # Can remove this step when ubuntu-latest uses a more recent Python 3.x as the default. - with: - python-version: '3.11' - - name: Build - run: source tools/ci.sh && ci_unix_settrace_stackless_build - - name: Run main test suite - run: source tools/ci.sh && ci_unix_settrace_stackless_run_tests - - name: Print failures - if: failure() - run: tests/run-tests.py --print-failures - - macos: - runs-on: macos-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: '3.8' - - name: Build - run: source tools/ci.sh && ci_unix_macos_build - - name: Run tests - run: source tools/ci.sh && ci_unix_macos_run_tests - - name: Print failures - if: failure() - run: tests/run-tests.py --print-failures - - qemu_mips: - # ubuntu-22.04 is needed for older libffi. - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4 - - name: Install packages - run: source tools/ci.sh && ci_unix_qemu_mips_setup - - name: Build - run: source tools/ci.sh && ci_unix_qemu_mips_build - - name: Run main test suite - run: source tools/ci.sh && ci_unix_qemu_mips_run_tests - - name: Print failures - if: failure() - run: tests/run-tests.py --print-failures - - qemu_arm: - # ubuntu-22.04 is needed for older libffi. - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4 - - name: Install packages - run: source tools/ci.sh && ci_unix_qemu_arm_setup - - name: Build - run: source tools/ci.sh && ci_unix_qemu_arm_build - - name: Run main test suite - run: source tools/ci.sh && ci_unix_qemu_arm_run_tests - - name: Print failures - if: failure() - run: tests/run-tests.py --print-failures - - qemu_riscv64: - # ubuntu-22.04 is needed for older libffi. - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4 - - name: Install packages - run: source tools/ci.sh && ci_unix_qemu_riscv64_setup - - name: Build - run: source tools/ci.sh && ci_unix_qemu_riscv64_build - - name: Run main test suite - run: source tools/ci.sh && ci_unix_qemu_riscv64_run_tests - - name: Print failures - if: failure() - run: tests/run-tests.py --print-failures - - sanitize_address: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - # Python 3.12 is the default for ubuntu-24.04, but that has compatibility issues with settrace tests. - # Can remove this step when ubuntu-latest uses a more recent Python 3.x as the default. - with: - python-version: '3.11' - - name: Install packages - run: source tools/ci.sh && ci_unix_coverage_setup - - name: Build - run: source tools/ci.sh && ci_unix_sanitize_address_build - - name: Run main test suite - run: source tools/ci.sh && ci_unix_sanitize_address_run_tests - - name: Test merging .mpy files - run: source tools/ci.sh && ci_unix_coverage_run_mpy_merge_tests - - name: Build native mpy modules - run: source tools/ci.sh && ci_native_mpy_modules_build - - name: Test importing .mpy generated by mpy_ld.py - run: source tools/ci.sh && ci_unix_coverage_run_native_mpy_tests - - name: Print failures - if: failure() - run: tests/run-tests.py --print-failures - - sanitize_undefined: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - # Python 3.12 is the default for ubuntu-24.04, but that has compatibility issues with settrace tests. - # Can remove this step when ubuntu-latest uses a more recent Python 3.x as the default. - with: - python-version: '3.11' - - name: Install packages - run: source tools/ci.sh && ci_unix_coverage_setup - - name: Build - run: source tools/ci.sh && ci_unix_sanitize_undefined_build - - name: Run main test suite - run: source tools/ci.sh && ci_unix_sanitize_undefined_run_tests - - name: Test merging .mpy files - run: source tools/ci.sh && ci_unix_coverage_run_mpy_merge_tests - - name: Build native mpy modules - run: source tools/ci.sh && ci_native_mpy_modules_build - - name: Test importing .mpy generated by mpy_ld.py - run: source tools/ci.sh && ci_unix_coverage_run_native_mpy_tests - - name: Print failures - if: failure() - run: tests/run-tests.py --print-failures diff --git a/extmod/moductypes.c b/extmod/moductypes.c index 4ba3fb7146b47..d0c3178a9fe16 100644 --- a/extmod/moductypes.c +++ b/extmod/moductypes.c @@ -48,13 +48,21 @@ static const mp_obj_type_t uctypes_struct_type; // Get size of any type descriptor static mp_uint_t uctypes_struct_size(mp_obj_t desc_in, int layout_type, mp_uint_t *max_field_size); +#define CTYPES_FLAGS_SIZE_BITS (2) +#define CTYPES_OFFSET_SIZE_BITS (8 * sizeof(uint32_t) - 2) + typedef struct _mp_obj_uctypes_struct_t { mp_obj_base_t base; mp_obj_t desc; - byte *addr; - uint32_t flags; + byte *ptrbase; + uint32_t flags : CTYPES_FLAGS_SIZE_BITS; + uint32_t offset : CTYPES_OFFSET_SIZE_BITS; } mp_obj_uctypes_struct_t; +static inline byte *struct_addr(mp_obj_uctypes_struct_t *s) { + return s->ptrbase + s->offset; +} + static MP_NORETURN void syntax_error(void) { mp_raise_TypeError(MP_ERROR_TEXT("syntax error in uctypes descriptor")); } @@ -80,10 +88,12 @@ mp_obj_t uctypes_struct_make_new(const mp_obj_type_t *type, size_t n_args, size_ } mp_buffer_info_t bufinfo; mp_obj_uctypes_struct_t *o = mp_obj_malloc(mp_obj_uctypes_struct_t, type); - if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_READ)) { - o->addr = bufinfo.buf; + if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_READ | MP_BUFFER_GET_BASE)) { + o->ptrbase = bufinfo.base; + o->offset = (char *)bufinfo.buf - (char *)bufinfo.base; } else { - o->addr = (void *)(uintptr_t)mp_obj_get_int_truncated(args[0]); + o->ptrbase = (void *)(uintptr_t)mp_obj_get_int_truncated(args[0]); + o->offset = 0; } o->desc = desc; o->flags = flags; @@ -107,9 +117,8 @@ mp_obj_t uctypes_struct_type_make_new(const mp_obj_type_t *type_in, size_t n_arg mp_uint_t size = uctypes_struct_size(desc, type->struct_flags, &max_field_size); mp_buffer_info_t bufinfo; - mp_obj_t bytearray = mp_obj_new_bytearray(size, NULL); - mp_get_buffer_raise(bytearray, &bufinfo, MP_BUFFER_WRITE); if (is_ptr(desc)) { + bufinfo.len = size; if (n_args != 1) { mp_raise_TypeError(NULL); } @@ -121,6 +130,9 @@ mp_obj_t uctypes_struct_type_make_new(const mp_obj_type_t *type_in, size_t n_arg mp_get_buffer_raise(args[0], &pointee, MP_BUFFER_WRITE); *(void **)bufinfo.buf = pointee.buf; } + } else { + mp_obj_t bytearray = mp_obj_new_bytearray(size, NULL); + mp_get_buffer_raise(bytearray, &bufinfo, MP_BUFFER_WRITE); } mp_obj_t args1[] = {mp_obj_new_int((intptr_t)bufinfo.buf), desc, mp_obj_new_int(type->struct_flags)}; @@ -180,7 +192,7 @@ void uctypes_struct_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ki typen = "ERROR"; } - mp_printf(print, "<%q %s %p>", (qstr)mp_obj_get_type_qstr(self_in), typen, self->addr); + mp_printf(print, "<%q %s %p>", (qstr)mp_obj_get_type_qstr(self_in), typen, struct_addr(self)); } // Get size of scalar type descriptor @@ -477,16 +489,16 @@ static mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set if (val_type <= INT64 || val_type == FLOAT32 || val_type == FLOAT64) { if (self->flags == LAYOUT_NATIVE) { if (set_val == MP_OBJ_NULL) { - return get_aligned(val_type, self->addr + offset, 0); + return get_aligned(val_type, struct_addr(self) + offset, 0); } else { - set_aligned(val_type, self->addr + offset, 0, set_val); + set_aligned(val_type, struct_addr(self) + offset, 0, set_val); return set_val; // just !MP_OBJ_NULL } } else { if (set_val == MP_OBJ_NULL) { - return get_unaligned(val_type, self->addr + offset, self->flags); + return get_unaligned(val_type, struct_addr(self) + offset, self->flags); } else { - set_unaligned(val_type, self->addr + offset, self->flags, set_val); + set_unaligned(val_type, struct_addr(self) + offset, self->flags, set_val); return set_val; // just !MP_OBJ_NULL } } @@ -496,9 +508,9 @@ static mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set offset &= (1 << OFFSET_BITS) - 1; mp_uint_t val; if (self->flags == LAYOUT_NATIVE) { - val = get_aligned_basic(val_type & 6, self->addr + offset); + val = get_aligned_basic(val_type & 6, struct_addr(self) + offset); } else { - val = mp_binary_get_int(GET_SCALAR_SIZE(val_type & 7), val_type & 1, self->flags, self->addr + offset); + val = mp_binary_get_int(GET_SCALAR_SIZE(val_type & 7), val_type & 1, self->flags, struct_addr(self) + offset); } if (set_val == MP_OBJ_NULL) { val >>= bit_offset; @@ -515,10 +527,10 @@ static mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set val = (val & ~mask) | set_val_int; if (self->flags == LAYOUT_NATIVE) { - set_aligned_basic(val_type & 6, self->addr + offset, val); + set_aligned_basic(val_type & 6, struct_addr(self) + offset, val); } else { mp_binary_set_int(GET_SCALAR_SIZE(val_type & 7), self->flags == LAYOUT_BIG_ENDIAN, - self->addr + offset, val); + struct_addr(self) + offset, val); } return set_val; // just !MP_OBJ_NULL } @@ -544,19 +556,19 @@ static mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set switch (agg_type) { case STRUCT: { - mp_obj_t args[] = { mp_obj_new_int((mp_uint_t)(uintptr_t)self->addr + offset), sub->items[1], mp_obj_new_int(self->flags) }; + mp_obj_t args[] = { mp_obj_new_int((mp_uint_t)(uintptr_t)struct_addr(self) + offset), sub->items[1], mp_obj_new_int(self->flags) }; return uctypes_struct_make_new(&uctypes_struct_type, MP_ARRAY_SIZE(args), 0, args); } case ARRAY: { mp_uint_t dummy; if (IS_SCALAR_ARRAY(sub) && IS_SCALAR_ARRAY_OF_BYTES(sub)) { - return mp_obj_new_bytearray_by_ref(uctypes_struct_agg_size(sub, self->flags, &dummy), self->addr + offset); + return mp_obj_new_bytearray_by_ref(uctypes_struct_agg_size(sub, self->flags, &dummy), struct_addr(self) + offset); } // Fall thru to return uctypes struct object MP_FALLTHROUGH } case PTR: { - mp_obj_t args[] = { mp_obj_new_int((mp_uint_t)(uintptr_t)self->addr + offset), deref, mp_obj_new_int(self->flags) }; + mp_obj_t args[] = { mp_obj_new_int((mp_uint_t)(uintptr_t)struct_addr(self) + offset), deref, mp_obj_new_int(self->flags) }; return uctypes_struct_make_new(&uctypes_struct_type, MP_ARRAY_SIZE(args), 0, args); } } @@ -640,13 +652,13 @@ mp_obj_t uctypes_struct_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t val // array of scalars if (self->flags == LAYOUT_NATIVE) { if (value == MP_OBJ_SENTINEL) { - return get_aligned(val_type, self->addr, index); + return get_aligned(val_type, struct_addr(self), index); } else { - set_aligned(val_type, self->addr, index, value); + set_aligned(val_type, struct_addr(self), index, value); return value; // just !MP_OBJ_NULL } } else { - byte *p = self->addr + uctypes_struct_scalar_size(val_type) * index; + byte *p = struct_addr(self) + uctypes_struct_scalar_size(val_type) * index; if (value == MP_OBJ_SENTINEL) { return get_unaligned(val_type, p, self->flags); } else { @@ -657,14 +669,14 @@ mp_obj_t uctypes_struct_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t val } else if (value == MP_OBJ_SENTINEL) { mp_uint_t dummy = 0; mp_uint_t size = uctypes_struct_size(t->items[2], self->flags, &dummy); - mp_obj_t args[] = { mp_obj_new_int((mp_uint_t)(uintptr_t)self->addr + size * index), t->items[2], mp_obj_new_int(self->flags) }; + mp_obj_t args[] = { mp_obj_new_int((mp_uint_t)(uintptr_t)struct_addr(self) + size * index), t->items[2], mp_obj_new_int(self->flags) }; return uctypes_struct_make_new(&uctypes_struct_type, MP_ARRAY_SIZE(args), 0, args); } else { return MP_OBJ_NULL; // op not supported } } else if (agg_type == PTR) { - byte *p = *(void **)self->addr; + byte *p = *(void **)struct_addr(self); if (mp_obj_is_small_int(t->items[1])) { uint val_type = GET_TYPE(MP_OBJ_SMALL_INT_VALUE(t->items[1]), VAL_TYPE_BITS); if (value == MP_OBJ_SENTINEL) { @@ -695,7 +707,7 @@ mp_obj_t uctypes_struct_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]); uint agg_type = GET_TYPE(offset, AGG_TYPE_BITS); if (agg_type == PTR) { - byte *p = *(void **)self->addr; + byte *p = *(void **)struct_addr(self); return mp_obj_new_int_from_uint((uintptr_t)p); } } @@ -712,9 +724,13 @@ mp_int_t uctypes_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint mp_uint_t max_field_size = 0; mp_uint_t size = uctypes_struct_size(self->desc, self->flags, &max_field_size); - bufinfo->buf = self->addr; + bufinfo->buf = struct_addr(self); bufinfo->len = size; bufinfo->typecode = BYTEARRAY_TYPECODE; + if (flags & MP_BUFFER_GET_BASE) { + bufinfo->base = (void *)self->ptrbase; + } + return 0; } diff --git a/extmod/vfs_rom_file.c b/extmod/vfs_rom_file.c index 57aca8c5dc7d3..0811e0f9b1cab 100644 --- a/extmod/vfs_rom_file.c +++ b/extmod/vfs_rom_file.c @@ -82,7 +82,7 @@ mp_obj_t mp_vfs_rom_file_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_ static mp_int_t vfs_rom_file_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { mp_obj_vfs_rom_file_t *self = MP_OBJ_TO_PTR(self_in); - if (flags == MP_BUFFER_READ) { + if ((flags & MP_BUFFER_RW) == MP_BUFFER_READ) { bufinfo->buf = (void *)self->file_data; bufinfo->len = self->file_size; bufinfo->typecode = 'B'; diff --git a/ports/alif/alif_flash.c b/ports/alif/alif_flash.c index 722afadae1f7b..ddc1668953ca9 100644 --- a/ports/alif/alif_flash.c +++ b/ports/alif/alif_flash.c @@ -82,7 +82,7 @@ static mp_obj_t alif_flash_make_new(const mp_obj_type_t *type, size_t n_args, si static mp_int_t alif_flash_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { alif_flash_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (flags == MP_BUFFER_READ) { + if ((flags & MP_BUFFER_RW) == MP_BUFFER_READ) { bufinfo->buf = (void *)(ospi_flash_get_xip_base() + self->flash_base_addr); bufinfo->len = self->flash_size; bufinfo->typecode = 'B'; diff --git a/ports/esp32/esp32_partition.c b/ports/esp32/esp32_partition.c index f33e9da671b8c..f5184f79323ca 100644 --- a/ports/esp32/esp32_partition.c +++ b/ports/esp32/esp32_partition.c @@ -131,7 +131,7 @@ static mp_obj_t esp32_partition_make_new(const mp_obj_type_t *type, size_t n_arg #if MICROPY_VFS_ROM_IOCTL static mp_int_t esp32_partition_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { esp32_partition_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (self == &esp32_partition_romfs_obj && flags == MP_BUFFER_READ) { + if (self == &esp32_partition_romfs_obj && (flags & MP_BUFFER_RW) == MP_BUFFER_READ) { if (esp32_partition_romfs_ptr == NULL) { check_esp_err(esp_partition_mmap(self->part, 0, self->part->size, ESP_PARTITION_MMAP_DATA, &esp32_partition_romfs_ptr, &esp32_partition_romfs_handle)); } diff --git a/ports/rp2/rp2_flash.c b/ports/rp2/rp2_flash.c index d6b9e13653315..cba6df4fa767d 100644 --- a/ports/rp2/rp2_flash.c +++ b/ports/rp2/rp2_flash.c @@ -232,7 +232,7 @@ static mp_obj_t rp2_flash_make_new(const mp_obj_type_t *type, size_t n_args, siz static mp_int_t rp2_flash_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { rp2_flash_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (flags == MP_BUFFER_READ) { + if ((flags & MP_BUFFER_RW) == MP_BUFFER_READ) { bufinfo->buf = (void *)(XIP_BASE + self->flash_base); bufinfo->len = self->flash_size; bufinfo->typecode = 'B'; diff --git a/py/obj.c b/py/obj.c index 9e7c347b51cb7..f5efe1d320d15 100644 --- a/py/obj.c +++ b/py/obj.c @@ -586,8 +586,14 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_identity_obj, mp_identity); bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) { const mp_obj_type_t *type = mp_obj_get_type(obj); + if (flags & MP_BUFFER_GET_BASE) { + bufinfo->base = NULL; + } if (MP_OBJ_TYPE_HAS_SLOT(type, buffer) - && MP_OBJ_TYPE_GET_SLOT(type, buffer)(obj, bufinfo, flags & MP_BUFFER_RW) == 0) { + && MP_OBJ_TYPE_GET_SLOT(type, buffer)(obj, bufinfo, flags & ~MP_BUFFER_RAISE_IF_UNSUPPORTED) == 0) { + if ((flags & MP_BUFFER_GET_BASE) && !bufinfo->base) { + bufinfo->base = bufinfo->buf; + } return true; } if (flags & MP_BUFFER_RAISE_IF_UNSUPPORTED) { diff --git a/py/obj.h b/py/obj.h index 0f87282a9f40b..5239f1a26c262 100644 --- a/py/obj.h +++ b/py/obj.h @@ -608,12 +608,14 @@ typedef struct _mp_buffer_info_t { void *buf; // can be NULL if len == 0 size_t len; // in bytes int typecode; // as per binary.h + void *base; // the "base address" of the buffer, only populated if MP_BUFFER_GET_BASE flag is set and the type supports it. } mp_buffer_info_t; #define MP_BUFFER_READ (1) #define MP_BUFFER_WRITE (2) #define MP_BUFFER_RW (MP_BUFFER_READ | MP_BUFFER_WRITE) #define MP_BUFFER_RAISE_IF_UNSUPPORTED (4) +#define MP_BUFFER_GET_BASE (8) // populate the "base" pointer typedef mp_int_t (*mp_buffer_fun_t)(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags); diff --git a/py/objarray.c b/py/objarray.c index bff93088fc8ac..db812b00671ca 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -225,7 +225,7 @@ static mp_obj_t memoryview_make_new(const mp_obj_type_t *type_in, size_t n_args, mp_arg_check_num(n_args, n_kw, 1, 1, false); mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); + mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ | MP_BUFFER_GET_BASE); mp_obj_array_t *self = MP_OBJ_TO_PTR(mp_obj_new_memoryview(bufinfo.typecode, bufinfo.len / mp_binary_get_size('@', bufinfo.typecode, NULL), @@ -233,12 +233,8 @@ static mp_obj_t memoryview_make_new(const mp_obj_type_t *type_in, size_t n_args, // If the input object is a memoryview then need to point the items of the // new memoryview to the start of the buffer so the GC can trace it. - if (mp_obj_get_type(args[0]) == &mp_type_memoryview) { - mp_obj_array_t *other = MP_OBJ_TO_PTR(args[0]); - self->memview_offset = other->memview_offset; - self->items = other->items; - } - + self->memview_offset = (char *)bufinfo.buf - (char *)bufinfo.base; + self->items = bufinfo.base; // test if the object can be written to if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_RW)) { self->typecode |= MP_OBJ_ARRAY_TYPECODE_FLAG_RW; // indicate writable buffer @@ -599,6 +595,9 @@ static mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_ui return 1; } bufinfo->buf = (uint8_t *)bufinfo->buf + (size_t)o->memview_offset * sz; + if (flags & MP_BUFFER_GET_BASE) { + bufinfo->base = (uint8_t *)o->items; + } } #else (void)flags; diff --git a/py/objringio.c b/py/objringio.c index ba1ec25307ea4..d89bcc6daf543 100644 --- a/py/objringio.c +++ b/py/objringio.c @@ -40,7 +40,7 @@ typedef struct _micropython_ringio_obj_t { static mp_obj_t micropython_ringio_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); mp_int_t buff_size = -1; - mp_buffer_info_t bufinfo = {NULL, 0, 0}; + mp_buffer_info_t bufinfo = {NULL, 0, 0, 0}; if (!mp_get_buffer(args[0], &bufinfo, MP_BUFFER_RW)) { buff_size = mp_obj_get_int(args[0]); diff --git a/py/objstr.c b/py/objstr.c index c81fc682fd4e8..6f1ebbdd1fa32 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -2060,7 +2060,7 @@ static MP_DEFINE_CONST_CLASSMETHOD_OBJ(bytes_fromhex_classmethod_obj, MP_ROM_PTR #endif // MICROPY_PY_BUILTINS_BYTES_HEX mp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { - if (flags == MP_BUFFER_READ) { + if ((flags & MP_BUFFER_RW) == MP_BUFFER_READ) { GET_STR_DATA_LEN(self_in, str_data, str_len); bufinfo->buf = (void *)str_data; bufinfo->len = str_len;