Implement basic class/object in native code.
This commit is contained in:
parent
a397776d6b
commit
7f5dacf345
@ -354,8 +354,9 @@ static void emit_bc_store_subscr(emit_t *emit) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void emit_bc_store_locals(emit_t *emit) {
|
static void emit_bc_store_locals(emit_t *emit) {
|
||||||
// not needed for byte code
|
// not needed
|
||||||
emit_pre(emit, -1);
|
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) {
|
static void emit_bc_delete_fast(emit_t *emit, qstr qstr, int local_num) {
|
||||||
|
@ -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++) {
|
for (int i = 0; i < emit->stack_size; i++) {
|
||||||
stack_info_t *si = &emit->stack_info[i];
|
stack_info_t *si = &emit->stack_info[i];
|
||||||
if (si->kind == STACK_REG) {
|
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);
|
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) {
|
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
|
// 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) {
|
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++) {
|
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);
|
ASM_MOV_LOCAL_ADDR_TO_REG(emit->stack_start + emit->stack_size - 1, reg_dest);
|
||||||
adjust_stack(emit, -n_pop);
|
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
|
// 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) {
|
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++) {
|
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;
|
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);
|
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) {
|
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);
|
ASM_MOV_IMM_TO_REG(arg_val, arg_reg);
|
||||||
emit_call(emit, fun_kind, fun);
|
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) {
|
static void emit_native_load_const_id(emit_t *emit, qstr qstr) {
|
||||||
// not supported for viper?
|
emit_pre(emit);
|
||||||
|
if (emit->do_viper_types) {
|
||||||
assert(0);
|
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) {
|
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) {
|
static void emit_native_load_build_class(emit_t *emit) {
|
||||||
// not supported
|
emit_pre(emit);
|
||||||
assert(0);
|
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) {
|
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) {
|
static void emit_native_store_attr(emit_t *emit, qstr qstr) {
|
||||||
// not implemented
|
vtype_kind_t vtype_base, vtype_val;
|
||||||
assert(0);
|
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) {
|
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);
|
assert(vtype_arg1 == VTYPE_PYOBJ);
|
||||||
emit_call(emit, RT_F_CALL_METHOD_2, rt_call_method_2);
|
emit_call(emit, RT_F_CALL_METHOD_2, rt_call_method_2);
|
||||||
} else {
|
} 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);
|
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
|
||||||
}
|
}
|
||||||
|
26
py/runtime.c
26
py/runtime.c
@ -9,11 +9,13 @@
|
|||||||
#include "runtime.h"
|
#include "runtime.h"
|
||||||
#include "vm.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...) (void)0
|
||||||
//#define DEBUG_printf(args...) printf(args)
|
|
||||||
|
|
||||||
#define DEBUG_OP_printf(args...) (void)0
|
#define DEBUG_OP_printf(args...) (void)0
|
||||||
//#define DEBUG_OP_printf(args...) printf(args)
|
#endif
|
||||||
|
|
||||||
// enable/disable float support with this definition
|
// enable/disable float support with this definition
|
||||||
#define PY_FLOAT (1)
|
#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) {
|
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)) {
|
if (IS_O(fun, O_FUN_2)) {
|
||||||
py_obj_base_t *o = fun;
|
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);
|
return ((py_fun_2_t)o->u_fun.fun)(arg1, arg2);
|
||||||
} else if (IS_O(fun, O_FUN_BC)) {
|
} else if (IS_O(fun, O_FUN_BC)) {
|
||||||
py_obj_base_t *o = fun;
|
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
|
// 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) {
|
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;
|
py_obj_base_t *o = fun;
|
||||||
assert(o->u_fun_bc.n_args == n_args);
|
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);
|
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) {
|
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) {
|
if (self == NULL) {
|
||||||
return rt_call_function_0(fun);
|
return rt_call_function_0(fun);
|
||||||
} else {
|
} 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) {
|
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) {
|
if (self == NULL) {
|
||||||
return rt_call_function_1(fun, arg);
|
return rt_call_function_1(fun, arg);
|
||||||
} else {
|
} 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
|
// 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
|
// 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) {
|
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);
|
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_const_str,
|
||||||
rt_load_name,
|
rt_load_name,
|
||||||
rt_load_global,
|
rt_load_global,
|
||||||
|
rt_load_build_class,
|
||||||
rt_load_attr,
|
rt_load_attr,
|
||||||
rt_load_method,
|
rt_load_method,
|
||||||
rt_store_name,
|
rt_store_name,
|
||||||
|
rt_store_attr,
|
||||||
rt_store_subscr,
|
rt_store_subscr,
|
||||||
rt_is_true,
|
rt_is_true,
|
||||||
rt_unary_op,
|
rt_unary_op,
|
||||||
@ -1202,6 +1211,7 @@ void *rt_fun_table[RT_F_NUMBER_OF] = {
|
|||||||
rt_call_function_2,
|
rt_call_function_2,
|
||||||
rt_call_method_1,
|
rt_call_method_1,
|
||||||
rt_call_method_2,
|
rt_call_method_2,
|
||||||
|
rt_call_method_n,
|
||||||
rt_binary_op,
|
rt_binary_op,
|
||||||
rt_compare_op,
|
rt_compare_op,
|
||||||
};
|
};
|
||||||
|
@ -51,9 +51,11 @@ typedef enum {
|
|||||||
RT_F_LOAD_CONST_STR = 0,
|
RT_F_LOAD_CONST_STR = 0,
|
||||||
RT_F_LOAD_NAME,
|
RT_F_LOAD_NAME,
|
||||||
RT_F_LOAD_GLOBAL,
|
RT_F_LOAD_GLOBAL,
|
||||||
|
RT_F_LOAD_BUILD_CLASS,
|
||||||
RT_F_LOAD_ATTR,
|
RT_F_LOAD_ATTR,
|
||||||
RT_F_LOAD_METHOD,
|
RT_F_LOAD_METHOD,
|
||||||
RT_F_STORE_NAME,
|
RT_F_STORE_NAME,
|
||||||
|
RT_F_STORE_ATTR,
|
||||||
RT_F_STORE_SUBSCR,
|
RT_F_STORE_SUBSCR,
|
||||||
RT_F_IS_TRUE,
|
RT_F_IS_TRUE,
|
||||||
RT_F_UNARY_OP,
|
RT_F_UNARY_OP,
|
||||||
@ -67,6 +69,7 @@ typedef enum {
|
|||||||
RT_F_CALL_FUNCTION_2,
|
RT_F_CALL_FUNCTION_2,
|
||||||
RT_F_CALL_METHOD_1,
|
RT_F_CALL_METHOD_1,
|
||||||
RT_F_CALL_METHOD_2,
|
RT_F_CALL_METHOD_2,
|
||||||
|
RT_F_CALL_METHOD_N,
|
||||||
RT_F_BINARY_OP,
|
RT_F_BINARY_OP,
|
||||||
RT_F_COMPARE_OP,
|
RT_F_COMPARE_OP,
|
||||||
RT_F_NUMBER_OF,
|
RT_F_NUMBER_OF,
|
||||||
|
Loading…
Reference in New Issue
Block a user