Skip to content

Commit a32c1e4

Browse files
committed
py: Improve native emitter; now supports more opcodes.
1 parent 36db6bc commit a32c1e4

8 files changed

Lines changed: 80 additions & 21 deletions

File tree

py/emitnative.c

Lines changed: 69 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,17 @@ STATIC void emit_call_with_imm_arg(emit_t *emit, mp_fun_kind_t fun_kind, void *f
561561
#endif
562562
}
563563

564+
// the first arg is stored in the code aligned on a machine_uint_t boundary
565+
STATIC void emit_call_with_imm_arg_aligned(emit_t *emit, mp_fun_kind_t fun_kind, void *fun, machine_int_t arg_val, int arg_reg) {
566+
need_reg_all(emit);
567+
ASM_MOV_ALIGNED_IMM_TO_REG(arg_val, arg_reg);
568+
#if N_X64
569+
asm_x64_call_ind(emit->as, fun, REG_RAX);
570+
#elif N_THUMB
571+
asm_thumb_bl_ind(emit->as, mp_fun_table[fun_kind], fun_kind, REG_R3);
572+
#endif
573+
}
574+
564575
STATIC void emit_call_with_2_imm_args(emit_t *emit, mp_fun_kind_t fun_kind, void *fun, machine_int_t arg_val1, int arg_reg1, machine_int_t arg_val2, int arg_reg2) {
565576
need_reg_all(emit);
566577
ASM_MOV_IMM_TO_REG(arg_val1, arg_reg1);
@@ -688,7 +699,7 @@ STATIC void emit_native_load_const_int(emit_t *emit, qstr qst) {
688699
DEBUG_printf("load_const_int %s\n", qstr_str(st));
689700
// for viper: load integer, check fits in 32 bits
690701
emit_native_pre(emit);
691-
emit_call_with_imm_arg(emit, MP_F_LOAD_CONST_INT, mp_obj_new_int_from_long_str, qst, REG_ARG_1);
702+
emit_call_with_imm_arg(emit, MP_F_LOAD_CONST_INT, mp_obj_new_int_from_qstr, qst, REG_ARG_1);
692703
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
693704
}
694705

@@ -945,6 +956,8 @@ STATIC void emit_native_rot_three(emit_t *emit) {
945956

946957
STATIC void emit_native_jump(emit_t *emit, uint label) {
947958
emit_native_pre(emit);
959+
// need to commit stack because we are jumping elsewhere
960+
need_stack_settled(emit);
948961
#if N_X64
949962
asm_x64_jmp_label(emit->as, label);
950963
#elif N_THUMB
@@ -953,21 +966,41 @@ STATIC void emit_native_jump(emit_t *emit, uint label) {
953966
emit_post(emit);
954967
}
955968

956-
STATIC void emit_native_pop_jump_pre_helper(emit_t *emit, uint label) {
969+
STATIC void emit_native_jump_helper(emit_t *emit, uint label, bool pop) {
957970
vtype_kind_t vtype = peek_vtype(emit);
958971
if (vtype == VTYPE_BOOL) {
959972
emit_pre_pop_reg(emit, &vtype, REG_RET);
973+
if (!pop) {
974+
adjust_stack(emit, 1);
975+
}
960976
} else if (vtype == VTYPE_PYOBJ) {
961977
emit_pre_pop_reg(emit, &vtype, REG_ARG_1);
962978
emit_call(emit, MP_F_OBJ_IS_TRUE, mp_obj_is_true);
979+
if (!pop) {
980+
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
981+
}
963982
} else {
964983
printf("ViperTypeError: expecting a bool or pyobj, got %d\n", vtype);
965984
assert(0);
966985
}
986+
// need to commit stack because we may jump elsewhere
987+
need_stack_settled(emit);
988+
}
989+
990+
STATIC void emit_native_pop_jump_if_true(emit_t *emit, uint label) {
991+
emit_native_jump_helper(emit, label, true);
992+
#if N_X64
993+
asm_x64_test_r8_with_r8(emit->as, REG_RET, REG_RET);
994+
asm_x64_jcc_label(emit->as, JCC_JNZ, label);
995+
#elif N_THUMB
996+
asm_thumb_cmp_rlo_i8(emit->as, REG_RET, 0);
997+
asm_thumb_bcc_label(emit->as, THUMB_CC_NE, label);
998+
#endif
999+
emit_post(emit);
9671000
}
9681001

9691002
STATIC void emit_native_pop_jump_if_false(emit_t *emit, uint label) {
970-
emit_native_pop_jump_pre_helper(emit, label);
1003+
emit_native_jump_helper(emit, label, true);
9711004
#if N_X64
9721005
asm_x64_test_r8_with_r8(emit->as, REG_RET, REG_RET);
9731006
asm_x64_jcc_label(emit->as, JCC_JZ, label);
@@ -978,31 +1011,40 @@ STATIC void emit_native_pop_jump_if_false(emit_t *emit, uint label) {
9781011
emit_post(emit);
9791012
}
9801013

981-
STATIC void emit_native_pop_jump_if_true(emit_t *emit, uint label) {
982-
emit_native_pop_jump_pre_helper(emit, label);
1014+
STATIC void emit_native_jump_if_true_or_pop(emit_t *emit, uint label) {
1015+
emit_native_jump_helper(emit, label, false);
9831016
#if N_X64
9841017
asm_x64_test_r8_with_r8(emit->as, REG_RET, REG_RET);
9851018
asm_x64_jcc_label(emit->as, JCC_JNZ, label);
9861019
#elif N_THUMB
9871020
asm_thumb_cmp_rlo_i8(emit->as, REG_RET, 0);
9881021
asm_thumb_bcc_label(emit->as, THUMB_CC_NE, label);
9891022
#endif
1023+
adjust_stack(emit, -1);
9901024
emit_post(emit);
9911025
}
9921026

993-
STATIC void emit_native_jump_if_true_or_pop(emit_t *emit, uint label) {
994-
assert(0);
995-
}
9961027
STATIC void emit_native_jump_if_false_or_pop(emit_t *emit, uint label) {
997-
assert(0);
1028+
emit_native_jump_helper(emit, label, false);
1029+
#if N_X64
1030+
asm_x64_test_r8_with_r8(emit->as, REG_RET, REG_RET);
1031+
asm_x64_jcc_label(emit->as, JCC_JZ, label);
1032+
#elif N_THUMB
1033+
asm_thumb_cmp_rlo_i8(emit->as, REG_RET, 0);
1034+
asm_thumb_bcc_label(emit->as, THUMB_CC_EQ, label);
1035+
#endif
1036+
adjust_stack(emit, -1);
1037+
emit_post(emit);
9981038
}
9991039

10001040
STATIC void emit_native_break_loop(emit_t *emit, uint label, int except_depth) {
10011041
emit_native_jump(emit, label); // TODO properly
10021042
}
1043+
10031044
STATIC void emit_native_continue_loop(emit_t *emit, uint label, int except_depth) {
1004-
assert(0);
1045+
emit_native_jump(emit, label); // TODO properly
10051046
}
1047+
10061048
STATIC void emit_native_setup_with(emit_t *emit, uint label) {
10071049
// not supported, or could be with runtime call
10081050
assert(0);
@@ -1037,7 +1079,7 @@ STATIC void emit_native_for_iter(emit_t *emit, uint label) {
10371079
emit_access_stack(emit, 1, &vtype, REG_ARG_1);
10381080
assert(vtype == VTYPE_PYOBJ);
10391081
emit_call(emit, MP_F_ITERNEXT, mp_iternext);
1040-
ASM_MOV_IMM_TO_REG((machine_uint_t)MP_OBJ_NULL, REG_TEMP1);
1082+
ASM_MOV_IMM_TO_REG((machine_uint_t)MP_OBJ_STOP_ITERATION, REG_TEMP1);
10411083
#if N_X64
10421084
asm_x64_cmp_r64_with_r64(emit->as, REG_RET, REG_TEMP1);
10431085
asm_x64_jcc_label(emit->as, JCC_JE, label);
@@ -1203,14 +1245,27 @@ STATIC void emit_native_unpack_sequence(emit_t *emit, int n_args) {
12031245
}
12041246

12051247
STATIC void emit_native_unpack_ex(emit_t *emit, int n_left, int n_right) {
1206-
assert(0);
1248+
// TODO this is untested
1249+
DEBUG_printf("unpack_ex %d %d\n", n_left, n_right);
1250+
vtype_kind_t vtype_base;
1251+
emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = seq
1252+
assert(vtype_base == VTYPE_PYOBJ);
1253+
emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, n_left + n_right); // arg3 = dest ptr
1254+
emit_call_with_imm_arg(emit, MP_F_UNPACK_EX, mp_unpack_ex, n_left + n_right, REG_ARG_2); // arg2 = n_left + n_right
12071255
}
12081256

12091257
STATIC void emit_native_make_function(emit_t *emit, scope_t *scope, uint n_pos_defaults, uint n_kw_defaults) {
12101258
// call runtime, with type info for args, or don't support dict/default params, or only support Python objects for them
1211-
assert(n_pos_defaults == 0 && n_kw_defaults == 0);
12121259
emit_native_pre(emit);
1213-
emit_call_with_3_imm_args_and_first_aligned(emit, MP_F_MAKE_FUNCTION_FROM_RAW_CODE, mp_make_function_from_raw_code, (machine_uint_t)scope->raw_code, REG_ARG_1, (machine_uint_t)MP_OBJ_NULL, REG_ARG_2, (machine_uint_t)MP_OBJ_NULL, REG_ARG_3);
1260+
if (n_pos_defaults == 0 && n_kw_defaults == 0) {
1261+
emit_call_with_3_imm_args_and_first_aligned(emit, MP_F_MAKE_FUNCTION_FROM_RAW_CODE, mp_make_function_from_raw_code, (machine_uint_t)scope->raw_code, REG_ARG_1, (machine_uint_t)MP_OBJ_NULL, REG_ARG_2, (machine_uint_t)MP_OBJ_NULL, REG_ARG_3);
1262+
} else {
1263+
vtype_kind_t vtype_def_tuple, vtype_def_dict;
1264+
emit_pre_pop_reg_reg(emit, &vtype_def_dict, REG_ARG_3, &vtype_def_tuple, REG_ARG_2);
1265+
assert(vtype_def_tuple == VTYPE_PYOBJ);
1266+
assert(vtype_def_dict == VTYPE_PYOBJ);
1267+
emit_call_with_imm_arg_aligned(emit, MP_F_MAKE_FUNCTION_FROM_RAW_CODE, mp_make_function_from_raw_code, (machine_uint_t)scope->raw_code, REG_ARG_1);
1268+
}
12141269
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
12151270
}
12161271

py/obj.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ mp_obj_t mp_obj_new_bool(bool value);
370370
mp_obj_t mp_obj_new_cell(mp_obj_t obj);
371371
mp_obj_t mp_obj_new_int(machine_int_t value);
372372
mp_obj_t mp_obj_new_int_from_uint(machine_uint_t value);
373-
mp_obj_t mp_obj_new_int_from_long_str(const char *s);
373+
mp_obj_t mp_obj_new_int_from_qstr(qstr qst);
374374
mp_obj_t mp_obj_new_int_from_ll(long long val); // this must return a multi-precision integer object (or raise an overflow exception)
375375
mp_obj_t mp_obj_new_str(const byte* data, uint len, bool make_qstr_if_not_already);
376376
mp_obj_t mp_obj_new_bytes(const byte* data, uint len);

py/objint.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ mp_obj_t mp_obj_int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
228228
}
229229

230230
// This is called only with strings whose value doesn't fit in SMALL_INT
231-
mp_obj_t mp_obj_new_int_from_long_str(const char *s) {
231+
mp_obj_t mp_obj_new_int_from_qstr(qstr qst) {
232232
nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "long int not supported in this build"));
233233
return mp_const_none;
234234
}

py/objint_longlong.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,8 @@ mp_obj_t mp_obj_new_int_from_ll(long long val) {
161161
return o;
162162
}
163163

164-
mp_obj_t mp_obj_new_int_from_long_str(const char *s) {
164+
mp_obj_t mp_obj_new_int_from_qstr(qstr qst) {
165+
const char *s = qstr_str(qst);
165166
long long v;
166167
char *end;
167168
// TODO: this doesn't handle Python hacked 0o octal syntax

py/objint_mpz.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,10 @@ mp_obj_t mp_obj_new_int_from_uint(machine_uint_t value) {
260260
return mp_obj_new_int_from_ll(value);
261261
}
262262

263-
mp_obj_t mp_obj_new_int_from_long_str(const char *str) {
263+
mp_obj_t mp_obj_new_int_from_qstr(qstr qst) {
264264
mp_obj_int_t *o = mp_obj_int_new_mpz();
265-
uint len = strlen(str);
265+
uint len;
266+
const char* str = (const char*)qstr_data(qst, &len);
266267
int base = 0;
267268
int skip = mp_parse_num_base(str, len, &base);
268269
str += skip;

py/runtime.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1132,7 +1132,7 @@ void *m_malloc_fail(int num_bytes) {
11321132
// these must correspond to the respective enum
11331133
void *const mp_fun_table[MP_F_NUMBER_OF] = {
11341134
mp_load_const_dec,
1135-
mp_obj_new_int_from_long_str,
1135+
mp_obj_new_int_from_qstr,
11361136
mp_load_const_str,
11371137
mp_load_name,
11381138
mp_load_global,
@@ -1162,6 +1162,7 @@ void *const mp_fun_table[MP_F_NUMBER_OF] = {
11621162
mp_import_all,
11631163
mp_obj_new_slice,
11641164
mp_unpack_sequence,
1165+
mp_unpack_ex,
11651166
};
11661167

11671168
/*

py/runtime0.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ typedef enum {
121121
MP_F_IMPORT_ALL,
122122
MP_F_NEW_SLICE,
123123
MP_F_UNPACK_SEQUENCE,
124+
MP_F_UNPACK_EX,
124125
MP_F_NUMBER_OF,
125126
} mp_fun_kind_t;
126127

py/vm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ mp_vm_return_kind_t mp_execute_byte_code_2(const byte *code_info, const byte **i
314314

315315
ENTRY(MP_BC_LOAD_CONST_INT):
316316
DECODE_QSTR;
317-
PUSH(mp_obj_new_int_from_long_str(qstr_str(qst)));
317+
PUSH(mp_obj_new_int_from_qstr(qst));
318318
DISPATCH();
319319

320320
ENTRY(MP_BC_LOAD_CONST_DEC):

0 commit comments

Comments
 (0)