Skip to content

Commit 21ca2d7

Browse files
committed
py: Partially fix viper multi-comparison; add test for it.
1 parent 9c9db3a commit 21ca2d7

File tree

3 files changed

+57
-4
lines changed

3 files changed

+57
-4
lines changed

py/emitnative.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,7 @@ struct _emit_t {
507507

508508
mp_uint_t stack_info_alloc;
509509
stack_info_t *stack_info;
510+
vtype_kind_t saved_stack_vtype;
510511

511512
int stack_start;
512513
int stack_size;
@@ -714,15 +715,23 @@ STATIC bool emit_native_last_emit_was_return_value(emit_t *emit) {
714715
}
715716

716717
STATIC void adjust_stack(emit_t *emit, mp_int_t stack_size_delta) {
717-
DEBUG_printf(" adjust_stack; stack_size=%d, delta=%d\n", emit->stack_size, stack_size_delta);
718718
assert((mp_int_t)emit->stack_size + stack_size_delta >= 0);
719719
emit->stack_size += stack_size_delta;
720720
if (emit->pass > MP_PASS_SCOPE && emit->stack_size > emit->scope->stack_size) {
721721
emit->scope->stack_size = emit->stack_size;
722722
}
723+
#ifdef DEBUG_PRINT
724+
DEBUG_printf(" adjust_stack; stack_size=%d+%d; stack now:", emit->stack_size - stack_size_delta, stack_size_delta);
725+
for (int i = 0; i < emit->stack_size; i++) {
726+
stack_info_t *si = &emit->stack_info[i];
727+
DEBUG_printf(" (v=%d k=%d %d)", si->vtype, si->kind, si->u_reg);
728+
}
729+
DEBUG_printf("\n");
730+
#endif
723731
}
724732

725733
STATIC void emit_native_adjust_stack_size(emit_t *emit, mp_int_t delta) {
734+
DEBUG_printf("adjust_stack_size(" INT_FMT ")\n", delta);
726735
// If we are adjusting the stack in a positive direction (pushing) then we
727736
// need to fill in values for the stack kind and vtype of the newly-pushed
728737
// entries. These should be set to "value" (ie not reg or imm) because we
@@ -731,7 +740,13 @@ STATIC void emit_native_adjust_stack_size(emit_t *emit, mp_int_t delta) {
731740
for (mp_int_t i = 0; i < delta; i++) {
732741
stack_info_t *si = &emit->stack_info[emit->stack_size + i];
733742
si->kind = STACK_VALUE;
734-
si->vtype = VTYPE_PYOBJ; // XXX we don't know the vtype...
743+
// TODO we don't know the vtype to use here. At the moment this is a
744+
// hack to get the case of multi comparison working.
745+
if (delta == 1) {
746+
si->vtype = emit->saved_stack_vtype;
747+
} else {
748+
si->vtype = VTYPE_PYOBJ;
749+
}
735750
}
736751
adjust_stack(emit, delta);
737752
}
@@ -1175,6 +1190,7 @@ STATIC void emit_native_load_null(emit_t *emit) {
11751190
}
11761191

11771192
STATIC void emit_native_load_fast(emit_t *emit, qstr qst, mp_uint_t id_flags, mp_uint_t local_num) {
1193+
DEBUG_printf("load_fast(%s, " UINT_FMT ", " UINT_FMT ")\n", qstr_str(qst), id_flags, local_num);
11781194
vtype_kind_t vtype = emit->local_vtype[local_num];
11791195
if (vtype == VTYPE_UNBOUND) {
11801196
printf("ViperTypeError: local %s used before type known\n", qstr_str(qst));
@@ -1657,8 +1673,9 @@ STATIC void emit_native_delete_subscr(emit_t *emit) {
16571673
STATIC void emit_native_dup_top(emit_t *emit) {
16581674
DEBUG_printf("dup_top\n");
16591675
vtype_kind_t vtype;
1660-
emit_pre_pop_reg(emit, &vtype, REG_TEMP0);
1661-
emit_post_push_reg_reg(emit, vtype, REG_TEMP0, vtype, REG_TEMP0);
1676+
int reg = REG_TEMP0;
1677+
emit_pre_pop_reg_flexible(emit, &vtype, &reg, -1, -1);
1678+
emit_post_push_reg_reg(emit, vtype, reg, vtype, reg);
16621679
}
16631680

16641681
STATIC void emit_native_dup_top_two(emit_t *emit) {
@@ -1718,6 +1735,11 @@ STATIC void emit_native_jump_helper(emit_t *emit, mp_uint_t label, bool pop) {
17181735
printf("ViperTypeError: expecting a bool or pyobj, got %d\n", vtype);
17191736
assert(0);
17201737
}
1738+
// For non-pop need to save the vtype so that emit_native_adjust_stack_size
1739+
// can use it. This is a bit of a hack.
1740+
if (!pop) {
1741+
emit->saved_stack_vtype = vtype;
1742+
}
17211743
// need to commit stack because we may jump elsewhere
17221744
need_stack_settled(emit);
17231745
}
@@ -1907,6 +1929,7 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) {
19071929
// MP_BINARY_OP_LESS_EQUAL
19081930
// MP_BINARY_OP_MORE_EQUAL
19091931
// MP_BINARY_OP_NOT_EQUAL
1932+
need_reg_single(emit, REG_RET, 0);
19101933
#if N_X64
19111934
asm_x64_xor_r64_r64(emit->as, REG_RET, REG_RET);
19121935
asm_x64_cmp_r64_with_r64(emit->as, reg_rhs, REG_ARG_2);
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# test multi comparison operators
2+
@micropython.viper
3+
def f(x:int, y:int):
4+
if 0 < x < y:
5+
print(x, "<", y)
6+
if 3 > x > y:
7+
print(x, ">", y)
8+
if 1 == x == y:
9+
print(x, "==", y)
10+
if -2 == x <= y:
11+
print(x, "<=", y)
12+
if 2 == x >= y:
13+
print(x, ">=", y)
14+
if 2 == x != y:
15+
print(x, "!=", y)
16+
17+
f(1, 1)
18+
f(2, 1)
19+
f(1, 2)
20+
f(2, -1)
21+
f(-2, 1)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
1 == 1
2+
2 > 1
3+
2 >= 1
4+
2 != 1
5+
1 < 2
6+
2 > -1
7+
2 >= -1
8+
2 != -1
9+
-2 <= 1

0 commit comments

Comments
 (0)