Skip to content

Commit

Permalink
py/runtime: Reorder some binary ops so they don't require conditionals.
Browse files Browse the repository at this point in the history
runtime0.h is part of the MicroPython ABI so it's simpler if it's
independent of config options, like MICROPY_PY_REVERSE_SPECIAL_METHODS.

What's effectively done here is to move MP_BINARY_OP_DIVMOD and
MP_BINARY_OP_CONTAINS up in the enum, then remove the #if
MICROPY_PY_REVERSE_SPECIAL_METHODS conditional.

Without this change .mpy files would need to have a feature flag for
MICROPY_PY_REVERSE_SPECIAL_METHODS (when embedding native code that uses
this enum).

This commit has no effect when MICROPY_PY_REVERSE_SPECIAL_METHODS is
disabled.  With this option enabled this commit reduces code size by about
60 bytes.
  • Loading branch information
dpgeorge committed Oct 29, 2019
1 parent 25946d1 commit 323d478
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 31 deletions.
13 changes: 7 additions & 6 deletions py/runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -570,16 +570,17 @@ mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) {
}

#if MICROPY_PY_REVERSE_SPECIAL_METHODS
if (op >= MP_BINARY_OP_OR && op <= MP_BINARY_OP_REVERSE_POWER) {
if (op >= MP_BINARY_OP_OR && op <= MP_BINARY_OP_POWER) {
mp_obj_t t = rhs;
rhs = lhs;
lhs = t;
if (op <= MP_BINARY_OP_POWER) {
op += MP_BINARY_OP_REVERSE_OR - MP_BINARY_OP_OR;
goto generic_binary_op;
}

op += MP_BINARY_OP_REVERSE_OR - MP_BINARY_OP_OR;
goto generic_binary_op;
} else if (op >= MP_BINARY_OP_REVERSE_OR) {
// Convert __rop__ back to __op__ for error message
mp_obj_t t = rhs;
rhs = lhs;
lhs = t;
op -= MP_BINARY_OP_REVERSE_OR - MP_BINARY_OP_OR;
}
#endif
Expand Down
52 changes: 27 additions & 25 deletions py/runtime0.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,18 @@
#define MP_NATIVE_TYPE_PTR16 (0x06)
#define MP_NATIVE_TYPE_PTR32 (0x07)

// Bytecode and runtime boundaries for unary ops
#define MP_UNARY_OP_NUM_BYTECODE (MP_UNARY_OP_NOT + 1)
#define MP_UNARY_OP_NUM_RUNTIME (MP_UNARY_OP_SIZEOF + 1)

// Bytecode and runtime boundaries for binary ops
#define MP_BINARY_OP_NUM_BYTECODE (MP_BINARY_OP_POWER + 1)
#if MICROPY_PY_REVERSE_SPECIAL_METHODS
#define MP_BINARY_OP_NUM_RUNTIME (MP_BINARY_OP_REVERSE_POWER + 1)
#else
#define MP_BINARY_OP_NUM_RUNTIME (MP_BINARY_OP_CONTAINS + 1)
#endif

typedef enum {
// These ops may appear in the bytecode. Changing this group
// in any way requires changing the bytecode version.
Expand All @@ -55,21 +67,18 @@ typedef enum {
MP_UNARY_OP_NOT,

// Following ops cannot appear in the bytecode
MP_UNARY_OP_NUM_BYTECODE,

MP_UNARY_OP_BOOL = MP_UNARY_OP_NUM_BYTECODE, // __bool__
MP_UNARY_OP_BOOL, // __bool__
MP_UNARY_OP_LEN, // __len__
MP_UNARY_OP_HASH, // __hash__; must return a small int
MP_UNARY_OP_ABS, // __abs__
MP_UNARY_OP_INT, // __int__
MP_UNARY_OP_SIZEOF, // for sys.getsizeof()

MP_UNARY_OP_NUM_RUNTIME,
} mp_unary_op_t;

// Note: the first 9+12+12 of these are used in bytecode and changing
// them requires changing the bytecode version.
typedef enum {
// The following 9+13+13 ops are used in bytecode and changing
// them requires changing the bytecode version.

// 9 relational operations, should return a bool; order of first 6 matches corresponding mp_token_kind_t
MP_BINARY_OP_LESS,
MP_BINARY_OP_MORE,
Expand Down Expand Up @@ -113,11 +122,18 @@ typedef enum {

// Operations below this line don't appear in bytecode, they
// just identify special methods.
MP_BINARY_OP_NUM_BYTECODE,

// MP_BINARY_OP_REVERSE_* must follow immediately after MP_BINARY_OP_*
#if MICROPY_PY_REVERSE_SPECIAL_METHODS
MP_BINARY_OP_REVERSE_OR = MP_BINARY_OP_NUM_BYTECODE,
// This is not emitted by the compiler but is supported by the runtime.
// It must follow immediately after MP_BINARY_OP_POWER.
MP_BINARY_OP_DIVMOD,

// The runtime will convert MP_BINARY_OP_IN to this operator with swapped args.
// A type should implement this containment operator instead of MP_BINARY_OP_IN.
MP_BINARY_OP_CONTAINS,

// 13 MP_BINARY_OP_REVERSE_* operations must be in the same order as MP_BINARY_OP_*,
// and be the last ones supported by the runtime.
MP_BINARY_OP_REVERSE_OR,
MP_BINARY_OP_REVERSE_XOR,
MP_BINARY_OP_REVERSE_AND,
MP_BINARY_OP_REVERSE_LSHIFT,
Expand All @@ -130,20 +146,6 @@ typedef enum {
MP_BINARY_OP_REVERSE_TRUE_DIVIDE,
MP_BINARY_OP_REVERSE_MODULO,
MP_BINARY_OP_REVERSE_POWER,
#endif

// This is not emitted by the compiler but is supported by the runtime
MP_BINARY_OP_DIVMOD
#if !MICROPY_PY_REVERSE_SPECIAL_METHODS
= MP_BINARY_OP_NUM_BYTECODE
#endif
,

// The runtime will convert MP_BINARY_OP_IN to this operator with swapped args.
// A type should implement this containment operator instead of MP_BINARY_OP_IN.
MP_BINARY_OP_CONTAINS,

MP_BINARY_OP_NUM_RUNTIME,

// These 2 are not supported by the runtime and must be synthesised by the emitter
MP_BINARY_OP_NOT_IN,
Expand Down

0 comments on commit 323d478

Please sign in to comment.