diff --git a/py/emitbc.c b/py/emitbc.c index d1ac74f0e9..7fd0f8abcb 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -354,8 +354,9 @@ static void emit_bc_store_subscr(emit_t *emit) { } static void emit_bc_store_locals(emit_t *emit) { - // not needed for byte code + // not needed emit_pre(emit, -1); + emit_write_byte_1(emit, PYBC_POP_TOP); } static void emit_bc_delete_fast(emit_t *emit, qstr qstr, int local_num) { diff --git a/py/emitnative.c b/py/emitnative.c index 4c2f941e03..2687e4fba6 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -344,7 +344,7 @@ static void need_reg_single(emit_t *emit, int reg_needed) { } } -static void need_reg_all(emit_t *emit) { +static void need_reg_all(emit_t *emit, int num_stack_top_that_must_be_value) { for (int i = 0; i < emit->stack_size; i++) { stack_info_t *si = &emit->stack_info[i]; if (si->kind == STACK_REG) { @@ -352,6 +352,14 @@ static void need_reg_all(emit_t *emit) { ASM_MOV_REG_TO_LOCAL(si->u_reg, emit->stack_start + i); } } + // must do this after making all registers available because ASM_MOV_IMM_TO_LOCAL uses a temporary register + for (int i = 0; i < num_stack_top_that_must_be_value; i++) { + stack_info_t *si = &emit->stack_info[emit->stack_size - 1 - i]; + if (si->kind == STACK_IMM) { + si->kind = STACK_VALUE; + ASM_MOV_IMM_TO_LOCAL(si->u_imm, emit->stack_start + emit->stack_size - 1 - i); + } + } } static void emit_pre_pop_reg(emit_t *emit, vtype_kind_t *vtype, int reg_dest) { @@ -427,9 +435,10 @@ static void emit_post_push_reg_reg_reg_reg(emit_t *emit, vtype_kind_t vtypea, in // vtype of all n_pop objects is VTYPE_PYOBJ static void emit_get_stack_pointer_to_reg_for_pop(emit_t *emit, int reg_dest, int n_pop) { - need_reg_all(emit); + need_reg_all(emit, n_pop); for (int i = 0; i < n_pop; i++) { - assert(emit->stack_info[emit->stack_size + i].vtype == VTYPE_PYOBJ); + assert(emit->stack_info[emit->stack_size - 1 - i].kind == STACK_VALUE); + assert(emit->stack_info[emit->stack_size - 1 - i].vtype == VTYPE_PYOBJ); } ASM_MOV_LOCAL_ADDR_TO_REG(emit->stack_start + emit->stack_size - 1, reg_dest); adjust_stack(emit, -n_pop); @@ -437,8 +446,9 @@ static void emit_get_stack_pointer_to_reg_for_pop(emit_t *emit, int reg_dest, in // vtype of all n_push objects is VTYPE_PYOBJ static void emit_get_stack_pointer_to_reg_for_push(emit_t *emit, int reg_dest, int n_push) { - need_reg_all(emit); + need_reg_all(emit, 0); for (int i = 0; i < n_push; i++) { + emit->stack_info[emit->stack_size + i].kind = STACK_VALUE; emit->stack_info[emit->stack_size + i].vtype = VTYPE_PYOBJ; } ASM_MOV_LOCAL_ADDR_TO_REG(emit->stack_start + emit->stack_size + n_push - 1, reg_dest); @@ -454,7 +464,7 @@ static void emit_call(emit_t *emit, rt_fun_kind_t fun_kind, void *fun) { } static void emit_call_with_imm_arg(emit_t *emit, rt_fun_kind_t fun_kind, void *fun, machine_int_t arg_val, int arg_reg) { - need_reg_all(emit); + need_reg_all(emit, 0); ASM_MOV_IMM_TO_REG(arg_val, arg_reg); emit_call(emit, fun_kind, fun); } @@ -549,8 +559,13 @@ static void emit_native_load_const_dec(emit_t *emit, qstr qstr) { } static void emit_native_load_const_id(emit_t *emit, qstr qstr) { - // not supported for viper? - assert(0); + emit_pre(emit); + if (emit->do_viper_types) { + assert(0); + } else { + emit_call_with_imm_arg(emit, RT_F_LOAD_CONST_STR, rt_load_const_str, qstr, REG_ARG_1); // TODO + emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); + } } static void emit_native_load_const_str(emit_t *emit, qstr qstr, bool bytes) { @@ -669,8 +684,9 @@ static void emit_native_load_method(emit_t *emit, qstr qstr) { } static void emit_native_load_build_class(emit_t *emit) { - // not supported - assert(0); + emit_pre(emit); + emit_call(emit, RT_F_LOAD_BUILD_CLASS, rt_load_build_class); + emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } static void emit_native_store_fast(emit_t *emit, qstr qstr, int local_num) { @@ -727,8 +743,12 @@ static void emit_native_store_deref(emit_t *emit, qstr qstr) { } static void emit_native_store_attr(emit_t *emit, qstr qstr) { - // not implemented - assert(0); + vtype_kind_t vtype_base, vtype_val; + emit_pre_pop_reg_reg(emit, &vtype_base, REG_ARG_1, &vtype_val, REG_ARG_3); // arg1 = base, arg3 = value + assert(vtype_base == VTYPE_PYOBJ); + assert(vtype_val == VTYPE_PYOBJ); + emit_call_with_imm_arg(emit, RT_F_STORE_ATTR, rt_store_attr, qstr, REG_ARG_2); // arg2 = attribute name + emit_post(emit); } static void emit_native_store_subscr(emit_t *emit) { @@ -1069,7 +1089,9 @@ static void emit_native_call_method(emit_t *emit, int n_positional, int n_keywor assert(vtype_arg1 == VTYPE_PYOBJ); emit_call(emit, RT_F_CALL_METHOD_2, rt_call_method_2); } else { - assert(0); + emit_pre(emit); + emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, n_positional + 2); // pointer to items in reverse order, including meth and self + emit_call_with_imm_arg(emit, RT_F_CALL_METHOD_N, rt_call_method_n, n_positional, REG_ARG_1); } emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } diff --git a/py/runtime.c b/py/runtime.c index 7e7164d4f0..e9a8614389 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -9,11 +9,13 @@ #include "runtime.h" #include "vm.h" +#if 0 // print debugging info +#define DEBUG_printf(args...) printf(args) +#define DEBUG_OP_printf(args...) printf(args) +#else // don't print debugging info #define DEBUG_printf(args...) (void)0 -//#define DEBUG_printf(args...) printf(args) - #define DEBUG_OP_printf(args...) (void)0 -//#define DEBUG_OP_printf(args...) printf(args) +#endif // enable/disable float support with this definition #define PY_FLOAT (1) @@ -914,7 +916,7 @@ py_obj_t rt_call_function_1(py_obj_t fun, py_obj_t arg) { py_obj_t rt_call_function_2(py_obj_t fun, py_obj_t arg1, py_obj_t arg2) { if (IS_O(fun, O_FUN_2)) { py_obj_base_t *o = fun; - DEBUG_OP_printf("calling native %p with 2 args\n", o->u_fun.fun); + DEBUG_OP_printf("calling native %p(%p, %p)\n", o->u_fun.fun, arg1, arg2); return ((py_fun_2_t)o->u_fun.fun)(arg1, arg2); } else if (IS_O(fun, O_FUN_BC)) { py_obj_base_t *o = fun; @@ -937,7 +939,12 @@ py_obj_t rt_call_function_2(py_obj_t fun, py_obj_t arg1, py_obj_t arg2) { // args are in reverse order in the array py_obj_t rt_call_function_n(py_obj_t fun, int n_args, const py_obj_t *args) { - if (IS_O(fun, O_FUN_BC)) { + if (IS_O(fun, O_FUN_2)) { + assert(n_args == 2); + py_obj_base_t *o = fun; + DEBUG_OP_printf("calling native %p(%p, %p)\n", o->u_fun.fun, args[1], args[0]); + return ((py_fun_2_t)o->u_fun.fun)(args[1], args[0]); + } else if (IS_O(fun, O_FUN_BC)) { py_obj_base_t *o = fun; assert(o->u_fun_bc.n_args == n_args); DEBUG_OP_printf("calling byte code %p with %d args\n", o->u_fun_bc.code, n_args); @@ -949,7 +956,7 @@ py_obj_t rt_call_function_n(py_obj_t fun, int n_args, const py_obj_t *args) { } py_obj_t rt_call_method_1(py_obj_t fun, py_obj_t self) { - DEBUG_OP_printf("call method %p %p\n", fun, self); + DEBUG_OP_printf("call method %p(self=%p)\n", fun, self); if (self == NULL) { return rt_call_function_0(fun); } else { @@ -958,7 +965,7 @@ py_obj_t rt_call_method_1(py_obj_t fun, py_obj_t self) { } py_obj_t rt_call_method_2(py_obj_t fun, py_obj_t self, py_obj_t arg) { - DEBUG_OP_printf("call method %p %p %p\n", fun, self, arg); + DEBUG_OP_printf("call method %p(self=%p, %p)\n", fun, self, arg); if (self == NULL) { return rt_call_function_1(fun, arg); } else { @@ -969,7 +976,7 @@ py_obj_t rt_call_method_2(py_obj_t fun, py_obj_t self, py_obj_t arg) { // args contains: arg(n_args-1) arg(n_args-2) ... arg(0) self/NULL fun // if n_args==0 then there are only self/NULL and fun py_obj_t rt_call_method_n(int n_args, const py_obj_t *args) { - DEBUG_OP_printf("call method %p %p %d args\n", args[n_args + 1], args[n_args] , n_args); + DEBUG_OP_printf("call method %p(self=%p, n_args=%d)\n", args[n_args + 1], args[n_args], n_args); return rt_call_function_n(args[n_args + 1], n_args + ((args[n_args] == NULL) ? 0 : 1), args); } @@ -1186,9 +1193,11 @@ void *rt_fun_table[RT_F_NUMBER_OF] = { rt_load_const_str, rt_load_name, rt_load_global, + rt_load_build_class, rt_load_attr, rt_load_method, rt_store_name, + rt_store_attr, rt_store_subscr, rt_is_true, rt_unary_op, @@ -1202,6 +1211,7 @@ void *rt_fun_table[RT_F_NUMBER_OF] = { rt_call_function_2, rt_call_method_1, rt_call_method_2, + rt_call_method_n, rt_binary_op, rt_compare_op, }; diff --git a/py/runtime.h b/py/runtime.h index d72182cb39..f1832be247 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -51,9 +51,11 @@ typedef enum { RT_F_LOAD_CONST_STR = 0, RT_F_LOAD_NAME, RT_F_LOAD_GLOBAL, + RT_F_LOAD_BUILD_CLASS, RT_F_LOAD_ATTR, RT_F_LOAD_METHOD, RT_F_STORE_NAME, + RT_F_STORE_ATTR, RT_F_STORE_SUBSCR, RT_F_IS_TRUE, RT_F_UNARY_OP, @@ -67,6 +69,7 @@ typedef enum { RT_F_CALL_FUNCTION_2, RT_F_CALL_METHOD_1, RT_F_CALL_METHOD_2, + RT_F_CALL_METHOD_N, RT_F_BINARY_OP, RT_F_COMPARE_OP, RT_F_NUMBER_OF,