Skip to content

Commit c84ab58

Browse files
committed
WIP: py/objint,py/binary: Reduce code size of int to byte conversions.
Refactors similar code paths to a common mp_obj_int_to_bytes() function to reduce code size. This commit should have no functional changes. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
1 parent db36ec0 commit c84ab58

File tree

10 files changed

+156
-154
lines changed

10 files changed

+156
-154
lines changed

extmod/moductypes.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -448,8 +448,8 @@ static mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
448448
if (self->flags == LAYOUT_NATIVE) {
449449
set_aligned_basic(val_type & 6, self->addr + offset, val);
450450
} else {
451-
mp_binary_set_int(GET_SCALAR_SIZE(val_type & 7), self->flags == LAYOUT_BIG_ENDIAN,
452-
self->addr + offset, val);
451+
size_t item_size = GET_SCALAR_SIZE(val_type & 7);
452+
mp_binary_set_int(item_size, self->addr + offset, item_size, val, self->flags == LAYOUT_BIG_ENDIAN);
453453
}
454454
return set_val; // just !MP_OBJ_NULL
455455
}

ports/unix/modffi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ static unsigned long long ffi_get_int_value(mp_obj_t o) {
446446
return MP_OBJ_SMALL_INT_VALUE(o);
447447
} else {
448448
unsigned long long res;
449-
mp_obj_int_to_bytes_impl(o, MP_ENDIANNESS_BIG, sizeof(res), (byte *)&res);
449+
mp_obj_int_to_bytes(o, sizeof(res), (byte *)&res, MP_ENDIANNESS_BIG, false, false);
450450
return res;
451451
}
452452
}

py/binary.c

Lines changed: 25 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,21 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte *p_base, byte *
374374
}
375375
}
376376

377-
void mp_binary_set_int(size_t val_sz, bool big_endian, byte *dest, mp_uint_t val) {
377+
void mp_binary_set_int(size_t dest_sz, byte *dest, size_t val_sz, mp_uint_t val, bool big_endian) {
378+
if (dest_sz > val_sz) {
379+
// zero/sign extension if needed
380+
int c = ((mp_int_t)val < 0) ? 0xff : 0x00;
381+
memset(dest, c, dest_sz);
382+
383+
// big endian: write val_sz bytes at end of 'dest'
384+
if (big_endian) {
385+
dest += dest_sz - val_sz;
386+
}
387+
} else if (dest_sz < val_sz) {
388+
// truncate 'val' into 'dest'
389+
val_sz = dest_sz;
390+
}
391+
378392
if (MP_ENDIANNESS_LITTLE && !big_endian) {
379393
memcpy(dest, &val, val_sz);
380394
} else if (MP_ENDIANNESS_BIG && big_endian) {
@@ -438,48 +452,21 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p
438452
val = fp_dp.i64;
439453
} else {
440454
int be = struct_type == '>';
441-
mp_binary_set_int(sizeof(uint32_t), be, p, fp_dp.i32[MP_ENDIANNESS_BIG ^ be]);
455+
mp_binary_set_int(sizeof(uint32_t), p, sizeof(uint32_t), fp_dp.i32[MP_ENDIANNESS_BIG ^ be], be);
456+
// Now fall through and copy the second word, below
442457
p += sizeof(uint32_t);
458+
size = sizeof(uint32_t);
443459
val = fp_dp.i32[MP_ENDIANNESS_LITTLE ^ be];
444460
}
445461
break;
446462
}
447463
#endif
448-
default: {
449-
#if OVERFLOW_CHECKS
450-
bool signed_type = is_signed(val_type);
451-
#endif
452-
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
453-
if (mp_obj_is_exact_type(val_in, &mp_type_int)) {
454-
// It's a longint.
455-
#if OVERFLOW_CHECKS
456-
mp_obj_int_buffer_overflow_check(val_in, size, signed_type);
457-
#endif
458-
mp_obj_int_to_bytes_impl(val_in, struct_type == '>', size, p);
459-
return;
460-
}
461-
#endif
462-
{
463-
val = mp_obj_get_int(val_in);
464-
465-
#if OVERFLOW_CHECKS
466-
// Small int checking is separate, to be fast.
467-
mp_small_int_buffer_overflow_check(val, size, signed_type);
468-
#endif
469-
// zero/sign extend if needed
470-
if (MP_BYTES_PER_OBJ_WORD < 8 && size > sizeof(val)) {
471-
int c = (mp_int_t)val < 0 ? 0xff : 0x00;
472-
memset(p, c, size);
473-
if (struct_type == '>') {
474-
p += size - sizeof(val);
475-
}
476-
}
477-
}
478-
break;
479-
}
464+
default:
465+
mp_obj_int_to_bytes(val_in, size, p, struct_type == '>', is_signed(val_type), OVERFLOW_CHECKS);
466+
return;
480467
}
481468

482-
mp_binary_set_int(MIN((size_t)size, sizeof(val)), struct_type == '>', p, val);
469+
mp_binary_set_int(size, p, sizeof(val), val, struct_type == '>');
483470
}
484471

485472
void mp_binary_set_val_array(char typecode, void *p, size_t index, mp_obj_t val_in) {
@@ -498,29 +485,9 @@ void mp_binary_set_val_array(char typecode, void *p, size_t index, mp_obj_t val_
498485
break;
499486
default: {
500487
size_t size = mp_binary_get_size('@', typecode, NULL);
501-
#if OVERFLOW_CHECKS
502-
bool signed_type = is_signed(typecode);
503-
#endif
504-
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
505-
if (mp_obj_is_exact_type(val_in, &mp_type_int)) {
506-
// It's a long int.
507-
#if OVERFLOW_CHECKS
508-
mp_obj_int_buffer_overflow_check(val_in, size, signed_type);
509-
#endif
510-
mp_obj_int_to_bytes_impl(val_in, MP_ENDIANNESS_BIG,
511-
size, (uint8_t *)p + index * size);
512-
return;
513-
}
514-
#endif
515-
mp_int_t val = mp_obj_get_int(val_in);
516-
if (val < 0 && typecode == BYTEARRAY_TYPECODE) {
517-
val = val & 0xFF;
518-
}
519-
#if OVERFLOW_CHECKS
520-
// Small int checking is separate, to be fast.
521-
mp_small_int_buffer_overflow_check(val, size, signed_type);
522-
#endif
523-
mp_binary_set_val_array_from_int(typecode, p, index, val);
488+
p = (uint8_t *)p + index * size;
489+
mp_obj_int_to_bytes(val_in, size, p, MP_ENDIANNESS_BIG, is_signed(typecode), OVERFLOW_CHECKS);
490+
return;
524491
}
525492
}
526493
}

py/binary.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,6 @@ void mp_binary_set_val_array_from_int(char typecode, void *p, size_t index, mp_i
4141
mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte *p_base, byte **ptr);
4242
void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p_base, byte **ptr);
4343
long long mp_binary_get_int(size_t size, bool is_signed, bool big_endian, const byte *src);
44-
void mp_binary_set_int(size_t val_sz, bool big_endian, byte *dest, mp_uint_t val);
44+
void mp_binary_set_int(size_t dest_sz, byte *dest, size_t val_sz, mp_uint_t val, bool big_endian);
4545

4646
#endif // MICROPY_INCLUDED_PY_BINARY_H

py/mpz.c

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,7 +1589,7 @@ bool mpz_as_uint_checked(const mpz_t *i, mp_uint_t *value) {
15891589
return true;
15901590
}
15911591

1592-
bool mpz_as_bytes(const mpz_t *z, bool big_endian, bool as_signed, size_t len, byte *buf) {
1592+
void mpz_as_bytes(const mpz_t *z, bool big_endian, bool as_signed, size_t len, byte *buf) {
15931593
byte *b = buf;
15941594
if (big_endian) {
15951595
b += len;
@@ -1599,7 +1599,6 @@ bool mpz_as_bytes(const mpz_t *z, bool big_endian, bool as_signed, size_t len, b
15991599
mpz_dbl_dig_t d = 0;
16001600
mpz_dbl_dig_t carry = 1;
16011601
size_t olen = len; // bytes in output buffer
1602-
bool ok = true;
16031602
for (size_t zlen = z->len; zlen > 0; --zlen) {
16041603
bits += DIG_SIZE;
16051604
d = (d << DIG_SIZE) | *zdig++;
@@ -1612,7 +1611,6 @@ bool mpz_as_bytes(const mpz_t *z, bool big_endian, bool as_signed, size_t len, b
16121611

16131612
if (!olen) {
16141613
// Buffer is full, only OK if all remaining bytes are zeroes
1615-
ok = ok && ((byte)val == 0);
16161614
continue;
16171615
}
16181616

@@ -1625,16 +1623,10 @@ bool mpz_as_bytes(const mpz_t *z, bool big_endian, bool as_signed, size_t len, b
16251623
}
16261624
}
16271625

1628-
if (as_signed && olen == 0 && len > 0) {
1629-
// If output exhausted then ensure there was enough space for the sign bit
1630-
byte most_sig = big_endian ? buf[0] : buf[len - 1];
1631-
ok = ok && (bool)(most_sig & 0x80) == (bool)z->neg;
1632-
} else {
1626+
if (!(as_signed && olen == 0 && len > 0)) {
16331627
// fill remainder of buf with zero/sign extension of the integer
16341628
memset(big_endian ? buf : b, z->neg ? 0xff : 0x00, olen);
16351629
}
1636-
1637-
return ok;
16381630
}
16391631

16401632
#if MICROPY_PY_BUILTINS_FLOAT

py/mpz.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,7 @@ static inline size_t mpz_max_num_bits(const mpz_t *z) {
145145
mp_int_t mpz_hash(const mpz_t *z);
146146
bool mpz_as_int_checked(const mpz_t *z, mp_int_t *value);
147147
bool mpz_as_uint_checked(const mpz_t *z, mp_uint_t *value);
148-
// Returns true if 'z' fit into 'len' bytes of 'buf' without overflowing, 'buf' is truncated otherwise.
149-
bool mpz_as_bytes(const mpz_t *z, bool big_endian, bool as_signed, size_t len, byte *buf);
148+
void mpz_as_bytes(const mpz_t *z, bool big_endian, bool as_signed, size_t len, byte *buf);
150149
#if MICROPY_PY_BUILTINS_FLOAT
151150
mp_float_t mpz_as_float(const mpz_t *z);
152151
#endif

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy