Skip to content

Commit bdbe8c9

Browse files
committed
py: Make UNARY_OP_NOT a first-class op, to agree with Py not semantics.
Fixes adafruit#1684 and makes "not" match Python semantics. The code is also simplified (the separate MP_BC_NOT opcode is removed) and the patch saves 68 bytes for bare-arm/ and 52 bytes for minimal/. Previously "not x" was implemented as !mp_unary_op(x, MP_UNARY_OP_BOOL), so any given object only needs to implement MP_UNARY_OP_BOOL (and the VM had a special opcode to do the ! bit). With this patch "not x" is implemented as mp_unary_op(x, MP_UNARY_OP_NOT), but this operation is caught at the start of mp_unary_op and dispatched as !mp_obj_is_true(x). mp_obj_is_true has special logic to test for truthness, and is the correct way to handle the not operation.
1 parent e242b17 commit bdbe8c9

9 files changed

Lines changed: 12 additions & 47 deletions

File tree

py/bc0.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,6 @@
8080
#define MP_BC_POP_EXCEPT (0x45)
8181
#define MP_BC_UNWIND_JUMP (0x46) // rel byte code offset, 16-bit signed, in excess; then a byte
8282

83-
#define MP_BC_NOT (0x47)
84-
8583
#define MP_BC_BUILD_TUPLE (0x50) // uint
8684
#define MP_BC_BUILD_LIST (0x51) // uint
8785
#define MP_BC_LIST_APPEND (0x52) // uint
@@ -115,7 +113,7 @@
115113
#define MP_BC_LOAD_CONST_SMALL_INT_MULTI (0x70) // + N(64)
116114
#define MP_BC_LOAD_FAST_MULTI (0xb0) // + N(16)
117115
#define MP_BC_STORE_FAST_MULTI (0xc0) // + N(16)
118-
#define MP_BC_UNARY_OP_MULTI (0xd0) // + op(6)
119-
#define MP_BC_BINARY_OP_MULTI (0xd6) // + op(36)
116+
#define MP_BC_UNARY_OP_MULTI (0xd0) // + op(7)
117+
#define MP_BC_BINARY_OP_MULTI (0xd7) // + op(36)
120118

121119
#endif // __MICROPY_INCLUDED_PY_BC0_H__

py/emitbc.c

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -801,15 +801,8 @@ void mp_emit_bc_pop_except(emit_t *emit) {
801801
}
802802

803803
void mp_emit_bc_unary_op(emit_t *emit, mp_unary_op_t op) {
804-
if (op == MP_UNARY_OP_NOT) {
805-
emit_bc_pre(emit, 0);
806-
emit_write_bytecode_byte(emit, MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_BOOL);
807-
emit_bc_pre(emit, 0);
808-
emit_write_bytecode_byte(emit, MP_BC_NOT);
809-
} else {
810-
emit_bc_pre(emit, 0);
811-
emit_write_bytecode_byte(emit, MP_BC_UNARY_OP_MULTI + op);
812-
}
804+
emit_bc_pre(emit, 0);
805+
emit_write_bytecode_byte(emit, MP_BC_UNARY_OP_MULTI + op);
813806
}
814807

815808
void mp_emit_bc_binary_op(emit_t *emit, mp_binary_op_t op) {
@@ -825,7 +818,7 @@ void mp_emit_bc_binary_op(emit_t *emit, mp_binary_op_t op) {
825818
emit_write_bytecode_byte(emit, MP_BC_BINARY_OP_MULTI + op);
826819
if (invert) {
827820
emit_bc_pre(emit, 0);
828-
emit_write_bytecode_byte(emit, MP_BC_NOT);
821+
emit_write_bytecode_byte(emit, MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_NOT);
829822
}
830823
}
831824

py/emitnative.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2061,11 +2061,6 @@ STATIC void emit_native_unary_op(emit_t *emit, mp_unary_op_t op) {
20612061
vtype_kind_t vtype;
20622062
emit_pre_pop_reg(emit, &vtype, REG_ARG_2);
20632063
if (vtype == VTYPE_PYOBJ) {
2064-
if (op == MP_UNARY_OP_NOT) {
2065-
// we need to synthesise this operation by converting to bool first
2066-
emit_call_with_imm_arg(emit, MP_F_UNARY_OP, MP_UNARY_OP_BOOL, REG_ARG_1);
2067-
ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_RET);
2068-
}
20692064
emit_call_with_imm_arg(emit, MP_F_UNARY_OP, op, REG_ARG_1);
20702065
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
20712066
} else {

py/objbool.c

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,6 @@ STATIC mp_obj_t bool_unary_op(mp_uint_t op, mp_obj_t o_in) {
7474
case MP_UNARY_OP_POSITIVE: return MP_OBJ_NEW_SMALL_INT(value);
7575
case MP_UNARY_OP_NEGATIVE: return MP_OBJ_NEW_SMALL_INT(-value);
7676
case MP_UNARY_OP_INVERT: return MP_OBJ_NEW_SMALL_INT(~value);
77-
78-
// only bool needs to implement MP_UNARY_OP_NOT
79-
case MP_UNARY_OP_NOT:
80-
if (value) {
81-
return mp_const_false;
82-
} else {
83-
return mp_const_true;
84-
}
85-
8677
default: return MP_OBJ_NULL; // op not supported
8778
}
8879
}

py/runtime.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,10 @@ void mp_delete_global(qstr qst) {
184184
mp_obj_t mp_unary_op(mp_uint_t op, mp_obj_t arg) {
185185
DEBUG_OP_printf("unary " UINT_FMT " %p\n", op, arg);
186186

187-
if (MP_OBJ_IS_SMALL_INT(arg)) {
187+
if (op == MP_UNARY_OP_NOT) {
188+
// "not x" is the negative of whether "x" is true per Python semantics
189+
return mp_obj_new_bool(mp_obj_is_true(arg) == 0);
190+
} else if (MP_OBJ_IS_SMALL_INT(arg)) {
188191
mp_int_t val = MP_OBJ_SMALL_INT_VALUE(arg);
189192
switch (op) {
190193
case MP_UNARY_OP_BOOL:

py/runtime0.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,6 @@ typedef enum {
4545
MP_UNARY_OP_POSITIVE,
4646
MP_UNARY_OP_NEGATIVE,
4747
MP_UNARY_OP_INVERT,
48-
// The NOT op is only implemented by bool. The emitter must synthesise NOT
49-
// for other types by calling BOOL then inverting (eg by then calling NOT).
5048
MP_UNARY_OP_NOT,
5149
} mp_unary_op_t;
5250

py/showbc.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -399,10 +399,6 @@ const byte *mp_bytecode_print_str(const byte *ip) {
399399
printf("POP_EXCEPT");
400400
break;
401401

402-
case MP_BC_NOT:
403-
printf("NOT");
404-
break;
405-
406402
case MP_BC_BUILD_TUPLE:
407403
DECODE_UINT;
408404
printf("BUILD_TUPLE " UINT_FMT, unum);
@@ -541,7 +537,7 @@ const byte *mp_bytecode_print_str(const byte *ip) {
541537
printf("LOAD_FAST " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_LOAD_FAST_MULTI);
542538
} else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) {
543539
printf("STORE_FAST " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_STORE_FAST_MULTI);
544-
} else if (ip[-1] < MP_BC_UNARY_OP_MULTI + 6) {
540+
} else if (ip[-1] < MP_BC_UNARY_OP_MULTI + 7) {
545541
printf("UNARY_OP " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_UNARY_OP_MULTI);
546542
} else if (ip[-1] < MP_BC_BINARY_OP_MULTI + 36) {
547543
mp_uint_t op = ip[-1] - MP_BC_BINARY_OP_MULTI;

py/vm.c

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -760,14 +760,6 @@ unwind_jump:;
760760
//sp -= 3; // pop 3 exception values
761761
DISPATCH();
762762

763-
ENTRY(MP_BC_NOT):
764-
if (TOP() == mp_const_true) {
765-
SET_TOP(mp_const_false);
766-
} else {
767-
SET_TOP(mp_const_true);
768-
}
769-
DISPATCH();
770-
771763
ENTRY(MP_BC_BUILD_TUPLE): {
772764
MARK_EXC_IP_SELECTIVE();
773765
DECODE_UINT;
@@ -1230,7 +1222,7 @@ unwind_jump:;
12301222
} else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) {
12311223
fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
12321224
DISPATCH();
1233-
} else if (ip[-1] < MP_BC_UNARY_OP_MULTI + 6) {
1225+
} else if (ip[-1] < MP_BC_UNARY_OP_MULTI + 7) {
12341226
SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
12351227
DISPATCH();
12361228
} else if (ip[-1] < MP_BC_BINARY_OP_MULTI + 36) {

py/vmentrytable.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ static void* entry_table[256] = {
7676
[MP_BC_FOR_ITER] = &&entry_MP_BC_FOR_ITER,
7777
[MP_BC_POP_BLOCK] = &&entry_MP_BC_POP_BLOCK,
7878
[MP_BC_POP_EXCEPT] = &&entry_MP_BC_POP_EXCEPT,
79-
[MP_BC_NOT] = &&entry_MP_BC_NOT,
8079
[MP_BC_BUILD_TUPLE] = &&entry_MP_BC_BUILD_TUPLE,
8180
[MP_BC_BUILD_LIST] = &&entry_MP_BC_BUILD_LIST,
8281
[MP_BC_LIST_APPEND] = &&entry_MP_BC_LIST_APPEND,
@@ -110,7 +109,7 @@ static void* entry_table[256] = {
110109
[MP_BC_LOAD_CONST_SMALL_INT_MULTI ... MP_BC_LOAD_CONST_SMALL_INT_MULTI + 63] = &&entry_MP_BC_LOAD_CONST_SMALL_INT_MULTI,
111110
[MP_BC_LOAD_FAST_MULTI ... MP_BC_LOAD_FAST_MULTI + 15] = &&entry_MP_BC_LOAD_FAST_MULTI,
112111
[MP_BC_STORE_FAST_MULTI ... MP_BC_STORE_FAST_MULTI + 15] = &&entry_MP_BC_STORE_FAST_MULTI,
113-
[MP_BC_UNARY_OP_MULTI ... MP_BC_UNARY_OP_MULTI + 5] = &&entry_MP_BC_UNARY_OP_MULTI,
112+
[MP_BC_UNARY_OP_MULTI ... MP_BC_UNARY_OP_MULTI + 6] = &&entry_MP_BC_UNARY_OP_MULTI,
114113
[MP_BC_BINARY_OP_MULTI ... MP_BC_BINARY_OP_MULTI + 35] = &&entry_MP_BC_BINARY_OP_MULTI,
115114
};
116115

0 commit comments

Comments
 (0)