From b05d707b2329a9534121e09e26eb9f8fef1917d3 Mon Sep 17 00:00:00 2001 From: Damien Date: Sat, 5 Oct 2013 13:37:10 +0100 Subject: Further factorise PASS_1 out of specific emit code. --- py/Makefile | 3 +- py/asmx64.h | 2 +- py/bc.c | 272 --------------------------------------------------------- py/bc.h | 97 -------------------- py/compile.c | 98 ++++++++++++--------- py/emit.h | 11 ++- py/emitbc.c | 61 +++++-------- py/emitcpy.c | 46 ++++------ py/emitthumb.c | 3 - py/emitx64.c | 7 +- py/runtime.c | 7 +- py/scope.c | 4 +- py/scope.h | 4 +- py/vm.c | 272 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ py/vm.h | 97 ++++++++++++++++++++ 15 files changed, 483 insertions(+), 501 deletions(-) delete mode 100644 py/bc.c delete mode 100644 py/bc.h create mode 100644 py/vm.c create mode 100644 py/vm.h (limited to 'py') diff --git a/py/Makefile b/py/Makefile index 36d2a5036..5b3eb1766 100644 --- a/py/Makefile +++ b/py/Makefile @@ -12,6 +12,7 @@ SRC = \ scope.c \ compile.c \ emitcommon.c \ + emitpass1.c \ emitcpy.c \ emitbc.c \ asmx64.c \ @@ -19,7 +20,7 @@ SRC = \ emitthumb.c \ asmthumb.c \ runtime.c \ - bc.c \ + vm.c \ main.c \ SRC_ASM = \ diff --git a/py/asmx64.h b/py/asmx64.h index 4871dbff8..34d5a4835 100644 --- a/py/asmx64.h +++ b/py/asmx64.h @@ -26,7 +26,7 @@ typedef struct _asm_x64_t asm_x64_t; -asm_x64_t* asm_x64_new(); +asm_x64_t* asm_x64_new(uint max_num_labels); void asm_x64_free(asm_x64_t* as, bool free_code); void asm_x64_start_pass(asm_x64_t *as, int pass); void asm_x64_end_pass(asm_x64_t *as); diff --git a/py/bc.c b/py/bc.c deleted file mode 100644 index 1edd911ab..000000000 --- a/py/bc.c +++ /dev/null @@ -1,272 +0,0 @@ -#include -#include -#include -#include -#include - -#include "misc.h" -#include "machine.h" -#include "runtime.h" -#include "bc.h" - -#define DECODE_UINT do { unum = *ip++; if (unum > 127) { unum = ((unum & 0x3f) << 8) | (*ip++); } } 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++) - -py_obj_t py_execute_byte_code(byte *code, uint len, py_obj_t *args, uint n_args) { - byte *ip = code; - py_obj_t stack[10]; - py_obj_t *sp = &stack[10]; // stack grows down, sp points to top of stack - machine_uint_t unum; - machine_int_t snum; - qstr qstr; - py_obj_t obj1, obj2; - py_obj_t fast0 = NULL, fast1 = NULL, fast2 = NULL, fastn[4] = {NULL, NULL, NULL, NULL}; - - // init args - for (int i = 0; i < n_args; i++) { - if (i == 0) { - fast0 = args[0]; - } else if (i == 1) { - fast1 = args[1]; - } else if (i == 2) { - fast2 = args[2]; - } else { - assert(i - 3 < 4); - fastn[i - 3] = args[i]; - } - } - - // execute byte code - for (;;) { - int op = *ip++; - switch (op) { - case PYBC_LOAD_CONST_FALSE: - PUSH(py_const_false); - break; - - case PYBC_LOAD_CONST_NONE: - PUSH(py_const_none); - break; - - case PYBC_LOAD_CONST_TRUE: - PUSH(py_const_true); - break; - - case PYBC_LOAD_CONST_SMALL_INT: - snum = ip[0] | (ip[1] << 8); - if (snum & 0x8000) { - snum |= ~0xffff; - } - ip += 2; - PUSH((py_obj_t)(snum << 1 | 1)); - break; - - case PYBC_LOAD_CONST_ID: - DECODE_QSTR; - PUSH(rt_load_const_str(qstr)); // TODO - break; - - case PYBC_LOAD_CONST_STRING: - DECODE_QSTR; - PUSH(rt_load_const_str(qstr)); - break; - - case PYBC_LOAD_FAST_0: - PUSH(fast0); - break; - - case PYBC_LOAD_FAST_1: - PUSH(fast1); - break; - - case PYBC_LOAD_FAST_2: - PUSH(fast2); - break; - - case PYBC_LOAD_FAST_N: - DECODE_UINT; - PUSH(fastn[unum - 3]); - break; - - case PYBC_LOAD_NAME: - DECODE_QSTR; - PUSH(rt_load_name(qstr)); - break; - - case PYBC_LOAD_GLOBAL: - DECODE_QSTR; - PUSH(rt_load_global(qstr)); - break; - - case PYBC_LOAD_ATTR: - DECODE_QSTR; - *sp = rt_load_attr(*sp, qstr); - break; - - case PYBC_LOAD_METHOD: - DECODE_QSTR; - sp -= 1; - rt_load_method(sp[1], qstr, sp); - break; - - case PYBC_LOAD_BUILD_CLASS: - PUSH(rt_load_build_class()); - break; - - case PYBC_STORE_FAST_0: - fast0 = POP(); - break; - - case PYBC_STORE_FAST_1: - fast1 = POP(); - break; - - case PYBC_STORE_FAST_2: - fast2 = POP(); - break; - - case PYBC_STORE_FAST_N: - DECODE_UINT; - fastn[unum - 3] = POP(); - break; - - case PYBC_STORE_NAME: - DECODE_QSTR; - rt_store_name(qstr, POP()); - break; - - case PYBC_STORE_SUBSCR: - rt_store_subscr(sp[1], sp[0], sp[2]); - sp += 3; - break; - - case PYBC_DUP_TOP: - obj1 = *sp; - PUSH(obj1); - break; - - case PYBC_DUP_TOP_TWO: - sp -= 2; - sp[0] = sp[2]; - sp[1] = sp[3]; - break; - - case PYBC_POP_TOP: - ++sp; - break; - - case PYBC_ROT_THREE: - obj1 = sp[0]; - sp[0] = sp[1]; - sp[1] = sp[2]; - sp[2] = obj1; - break; - - case PYBC_JUMP: - DECODE_UINT; - ip = code + unum; - break; - - case PYBC_POP_JUMP_IF_FALSE: - DECODE_UINT; - if (!rt_is_true(POP())) { - ip = code + unum; - } - break; - - case PYBC_SETUP_LOOP: - DECODE_UINT; - break; - - case PYBC_POP_BLOCK: - break; - - case PYBC_BINARY_OP: - unum = *ip++; - obj2 = POP(); - obj1 = *sp; - *sp = rt_binary_op(unum, obj1, obj2); - break; - - case PYBC_COMPARE_OP: - unum = *ip++; - obj2 = POP(); - obj1 = *sp; - *sp = rt_compare_op(unum, obj1, obj2); - break; - - case PYBC_BUILD_LIST: - DECODE_UINT; - obj1 = rt_build_list(unum, sp); - sp += unum - 1; - *sp = obj1; - break; - - case PYBC_BUILD_MAP: - DECODE_UINT; - PUSH(rt_build_map(unum)); - break; - - case PYBC_STORE_MAP: - sp += 2; - rt_store_map(sp[0], sp[-2], sp[-1]); - break; - - case PYBC_BUILD_SET: - DECODE_UINT; - obj1 = rt_build_set(unum, sp); - sp += unum - 1; - *sp = obj1; - break; - - case PYBC_MAKE_FUNCTION: - DECODE_UINT; - PUSH(rt_make_function_from_id(unum)); - break; - - case PYBC_CALL_FUNCTION: - DECODE_UINT; - assert((unum & 0xff00) == 0); // n_keyword - // switch on n_positional - if ((unum & 0xff) == 0) { - *sp = rt_call_function_0(*sp); - } else if ((unum & 0xff) == 1) { - obj1 = *sp++; // the single argument - *sp = rt_call_function_1(*sp, obj1); - } else if ((unum & 0xff) == 2) { - obj2 = *sp++; // the second argument - obj1 = *sp++; // the first argument - *sp = rt_call_function_2(*sp, obj1, obj2); - } else { - assert(0); - } - break; - - case PYBC_CALL_METHOD: - DECODE_UINT; - assert((unum & 0xff00) == 0); // n_keyword - // switch on n_positional - if ((unum & 0xff) == 0) { - obj1 = *sp++; // the self object (or NULL) - *sp = rt_call_method_1(*sp, obj1); - } else if ((unum & 0xff) == 1) { - obj2 = *sp++; // the first argument - obj1 = *sp++; // the self object (or NULL) - *sp = rt_call_function_2(*sp, obj1, obj2); - } else { - assert(0); - } - break; - - case PYBC_RETURN_VALUE: - return *sp; - - default: - printf("code %p, offset %u, byte code 0x%02x not implemented\n", code, (uint)(ip - code), op); - assert(0); - return py_const_none; - } - } -} diff --git a/py/bc.h b/py/bc.h deleted file mode 100644 index f09843a96..000000000 --- a/py/bc.h +++ /dev/null @@ -1,97 +0,0 @@ -#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_INT (0x14) // qstr -#define PYBC_LOAD_CONST_DEC (0x15) // qstr -#define PYBC_LOAD_CONST_ID (0x16) // qstr -#define PYBC_LOAD_CONST_BYTES (0x17) // qstr -#define PYBC_LOAD_CONST_STRING (0x18) // qstr - -#define PYBC_LOAD_FAST_0 (0x20) -#define PYBC_LOAD_FAST_1 (0x21) -#define PYBC_LOAD_FAST_2 (0x22) -#define PYBC_LOAD_FAST_N (0x23) // uint -#define PYBC_LOAD_NAME (0x24) // qstr -#define PYBC_LOAD_GLOBAL (0x25) // qstr -#define PYBC_LOAD_ATTR (0x26) // qstr -#define PYBC_LOAD_METHOD (0x27) // qstr -#define PYBC_LOAD_BUILD_CLASS (0x28) - -#define PYBC_STORE_FAST_0 (0x30) -#define PYBC_STORE_FAST_1 (0x31) -#define PYBC_STORE_FAST_2 (0x32) -#define PYBC_STORE_FAST_N (0x33) // uint -#define PYBC_STORE_NAME (0x34) // qstr -#define PYBC_STORE_GLOBAL (0x35) // qstr -#define PYBC_STORE_ATTR (0x36) // qstr -#define PYBC_STORE_LOCALS (0x37) -#define PYBC_STORE_SUBSCR (0x38) - -#define PYBC_DELETE_FAST_N (0x39) // uint -#define PYBC_DELETE_NAME (0x3a) // qstr -#define PYBC_DELETE_GLOBAL (0x3b) // qstr -#define PYBC_DELETE_DEREF (0x3c) // qstr -#define PYBC_DELETE_ATTR (0x3d) // qstr -#define PYBC_DELETE_SUBSCR (0x3e) - -#define PYBC_DUP_TOP (0x40) -#define PYBC_DUP_TOP_TWO (0x41) -#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_WITH_CLEANUP (0x4e) -#define PYBC_SETUP_EXCEPT (0x4f) // pos -#define PYBC_SETUP_FINALLY (0x50) // pos -#define PYBC_END_FINALLY (0x51) -#define PYBC_GET_ITER (0x52) -#define PYBC_FOR_ITER (0x53) // pos -#define PYBC_POP_BLOCK (0x54) -#define PYBC_POP_EXCEPT (0x55) - -#define PYBC_UNARY_OP (0x60) // byte -#define PYBC_BINARY_OP (0x61) // byte -#define PYBC_COMPARE_OP (0x62) // byte - -#define PYBC_BUILD_TUPLE (0x70) // uint -#define PYBC_BUILD_LIST (0x71) // uint -#define PYBC_LIST_APPEND (0x72) // uint -#define PYBC_BUILD_MAP (0x73) // uint -#define PYBC_STORE_MAP (0x74) -#define PYBC_MAP_ADD (0x75) // uint -#define PYBC_BUILD_SET (0x76) // uint -#define PYBC_SET_ADD (0x77) // uint -#define PYBC_BUILD_SLICE (0x78) // uint -#define PYBC_UNPACK_SEQUENCE (0x79) // uint -#define PYBC_UNPACK_EX (0x7a) // uint - -#define PYBC_RETURN_VALUE (0x80) -#define PYBC_RAISE_VARARGS (0x81) // uint -#define PYBC_YIELD_VALUE (0x82) -#define PYBC_YIELD_FROM (0x83) - -#define PYBC_MAKE_FUNCTION (0x90) // uint -#define PYBC_MAKE_CLOSURE (0x91) // uint? -#define PYBC_CALL_FUNCTION (0x92) // uint -#define PYBC_CALL_FUNCTION_VAR (0x93) // uint -#define PYBC_CALL_FUNCTION_KW (0x94) // uint -#define PYBC_CALL_FUNCTION_VAR_KW (0x95) // uint -#define PYBC_CALL_METHOD (0x96) // uint -#define PYBC_CALL_METHOD_VAR (0x97) // uint -#define PYBC_CALL_METHOD_KW (0x98) // uint -#define PYBC_CALL_METHOD_VAR_KW (0x99) // uint - -#define PYBC_IMPORT_NAME (0xe0) -#define PYBC_IMPORT_FROM (0xe1) -#define PYBC_IMPORT_STAR (0xe2) - -py_obj_t py_execute_byte_code(byte *code, uint len, py_obj_t *args, uint n_args); diff --git a/py/compile.c b/py/compile.c index 5a90bdcf7..c6b195ede 100644 --- a/py/compile.c +++ b/py/compile.c @@ -39,6 +39,9 @@ typedef struct _compiler_t { pass_kind_t pass; + int next_label; + int max_num_labels; + int break_label; int continue_label; int except_nest_level; @@ -159,8 +162,12 @@ py_parse_node_t fold_constants(py_parse_node_t pn) { void compile_node(compiler_t *comp, py_parse_node_t pn); -scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, py_parse_node_t pn) { - scope_t *scope = scope_new(kind, pn); +static int comp_next_label(compiler_t *comp) { + return comp->next_label++; +} + +static scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, py_parse_node_t pn) { + scope_t *scope = scope_new(kind, pn, rt_get_new_unique_code_id()); scope->parent = comp->scope_cur; scope->next = NULL; if (comp->scope_head == NULL) { @@ -175,7 +182,7 @@ scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, py_parse_node_t return scope; } -int list_len(py_parse_node_t pn, int pn_kind) { +static int list_len(py_parse_node_t pn, int pn_kind) { if (PY_PARSE_NODE_IS_NULL(pn)) { return 0; } else if (PY_PARSE_NODE_IS_LEAF(pn)) { @@ -190,7 +197,7 @@ int list_len(py_parse_node_t pn, int pn_kind) { } } -void apply_to_single_or_list(compiler_t *comp, py_parse_node_t pn, int pn_list_kind, void (*f)(compiler_t*, py_parse_node_t)) { +static void apply_to_single_or_list(compiler_t *comp, py_parse_node_t pn, int pn_list_kind, void (*f)(compiler_t*, py_parse_node_t)) { if (PY_PARSE_NODE_IS_STRUCT(pn) && PY_PARSE_NODE_STRUCT_KIND((py_parse_node_struct_t*)pn) == pn_list_kind) { py_parse_node_struct_t *pns = (py_parse_node_struct_t*)pn; int num_nodes = PY_PARSE_NODE_STRUCT_NUM_NODES(pns); @@ -202,7 +209,7 @@ void apply_to_single_or_list(compiler_t *comp, py_parse_node_t pn, int pn_list_k } } -int list_get(py_parse_node_t *pn, int pn_kind, py_parse_node_t **nodes) { +static int list_get(py_parse_node_t *pn, int pn_kind, py_parse_node_t **nodes) { if (PY_PARSE_NODE_IS_NULL(*pn)) { *nodes = NULL; return 0; @@ -353,7 +360,7 @@ void c_if_cond_2(compiler_t *comp, py_parse_node_t pn, bool jump_if, int label, int n = PY_PARSE_NODE_STRUCT_NUM_NODES(pns); if (PY_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) { if (jump_if == false) { - int label2 = EMIT(label_new); + int label2 = comp_next_label(comp); for (int i = 0; i < n - 1; i++) { c_if_cond_2(comp, pns->nodes[i], true, label2, true); } @@ -371,7 +378,7 @@ void c_if_cond_2(compiler_t *comp, py_parse_node_t pn, bool jump_if, int label, c_if_cond_2(comp, pns->nodes[i], false, label, true); } } else { - int label2 = EMIT(label_new); + int label2 = comp_next_label(comp); for (int i = 0; i < n - 1; i++) { c_if_cond_2(comp, pns->nodes[i], false, label2, true); } @@ -893,7 +900,7 @@ void compile_return_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { py_parse_node_struct_t *pns_test_if_expr = (py_parse_node_struct_t*)pns->nodes[0]; py_parse_node_struct_t *pns_test_if_else = (py_parse_node_struct_t*)pns_test_if_expr->nodes[1]; - int l_fail = EMIT(label_new); + int l_fail = comp_next_label(comp); c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition compile_node(comp, pns_test_if_expr->nodes[0]); // success value EMIT(return_value); @@ -1073,7 +1080,7 @@ void compile_nonlocal_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { } void compile_assert_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { - int l_end = EMIT(label_new); + int l_end = comp_next_label(comp); c_if_cond(comp, pns->nodes[0], true, l_end); EMIT_COMMON(load_id, comp->qstr___class__, comp->qstr_assertion_error); if (!PY_PARSE_NODE_IS_NULL(pns->nodes[1])) { @@ -1088,9 +1095,9 @@ void compile_assert_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { void compile_if_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { // TODO proper and/or short circuiting - int l_end = EMIT(label_new); + int l_end = comp_next_label(comp); - int l_fail = EMIT(label_new); + int l_fail = comp_next_label(comp); c_if_cond(comp, pns->nodes[0], false, l_fail); // if condition compile_node(comp, pns->nodes[1]); // if block @@ -1113,7 +1120,7 @@ void compile_if_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { int n = PY_PARSE_NODE_STRUCT_NUM_NODES(pns_elif); for (int i = 0; i < n; i++) { py_parse_node_struct_t *pns_elif2 = (py_parse_node_struct_t*)pns_elif->nodes[i]; - l_fail = EMIT(label_new); + l_fail = comp_next_label(comp); c_if_cond(comp, pns_elif2->nodes[0], false, l_fail); // elif condition compile_node(comp, pns_elif2->nodes[1]); // elif block @@ -1126,7 +1133,7 @@ void compile_if_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { } else { // a single elif block - l_fail = EMIT(label_new); + l_fail = comp_next_label(comp); c_if_cond(comp, pns_elif->nodes[0], false, l_fail); // elif condition compile_node(comp, pns_elif->nodes[1]); // elif block @@ -1147,10 +1154,10 @@ void compile_while_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { int old_break_label = comp->break_label; int old_continue_label = comp->continue_label; - int done_label = EMIT(label_new); - int end_label = EMIT(label_new); - int break_label = EMIT(label_new); - int continue_label = EMIT(label_new); + int done_label = comp_next_label(comp); + int end_label = comp_next_label(comp); + int break_label = comp_next_label(comp); + int continue_label = comp_next_label(comp); comp->break_label = break_label; comp->continue_label = continue_label; @@ -1184,11 +1191,11 @@ void compile_for_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { int old_break_label = comp->break_label; int old_continue_label = comp->continue_label; - int for_label = EMIT(label_new); - int pop_label = EMIT(label_new); - int end_label = EMIT(label_new); + int for_label = comp_next_label(comp); + int pop_label = comp_next_label(comp); + int end_label = comp_next_label(comp); - int break_label = EMIT(label_new); + int break_label = comp_next_label(comp); comp->continue_label = for_label; comp->break_label = break_label; @@ -1224,22 +1231,22 @@ void compile_try_except(compiler_t *comp, py_parse_node_t pn_body, int n_except, // setup code int stack_size = EMIT(get_stack_size); - int l1 = EMIT(label_new); - int success_label = EMIT(label_new); + int l1 = comp_next_label(comp); + int success_label = comp_next_label(comp); comp->except_nest_level += 1; // for correct handling of continue EMIT(setup_except, l1); compile_node(comp, pn_body); // body EMIT(pop_block); EMIT(jump, success_label); EMIT(label_assign, l1); - int l2 = EMIT(label_new); + int l2 = comp_next_label(comp); for (int i = 0; i < n_except; i++) { assert(PY_PARSE_NODE_IS_STRUCT_KIND(pn_excepts[i], PN_try_stmt_except)); // should be py_parse_node_struct_t *pns_except = (py_parse_node_struct_t*)pn_excepts[i]; qstr qstr_exception_local = 0; - int end_finally_label = EMIT(label_new); + int end_finally_label = comp_next_label(comp); if (PY_PARSE_NODE_IS_NULL(pns_except->nodes[0])) { // this is a catch all exception handler @@ -1276,7 +1283,7 @@ void compile_try_except(compiler_t *comp, py_parse_node_t pn_body, int n_except, int l3; if (qstr_exception_local != 0) { - l3 = EMIT(label_new); + l3 = comp_next_label(comp); EMIT(setup_finally, l3); } compile_node(comp, pns_except->nodes[1]); @@ -1307,7 +1314,7 @@ void compile_try_except(compiler_t *comp, py_parse_node_t pn_body, int n_except, void compile_try_finally(compiler_t *comp, py_parse_node_t pn_body, int n_except, py_parse_node_t *pn_except, py_parse_node_t pn_else, py_parse_node_t pn_finally) { // don't understand how the stack works with exceptions, so we force it to return to the correct value int stack_size = EMIT(get_stack_size); - int l_finally_block = EMIT(label_new); + int l_finally_block = comp_next_label(comp); EMIT(setup_finally, l_finally_block); if (n_except == 0) { assert(PY_PARSE_NODE_IS_NULL(pn_else)); @@ -1357,7 +1364,7 @@ void compile_with_stmt_helper(compiler_t *comp, int n, py_parse_node_t *nodes, p // no more pre-bits, compile the body of the with compile_node(comp, body); } else { - int l_end = EMIT(label_new); + int l_end = comp_next_label(comp); if (PY_PARSE_NODE_IS_STRUCT_KIND(nodes[0], PN_with_item)) { // this pre-bit is of the form "a as b" py_parse_node_struct_t *pns = (py_parse_node_struct_t*)nodes[0]; @@ -1490,8 +1497,8 @@ void compile_test_if_expr(compiler_t *comp, py_parse_node_struct_t *pns) { py_parse_node_struct_t *pns_test_if_else = (py_parse_node_struct_t*)pns->nodes[1]; int stack_size = EMIT(get_stack_size); - int l_fail = EMIT(label_new); - int l_end = EMIT(label_new); + int l_fail = comp_next_label(comp); + int l_end = comp_next_label(comp); c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition compile_node(comp, pns->nodes[0]); // success value EMIT(jump, l_end); @@ -1521,7 +1528,7 @@ void compile_lambdef(compiler_t *comp, py_parse_node_struct_t *pns) { } void compile_or_test(compiler_t *comp, py_parse_node_struct_t *pns) { - int l_end = EMIT(label_new); + int l_end = comp_next_label(comp); int n = PY_PARSE_NODE_STRUCT_NUM_NODES(pns); for (int i = 0; i < n; i += 1) { compile_node(comp, pns->nodes[i]); @@ -1533,7 +1540,7 @@ void compile_or_test(compiler_t *comp, py_parse_node_struct_t *pns) { } void compile_and_test(compiler_t *comp, py_parse_node_struct_t *pns) { - int l_end = EMIT(label_new); + int l_end = comp_next_label(comp); int n = PY_PARSE_NODE_STRUCT_NUM_NODES(pns); for (int i = 0; i < n; i += 1) { compile_node(comp, pns->nodes[i]); @@ -1556,7 +1563,7 @@ void compile_comparison(compiler_t *comp, py_parse_node_struct_t *pns) { bool multi = (num_nodes > 3); int l_fail = 0; if (multi) { - l_fail = EMIT(label_new); + l_fail = comp_next_label(comp); } for (int i = 1; i + 1 < num_nodes; i += 2) { compile_node(comp, pns->nodes[i + 1]); @@ -1602,7 +1609,7 @@ void compile_comparison(compiler_t *comp, py_parse_node_struct_t *pns) { } } if (multi) { - int l_end = EMIT(label_new); + int l_end = comp_next_label(comp); EMIT(jump, l_end); EMIT(label_assign, l_fail); EMIT(rot_two); @@ -2255,8 +2262,8 @@ void compile_scope_comp_iter(compiler_t *comp, py_parse_node_t pn_iter, py_parse // for loop py_parse_node_struct_t *pns_comp_for2 = (py_parse_node_struct_t*)pn_iter; compile_node(comp, pns_comp_for2->nodes[1]); - int l_end2 = EMIT(label_new); - int l_top2 = EMIT(label_new); + int l_end2 = comp_next_label(comp); + int l_top2 = comp_next_label(comp); EMIT(get_iter); EMIT(label_assign, l_top2); EMIT(for_iter, l_end2); @@ -2302,6 +2309,7 @@ void check_for_doc_string(compiler_t *comp, py_parse_node_t pn) { void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { comp->pass = pass; comp->scope_cur = scope; + comp->next_label = 1; EMIT(start_pass, pass, scope); if (comp->pass == PASS_1) { @@ -2377,8 +2385,8 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { EMIT(build_set, 0); } - int l_end = EMIT(label_new); - int l_top = EMIT(label_new); + int l_end = comp_next_label(comp); + int l_top = comp_next_label(comp); EMIT_COMMON(load_id, comp->qstr___class__, qstr_arg); EMIT(label_assign, l_top); EMIT(for_iter, l_end); @@ -2431,6 +2439,11 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { } EMIT(end_pass); + + // update maximim number of labels needed + if (comp->next_label > comp->max_num_labels) { + comp->max_num_labels = comp->next_label; + } } void compile_scope_compute_things(compiler_t *comp, scope_t *scope) { @@ -2489,15 +2502,14 @@ void py_compile(py_parse_node_t pn) { comp->qstr___doc__ = qstr_from_strn_copy("__doc__", 7); comp->qstr_assertion_error = qstr_from_strn_copy("AssertionError", 14); + comp->max_num_labels = 0; comp->break_label = 0; comp->continue_label = 0; comp->except_nest_level = 0; comp->scope_head = NULL; comp->scope_cur = NULL; - emit_new_cpython(&comp->emit, &comp->emit_method_table); - //emit_new_bc(&comp->emit, &comp->emit_method_table); - //emit_new_x64(&comp->emit, &comp->emit_method_table); + emit_pass1_new(&comp->emit, &comp->emit_method_table); pn = fold_constants(pn); scope_new_and_link(comp, SCOPE_MODULE, pn); @@ -2510,6 +2522,10 @@ void py_compile(py_parse_node_t pn) { compile_scope_compute_things(comp, s); } + //emit_cpython_new(&comp->emit, &comp->emit_method_table, comp->max_num_labels); + emit_bc_new(&comp->emit, &comp->emit_method_table, comp->max_num_labels); + //emit_new_x64(&comp->emit, &comp->emit_method_table, comp->max_num_labels); + for (scope_t *s = comp->scope_head; s != NULL; s = s->next) { compile_scope(comp, s, PASS_2); compile_scope(comp, s, PASS_3); diff --git a/py/emit.h b/py/emit.h index dcafbc08d..b2d451efd 100644 --- a/py/emit.h +++ b/py/emit.h @@ -113,10 +113,13 @@ void emit_common_load_id(pass_kind_t pass, scope_t *scope, emit_t *emit, const e void emit_common_store_id(pass_kind_t pass, scope_t *scope, emit_t *emit, const emit_method_table_t *emit_method_table, qstr qstr); void emit_common_delete_id(pass_kind_t pass, scope_t *scope, emit_t *emit, const emit_method_table_t *emit_method_table, qstr qstr); -void emit_new_cpython(emit_t **emit, const emit_method_table_t **emit_method_table); -void emit_new_bc(emit_t **emit, const emit_method_table_t **emit_method_table); -void emit_new_x64(emit_t **emit, const emit_method_table_t **emit_method_table); -void emit_new_thumb(emit_t **emit, const emit_method_table_t **emit_method_table); +void emit_pass1_new(emit_t **emit, const emit_method_table_t **emit_method_table); +uint emit_pass1_get_max_num_labels(emit_t *emit); + +void emit_cpython_new(emit_t **emit_out, const emit_method_table_t **emit_method_table_out, uint max_num_labels); +void emit_bc_new(emit_t **emit, const emit_method_table_t **emit_method_table, uint max_num_labels); +void emit_x64_new(emit_t **emit, const emit_method_table_t **emit_method_table, uint max_num_labels); +void emit_thumb_new(emit_t **emit, const emit_method_table_t **emit_method_table, uint max_num_labels); /* void emit_set_native_types(emitter_t *emit, bool do_native_types); diff --git a/py/emitbc.c b/py/emitbc.c index 27540f18d..fae394bd9 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -13,7 +13,7 @@ #include "scope.h" #include "runtime.h" #include "emit.h" -#include "bc.h" +#include "vm.h" struct _emit_t { pass_kind_t pass; @@ -23,7 +23,7 @@ struct _emit_t { scope_t *scope; - int max_num_labels; + uint max_num_labels; uint *label_offsets; uint code_offset; @@ -49,15 +49,8 @@ static void emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) { emit->stack_size = 0; emit->last_emit_was_return_value = false; emit->scope = scope; - if (pass == PASS_1) { - scope->unique_code_id = rt_get_new_unique_code_id(); - } else if (pass > PASS_1) { - if (emit->label_offsets == NULL) { - emit->label_offsets = m_new(uint, emit->max_num_labels); - } - if (pass == PASS_2) { - memset(emit->label_offsets, -1, emit->max_num_labels * sizeof(uint)); - } + if (pass == PASS_2) { + memset(emit->label_offsets, -1, emit->max_num_labels * sizeof(uint)); } emit->code_offset = 0; } @@ -68,13 +61,7 @@ static void emit_bc_end_pass(emit_t *emit) { printf("ERROR: stack size not back to zero; got %d\n", emit->stack_size); } - if (emit->pass == PASS_1) { - // calculate number of labels need - if (emit->next_label > emit->max_num_labels) { - emit->max_num_labels = emit->next_label; - } - - } else if (emit->pass == PASS_2) { + if (emit->pass == PASS_2) { // calculate size of code in bytes emit->code_size = emit->code_offset; emit->code_base = m_new(byte, emit->code_size); @@ -160,17 +147,13 @@ int emit_bc_get_stack_size(emit_t *emit) { } static void emit_bc_set_stack_size(emit_t *emit, int size) { - if (emit->pass > PASS_1) { - emit->stack_size = size; - } + emit->stack_size = size; } static void emit_pre(emit_t *emit, int stack_size_delta) { - if (emit->pass > PASS_1) { - emit->stack_size += stack_size_delta; - if (emit->stack_size > emit->scope->stack_size) { - emit->scope->stack_size = emit->stack_size; - } + emit->stack_size += stack_size_delta; + if (emit->stack_size > emit->scope->stack_size) { + emit->scope->stack_size = emit->stack_size; } emit->last_emit_was_return_value = false; } @@ -181,17 +164,15 @@ static int emit_bc_label_new(emit_t *emit) { static void emit_bc_label_assign(emit_t *emit, int l) { emit_pre(emit, 0); - if (emit->pass > PASS_1) { - assert(l < emit->max_num_labels); - if (emit->pass == PASS_2) { - // assign label offset - assert(emit->label_offsets[l] == -1); - emit->label_offsets[l] = emit->code_offset; - } else if (emit->pass == PASS_3) { - // ensure label offset has not changed from PASS_2 to PASS_3 - assert(emit->label_offsets[l] == emit->code_offset); - //printf("l%d: (at %d)\n", l, emit->code_offset); - } + assert(l < emit->max_num_labels); + if (emit->pass == PASS_2) { + // assign label offset + assert(emit->label_offsets[l] == -1); + emit->label_offsets[l] = emit->code_offset; + } else if (emit->pass == PASS_3) { + // ensure label offset has not changed from PASS_2 to PASS_3 + assert(emit->label_offsets[l] == emit->code_offset); + //printf("l%d: (at %d)\n", l, emit->code_offset); } } @@ -773,10 +754,10 @@ static const emit_method_table_t emit_bc_method_table = { emit_bc_yield_from, }; -void emit_new_bc(emit_t **emit_out, const emit_method_table_t **emit_method_table_out) { +void emit_bc_new(emit_t **emit_out, const emit_method_table_t **emit_method_table_out, uint max_num_labels) { emit_t *emit = m_new(emit_t, 1); - emit->max_num_labels = 0; - emit->label_offsets = NULL; + emit->max_num_labels = max_num_labels; + emit->label_offsets = m_new(uint, emit->max_num_labels); emit->code_offset = 0; emit->code_size = 0; emit->code_base = NULL; diff --git a/py/emitcpy.c b/py/emitcpy.c index 1c600ac57..72f4d4daa 100644 --- a/py/emitcpy.c +++ b/py/emitcpy.c @@ -25,7 +25,7 @@ struct _emit_t { scope_t *scope; - int max_num_labels; + uint max_num_labels; int *label_offsets; }; @@ -39,13 +39,8 @@ static void emit_cpy_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) emit->stack_size = 0; emit->last_emit_was_return_value = false; emit->scope = scope; - if (pass > PASS_1) { - if (emit->label_offsets == NULL) { - emit->label_offsets = m_new(int, emit->max_num_labels); - } - if (pass == PASS_2) { - memset(emit->label_offsets, -1, emit->max_num_labels * sizeof(int)); - } + if (pass == PASS_2) { + memset(emit->label_offsets, -1, emit->max_num_labels * sizeof(int)); } } @@ -54,13 +49,6 @@ static void emit_cpy_end_pass(emit_t *emit) { if (emit->stack_size != 0) { printf("ERROR: stack size not back to zero; got %d\n", emit->stack_size); } - - // calculate number of labels need - if (emit->pass == PASS_1) { - if (emit->next_label > emit->max_num_labels) { - emit->max_num_labels = emit->next_label; - } - } } static bool emit_cpy_last_emit_was_return_value(emit_t *emit) { @@ -77,7 +65,7 @@ static void emit_cpy_set_stack_size(emit_t *emit, int size) { static void emit_pre(emit_t *emit, int stack_size_delta, int byte_code_size) { emit->stack_size += stack_size_delta; - if (emit->pass > PASS_1 && emit->stack_size > emit->scope->stack_size) { + if (emit->stack_size > emit->scope->stack_size) { emit->scope->stack_size = emit->stack_size; } emit->last_emit_was_return_value = false; @@ -97,17 +85,15 @@ static int emit_cpy_label_new(emit_t *emit) { static void emit_cpy_label_assign(emit_t *emit, int l) { emit_pre(emit, 0, 0); - if (emit->pass > PASS_1) { - assert(l < emit->max_num_labels); - if (emit->pass == PASS_2) { - // assign label offset - assert(emit->label_offsets[l] == -1); - emit->label_offsets[l] = emit->byte_code_offset; - } else if (emit->pass == PASS_3) { - // ensure label offset has not changed from PASS_2 to PASS_3 - assert(emit->label_offsets[l] == emit->byte_code_offset); - //printf("l%d: (at %d)\n", l, emit->byte_code_offset); - } + assert(l < emit->max_num_labels); + if (emit->pass == PASS_2) { + // assign label offset + assert(emit->label_offsets[l] == -1); + emit->label_offsets[l] = emit->byte_code_offset; + } else if (emit->pass == PASS_3) { + // ensure label offset has not changed from PASS_2 to PASS_3 + assert(emit->label_offsets[l] == emit->byte_code_offset); + //printf("l%d: (at %d)\n", l, emit->byte_code_offset); } } @@ -921,10 +907,10 @@ static const emit_method_table_t emit_cpy_method_table = { emit_cpy_yield_from, }; -void emit_new_cpython(emit_t **emit_out, const emit_method_table_t **emit_method_table_out) { +void emit_cpython_new(emit_t **emit_out, const emit_method_table_t **emit_method_table_out, uint max_num_labels) { emit_t *emit = m_new(emit_t, 1); - emit->max_num_labels = 0; - emit->label_offsets = NULL; + emit->max_num_labels = max_num_labels; + emit->label_offsets = m_new(int, max_num_labels); *emit_out = emit; *emit_method_table_out = &emit_cpy_method_table; diff --git a/py/emitthumb.c b/py/emitthumb.c index cad6b6504..9bccda801 100644 --- a/py/emitthumb.c +++ b/py/emitthumb.c @@ -57,9 +57,6 @@ void emit_start_pass(emitter_t *emit, pass_kind_t pass, scope_t *scope) { emit->last_emit_was_return_value = false; emit->need_to_push = NEED_TO_PUSH_NOTHING; emit->scope = scope; - if (pass == PASS_1) { - scope->unique_code_id = rt_get_new_unique_code_id(); - } asm_thumb_start_pass(emit->as, pass); diff --git a/py/emitx64.c b/py/emitx64.c index 38d519063..c9307dc00 100644 --- a/py/emitx64.c +++ b/py/emitx64.c @@ -64,9 +64,6 @@ static void emit_x64_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) emit->last_emit_was_return_value = false; emit->need_to_push = NEED_TO_PUSH_NOTHING; emit->scope = scope; - if (pass == PASS_1) { - scope->unique_code_id = rt_get_new_unique_code_id(); - } asm_x64_start_pass(emit->as, pass); @@ -763,9 +760,9 @@ static const emit_method_table_t emit_x64_method_table = { emit_x64_yield_from, }; -void emit_new_x64(emit_t **emit_out, const emit_method_table_t **emit_method_table_out) { +void emit_x64_new(emit_t **emit_out, const emit_method_table_t **emit_method_table_out, uint max_num_labels) { emit_t *emit = m_new(emit_t, 1); - emit->as = asm_x64_new(); + emit->as = asm_x64_new(max_num_labels); emit->do_native_types = false; *emit_out = emit; diff --git a/py/runtime.c b/py/runtime.c index bf2e2ee06..21f3c8c50 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -7,7 +7,7 @@ #include "misc.h" #include "machine.h" #include "runtime.h" -#include "bc.h" +#include "vm.h" #define DEBUG_printf(args...) (void)0 //#define DEBUG_printf(args...) printf(args) @@ -372,7 +372,7 @@ void rt_assign_native_code(int unique_code_id, py_fun_t fun, uint len, int n_arg if (unique_codes == NULL) { unique_codes = m_new(py_code_t, next_unique_code_id); } - assert(unique_code_id < next_unique_code_id); + assert(1 <= unique_code_id && unique_code_id < next_unique_code_id); unique_codes[unique_code_id].kind = PY_CODE_NATIVE; unique_codes[unique_code_id].n_args = n_args; unique_codes[unique_code_id].u_native.fun = fun; @@ -635,7 +635,8 @@ py_obj_t rt_compare_op(int op, py_obj_t lhs, py_obj_t rhs) { } py_obj_t rt_make_function_from_id(int unique_code_id) { - if (unique_code_id >= next_unique_code_id) { + DEBUG_OP_printf("make_function_from_id %d\n", unique_code_id); + if (unique_code_id < 1 || unique_code_id >= next_unique_code_id) { // illegal code id return py_const_none; } diff --git a/py/scope.c b/py/scope.c index 5773ae0b4..57a7e6875 100644 --- a/py/scope.c +++ b/py/scope.c @@ -8,7 +8,7 @@ #include "parse.h" #include "scope.h" -scope_t *scope_new(scope_kind_t kind, py_parse_node_t pn) { +scope_t *scope_new(scope_kind_t kind, py_parse_node_t pn, uint unique_code_id) { scope_t *scope = m_new(scope_t, 1); scope->kind = kind; scope->parent = NULL; @@ -52,7 +52,7 @@ scope_t *scope_new(scope_kind_t kind, py_parse_node_t pn) { scope->num_dict_params = 0; */ scope->num_locals = 0; - scope->unique_code_id = 0; + scope->unique_code_id = unique_code_id; return scope; } diff --git a/py/scope.h b/py/scope.h index cb5e606c3..f9ad748d9 100644 --- a/py/scope.h +++ b/py/scope.h @@ -46,10 +46,10 @@ typedef struct _scope_t { */ int num_locals; int stack_size; - int unique_code_id; + uint unique_code_id; } scope_t; -scope_t *scope_new(scope_kind_t kind, py_parse_node_t pn); +scope_t *scope_new(scope_kind_t kind, py_parse_node_t pn, uint unique_code_id); id_info_t *scope_find_or_add_id(scope_t *scope, qstr qstr, bool *added); id_info_t *scope_find(scope_t *scope, qstr qstr); id_info_t *scope_find_global(scope_t *scope, qstr qstr); diff --git a/py/vm.c b/py/vm.c new file mode 100644 index 000000000..63a478fcf --- /dev/null +++ b/py/vm.c @@ -0,0 +1,272 @@ +#include +#include +#include +#include +#include + +#include "misc.h" +#include "machine.h" +#include "runtime.h" +#include "vm.h" + +#define DECODE_UINT do { unum = *ip++; if (unum > 127) { unum = ((unum & 0x3f) << 8) | (*ip++); } } 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++) + +py_obj_t py_execute_byte_code(byte *code, uint len, py_obj_t *args, uint n_args) { + byte *ip = code; + py_obj_t stack[10]; + py_obj_t *sp = &stack[10]; // stack grows down, sp points to top of stack + machine_uint_t unum; + machine_int_t snum; + qstr qstr; + py_obj_t obj1, obj2; + py_obj_t fast0 = NULL, fast1 = NULL, fast2 = NULL, fastn[4] = {NULL, NULL, NULL, NULL}; + + // init args + for (int i = 0; i < n_args; i++) { + if (i == 0) { + fast0 = args[0]; + } else if (i == 1) { + fast1 = args[1]; + } else if (i == 2) { + fast2 = args[2]; + } else { + assert(i - 3 < 4); + fastn[i - 3] = args[i]; + } + } + + // execute byte code + for (;;) { + int op = *ip++; + switch (op) { + case PYBC_LOAD_CONST_FALSE: + PUSH(py_const_false); + break; + + case PYBC_LOAD_CONST_NONE: + PUSH(py_const_none); + break; + + case PYBC_LOAD_CONST_TRUE: + PUSH(py_const_true); + break; + + case PYBC_LOAD_CONST_SMALL_INT: + snum = ip[0] | (ip[1] << 8); + if (snum & 0x8000) { + snum |= ~0xffff; + } + ip += 2; + PUSH((py_obj_t)(snum << 1 | 1)); + break; + + case PYBC_LOAD_CONST_ID: + DECODE_QSTR; + PUSH(rt_load_const_str(qstr)); // TODO + break; + + case PYBC_LOAD_CONST_STRING: + DECODE_QSTR; + PUSH(rt_load_const_str(qstr)); + break; + + case PYBC_LOAD_FAST_0: + PUSH(fast0); + break; + + case PYBC_LOAD_FAST_1: + PUSH(fast1); + break; + + case PYBC_LOAD_FAST_2: + PUSH(fast2); + break; + + case PYBC_LOAD_FAST_N: + DECODE_UINT; + PUSH(fastn[unum - 3]); + break; + + case PYBC_LOAD_NAME: + DECODE_QSTR; + PUSH(rt_load_name(qstr)); + break; + + case PYBC_LOAD_GLOBAL: + DECODE_QSTR; + PUSH(rt_load_global(qstr)); + break; + + case PYBC_LOAD_ATTR: + DECODE_QSTR; + *sp = rt_load_attr(*sp, qstr); + break; + + case PYBC_LOAD_METHOD: + DECODE_QSTR; + sp -= 1; + rt_load_method(sp[1], qstr, sp); + break; + + case PYBC_LOAD_BUILD_CLASS: + PUSH(rt_load_build_class()); + break; + + case PYBC_STORE_FAST_0: + fast0 = POP(); + break; + + case PYBC_STORE_FAST_1: + fast1 = POP(); + break; + + case PYBC_STORE_FAST_2: + fast2 = POP(); + break; + + case PYBC_STORE_FAST_N: + DECODE_UINT; + fastn[unum - 3] = POP(); + break; + + case PYBC_STORE_NAME: + DECODE_QSTR; + rt_store_name(qstr, POP()); + break; + + case PYBC_STORE_SUBSCR: + rt_store_subscr(sp[1], sp[0], sp[2]); + sp += 3; + break; + + case PYBC_DUP_TOP: + obj1 = *sp; + PUSH(obj1); + break; + + case PYBC_DUP_TOP_TWO: + sp -= 2; + sp[0] = sp[2]; + sp[1] = sp[3]; + break; + + case PYBC_POP_TOP: + ++sp; + break; + + case PYBC_ROT_THREE: + obj1 = sp[0]; + sp[0] = sp[1]; + sp[1] = sp[2]; + sp[2] = obj1; + break; + + case PYBC_JUMP: + DECODE_UINT; + ip = code + unum; + break; + + case PYBC_POP_JUMP_IF_FALSE: + DECODE_UINT; + if (!rt_is_true(POP())) { + ip = code + unum; + } + break; + + case PYBC_SETUP_LOOP: + DECODE_UINT; + break; + + case PYBC_POP_BLOCK: + break; + + case PYBC_BINARY_OP: + unum = *ip++; + obj2 = POP(); + obj1 = *sp; + *sp = rt_binary_op(unum, obj1, obj2); + break; + + case PYBC_COMPARE_OP: + unum = *ip++; + obj2 = POP(); + obj1 = *sp; + *sp = rt_compare_op(unum, obj1, obj2); + break; + + case PYBC_BUILD_LIST: + DECODE_UINT; + obj1 = rt_build_list(unum, sp); + sp += unum - 1; + *sp = obj1; + break; + + case PYBC_BUILD_MAP: + DECODE_UINT; + PUSH(rt_build_map(unum)); + break; + + case PYBC_STORE_MAP: + sp += 2; + rt_store_map(sp[0], sp[-2], sp[-1]); + break; + + case PYBC_BUILD_SET: + DECODE_UINT; + obj1 = rt_build_set(unum, sp); + sp += unum - 1; + *sp = obj1; + break; + + case PYBC_MAKE_FUNCTION: + DECODE_UINT; + PUSH(rt_make_function_from_id(unum)); + break; + + case PYBC_CALL_FUNCTION: + DECODE_UINT; + assert((unum & 0xff00) == 0); // n_keyword + // switch on n_positional + if ((unum & 0xff) == 0) { + *sp = rt_call_function_0(*sp); + } else if ((unum & 0xff) == 1) { + obj1 = *sp++; // the single argument + *sp = rt_call_function_1(*sp, obj1); + } else if ((unum & 0xff) == 2) { + obj2 = *sp++; // the second argument + obj1 = *sp++; // the first argument + *sp = rt_call_function_2(*sp, obj1, obj2); + } else { + assert(0); + } + break; + + case PYBC_CALL_METHOD: + DECODE_UINT; + assert((unum & 0xff00) == 0); // n_keyword + // switch on n_positional + if ((unum & 0xff) == 0) { + obj1 = *sp++; // the self object (or NULL) + *sp = rt_call_method_1(*sp, obj1); + } else if ((unum & 0xff) == 1) { + obj2 = *sp++; // the first argument + obj1 = *sp++; // the self object (or NULL) + *sp = rt_call_function_2(*sp, obj1, obj2); + } else { + assert(0); + } + break; + + case PYBC_RETURN_VALUE: + return *sp; + + default: + printf("code %p, offset %u, byte code 0x%02x not implemented\n", code, (uint)(ip - code), op); + assert(0); + return py_const_none; + } + } +} diff --git a/py/vm.h b/py/vm.h new file mode 100644 index 000000000..f09843a96 --- /dev/null +++ b/py/vm.h @@ -0,0 +1,97 @@ +#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_INT (0x14) // qstr +#define PYBC_LOAD_CONST_DEC (0x15) // qstr +#define PYBC_LOAD_CONST_ID (0x16) // qstr +#define PYBC_LOAD_CONST_BYTES (0x17) // qstr +#define PYBC_LOAD_CONST_STRING (0x18) // qstr + +#define PYBC_LOAD_FAST_0 (0x20) +#define PYBC_LOAD_FAST_1 (0x21) +#define PYBC_LOAD_FAST_2 (0x22) +#define PYBC_LOAD_FAST_N (0x23) // uint +#define PYBC_LOAD_NAME (0x24) // qstr +#define PYBC_LOAD_GLOBAL (0x25) // qstr +#define PYBC_LOAD_ATTR (0x26) // qstr +#define PYBC_LOAD_METHOD (0x27) // qstr +#define PYBC_LOAD_BUILD_CLASS (0x28) + +#define PYBC_STORE_FAST_0 (0x30) +#define PYBC_STORE_FAST_1 (0x31) +#define PYBC_STORE_FAST_2 (0x32) +#define PYBC_STORE_FAST_N (0x33) // uint +#define PYBC_STORE_NAME (0x34) // qstr +#define PYBC_STORE_GLOBAL (0x35) // qstr +#define PYBC_STORE_ATTR (0x36) // qstr +#define PYBC_STORE_LOCALS (0x37) +#define PYBC_STORE_SUBSCR (0x38) + +#define PYBC_DELETE_FAST_N (0x39) // uint +#define PYBC_DELETE_NAME (0x3a) // qstr +#define PYBC_DELETE_GLOBAL (0x3b) // qstr +#define PYBC_DELETE_DEREF (0x3c) // qstr +#define PYBC_DELETE_ATTR (0x3d) // qstr +#define PYBC_DELETE_SUBSCR (0x3e) + +#define PYBC_DUP_TOP (0x40) +#define PYBC_DUP_TOP_TWO (0x41) +#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_WITH_CLEANUP (0x4e) +#define PYBC_SETUP_EXCEPT (0x4f) // pos +#define PYBC_SETUP_FINALLY (0x50) // pos +#define PYBC_END_FINALLY (0x51) +#define PYBC_GET_ITER (0x52) +#define PYBC_FOR_ITER (0x53) // pos +#define PYBC_POP_BLOCK (0x54) +#define PYBC_POP_EXCEPT (0x55) + +#define PYBC_UNARY_OP (0x60) // byte +#define PYBC_BINARY_OP (0x61) // byte +#define PYBC_COMPARE_OP (0x62) // byte + +#define PYBC_BUILD_TUPLE (0x70) // uint +#define PYBC_BUILD_LIST (0x71) // uint +#define PYBC_LIST_APPEND (0x72) // uint +#define PYBC_BUILD_MAP (0x73) // uint +#define PYBC_STORE_MAP (0x74) +#define PYBC_MAP_ADD (0x75) // uint +#define PYBC_BUILD_SET (0x76) // uint +#define PYBC_SET_ADD (0x77) // uint +#define PYBC_BUILD_SLICE (0x78) // uint +#define PYBC_UNPACK_SEQUENCE (0x79) // uint +#define PYBC_UNPACK_EX (0x7a) // uint + +#define PYBC_RETURN_VALUE (0x80) +#define PYBC_RAISE_VARARGS (0x81) // uint +#define PYBC_YIELD_VALUE (0x82) +#define PYBC_YIELD_FROM (0x83) + +#define PYBC_MAKE_FUNCTION (0x90) // uint +#define PYBC_MAKE_CLOSURE (0x91) // uint? +#define PYBC_CALL_FUNCTION (0x92) // uint +#define PYBC_CALL_FUNCTION_VAR (0x93) // uint +#define PYBC_CALL_FUNCTION_KW (0x94) // uint +#define PYBC_CALL_FUNCTION_VAR_KW (0x95) // uint +#define PYBC_CALL_METHOD (0x96) // uint +#define PYBC_CALL_METHOD_VAR (0x97) // uint +#define PYBC_CALL_METHOD_KW (0x98) // uint +#define PYBC_CALL_METHOD_VAR_KW (0x99) // uint + +#define PYBC_IMPORT_NAME (0xe0) +#define PYBC_IMPORT_FROM (0xe1) +#define PYBC_IMPORT_STAR (0xe2) + +py_obj_t py_execute_byte_code(byte *code, uint len, py_obj_t *args, uint n_args); -- cgit v1.2.3