Bytecode int varlen encoding: support arbitrary values for signed ints too.
This commit is contained in:
parent
0f96ec8268
commit
047cd40313
32
py/emitbc.c
32
py/emitbc.c
|
@ -123,15 +123,31 @@ STATIC void emit_write_byte_code_uint(emit_t* emit, uint num) {
|
||||||
*c = *p;
|
*c = *p;
|
||||||
}
|
}
|
||||||
|
|
||||||
// integers (for small ints) are stored as 24 bits, in excess
|
// Similar to emit_write_byte_code_uint(), just some extra handling to encode sign
|
||||||
STATIC void emit_write_byte_code_byte_int(emit_t* emit, byte b1, machine_int_t num) {
|
STATIC void emit_write_byte_code_byte_int(emit_t* emit, byte b1, machine_int_t num) {
|
||||||
num += 0x800000;
|
emit_write_byte_code_byte(emit, b1);
|
||||||
assert(0 <= num && num <= 0xffffff);
|
|
||||||
byte* c = emit_get_cur_to_write_byte_code(emit, 4);
|
// We store each 7 bits in a separate byte, and that's how many bytes needed
|
||||||
c[0] = b1;
|
byte buf[(BYTES_PER_WORD * 8 + 7) / 7];
|
||||||
c[1] = num;
|
byte *p = buf + sizeof(buf);
|
||||||
c[2] = num >> 8;
|
// We encode in little-ending order, but store in big-endian, to help decoding
|
||||||
c[3] = num >> 16;
|
do {
|
||||||
|
*--p = num & 0x7f;
|
||||||
|
num >>= 7;
|
||||||
|
} while (num != 0 && num != -1);
|
||||||
|
// Make sure that highest bit we stored (mask 0x40) matches sign
|
||||||
|
// of the number. If not, store extra byte just to encode sign
|
||||||
|
if (num == -1 && (*p & 0x40) == 0) {
|
||||||
|
*--p = 0x7f;
|
||||||
|
} else if (num == 0 && (*p & 0x40) != 0) {
|
||||||
|
*--p = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte* c = emit_get_cur_to_write_byte_code(emit, buf + sizeof(buf) - p);
|
||||||
|
while (p != buf + sizeof(buf) - 1) {
|
||||||
|
*c++ = *p++ | 0x80;
|
||||||
|
}
|
||||||
|
*c = *p;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void emit_write_byte_code_byte_uint(emit_t* emit, byte b, uint num) {
|
STATIC void emit_write_byte_code_byte_uint(emit_t* emit, byte b, uint num) {
|
||||||
|
|
15
py/showbc.c
15
py/showbc.c
|
@ -57,11 +57,18 @@ void mp_byte_code_print(const byte *ip, int len) {
|
||||||
printf("LOAD_CONST_ELLIPSIS");
|
printf("LOAD_CONST_ELLIPSIS");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MP_BC_LOAD_CONST_SMALL_INT:
|
case MP_BC_LOAD_CONST_SMALL_INT: {
|
||||||
unum = (ip[0] | (ip[1] << 8) | (ip[2] << 16)) - 0x800000;
|
int num = 0;
|
||||||
ip += 3;
|
if ((ip[0] & 0x40) != 0) {
|
||||||
printf("LOAD_CONST_SMALL_INT %d", (int)unum);
|
// Number is negative
|
||||||
|
num--;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
num = (num << 7) | (*ip & 0x7f);
|
||||||
|
} while ((*ip++ & 0x80) != 0);
|
||||||
|
printf("LOAD_CONST_SMALL_INT %d", num);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case MP_BC_LOAD_CONST_INT:
|
case MP_BC_LOAD_CONST_INT:
|
||||||
DECODE_QSTR;
|
DECODE_QSTR;
|
||||||
|
|
15
py/vm.c
15
py/vm.c
|
@ -156,11 +156,18 @@ dispatch_loop:
|
||||||
PUSH(mp_const_ellipsis);
|
PUSH(mp_const_ellipsis);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MP_BC_LOAD_CONST_SMALL_INT:
|
case MP_BC_LOAD_CONST_SMALL_INT: {
|
||||||
unum = (ip[0] | (ip[1] << 8) | (ip[2] << 16)) - 0x800000;
|
int num = 0;
|
||||||
ip += 3;
|
if ((ip[0] & 0x40) != 0) {
|
||||||
PUSH(MP_OBJ_NEW_SMALL_INT(unum));
|
// Number is negative
|
||||||
|
num--;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
num = (num << 7) | (*ip & 0x7f);
|
||||||
|
} while ((*ip++ & 0x80) != 0);
|
||||||
|
PUSH(MP_OBJ_NEW_SMALL_INT(num));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case MP_BC_LOAD_CONST_INT:
|
case MP_BC_LOAD_CONST_INT:
|
||||||
DECODE_QSTR;
|
DECODE_QSTR;
|
||||||
|
|
Loading…
Reference in New Issue