Make byte code jumps relative.
This commit is contained in:
parent
1c62d04e2e
commit
03c9cfb015
29
py/bc.h
29
py/bc.h
@ -1,7 +1,7 @@
|
||||
#define PYBC_LOAD_CONST_FALSE (0x10)
|
||||
#define PYBC_LOAD_CONST_NONE (0x11)
|
||||
#define PYBC_LOAD_CONST_TRUE (0x12)
|
||||
#define PYBC_LOAD_CONST_SMALL_INT (0x13) // int
|
||||
#define PYBC_LOAD_CONST_SMALL_INT (0x13) // 24-bit, in excess
|
||||
#define PYBC_LOAD_CONST_INT (0x14) // qstr
|
||||
#define PYBC_LOAD_CONST_DEC (0x15) // qstr
|
||||
#define PYBC_LOAD_CONST_ID (0x16) // qstr
|
||||
@ -39,21 +39,22 @@
|
||||
#define PYBC_POP_TOP (0x42)
|
||||
#define PYBC_ROT_TWO (0x43)
|
||||
#define PYBC_ROT_THREE (0x44)
|
||||
#define PYBC_JUMP (0x45) // pos
|
||||
#define PYBC_POP_JUMP_IF_TRUE (0x46) // pos
|
||||
#define PYBC_POP_JUMP_IF_FALSE (0x47) // pos
|
||||
#define PYBC_JUMP_IF_TRUE_OR_POP (0x48) // pos
|
||||
#define PYBC_JUMP_IF_FALSE_OR_POP (0x49) // pos
|
||||
#define PYBC_SETUP_LOOP (0x4a) // pos
|
||||
#define PYBC_BREAK_LOOP (0x4b) // pos
|
||||
#define PYBC_CONTINUE_LOOP (0x4c) // pos
|
||||
#define PYBC_SETUP_WITH (0x4d) // pos
|
||||
|
||||
#define PYBC_JUMP (0x45) // rel byte code offset, 16-bit signed, in excess
|
||||
#define PYBC_POP_JUMP_IF_TRUE (0x46) // rel byte code offset, 16-bit signed, in excess
|
||||
#define PYBC_POP_JUMP_IF_FALSE (0x47) // rel byte code offset, 16-bit signed, in excess
|
||||
#define PYBC_JUMP_IF_TRUE_OR_POP (0x48) // rel byte code offset, 16-bit signed, in excess
|
||||
#define PYBC_JUMP_IF_FALSE_OR_POP (0x49) // rel byte code offset, 16-bit signed, in excess
|
||||
#define PYBC_SETUP_LOOP (0x4a) // rel byte code offset, 16-bit unsigned
|
||||
#define PYBC_BREAK_LOOP (0x4b) // rel byte code offset, 16-bit unsigned
|
||||
#define PYBC_CONTINUE_LOOP (0x4c) // rel byte code offset, 16-bit unsigned
|
||||
#define PYBC_SETUP_WITH (0x4d) // rel byte code offset, 16-bit unsigned
|
||||
#define PYBC_WITH_CLEANUP (0x4e)
|
||||
#define PYBC_SETUP_EXCEPT (0x4f) // pos
|
||||
#define PYBC_SETUP_FINALLY (0x50) // pos
|
||||
#define PYBC_SETUP_EXCEPT (0x4f) // rel byte code offset, 16-bit unsigned
|
||||
#define PYBC_SETUP_FINALLY (0x50) // rel byte code offset, 16-bit unsigned
|
||||
#define PYBC_END_FINALLY (0x51)
|
||||
#define PYBC_GET_ITER (0x52)
|
||||
#define PYBC_FOR_ITER (0x53) // pos
|
||||
#define PYBC_FOR_ITER (0x53) // rel byte code offset, 16-bit unsigned
|
||||
#define PYBC_POP_BLOCK (0x54)
|
||||
#define PYBC_POP_EXCEPT (0x55)
|
||||
|
||||
@ -94,4 +95,4 @@
|
||||
#define PYBC_IMPORT_STAR (0xe2)
|
||||
|
||||
py_obj_t py_execute_byte_code(const byte *code, const py_obj_t *args, uint n_args);
|
||||
bool py_execute_byte_code_2(const byte *code, const byte **ip_in_out, py_obj_t *fastn, py_obj_t **sp_in_out);
|
||||
bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t **sp_in_out);
|
||||
|
52
py/emitbc.c
52
py/emitbc.c
@ -105,8 +105,10 @@ static void emit_write_byte_1_byte(emit_t* emit, byte b1, uint b2) {
|
||||
c[1] = b2;
|
||||
}
|
||||
|
||||
// integers (for small ints) are stored as 24 bits, in excess
|
||||
static void emit_write_byte_1_int(emit_t* emit, byte b1, int num) {
|
||||
assert((num & (~0x7fffff)) == 0 || (num & (~0x7fffff)) == (~0x7fffff));
|
||||
num += 0x800000;
|
||||
assert(0 <= num && num <= 0xffffff);
|
||||
byte* c = emit_get_cur_to_write_bytes(emit, 4);
|
||||
c[0] = b1;
|
||||
c[1] = num;
|
||||
@ -136,14 +138,32 @@ static void emit_write_byte_1_qstr(emit_t* emit, byte b1, qstr qstr) {
|
||||
emit_write_byte_1_uint(emit, b1, qstr);
|
||||
}
|
||||
|
||||
static void emit_write_byte_1_label(emit_t* emit, byte b1, int label) {
|
||||
// unsigned labels are relative to ip following this instruction, stored as 16 bits
|
||||
static void emit_write_byte_1_unsigned_label(emit_t* emit, byte b1, int label) {
|
||||
uint code_offset;
|
||||
if (emit->pass < PASS_3) {
|
||||
code_offset = 0;
|
||||
} else {
|
||||
code_offset = emit->label_offsets[label];
|
||||
code_offset = emit->label_offsets[label] - emit->code_offset - 3;
|
||||
}
|
||||
emit_write_byte_1_uint(emit, b1, code_offset);
|
||||
byte* c = emit_get_cur_to_write_bytes(emit, 3);
|
||||
c[0] = b1;
|
||||
c[1] = code_offset;
|
||||
c[2] = code_offset >> 8;
|
||||
}
|
||||
|
||||
// signed labels are relative to ip following this instruction, stored as 16 bits, in excess
|
||||
static void emit_write_byte_1_signed_label(emit_t* emit, byte b1, int label) {
|
||||
int code_offset;
|
||||
if (emit->pass < PASS_3) {
|
||||
code_offset = 0;
|
||||
} else {
|
||||
code_offset = emit->label_offsets[label] - emit->code_offset - 3 + 0x8000;
|
||||
}
|
||||
byte* c = emit_get_cur_to_write_bytes(emit, 3);
|
||||
c[0] = b1;
|
||||
c[1] = code_offset;
|
||||
c[2] = code_offset >> 8;
|
||||
}
|
||||
|
||||
bool emit_bc_last_emit_was_return_value(emit_t *emit) {
|
||||
@ -418,47 +438,47 @@ static void emit_bc_rot_three(emit_t *emit) {
|
||||
|
||||
static void emit_bc_jump(emit_t *emit, int label) {
|
||||
emit_pre(emit, 0);
|
||||
emit_write_byte_1_label(emit, PYBC_JUMP, label);
|
||||
emit_write_byte_1_signed_label(emit, PYBC_JUMP, label);
|
||||
}
|
||||
|
||||
static void emit_bc_pop_jump_if_true(emit_t *emit, int label) {
|
||||
emit_pre(emit, -1);
|
||||
emit_write_byte_1_label(emit, PYBC_POP_JUMP_IF_TRUE, label);
|
||||
emit_write_byte_1_signed_label(emit, PYBC_POP_JUMP_IF_TRUE, label);
|
||||
}
|
||||
|
||||
static void emit_bc_pop_jump_if_false(emit_t *emit, int label) {
|
||||
emit_pre(emit, -1);
|
||||
emit_write_byte_1_label(emit, PYBC_POP_JUMP_IF_FALSE, label);
|
||||
emit_write_byte_1_signed_label(emit, PYBC_POP_JUMP_IF_FALSE, label);
|
||||
}
|
||||
|
||||
static void emit_bc_jump_if_true_or_pop(emit_t *emit, int label) {
|
||||
emit_pre(emit, -1);
|
||||
emit_write_byte_1_label(emit, PYBC_JUMP_IF_TRUE_OR_POP, label);
|
||||
emit_write_byte_1_signed_label(emit, PYBC_JUMP_IF_TRUE_OR_POP, label);
|
||||
}
|
||||
|
||||
static void emit_bc_jump_if_false_or_pop(emit_t *emit, int label) {
|
||||
emit_pre(emit, -1);
|
||||
emit_write_byte_1_label(emit, PYBC_JUMP_IF_FALSE_OR_POP, label);
|
||||
emit_write_byte_1_signed_label(emit, PYBC_JUMP_IF_FALSE_OR_POP, label);
|
||||
}
|
||||
|
||||
static void emit_bc_setup_loop(emit_t *emit, int label) {
|
||||
emit_pre(emit, 0);
|
||||
emit_write_byte_1_label(emit, PYBC_SETUP_LOOP, label);
|
||||
emit_write_byte_1_unsigned_label(emit, PYBC_SETUP_LOOP, label);
|
||||
}
|
||||
|
||||
static void emit_bc_break_loop(emit_t *emit, int label) {
|
||||
emit_pre(emit, 0);
|
||||
emit_write_byte_1_label(emit, PYBC_BREAK_LOOP, label);
|
||||
emit_write_byte_1_unsigned_label(emit, PYBC_BREAK_LOOP, label);
|
||||
}
|
||||
|
||||
static void emit_bc_continue_loop(emit_t *emit, int label) {
|
||||
emit_pre(emit, 0);
|
||||
emit_write_byte_1_label(emit, PYBC_CONTINUE_LOOP, label);
|
||||
emit_write_byte_1_unsigned_label(emit, PYBC_CONTINUE_LOOP, label);
|
||||
}
|
||||
|
||||
static void emit_bc_setup_with(emit_t *emit, int label) {
|
||||
emit_pre(emit, 7);
|
||||
emit_write_byte_1_label(emit, PYBC_SETUP_WITH, label);
|
||||
emit_write_byte_1_unsigned_label(emit, PYBC_SETUP_WITH, label);
|
||||
}
|
||||
|
||||
static void emit_bc_with_cleanup(emit_t *emit) {
|
||||
@ -468,12 +488,12 @@ static void emit_bc_with_cleanup(emit_t *emit) {
|
||||
|
||||
static void emit_bc_setup_except(emit_t *emit, int label) {
|
||||
emit_pre(emit, 6);
|
||||
emit_write_byte_1_label(emit, PYBC_SETUP_EXCEPT, label);
|
||||
emit_write_byte_1_unsigned_label(emit, PYBC_SETUP_EXCEPT, label);
|
||||
}
|
||||
|
||||
static void emit_bc_setup_finally(emit_t *emit, int label) {
|
||||
emit_pre(emit, 6);
|
||||
emit_write_byte_1_label(emit, PYBC_SETUP_FINALLY, label);
|
||||
emit_write_byte_1_unsigned_label(emit, PYBC_SETUP_FINALLY, label);
|
||||
}
|
||||
|
||||
static void emit_bc_end_finally(emit_t *emit) {
|
||||
@ -488,7 +508,7 @@ static void emit_bc_get_iter(emit_t *emit) {
|
||||
|
||||
static void emit_bc_for_iter(emit_t *emit, int label) {
|
||||
emit_pre(emit, 1);
|
||||
emit_write_byte_1_label(emit, PYBC_FOR_ITER, label);
|
||||
emit_write_byte_1_unsigned_label(emit, PYBC_FOR_ITER, label);
|
||||
}
|
||||
|
||||
static void emit_bc_for_iter_end(emit_t *emit) {
|
||||
|
@ -2020,9 +2020,9 @@ py_obj_t rt_getiter(py_obj_t o_in) {
|
||||
py_obj_t rt_iternext(py_obj_t o_in) {
|
||||
if (IS_O(o_in, O_GEN_INSTANCE)) {
|
||||
py_obj_base_t *self = o_in;
|
||||
py_obj_base_t *fun = self->u_gen_instance.state[0];
|
||||
assert(fun->kind == O_FUN_BC);
|
||||
bool yield = py_execute_byte_code_2(fun->u_fun_bc.code, &self->u_gen_instance.ip, &self->u_gen_instance.state[1], &self->u_gen_instance.sp);
|
||||
//py_obj_base_t *fun = self->u_gen_instance.state[0];
|
||||
//assert(fun->kind == O_FUN_BC);
|
||||
bool yield = py_execute_byte_code_2(&self->u_gen_instance.ip, &self->u_gen_instance.state[1], &self->u_gen_instance.sp);
|
||||
if (yield) {
|
||||
return *self->u_gen_instance.sp;
|
||||
} else {
|
||||
|
38
py/vm.c
38
py/vm.c
@ -14,6 +14,8 @@
|
||||
// exception stack grows up, top element is pointed to
|
||||
|
||||
#define DECODE_UINT do { unum = *ip++; if (unum > 127) { unum = ((unum & 0x3f) << 8) | (*ip++); } } while (0)
|
||||
#define DECODE_ULABEL do { unum = (ip[0] | (ip[1] << 8)); ip += 2; } while (0)
|
||||
#define DECODE_SLABEL do { unum = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2; } while (0)
|
||||
#define DECODE_QSTR do { qstr = *ip++; if (qstr > 127) { qstr = ((qstr & 0x3f) << 8) | (*ip++); } } while (0)
|
||||
#define PUSH(val) *--sp = (val)
|
||||
#define POP() (*sp++)
|
||||
@ -28,7 +30,7 @@ py_obj_t py_execute_byte_code(const byte *code, const py_obj_t *args, uint n_arg
|
||||
}
|
||||
py_obj_t *sp = &state[18];
|
||||
const byte *ip = code;
|
||||
if (py_execute_byte_code_2(code, &ip, &state[0], &sp)) {
|
||||
if (py_execute_byte_code_2(&ip, &state[0], &sp)) {
|
||||
// it shouldn't yield
|
||||
assert(0);
|
||||
}
|
||||
@ -39,13 +41,12 @@ py_obj_t py_execute_byte_code(const byte *code, const py_obj_t *args, uint n_arg
|
||||
|
||||
// fastn has items in normal order
|
||||
// sp points to top of stack which grows down
|
||||
bool py_execute_byte_code_2(const byte *code, const byte **ip_in_out, py_obj_t *fastn, py_obj_t **sp_in_out) {
|
||||
bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t **sp_in_out) {
|
||||
// careful: be sure to declare volatile any variables read in the exception handler (written is ok, I think)
|
||||
|
||||
const byte *ip = *ip_in_out;
|
||||
py_obj_t *sp = *sp_in_out;
|
||||
machine_uint_t unum;
|
||||
machine_int_t snum;
|
||||
qstr qstr;
|
||||
py_obj_t obj1, obj2;
|
||||
py_obj_t fast0 = fastn[0], fast1 = fastn[1], fast2 = fastn[2];
|
||||
@ -75,12 +76,9 @@ bool py_execute_byte_code_2(const byte *code, const byte **ip_in_out, py_obj_t *
|
||||
break;
|
||||
|
||||
case PYBC_LOAD_CONST_SMALL_INT:
|
||||
snum = ip[0] | (ip[1] << 8) | (ip[2] << 16);
|
||||
if (snum & 0x8000) {
|
||||
snum |= ~0xffff;
|
||||
}
|
||||
unum = (ip[0] | (ip[1] << 8) | (ip[2] << 16)) - 0x800000;
|
||||
ip += 3;
|
||||
PUSH((py_obj_t)(snum << 1 | 1));
|
||||
PUSH((py_obj_t)(unum << 1 | 1));
|
||||
break;
|
||||
|
||||
case PYBC_LOAD_CONST_DEC:
|
||||
@ -207,34 +205,34 @@ bool py_execute_byte_code_2(const byte *code, const byte **ip_in_out, py_obj_t *
|
||||
break;
|
||||
|
||||
case PYBC_JUMP:
|
||||
DECODE_UINT;
|
||||
ip = code + unum;
|
||||
DECODE_SLABEL;
|
||||
ip += unum;
|
||||
break;
|
||||
|
||||
case PYBC_POP_JUMP_IF_TRUE:
|
||||
DECODE_UINT;
|
||||
DECODE_SLABEL;
|
||||
if (rt_is_true(POP())) {
|
||||
ip = code + unum;
|
||||
ip += unum;
|
||||
}
|
||||
break;
|
||||
|
||||
case PYBC_POP_JUMP_IF_FALSE:
|
||||
DECODE_UINT;
|
||||
DECODE_SLABEL;
|
||||
if (!rt_is_true(POP())) {
|
||||
ip = code + unum;
|
||||
ip += unum;
|
||||
}
|
||||
break;
|
||||
|
||||
/* we are trying to get away without using this opcode
|
||||
case PYBC_SETUP_LOOP:
|
||||
DECODE_UINT;
|
||||
// push_block(PYBC_SETUP_LOOP, code + unum, sp)
|
||||
// push_block(PYBC_SETUP_LOOP, ip + unum, sp)
|
||||
break;
|
||||
*/
|
||||
|
||||
case PYBC_SETUP_EXCEPT:
|
||||
DECODE_UINT;
|
||||
*++exc_sp = (machine_uint_t)code + unum;
|
||||
DECODE_ULABEL; // except labels are always forward
|
||||
*++exc_sp = (machine_uint_t)ip + unum;
|
||||
*++exc_sp = (machine_uint_t)sp;
|
||||
break;
|
||||
|
||||
@ -252,11 +250,11 @@ bool py_execute_byte_code_2(const byte *code, const byte **ip_in_out, py_obj_t *
|
||||
break;
|
||||
|
||||
case PYBC_FOR_ITER:
|
||||
DECODE_UINT; // the jump offset if iteration finishes
|
||||
DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
|
||||
obj1 = rt_iternext(*sp);
|
||||
if (obj1 == py_const_stop_iteration) {
|
||||
++sp; // pop the exhausted iterator
|
||||
ip = code + unum; // jump to after for-block
|
||||
ip += unum; // jump to after for-block
|
||||
} else {
|
||||
PUSH(obj1); // push the next iteration value
|
||||
}
|
||||
@ -386,7 +384,7 @@ bool py_execute_byte_code_2(const byte *code, const byte **ip_in_out, py_obj_t *
|
||||
return true;
|
||||
|
||||
default:
|
||||
printf("code %p, offset %u, byte code 0x%02x not implemented\n", code, (uint)(ip - code), op);
|
||||
printf("code %p, byte code 0x%02x not implemented\n", ip, op);
|
||||
assert(0);
|
||||
nlr_pop();
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user