Skip to content

Commit 78772ad

Browse files
committed
py: Implement calling functions with *args in native emitter.
1 parent 282ca09 commit 78772ad

4 files changed

Lines changed: 42 additions & 14 deletions

File tree

py/emitnative.c

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = {
184184
[MP_F_MAKE_FUNCTION_FROM_RAW_CODE] = 3,
185185
[MP_F_NATIVE_CALL_FUNCTION_N_KW] = 3,
186186
[MP_F_CALL_METHOD_N_KW] = 3,
187+
[MP_F_CALL_METHOD_N_KW_VAR] = 3,
187188
[MP_F_GETITER] = 1,
188189
[MP_F_ITERNEXT] = 1,
189190
[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
21892190
// TODO: in viper mode, call special runtime routine with type info for args,
21902191
// and wanted type info for return, to remove need for boxing/unboxing
21912192

2192-
assert(!star_flags);
2193-
21942193
emit_native_pre(emit);
21952194
vtype_kind_t vtype_fun = peek_vtype(emit, n_positional + 2 * n_keyword);
21962195
if (vtype_fun == VTYPE_BUILTIN_CAST) {
21972196
// casting operator
21982197
assert(n_positional == 1 && n_keyword == 0);
2198+
assert(!star_flags);
21992199
DEBUG_printf(" cast to %d\n", vtype_fun);
22002200
vtype_kind_t vtype_cast = peek_stack(emit, 1)->data.u_imm;
22012201
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
22212221
assert(!"TODO: convert obj to int");
22222222
}
22232223
} else {
2224-
if (n_positional != 0 || n_keyword != 0) {
2225-
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_positional + 2 * n_keyword); // pointer to args
2226-
}
2227-
emit_pre_pop_reg(emit, &vtype_fun, REG_ARG_1); // the function
22282224
assert(vtype_fun == VTYPE_PYOBJ);
2229-
emit_call_with_imm_arg(emit, MP_F_NATIVE_CALL_FUNCTION_N_KW, n_positional | (n_keyword << 8), REG_ARG_2);
2230-
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
2225+
if (star_flags) {
2226+
if (!(star_flags & MP_EMIT_STAR_FLAG_SINGLE)) {
2227+
// load dummy entry for non-existent pos_seq
2228+
emit_native_load_null(emit);
2229+
emit_native_rot_two(emit);
2230+
} else if (!(star_flags & MP_EMIT_STAR_FLAG_DOUBLE)) {
2231+
// load dummy entry for non-existent kw_dict
2232+
emit_native_load_null(emit);
2233+
}
2234+
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_positional + 2 * n_keyword + 3); // pointer to args
2235+
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);
2236+
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
2237+
} else {
2238+
if (n_positional != 0 || n_keyword != 0) {
2239+
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_positional + 2 * n_keyword); // pointer to args
2240+
}
2241+
emit_pre_pop_reg(emit, &vtype_fun, REG_ARG_1); // the function
2242+
emit_call_with_imm_arg(emit, MP_F_NATIVE_CALL_FUNCTION_N_KW, n_positional | (n_keyword << 8), REG_ARG_2);
2243+
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
2244+
}
22312245
}
22322246
}
22332247

22342248
STATIC void emit_native_call_method(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) {
2235-
assert(!star_flags);
2236-
emit_native_pre(emit);
2237-
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
2238-
emit_call_with_2_imm_args(emit, MP_F_CALL_METHOD_N_KW, n_positional, REG_ARG_1, n_keyword, REG_ARG_2);
2239-
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
2249+
if (star_flags) {
2250+
if (!(star_flags & MP_EMIT_STAR_FLAG_SINGLE)) {
2251+
// load dummy entry for non-existent pos_seq
2252+
emit_native_load_null(emit);
2253+
emit_native_rot_two(emit);
2254+
} else if (!(star_flags & MP_EMIT_STAR_FLAG_DOUBLE)) {
2255+
// load dummy entry for non-existent kw_dict
2256+
emit_native_load_null(emit);
2257+
}
2258+
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_positional + 2 * n_keyword + 4); // pointer to args
2259+
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);
2260+
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
2261+
} else {
2262+
emit_native_pre(emit);
2263+
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
2264+
emit_call_with_2_imm_args(emit, MP_F_CALL_METHOD_N_KW, n_positional, REG_ARG_1, n_keyword, REG_ARG_2);
2265+
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
2266+
}
22402267
}
22412268

22422269
STATIC void emit_native_return_value(emit_t *emit) {

py/nativeglue.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ void *const mp_fun_table[MP_F_NUMBER_OF] = {
117117
mp_make_function_from_raw_code,
118118
mp_native_call_function_n_kw,
119119
mp_call_method_n_kw,
120+
mp_call_method_n_kw_var,
120121
mp_getiter,
121122
mp_iternext,
122123
nlr_push,

py/runtime0.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ typedef enum {
133133
MP_F_MAKE_FUNCTION_FROM_RAW_CODE,
134134
MP_F_NATIVE_CALL_FUNCTION_N_KW,
135135
MP_F_CALL_METHOD_N_KW,
136+
MP_F_CALL_METHOD_N_KW_VAR,
136137
MP_F_GETITER,
137138
MP_F_ITERNEXT,
138139
MP_F_NLR_PUSH,

tests/run-tests

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,6 @@ def run_tests(pyb, tests, args):
160160
skip_tests.add('basics/boundmeth1.py') # requires support for many args
161161
skip_tests.add('basics/closure_manyvars.py') # requires closures
162162
skip_tests.add('float/string_format.py')
163-
skip_tests.add('float/cmath_fun.py') # requires f(*args) support
164163
skip_tests.add('import/gen_context.py')
165164
skip_tests.add('io/file_with.py')
166165
skip_tests.add('io/stringio_with.py')

0 commit comments

Comments
 (0)