py: Implement calling functions with *args in native emitter.
This commit is contained in:
parent
282ca09f8e
commit
78772ada0d
@ -184,6 +184,7 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = {
|
|||||||
[MP_F_MAKE_FUNCTION_FROM_RAW_CODE] = 3,
|
[MP_F_MAKE_FUNCTION_FROM_RAW_CODE] = 3,
|
||||||
[MP_F_NATIVE_CALL_FUNCTION_N_KW] = 3,
|
[MP_F_NATIVE_CALL_FUNCTION_N_KW] = 3,
|
||||||
[MP_F_CALL_METHOD_N_KW] = 3,
|
[MP_F_CALL_METHOD_N_KW] = 3,
|
||||||
|
[MP_F_CALL_METHOD_N_KW_VAR] = 3,
|
||||||
[MP_F_GETITER] = 1,
|
[MP_F_GETITER] = 1,
|
||||||
[MP_F_ITERNEXT] = 1,
|
[MP_F_ITERNEXT] = 1,
|
||||||
[MP_F_NLR_PUSH] = 1,
|
[MP_F_NLR_PUSH] = 1,
|
||||||
@ -2189,13 +2190,12 @@ STATIC void emit_native_call_function(emit_t *emit, mp_uint_t n_positional, mp_u
|
|||||||
// TODO: in viper mode, call special runtime routine with type info for args,
|
// TODO: in viper mode, call special runtime routine with type info for args,
|
||||||
// and wanted type info for return, to remove need for boxing/unboxing
|
// and wanted type info for return, to remove need for boxing/unboxing
|
||||||
|
|
||||||
assert(!star_flags);
|
|
||||||
|
|
||||||
emit_native_pre(emit);
|
emit_native_pre(emit);
|
||||||
vtype_kind_t vtype_fun = peek_vtype(emit, n_positional + 2 * n_keyword);
|
vtype_kind_t vtype_fun = peek_vtype(emit, n_positional + 2 * n_keyword);
|
||||||
if (vtype_fun == VTYPE_BUILTIN_CAST) {
|
if (vtype_fun == VTYPE_BUILTIN_CAST) {
|
||||||
// casting operator
|
// casting operator
|
||||||
assert(n_positional == 1 && n_keyword == 0);
|
assert(n_positional == 1 && n_keyword == 0);
|
||||||
|
assert(!star_flags);
|
||||||
DEBUG_printf(" cast to %d\n", vtype_fun);
|
DEBUG_printf(" cast to %d\n", vtype_fun);
|
||||||
vtype_kind_t vtype_cast = peek_stack(emit, 1)->data.u_imm;
|
vtype_kind_t vtype_cast = peek_stack(emit, 1)->data.u_imm;
|
||||||
switch (peek_vtype(emit, 0)) {
|
switch (peek_vtype(emit, 0)) {
|
||||||
@ -2221,22 +2221,49 @@ STATIC void emit_native_call_function(emit_t *emit, mp_uint_t n_positional, mp_u
|
|||||||
assert(!"TODO: convert obj to int");
|
assert(!"TODO: convert obj to int");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (n_positional != 0 || n_keyword != 0) {
|
|
||||||
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_positional + 2 * n_keyword); // pointer to args
|
|
||||||
}
|
|
||||||
emit_pre_pop_reg(emit, &vtype_fun, REG_ARG_1); // the function
|
|
||||||
assert(vtype_fun == VTYPE_PYOBJ);
|
assert(vtype_fun == VTYPE_PYOBJ);
|
||||||
emit_call_with_imm_arg(emit, MP_F_NATIVE_CALL_FUNCTION_N_KW, n_positional | (n_keyword << 8), REG_ARG_2);
|
if (star_flags) {
|
||||||
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
|
if (!(star_flags & MP_EMIT_STAR_FLAG_SINGLE)) {
|
||||||
|
// load dummy entry for non-existent pos_seq
|
||||||
|
emit_native_load_null(emit);
|
||||||
|
emit_native_rot_two(emit);
|
||||||
|
} else if (!(star_flags & MP_EMIT_STAR_FLAG_DOUBLE)) {
|
||||||
|
// load dummy entry for non-existent kw_dict
|
||||||
|
emit_native_load_null(emit);
|
||||||
|
}
|
||||||
|
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_positional + 2 * n_keyword + 3); // pointer to args
|
||||||
|
emit_call_with_2_imm_args(emit, MP_F_CALL_METHOD_N_KW_VAR, 0, REG_ARG_1, n_positional | (n_keyword << 8), REG_ARG_2);
|
||||||
|
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
|
||||||
|
} else {
|
||||||
|
if (n_positional != 0 || n_keyword != 0) {
|
||||||
|
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_positional + 2 * n_keyword); // pointer to args
|
||||||
|
}
|
||||||
|
emit_pre_pop_reg(emit, &vtype_fun, REG_ARG_1); // the function
|
||||||
|
emit_call_with_imm_arg(emit, MP_F_NATIVE_CALL_FUNCTION_N_KW, n_positional | (n_keyword << 8), REG_ARG_2);
|
||||||
|
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void emit_native_call_method(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) {
|
STATIC void emit_native_call_method(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) {
|
||||||
assert(!star_flags);
|
if (star_flags) {
|
||||||
emit_native_pre(emit);
|
if (!(star_flags & MP_EMIT_STAR_FLAG_SINGLE)) {
|
||||||
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, 2 + n_positional + 2 * n_keyword); // pointer to items, including meth and self
|
// load dummy entry for non-existent pos_seq
|
||||||
emit_call_with_2_imm_args(emit, MP_F_CALL_METHOD_N_KW, n_positional, REG_ARG_1, n_keyword, REG_ARG_2);
|
emit_native_load_null(emit);
|
||||||
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
|
emit_native_rot_two(emit);
|
||||||
|
} else if (!(star_flags & MP_EMIT_STAR_FLAG_DOUBLE)) {
|
||||||
|
// load dummy entry for non-existent kw_dict
|
||||||
|
emit_native_load_null(emit);
|
||||||
|
}
|
||||||
|
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_positional + 2 * n_keyword + 4); // pointer to args
|
||||||
|
emit_call_with_2_imm_args(emit, MP_F_CALL_METHOD_N_KW_VAR, 1, REG_ARG_1, n_positional | (n_keyword << 8), REG_ARG_2);
|
||||||
|
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
|
||||||
|
} else {
|
||||||
|
emit_native_pre(emit);
|
||||||
|
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, 2 + n_positional + 2 * n_keyword); // pointer to items, including meth and self
|
||||||
|
emit_call_with_2_imm_args(emit, MP_F_CALL_METHOD_N_KW, n_positional, REG_ARG_1, n_keyword, REG_ARG_2);
|
||||||
|
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void emit_native_return_value(emit_t *emit) {
|
STATIC void emit_native_return_value(emit_t *emit) {
|
||||||
|
@ -117,6 +117,7 @@ void *const mp_fun_table[MP_F_NUMBER_OF] = {
|
|||||||
mp_make_function_from_raw_code,
|
mp_make_function_from_raw_code,
|
||||||
mp_native_call_function_n_kw,
|
mp_native_call_function_n_kw,
|
||||||
mp_call_method_n_kw,
|
mp_call_method_n_kw,
|
||||||
|
mp_call_method_n_kw_var,
|
||||||
mp_getiter,
|
mp_getiter,
|
||||||
mp_iternext,
|
mp_iternext,
|
||||||
nlr_push,
|
nlr_push,
|
||||||
|
@ -133,6 +133,7 @@ typedef enum {
|
|||||||
MP_F_MAKE_FUNCTION_FROM_RAW_CODE,
|
MP_F_MAKE_FUNCTION_FROM_RAW_CODE,
|
||||||
MP_F_NATIVE_CALL_FUNCTION_N_KW,
|
MP_F_NATIVE_CALL_FUNCTION_N_KW,
|
||||||
MP_F_CALL_METHOD_N_KW,
|
MP_F_CALL_METHOD_N_KW,
|
||||||
|
MP_F_CALL_METHOD_N_KW_VAR,
|
||||||
MP_F_GETITER,
|
MP_F_GETITER,
|
||||||
MP_F_ITERNEXT,
|
MP_F_ITERNEXT,
|
||||||
MP_F_NLR_PUSH,
|
MP_F_NLR_PUSH,
|
||||||
|
@ -160,7 +160,6 @@ def run_tests(pyb, tests, args):
|
|||||||
skip_tests.add('basics/boundmeth1.py') # requires support for many args
|
skip_tests.add('basics/boundmeth1.py') # requires support for many args
|
||||||
skip_tests.add('basics/closure_manyvars.py') # requires closures
|
skip_tests.add('basics/closure_manyvars.py') # requires closures
|
||||||
skip_tests.add('float/string_format.py')
|
skip_tests.add('float/string_format.py')
|
||||||
skip_tests.add('float/cmath_fun.py') # requires f(*args) support
|
|
||||||
skip_tests.add('import/gen_context.py')
|
skip_tests.add('import/gen_context.py')
|
||||||
skip_tests.add('io/file_with.py')
|
skip_tests.add('io/file_with.py')
|
||||||
skip_tests.add('io/stringio_with.py')
|
skip_tests.add('io/stringio_with.py')
|
||||||
|
Loading…
Reference in New Issue
Block a user