Skip to content

Commit d6230f6

Browse files
committed
py: Make native emitter handle multi-compare and not/is not/not in ops.
1 parent 96e20c6 commit d6230f6

5 files changed

Lines changed: 76 additions & 28 deletions

File tree

py/emitnative.c

Lines changed: 62 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,8 @@ STATIC void emit_native_set_native_type(emit_t *emit, mp_uint_t op, mp_uint_t ar
488488
}
489489

490490
STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
491+
DEBUG_printf("start_pass(pass=%u, scope=%p)\n", pass, scope);
492+
491493
emit->pass = pass;
492494
emit->stack_start = 0;
493495
emit->stack_size = 0;
@@ -636,22 +638,32 @@ STATIC bool emit_native_last_emit_was_return_value(emit_t *emit) {
636638
return emit->last_emit_was_return_value;
637639
}
638640

639-
STATIC void emit_native_adjust_stack_size(emit_t *emit, mp_int_t delta) {
640-
emit->stack_size += delta;
641-
}
642-
643-
STATIC void emit_native_set_source_line(emit_t *emit, mp_uint_t source_line) {
644-
}
645-
646-
STATIC void adjust_stack(emit_t *emit, int stack_size_delta) {
647-
DEBUG_printf("adjust stack: stack:%d + delta:%d\n", emit->stack_size, stack_size_delta);
648-
assert((int)emit->stack_size + stack_size_delta >= 0);
641+
STATIC void adjust_stack(emit_t *emit, mp_int_t stack_size_delta) {
642+
DEBUG_printf(" adjust_stack; stack_size=%d, delta=%d\n", emit->stack_size, stack_size_delta);
643+
assert((mp_int_t)emit->stack_size + stack_size_delta >= 0);
649644
emit->stack_size += stack_size_delta;
650645
if (emit->pass > MP_PASS_SCOPE && emit->stack_size > emit->scope->stack_size) {
651646
emit->scope->stack_size = emit->stack_size;
652647
}
653648
}
654649

650+
STATIC void emit_native_adjust_stack_size(emit_t *emit, mp_int_t delta) {
651+
// If we are adjusting the stack in a positive direction (pushing) then we
652+
// need to fill in values for the stack kind and vtype of the newly-pushed
653+
// entries. These should be set to "value" (ie not reg or imm) because we
654+
// should only need to adjust the stack due to a jump to this part in the
655+
// code (and hence we have settled the stack before the jump).
656+
for (mp_int_t i = 0; i < delta; i++) {
657+
stack_info_t *si = &emit->stack_info[emit->stack_size + i];
658+
si->kind = STACK_VALUE;
659+
si->vtype = VTYPE_PYOBJ; // XXX we don't know the vtype...
660+
}
661+
adjust_stack(emit, delta);
662+
}
663+
664+
STATIC void emit_native_set_source_line(emit_t *emit, mp_uint_t source_line) {
665+
}
666+
655667
/*
656668
STATIC void emit_pre_raw(emit_t *emit, int stack_size_delta) {
657669
adjust_stack(emit, stack_size_delta);
@@ -716,16 +728,19 @@ STATIC void need_reg_all(emit_t *emit) {
716728
}
717729

718730
STATIC void need_stack_settled(emit_t *emit) {
731+
DEBUG_printf(" need_stack_settled; stack_size=%d\n", emit->stack_size);
719732
for (int i = 0; i < emit->stack_size; i++) {
720733
stack_info_t *si = &emit->stack_info[i];
721734
if (si->kind == STACK_REG) {
735+
DEBUG_printf(" reg(%u) to local(%u)\n", si->u_reg, emit->stack_start + i);
722736
si->kind = STACK_VALUE;
723737
ASM_MOV_REG_TO_LOCAL(emit->as, si->u_reg, emit->stack_start + i);
724738
}
725739
}
726740
for (int i = 0; i < emit->stack_size; i++) {
727741
stack_info_t *si = &emit->stack_info[i];
728742
if (si->kind == STACK_IMM) {
743+
DEBUG_printf(" imm(" INT_FMT ") to local(%u)\n", si->u_imm, emit->stack_start + i);
729744
si->kind = STACK_VALUE;
730745
ASM_MOV_IMM_TO_LOCAL_USING(emit->as, si->u_imm, emit->stack_start + i, REG_TEMP0);
731746
}
@@ -929,6 +944,7 @@ STATIC void emit_native_delete_id(emit_t *emit, qstr qst) {
929944
}
930945

931946
STATIC void emit_native_label_assign(emit_t *emit, mp_uint_t l) {
947+
DEBUG_printf("label_assign(" UINT_FMT ")\n", l);
932948
emit_native_pre(emit);
933949
// need to commit stack because we can jump here from elsewhere
934950
need_stack_settled(emit);
@@ -967,7 +983,7 @@ STATIC void emit_native_import_star(emit_t *emit) {
967983
}
968984

969985
STATIC void emit_native_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
970-
DEBUG_printf("load_const_tok %d\n", tok);
986+
DEBUG_printf("load_const_tok(tok=%u)\n", tok);
971987
emit_native_pre(emit);
972988
int vtype;
973989
mp_uint_t val;
@@ -991,7 +1007,7 @@ STATIC void emit_native_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
9911007
}
9921008

9931009
STATIC void emit_native_load_const_small_int(emit_t *emit, mp_int_t arg) {
994-
DEBUG_printf("load_const_small_int %d\n", arg);
1010+
DEBUG_printf("load_const_small_int(int=" INT_FMT ")\n", arg);
9951011
emit_native_pre(emit);
9961012
if (emit->do_viper_types) {
9971013
emit_post_push_imm(emit, VTYPE_INT, arg);
@@ -1001,7 +1017,7 @@ STATIC void emit_native_load_const_small_int(emit_t *emit, mp_int_t arg) {
10011017
}
10021018

10031019
STATIC void emit_native_load_const_int(emit_t *emit, qstr qst) {
1004-
DEBUG_printf("load_const_int %s\n", qstr_str(st));
1020+
DEBUG_printf("load_const_int %s\n", qstr_str(qst));
10051021
// for viper: load integer, check fits in 32 bits
10061022
emit_native_pre(emit);
10071023
emit_call_with_imm_arg(emit, MP_F_LOAD_CONST_INT, qst, REG_ARG_1);
@@ -1108,6 +1124,7 @@ STATIC void emit_native_load_deref(emit_t *emit, qstr qst, mp_uint_t local_num)
11081124
}
11091125

11101126
STATIC void emit_native_load_name(emit_t *emit, qstr qst) {
1127+
DEBUG_printf("load_name(%s)\n", qstr_str(qst));
11111128
emit_native_pre(emit);
11121129
emit_call_with_imm_arg(emit, MP_F_LOAD_NAME, qst, REG_ARG_1);
11131130
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
@@ -1305,6 +1322,7 @@ STATIC void emit_native_delete_subscr(emit_t *emit) {
13051322
}
13061323

13071324
STATIC void emit_native_dup_top(emit_t *emit) {
1325+
DEBUG_printf("dup_top\n");
13081326
vtype_kind_t vtype;
13091327
emit_pre_pop_reg(emit, &vtype, REG_TEMP0);
13101328
emit_post_push_reg_reg(emit, vtype, REG_TEMP0, vtype, REG_TEMP0);
@@ -1317,23 +1335,27 @@ STATIC void emit_native_dup_top_two(emit_t *emit) {
13171335
}
13181336

13191337
STATIC void emit_native_pop_top(emit_t *emit) {
1338+
DEBUG_printf("pop_top\n");
13201339
emit_pre_pop_discard(emit);
13211340
emit_post(emit);
13221341
}
13231342

13241343
STATIC void emit_native_rot_two(emit_t *emit) {
1344+
DEBUG_printf("rot_two\n");
13251345
vtype_kind_t vtype0, vtype1;
13261346
emit_pre_pop_reg_reg(emit, &vtype0, REG_TEMP0, &vtype1, REG_TEMP1);
13271347
emit_post_push_reg_reg(emit, vtype0, REG_TEMP0, vtype1, REG_TEMP1);
13281348
}
13291349

13301350
STATIC void emit_native_rot_three(emit_t *emit) {
1351+
DEBUG_printf("rot_three\n");
13311352
vtype_kind_t vtype0, vtype1, vtype2;
13321353
emit_pre_pop_reg_reg_reg(emit, &vtype0, REG_TEMP0, &vtype1, REG_TEMP1, &vtype2, REG_TEMP2);
13331354
emit_post_push_reg_reg_reg(emit, vtype0, REG_TEMP0, vtype2, REG_TEMP2, vtype1, REG_TEMP1);
13341355
}
13351356

13361357
STATIC void emit_native_jump(emit_t *emit, mp_uint_t label) {
1358+
DEBUG_printf("jump(label=" UINT_FMT ")\n", label);
13371359
emit_native_pre(emit);
13381360
// need to commit stack because we are jumping elsewhere
13391361
need_stack_settled(emit);
@@ -1363,25 +1385,29 @@ STATIC void emit_native_jump_helper(emit_t *emit, mp_uint_t label, bool pop) {
13631385
}
13641386

13651387
STATIC void emit_native_pop_jump_if_true(emit_t *emit, mp_uint_t label) {
1388+
DEBUG_printf("pop_jump_if_true(label=" UINT_FMT ")\n", label);
13661389
emit_native_jump_helper(emit, label, true);
13671390
ASM_JUMP_IF_REG_NONZERO(emit->as, REG_RET, label);
13681391
emit_post(emit);
13691392
}
13701393

13711394
STATIC void emit_native_pop_jump_if_false(emit_t *emit, mp_uint_t label) {
1395+
DEBUG_printf("pop_jump_if_false(label=" UINT_FMT ")\n", label);
13721396
emit_native_jump_helper(emit, label, true);
13731397
ASM_JUMP_IF_REG_ZERO(emit->as, REG_RET, label);
13741398
emit_post(emit);
13751399
}
13761400

13771401
STATIC void emit_native_jump_if_true_or_pop(emit_t *emit, mp_uint_t label) {
1402+
DEBUG_printf("jump_if_true_or_pop(label=" UINT_FMT ")\n", label);
13781403
emit_native_jump_helper(emit, label, false);
13791404
ASM_JUMP_IF_REG_NONZERO(emit->as, REG_RET, label);
13801405
adjust_stack(emit, -1);
13811406
emit_post(emit);
13821407
}
13831408

13841409
STATIC void emit_native_jump_if_false_or_pop(emit_t *emit, mp_uint_t label) {
1410+
DEBUG_printf("jump_if_false_or_pop(label=" UINT_FMT ")\n", label);
13851411
emit_native_jump_helper(emit, label, false);
13861412
ASM_JUMP_IF_REG_ZERO(emit->as, REG_RET, label);
13871413
adjust_stack(emit, -1);
@@ -1470,19 +1496,20 @@ STATIC void emit_native_pop_except(emit_t *emit) {
14701496
}
14711497

14721498
STATIC void emit_native_unary_op(emit_t *emit, mp_unary_op_t op) {
1499+
vtype_kind_t vtype;
1500+
emit_pre_pop_reg(emit, &vtype, REG_ARG_2);
1501+
assert(vtype == VTYPE_PYOBJ);
14731502
if (op == MP_UNARY_OP_NOT) {
1474-
// we need to synthesise this operation
1475-
assert(0);
1476-
} else {
1477-
vtype_kind_t vtype;
1478-
emit_pre_pop_reg(emit, &vtype, REG_ARG_2);
1479-
assert(vtype == VTYPE_PYOBJ);
1480-
emit_call_with_imm_arg(emit, MP_F_UNARY_OP, op, REG_ARG_1);
1481-
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
1503+
// we need to synthesise this operation by converting to bool first
1504+
emit_call_with_imm_arg(emit, MP_F_UNARY_OP, MP_UNARY_OP_BOOL, REG_ARG_1);
1505+
ASM_MOV_REG_TO_REG(emit->as, REG_RET, REG_ARG_2);
14821506
}
1507+
emit_call_with_imm_arg(emit, MP_F_UNARY_OP, op, REG_ARG_1);
1508+
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
14831509
}
14841510

14851511
STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) {
1512+
DEBUG_printf("binary_op(" UINT_FMT ")\n", op);
14861513
vtype_kind_t vtype_lhs, vtype_rhs;
14871514
emit_pre_pop_reg_reg(emit, &vtype_rhs, REG_ARG_3, &vtype_lhs, REG_ARG_2);
14881515
if (vtype_lhs == VTYPE_INT && vtype_rhs == VTYPE_INT) {
@@ -1524,7 +1551,19 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) {
15241551
assert(0);
15251552
}
15261553
} else if (vtype_lhs == VTYPE_PYOBJ && vtype_rhs == VTYPE_PYOBJ) {
1554+
bool invert = false;
1555+
if (op == MP_BINARY_OP_NOT_IN) {
1556+
invert = true;
1557+
op = MP_BINARY_OP_IN;
1558+
} else if (op == MP_BINARY_OP_IS_NOT) {
1559+
invert = true;
1560+
op = MP_BINARY_OP_IS;
1561+
}
15271562
emit_call_with_imm_arg(emit, MP_F_BINARY_OP, op, REG_ARG_1);
1563+
if (invert) {
1564+
ASM_MOV_REG_TO_REG(emit->as, REG_RET, REG_ARG_2);
1565+
emit_call_with_imm_arg(emit, MP_F_UNARY_OP, MP_UNARY_OP_NOT, REG_ARG_1);
1566+
}
15281567
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
15291568
} else {
15301569
printf("ViperTypeError: can't do binary op between types %d and %d\n", vtype_lhs, vtype_rhs);
@@ -1664,6 +1703,8 @@ STATIC void emit_native_make_closure(emit_t *emit, scope_t *scope, mp_uint_t n_c
16641703
}
16651704

16661705
STATIC void emit_native_call_function(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) {
1706+
DEBUG_printf("call_function(n_pos=" UINT_FMT ", n_kw=" UINT_FMT ", star_flags=" UINT_FMT ")\n", n_positional, n_keyword, star_flags);
1707+
16671708
// call special viper runtime routine with type info for args, and wanted type info for return
16681709
assert(!star_flags);
16691710

py/objbool.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,16 @@ STATIC mp_obj_t bool_unary_op(mp_uint_t op, mp_obj_t o_in) {
7474
case MP_UNARY_OP_BOOL: return o_in;
7575
case MP_UNARY_OP_POSITIVE: return MP_OBJ_NEW_SMALL_INT(value);
7676
case MP_UNARY_OP_NEGATIVE: return MP_OBJ_NEW_SMALL_INT(-value);
77-
case MP_UNARY_OP_INVERT:
77+
case MP_UNARY_OP_INVERT: return MP_OBJ_NEW_SMALL_INT(~value);
78+
79+
// only bool needs to implement MP_UNARY_OP_NOT
80+
case MP_UNARY_OP_NOT:
7881
default: // no other cases
79-
return MP_OBJ_NEW_SMALL_INT(~value);
82+
if (value) {
83+
return mp_const_false;
84+
} else {
85+
return mp_const_true;
86+
}
8087
}
8188
}
8289

py/runtime0.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ typedef enum {
5151
MP_UNARY_OP_POSITIVE,
5252
MP_UNARY_OP_NEGATIVE,
5353
MP_UNARY_OP_INVERT,
54-
// these are not supported by the runtime and must be synthesised by the emitter
54+
// The NOT op is only implemented by bool. The emitter must synthesise NOT
55+
// for other types by calling BOOL then inverting (eg by then calling NOT).
5556
MP_UNARY_OP_NOT,
5657
} mp_unary_op_t;
5758

tests/basics/containment.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44
print("{} not in {}: {}".format(i, o, i not in o))
55

66
haystack = "supercalifragilistc"
7-
for needle in (haystack[i:] for i in range(len(haystack))):
7+
for needle in [haystack[i:] for i in range(len(haystack))]:
88
print(needle, "in", haystack, "::", needle in haystack)
99
print(needle, "not in", haystack, "::", needle not in haystack)
1010
print(haystack, "in", needle, "::", haystack in needle)
1111
print(haystack, "not in", needle, "::", haystack not in needle)
12-
for needle in (haystack[:i+1] for i in range(len(haystack))):
12+
for needle in [haystack[:i+1] for i in range(len(haystack))]:
1313
print(needle, "in", haystack, "::", needle in haystack)
1414
print(needle, "not in", haystack, "::", needle not in haystack)
1515
print(haystack, "in", needle, "::", haystack in needle)

tests/run-tests

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,9 @@ def run_tests(pyb, tests, args):
4545
# Some tests are known to fail with native emitter
4646
# Remove them from the below when they work
4747
if args.emit == 'native':
48-
skip_tests.update({'basics/%s.py' % t for t in 'bytes_gen class_store_class class_super class_super_object closure1 closure2 closure_defargs compare_multi containment del_deref del_local fun3 fun_calldblstar fun_callstar fun_callstardblstar fun_defargs fun_defargs2 fun_kwargs fun_kwonly fun_kwonlydef fun_kwvarargs fun_varargs gen_yield_from gen_yield_from_close gen_yield_from_ducktype gen_yield_from_exc gen_yield_from_iter gen_yield_from_send gen_yield_from_throw generator1 generator2 generator_args generator_close generator_closure generator_exc generator_return generator_send globals_del is_isnot string_format string_join subclass_native2_list subclass_native2_tuple try2 try_finally1 try_finally_loops try_finally_return try_reraise try_reraise2 unary_op unboundlocal with1 with_break with_continue with_return'.split()})
48+
skip_tests.update({'basics/%s.py' % t for t in 'bytes_gen class_store_class class_super class_super_object closure1 closure2 closure_defargs del_deref del_local fun3 fun_calldblstar fun_callstar fun_callstardblstar fun_defargs fun_defargs2 fun_kwargs fun_kwonly fun_kwonlydef fun_kwvarargs fun_varargs gen_yield_from gen_yield_from_close gen_yield_from_ducktype gen_yield_from_exc gen_yield_from_iter gen_yield_from_send gen_yield_from_throw generator1 generator2 generator_args generator_close generator_closure generator_exc generator_return generator_send globals_del string_format string_join subclass_native2_list subclass_native2_tuple try2 try_finally1 try_finally_loops try_finally_return try_reraise try_reraise2 unboundlocal with1 with_break with_continue with_return'.split()})
4949
skip_tests.add('float/string_format.py')
5050
skip_tests.add('import/gen_context.py')
51-
skip_tests.add('import/import_pkg1.py')
5251
skip_tests.add('io/file_with.py')
5352
skip_tests.add('micropython/heapalloc.py')
5453
skip_tests.add('misc/features.py')

0 commit comments

Comments
 (0)