]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-98831: add variable stack effect support to cases generator (#101309)
authorIrit Katriel <1055913+iritkatriel@users.noreply.github.com>
Wed, 25 Jan 2023 20:41:03 +0000 (20:41 +0000)
committerGitHub <noreply@github.com>
Wed, 25 Jan 2023 20:41:03 +0000 (20:41 +0000)
Python/compile.c
Python/opcode_metadata.h
Tools/cases_generator/generate_cases.py

index 9fc997cdf525e9f204c38fe11cb230bc34e880f9..c31f08c0a1797bcd10630e0e93858f2f5cf55112 100644 (file)
@@ -36,7 +36,7 @@
 #include "pycore_pymem.h"         // _PyMem_IsPtrFreed()
 #include "pycore_symtable.h"      // PySTEntryObject
 
-#include "opcode_metadata.h"      // _PyOpcode_opcode_metadata
+#include "opcode_metadata.h"      // _PyOpcode_opcode_metadata, _PyOpcode_num_popped/pushed
 
 
 #define DEFAULT_BLOCK_SIZE 16
@@ -8651,13 +8651,15 @@ no_redundant_jumps(cfg_builder *g) {
 
 static bool
 opcode_metadata_is_sane(cfg_builder *g) {
+    bool result = true;
     for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
         for (int i = 0; i < b->b_iused; i++) {
             struct instr *instr = &b->b_instr[i];
             int opcode = instr->i_opcode;
+            int oparg = instr->i_oparg;
             assert(opcode <= MAX_REAL_OPCODE);
-            int pushed = _PyOpcode_opcode_metadata[opcode].n_pushed;
-            int popped = _PyOpcode_opcode_metadata[opcode].n_popped;
+            int popped = _PyOpcode_num_popped(opcode, oparg);
+            int pushed = _PyOpcode_num_pushed(opcode, oparg);
             assert((pushed < 0) == (popped < 0));
             if (pushed >= 0) {
                 assert(_PyOpcode_opcode_metadata[opcode].valid_entry);
@@ -8666,12 +8668,12 @@ opcode_metadata_is_sane(cfg_builder *g) {
                    fprintf(stderr,
                            "op=%d: stack_effect (%d) != pushed (%d) - popped (%d)\n",
                            opcode, effect, pushed, popped);
-                   return false;
+                   result = false;
                 }
             }
         }
     }
-    return true;
+    return result;
 }
 
 static bool
index f9c640187afe09db16e5904836caa0c3d44a0ce8..46fd9673e8fb64460232b699da040a41b78d2faf 100644 (file)
 // This file is generated by Tools/cases_generator/generate_cases.py --metadata
 // from Python/bytecodes.c
 // Do not edit!
+
+static int
+_PyOpcode_num_popped(int opcode, int oparg) {
+    switch(opcode) {
+        case NOP:
+            return 0;
+        case RESUME:
+            return 0;
+        case LOAD_CLOSURE:
+            return 0;
+        case LOAD_FAST_CHECK:
+            return 0;
+        case LOAD_FAST:
+            return 0;
+        case LOAD_CONST:
+            return 0;
+        case STORE_FAST:
+            return 1;
+        case LOAD_FAST__LOAD_FAST:
+            return 0+0;
+        case LOAD_FAST__LOAD_CONST:
+            return 0+0;
+        case STORE_FAST__LOAD_FAST:
+            return 1+0;
+        case STORE_FAST__STORE_FAST:
+            return 1+1;
+        case LOAD_CONST__LOAD_FAST:
+            return 0+0;
+        case POP_TOP:
+            return 1;
+        case PUSH_NULL:
+            return 0;
+        case END_FOR:
+            return 1+1;
+        case UNARY_NEGATIVE:
+            return 1;
+        case UNARY_NOT:
+            return 1;
+        case UNARY_INVERT:
+            return 1;
+        case BINARY_OP_MULTIPLY_INT:
+            return 2;
+        case BINARY_OP_MULTIPLY_FLOAT:
+            return 2;
+        case BINARY_OP_SUBTRACT_INT:
+            return 2;
+        case BINARY_OP_SUBTRACT_FLOAT:
+            return 2;
+        case BINARY_OP_ADD_UNICODE:
+            return 2;
+        case BINARY_OP_INPLACE_ADD_UNICODE:
+            return 2;
+        case BINARY_OP_ADD_FLOAT:
+            return 2;
+        case BINARY_OP_ADD_INT:
+            return 2;
+        case BINARY_SUBSCR:
+            return 2;
+        case BINARY_SLICE:
+            return 3;
+        case STORE_SLICE:
+            return 4;
+        case BINARY_SUBSCR_LIST_INT:
+            return 2;
+        case BINARY_SUBSCR_TUPLE_INT:
+            return 2;
+        case BINARY_SUBSCR_DICT:
+            return 2;
+        case BINARY_SUBSCR_GETITEM:
+            return 2;
+        case LIST_APPEND:
+            return (oparg-1) + 2;
+        case SET_ADD:
+            return (oparg-1) + 2;
+        case STORE_SUBSCR:
+            return 3;
+        case STORE_SUBSCR_LIST_INT:
+            return 3;
+        case STORE_SUBSCR_DICT:
+            return 3;
+        case DELETE_SUBSCR:
+            return 2;
+        case CALL_INTRINSIC_1:
+            return 1;
+        case RAISE_VARARGS:
+            return -1;
+        case INTERPRETER_EXIT:
+            return 1;
+        case RETURN_VALUE:
+            return 1;
+        case GET_AITER:
+            return 1;
+        case GET_ANEXT:
+            return 1;
+        case GET_AWAITABLE:
+            return 1;
+        case SEND:
+            return -1;
+        case YIELD_VALUE:
+            return 1;
+        case POP_EXCEPT:
+            return 1;
+        case RERAISE:
+            return -1;
+        case PREP_RERAISE_STAR:
+            return 2;
+        case END_ASYNC_FOR:
+            return -1;
+        case CLEANUP_THROW:
+            return -1;
+        case LOAD_ASSERTION_ERROR:
+            return 0;
+        case LOAD_BUILD_CLASS:
+            return 0;
+        case STORE_NAME:
+            return 1;
+        case DELETE_NAME:
+            return 0;
+        case UNPACK_SEQUENCE:
+            return -1;
+        case UNPACK_SEQUENCE_TWO_TUPLE:
+            return -1;
+        case UNPACK_SEQUENCE_TUPLE:
+            return -1;
+        case UNPACK_SEQUENCE_LIST:
+            return -1;
+        case UNPACK_EX:
+            return -1;
+        case STORE_ATTR:
+            return 2;
+        case DELETE_ATTR:
+            return 1;
+        case STORE_GLOBAL:
+            return 1;
+        case DELETE_GLOBAL:
+            return 0;
+        case LOAD_NAME:
+            return 0;
+        case LOAD_GLOBAL:
+            return -1;
+        case LOAD_GLOBAL_MODULE:
+            return -1;
+        case LOAD_GLOBAL_BUILTIN:
+            return -1;
+        case DELETE_FAST:
+            return 0;
+        case MAKE_CELL:
+            return 0;
+        case DELETE_DEREF:
+            return 0;
+        case LOAD_CLASSDEREF:
+            return 0;
+        case LOAD_DEREF:
+            return 0;
+        case STORE_DEREF:
+            return 1;
+        case COPY_FREE_VARS:
+            return 0;
+        case BUILD_STRING:
+            return oparg;
+        case BUILD_TUPLE:
+            return oparg;
+        case BUILD_LIST:
+            return oparg;
+        case LIST_EXTEND:
+            return (oparg-1) + 2;
+        case SET_UPDATE:
+            return (oparg-1) + 2;
+        case BUILD_SET:
+            return oparg;
+        case BUILD_MAP:
+            return oparg*2;
+        case SETUP_ANNOTATIONS:
+            return 0;
+        case BUILD_CONST_KEY_MAP:
+            return oparg + 1;
+        case DICT_UPDATE:
+            return 1;
+        case DICT_MERGE:
+            return 1;
+        case MAP_ADD:
+            return 2;
+        case LOAD_ATTR:
+            return -1;
+        case LOAD_ATTR_INSTANCE_VALUE:
+            return -1;
+        case LOAD_ATTR_MODULE:
+            return -1;
+        case LOAD_ATTR_WITH_HINT:
+            return -1;
+        case LOAD_ATTR_SLOT:
+            return -1;
+        case LOAD_ATTR_CLASS:
+            return -1;
+        case LOAD_ATTR_PROPERTY:
+            return -1;
+        case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN:
+            return -1;
+        case STORE_ATTR_INSTANCE_VALUE:
+            return 2;
+        case STORE_ATTR_WITH_HINT:
+            return 2;
+        case STORE_ATTR_SLOT:
+            return 2;
+        case COMPARE_OP:
+            return 2;
+        case COMPARE_AND_BRANCH:
+            return 2;
+        case COMPARE_AND_BRANCH_FLOAT:
+            return 2;
+        case COMPARE_AND_BRANCH_INT:
+            return 2;
+        case COMPARE_AND_BRANCH_STR:
+            return 2;
+        case IS_OP:
+            return 2;
+        case CONTAINS_OP:
+            return 2;
+        case CHECK_EG_MATCH:
+            return 2;
+        case CHECK_EXC_MATCH:
+            return 2;
+        case IMPORT_NAME:
+            return 2;
+        case IMPORT_FROM:
+            return 1;
+        case JUMP_FORWARD:
+            return 0;
+        case JUMP_BACKWARD:
+            return 0;
+        case POP_JUMP_IF_FALSE:
+            return -1;
+        case POP_JUMP_IF_TRUE:
+            return -1;
+        case POP_JUMP_IF_NOT_NONE:
+            return -1;
+        case POP_JUMP_IF_NONE:
+            return -1;
+        case JUMP_IF_FALSE_OR_POP:
+            return -1;
+        case JUMP_IF_TRUE_OR_POP:
+            return -1;
+        case JUMP_BACKWARD_NO_INTERRUPT:
+            return -1;
+        case GET_LEN:
+            return -1;
+        case MATCH_CLASS:
+            return 3;
+        case MATCH_MAPPING:
+            return 1;
+        case MATCH_SEQUENCE:
+            return 1;
+        case MATCH_KEYS:
+            return 2;
+        case GET_ITER:
+            return -1;
+        case GET_YIELD_FROM_ITER:
+            return -1;
+        case FOR_ITER:
+            return -1;
+        case FOR_ITER_LIST:
+            return -1;
+        case FOR_ITER_TUPLE:
+            return -1;
+        case FOR_ITER_RANGE:
+            return -1;
+        case FOR_ITER_GEN:
+            return -1;
+        case BEFORE_ASYNC_WITH:
+            return -1;
+        case BEFORE_WITH:
+            return -1;
+        case WITH_EXCEPT_START:
+            return 4;
+        case PUSH_EXC_INFO:
+            return -1;
+        case LOAD_ATTR_METHOD_WITH_VALUES:
+            return -1;
+        case LOAD_ATTR_METHOD_NO_DICT:
+            return -1;
+        case LOAD_ATTR_METHOD_LAZY_DICT:
+            return -1;
+        case CALL_BOUND_METHOD_EXACT_ARGS:
+            return -1;
+        case KW_NAMES:
+            return -1;
+        case CALL:
+            return -1;
+        case CALL_PY_EXACT_ARGS:
+            return -1;
+        case CALL_PY_WITH_DEFAULTS:
+            return -1;
+        case CALL_NO_KW_TYPE_1:
+            return -1;
+        case CALL_NO_KW_STR_1:
+            return -1;
+        case CALL_NO_KW_TUPLE_1:
+            return -1;
+        case CALL_BUILTIN_CLASS:
+            return -1;
+        case CALL_NO_KW_BUILTIN_O:
+            return -1;
+        case CALL_NO_KW_BUILTIN_FAST:
+            return -1;
+        case CALL_BUILTIN_FAST_WITH_KEYWORDS:
+            return -1;
+        case CALL_NO_KW_LEN:
+            return -1;
+        case CALL_NO_KW_ISINSTANCE:
+            return -1;
+        case CALL_NO_KW_LIST_APPEND:
+            return -1;
+        case CALL_NO_KW_METHOD_DESCRIPTOR_O:
+            return -1;
+        case CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS:
+            return -1;
+        case CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS:
+            return -1;
+        case CALL_NO_KW_METHOD_DESCRIPTOR_FAST:
+            return -1;
+        case CALL_FUNCTION_EX:
+            return -1;
+        case MAKE_FUNCTION:
+            return -1;
+        case RETURN_GENERATOR:
+            return -1;
+        case BUILD_SLICE:
+            return -1;
+        case FORMAT_VALUE:
+            return -1;
+        case COPY:
+            return -1;
+        case BINARY_OP:
+            return 2;
+        case SWAP:
+            return -1;
+        case EXTENDED_ARG:
+            return -1;
+        case CACHE:
+            return -1;
+        default:
+            Py_UNREACHABLE();
+    }
+}
+
+static int
+_PyOpcode_num_pushed(int opcode, int oparg) {
+    switch(opcode) {
+        case NOP:
+            return 0;
+        case RESUME:
+            return 0;
+        case LOAD_CLOSURE:
+            return 1;
+        case LOAD_FAST_CHECK:
+            return 1;
+        case LOAD_FAST:
+            return 1;
+        case LOAD_CONST:
+            return 1;
+        case STORE_FAST:
+            return 0;
+        case LOAD_FAST__LOAD_FAST:
+            return 1+1;
+        case LOAD_FAST__LOAD_CONST:
+            return 1+1;
+        case STORE_FAST__LOAD_FAST:
+            return 0+1;
+        case STORE_FAST__STORE_FAST:
+            return 0+0;
+        case LOAD_CONST__LOAD_FAST:
+            return 1+1;
+        case POP_TOP:
+            return 0;
+        case PUSH_NULL:
+            return 1;
+        case END_FOR:
+            return 0+0;
+        case UNARY_NEGATIVE:
+            return 1;
+        case UNARY_NOT:
+            return 1;
+        case UNARY_INVERT:
+            return 1;
+        case BINARY_OP_MULTIPLY_INT:
+            return 1;
+        case BINARY_OP_MULTIPLY_FLOAT:
+            return 1;
+        case BINARY_OP_SUBTRACT_INT:
+            return 1;
+        case BINARY_OP_SUBTRACT_FLOAT:
+            return 1;
+        case BINARY_OP_ADD_UNICODE:
+            return 1;
+        case BINARY_OP_INPLACE_ADD_UNICODE:
+            return 0;
+        case BINARY_OP_ADD_FLOAT:
+            return 1;
+        case BINARY_OP_ADD_INT:
+            return 1;
+        case BINARY_SUBSCR:
+            return 1;
+        case BINARY_SLICE:
+            return 1;
+        case STORE_SLICE:
+            return 0;
+        case BINARY_SUBSCR_LIST_INT:
+            return 1;
+        case BINARY_SUBSCR_TUPLE_INT:
+            return 1;
+        case BINARY_SUBSCR_DICT:
+            return 1;
+        case BINARY_SUBSCR_GETITEM:
+            return 1;
+        case LIST_APPEND:
+            return (oparg-1) + 1;
+        case SET_ADD:
+            return (oparg-1) + 1;
+        case STORE_SUBSCR:
+            return 0;
+        case STORE_SUBSCR_LIST_INT:
+            return 0;
+        case STORE_SUBSCR_DICT:
+            return 0;
+        case DELETE_SUBSCR:
+            return 0;
+        case CALL_INTRINSIC_1:
+            return 1;
+        case RAISE_VARARGS:
+            return -1;
+        case INTERPRETER_EXIT:
+            return 0;
+        case RETURN_VALUE:
+            return 0;
+        case GET_AITER:
+            return 1;
+        case GET_ANEXT:
+            return 2;
+        case GET_AWAITABLE:
+            return 1;
+        case SEND:
+            return -1;
+        case YIELD_VALUE:
+            return 1;
+        case POP_EXCEPT:
+            return 0;
+        case RERAISE:
+            return -1;
+        case PREP_RERAISE_STAR:
+            return 1;
+        case END_ASYNC_FOR:
+            return -1;
+        case CLEANUP_THROW:
+            return -1;
+        case LOAD_ASSERTION_ERROR:
+            return 1;
+        case LOAD_BUILD_CLASS:
+            return 1;
+        case STORE_NAME:
+            return 0;
+        case DELETE_NAME:
+            return 0;
+        case UNPACK_SEQUENCE:
+            return -1;
+        case UNPACK_SEQUENCE_TWO_TUPLE:
+            return -1;
+        case UNPACK_SEQUENCE_TUPLE:
+            return -1;
+        case UNPACK_SEQUENCE_LIST:
+            return -1;
+        case UNPACK_EX:
+            return -1;
+        case STORE_ATTR:
+            return 0;
+        case DELETE_ATTR:
+            return 0;
+        case STORE_GLOBAL:
+            return 0;
+        case DELETE_GLOBAL:
+            return 0;
+        case LOAD_NAME:
+            return 1;
+        case LOAD_GLOBAL:
+            return -1;
+        case LOAD_GLOBAL_MODULE:
+            return -1;
+        case LOAD_GLOBAL_BUILTIN:
+            return -1;
+        case DELETE_FAST:
+            return 0;
+        case MAKE_CELL:
+            return 0;
+        case DELETE_DEREF:
+            return 0;
+        case LOAD_CLASSDEREF:
+            return 1;
+        case LOAD_DEREF:
+            return 1;
+        case STORE_DEREF:
+            return 0;
+        case COPY_FREE_VARS:
+            return 0;
+        case BUILD_STRING:
+            return 1;
+        case BUILD_TUPLE:
+            return 1;
+        case BUILD_LIST:
+            return 1;
+        case LIST_EXTEND:
+            return (oparg-1) + 1;
+        case SET_UPDATE:
+            return (oparg-1) + 1;
+        case BUILD_SET:
+            return 1;
+        case BUILD_MAP:
+            return 1;
+        case SETUP_ANNOTATIONS:
+            return 0;
+        case BUILD_CONST_KEY_MAP:
+            return 1;
+        case DICT_UPDATE:
+            return 0;
+        case DICT_MERGE:
+            return 0;
+        case MAP_ADD:
+            return 0;
+        case LOAD_ATTR:
+            return -1;
+        case LOAD_ATTR_INSTANCE_VALUE:
+            return -1;
+        case LOAD_ATTR_MODULE:
+            return -1;
+        case LOAD_ATTR_WITH_HINT:
+            return -1;
+        case LOAD_ATTR_SLOT:
+            return -1;
+        case LOAD_ATTR_CLASS:
+            return -1;
+        case LOAD_ATTR_PROPERTY:
+            return -1;
+        case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN:
+            return -1;
+        case STORE_ATTR_INSTANCE_VALUE:
+            return 0;
+        case STORE_ATTR_WITH_HINT:
+            return 0;
+        case STORE_ATTR_SLOT:
+            return 0;
+        case COMPARE_OP:
+            return 1;
+        case COMPARE_AND_BRANCH:
+            return 0;
+        case COMPARE_AND_BRANCH_FLOAT:
+            return 0;
+        case COMPARE_AND_BRANCH_INT:
+            return 0;
+        case COMPARE_AND_BRANCH_STR:
+            return 0;
+        case IS_OP:
+            return 1;
+        case CONTAINS_OP:
+            return 1;
+        case CHECK_EG_MATCH:
+            return 2;
+        case CHECK_EXC_MATCH:
+            return 2;
+        case IMPORT_NAME:
+            return 1;
+        case IMPORT_FROM:
+            return 2;
+        case JUMP_FORWARD:
+            return 0;
+        case JUMP_BACKWARD:
+            return 0;
+        case POP_JUMP_IF_FALSE:
+            return -1;
+        case POP_JUMP_IF_TRUE:
+            return -1;
+        case POP_JUMP_IF_NOT_NONE:
+            return -1;
+        case POP_JUMP_IF_NONE:
+            return -1;
+        case JUMP_IF_FALSE_OR_POP:
+            return -1;
+        case JUMP_IF_TRUE_OR_POP:
+            return -1;
+        case JUMP_BACKWARD_NO_INTERRUPT:
+            return -1;
+        case GET_LEN:
+            return -1;
+        case MATCH_CLASS:
+            return 1;
+        case MATCH_MAPPING:
+            return 2;
+        case MATCH_SEQUENCE:
+            return 2;
+        case MATCH_KEYS:
+            return 3;
+        case GET_ITER:
+            return -1;
+        case GET_YIELD_FROM_ITER:
+            return -1;
+        case FOR_ITER:
+            return -1;
+        case FOR_ITER_LIST:
+            return -1;
+        case FOR_ITER_TUPLE:
+            return -1;
+        case FOR_ITER_RANGE:
+            return -1;
+        case FOR_ITER_GEN:
+            return -1;
+        case BEFORE_ASYNC_WITH:
+            return -1;
+        case BEFORE_WITH:
+            return -1;
+        case WITH_EXCEPT_START:
+            return 5;
+        case PUSH_EXC_INFO:
+            return -1;
+        case LOAD_ATTR_METHOD_WITH_VALUES:
+            return -1;
+        case LOAD_ATTR_METHOD_NO_DICT:
+            return -1;
+        case LOAD_ATTR_METHOD_LAZY_DICT:
+            return -1;
+        case CALL_BOUND_METHOD_EXACT_ARGS:
+            return -1;
+        case KW_NAMES:
+            return -1;
+        case CALL:
+            return -1;
+        case CALL_PY_EXACT_ARGS:
+            return -1;
+        case CALL_PY_WITH_DEFAULTS:
+            return -1;
+        case CALL_NO_KW_TYPE_1:
+            return -1;
+        case CALL_NO_KW_STR_1:
+            return -1;
+        case CALL_NO_KW_TUPLE_1:
+            return -1;
+        case CALL_BUILTIN_CLASS:
+            return -1;
+        case CALL_NO_KW_BUILTIN_O:
+            return -1;
+        case CALL_NO_KW_BUILTIN_FAST:
+            return -1;
+        case CALL_BUILTIN_FAST_WITH_KEYWORDS:
+            return -1;
+        case CALL_NO_KW_LEN:
+            return -1;
+        case CALL_NO_KW_ISINSTANCE:
+            return -1;
+        case CALL_NO_KW_LIST_APPEND:
+            return -1;
+        case CALL_NO_KW_METHOD_DESCRIPTOR_O:
+            return -1;
+        case CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS:
+            return -1;
+        case CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS:
+            return -1;
+        case CALL_NO_KW_METHOD_DESCRIPTOR_FAST:
+            return -1;
+        case CALL_FUNCTION_EX:
+            return -1;
+        case MAKE_FUNCTION:
+            return -1;
+        case RETURN_GENERATOR:
+            return -1;
+        case BUILD_SLICE:
+            return -1;
+        case FORMAT_VALUE:
+            return -1;
+        case COPY:
+            return -1;
+        case BINARY_OP:
+            return 1;
+        case SWAP:
+            return -1;
+        case EXTENDED_ARG:
+            return -1;
+        case CACHE:
+            return -1;
+        default:
+            Py_UNREACHABLE();
+    }
+}
 enum Direction { DIR_NONE, DIR_READ, DIR_WRITE };
 enum InstructionFormat { INSTR_FMT_IB, INSTR_FMT_IBC, INSTR_FMT_IBC0, INSTR_FMT_IBC000, INSTR_FMT_IBIB, INSTR_FMT_IX, INSTR_FMT_IXC, INSTR_FMT_IXC000 };
-static const struct {
-    short n_popped;
-    short n_pushed;
+struct opcode_metadata {
     enum Direction dir_op1;
     enum Direction dir_op2;
     enum Direction dir_op3;
     bool valid_entry;
     enum InstructionFormat instr_format;
 } _PyOpcode_opcode_metadata[256] = {
-    [NOP] = { 0, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [RESUME] = { 0, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [LOAD_CLOSURE] = { 0, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [LOAD_FAST_CHECK] = { 0, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [LOAD_FAST] = { 0, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [LOAD_CONST] = { 0, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [STORE_FAST] = { 1, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [LOAD_FAST__LOAD_FAST] = { 0, 2, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBIB },
-    [LOAD_FAST__LOAD_CONST] = { 0, 2, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBIB },
-    [STORE_FAST__LOAD_FAST] = { 1, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBIB },
-    [STORE_FAST__STORE_FAST] = { 2, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBIB },
-    [LOAD_CONST__LOAD_FAST] = { 0, 2, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBIB },
-    [POP_TOP] = { 1, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [PUSH_NULL] = { 0, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [END_FOR] = { 2, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [UNARY_NEGATIVE] = { 1, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [UNARY_NOT] = { 1, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [UNARY_INVERT] = { 1, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [BINARY_OP_MULTIPLY_INT] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
-    [BINARY_OP_MULTIPLY_FLOAT] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
-    [BINARY_OP_SUBTRACT_INT] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
-    [BINARY_OP_SUBTRACT_FLOAT] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
-    [BINARY_OP_ADD_UNICODE] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
-    [BINARY_OP_INPLACE_ADD_UNICODE] = { 2, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [BINARY_OP_ADD_FLOAT] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
-    [BINARY_OP_ADD_INT] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
-    [BINARY_SUBSCR] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 },
-    [BINARY_SLICE] = { 3, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [STORE_SLICE] = { 4, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [BINARY_SUBSCR_LIST_INT] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 },
-    [BINARY_SUBSCR_TUPLE_INT] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 },
-    [BINARY_SUBSCR_DICT] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 },
-    [BINARY_SUBSCR_GETITEM] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 },
-    [LIST_APPEND] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [SET_ADD] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [STORE_SUBSCR] = { 3, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
-    [STORE_SUBSCR_LIST_INT] = { 3, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
-    [STORE_SUBSCR_DICT] = { 3, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
-    [DELETE_SUBSCR] = { 2, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [CALL_INTRINSIC_1] = { 1, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [RAISE_VARARGS] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [INTERPRETER_EXIT] = { 1, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [RETURN_VALUE] = { 1, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [GET_AITER] = { 1, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [GET_ANEXT] = { 1, 2, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [GET_AWAITABLE] = { 1, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [SEND] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [YIELD_VALUE] = { 1, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [POP_EXCEPT] = { 1, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [RERAISE] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [PREP_RERAISE_STAR] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [END_ASYNC_FOR] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [CLEANUP_THROW] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [LOAD_ASSERTION_ERROR] = { 0, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [LOAD_BUILD_CLASS] = { 0, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [STORE_NAME] = { 1, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [DELETE_NAME] = { 0, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [UNPACK_SEQUENCE] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [UNPACK_SEQUENCE_TWO_TUPLE] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [UNPACK_SEQUENCE_TUPLE] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [UNPACK_SEQUENCE_LIST] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [UNPACK_EX] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [STORE_ATTR] = { 2, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC000 },
-    [DELETE_ATTR] = { 1, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [STORE_GLOBAL] = { 1, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [DELETE_GLOBAL] = { 0, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [LOAD_NAME] = { 0, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [LOAD_GLOBAL] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [LOAD_GLOBAL_MODULE] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [LOAD_GLOBAL_BUILTIN] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [DELETE_FAST] = { 0, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [MAKE_CELL] = { 0, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [DELETE_DEREF] = { 0, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [LOAD_CLASSDEREF] = { 0, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [LOAD_DEREF] = { 0, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [STORE_DEREF] = { 1, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [COPY_FREE_VARS] = { 0, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [BUILD_STRING] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [BUILD_TUPLE] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [BUILD_LIST] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [LIST_EXTEND] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [SET_UPDATE] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [BUILD_SET] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [BUILD_MAP] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [SETUP_ANNOTATIONS] = { 0, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [BUILD_CONST_KEY_MAP] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [DICT_UPDATE] = { 1, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [DICT_MERGE] = { 1, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [MAP_ADD] = { 2, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [LOAD_ATTR] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [LOAD_ATTR_INSTANCE_VALUE] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [LOAD_ATTR_MODULE] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [LOAD_ATTR_WITH_HINT] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [LOAD_ATTR_SLOT] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [LOAD_ATTR_CLASS] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [LOAD_ATTR_PROPERTY] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [STORE_ATTR_INSTANCE_VALUE] = { 2, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 },
-    [STORE_ATTR_WITH_HINT] = { 2, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC000 },
-    [STORE_ATTR_SLOT] = { 2, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 },
-    [COMPARE_OP] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC },
-    [COMPARE_AND_BRANCH] = { 2, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC0 },
-    [COMPARE_AND_BRANCH_FLOAT] = { 2, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC0 },
-    [COMPARE_AND_BRANCH_INT] = { 2, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC0 },
-    [COMPARE_AND_BRANCH_STR] = { 2, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC0 },
-    [IS_OP] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [CONTAINS_OP] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [CHECK_EG_MATCH] = { 2, 2, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [CHECK_EXC_MATCH] = { 2, 2, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [IMPORT_NAME] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [IMPORT_FROM] = { 1, 2, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [JUMP_FORWARD] = { 0, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [JUMP_BACKWARD] = { 0, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [POP_JUMP_IF_FALSE] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [POP_JUMP_IF_TRUE] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [POP_JUMP_IF_NOT_NONE] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [POP_JUMP_IF_NONE] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [JUMP_IF_FALSE_OR_POP] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [JUMP_IF_TRUE_OR_POP] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [JUMP_BACKWARD_NO_INTERRUPT] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [GET_LEN] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [MATCH_CLASS] = { 3, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [MATCH_MAPPING] = { 1, 2, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [MATCH_SEQUENCE] = { 1, 2, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [MATCH_KEYS] = { 2, 3, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [GET_ITER] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [GET_YIELD_FROM_ITER] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [FOR_ITER] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [FOR_ITER_LIST] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [FOR_ITER_TUPLE] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [FOR_ITER_RANGE] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [FOR_ITER_GEN] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [BEFORE_ASYNC_WITH] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [BEFORE_WITH] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [WITH_EXCEPT_START] = { 4, 5, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [PUSH_EXC_INFO] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [LOAD_ATTR_METHOD_WITH_VALUES] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [LOAD_ATTR_METHOD_NO_DICT] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [LOAD_ATTR_METHOD_LAZY_DICT] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [CALL_BOUND_METHOD_EXACT_ARGS] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [KW_NAMES] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [CALL] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [CALL_PY_EXACT_ARGS] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [CALL_PY_WITH_DEFAULTS] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [CALL_NO_KW_TYPE_1] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [CALL_NO_KW_STR_1] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [CALL_NO_KW_TUPLE_1] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [CALL_BUILTIN_CLASS] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [CALL_NO_KW_BUILTIN_O] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [CALL_NO_KW_BUILTIN_FAST] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [CALL_BUILTIN_FAST_WITH_KEYWORDS] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [CALL_NO_KW_LEN] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [CALL_NO_KW_ISINSTANCE] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [CALL_NO_KW_LIST_APPEND] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [CALL_NO_KW_METHOD_DESCRIPTOR_O] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [CALL_NO_KW_METHOD_DESCRIPTOR_FAST] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [CALL_FUNCTION_EX] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [MAKE_FUNCTION] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [RETURN_GENERATOR] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
-    [BUILD_SLICE] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [FORMAT_VALUE] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [COPY] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [BINARY_OP] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC },
-    [SWAP] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [EXTENDED_ARG] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
-    [CACHE] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [NOP] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [RESUME] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [LOAD_CLOSURE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [LOAD_FAST_CHECK] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [LOAD_FAST] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [LOAD_CONST] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [STORE_FAST] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [LOAD_FAST__LOAD_FAST] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBIB },
+    [LOAD_FAST__LOAD_CONST] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBIB },
+    [STORE_FAST__LOAD_FAST] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBIB },
+    [STORE_FAST__STORE_FAST] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBIB },
+    [LOAD_CONST__LOAD_FAST] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBIB },
+    [POP_TOP] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [PUSH_NULL] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [END_FOR] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [UNARY_NEGATIVE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [UNARY_NOT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [UNARY_INVERT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [BINARY_OP_MULTIPLY_INT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
+    [BINARY_OP_MULTIPLY_FLOAT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
+    [BINARY_OP_SUBTRACT_INT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
+    [BINARY_OP_SUBTRACT_FLOAT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
+    [BINARY_OP_ADD_UNICODE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
+    [BINARY_OP_INPLACE_ADD_UNICODE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [BINARY_OP_ADD_FLOAT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
+    [BINARY_OP_ADD_INT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
+    [BINARY_SUBSCR] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 },
+    [BINARY_SLICE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [STORE_SLICE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [BINARY_SUBSCR_LIST_INT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 },
+    [BINARY_SUBSCR_TUPLE_INT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 },
+    [BINARY_SUBSCR_DICT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 },
+    [BINARY_SUBSCR_GETITEM] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 },
+    [LIST_APPEND] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [SET_ADD] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [STORE_SUBSCR] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
+    [STORE_SUBSCR_LIST_INT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
+    [STORE_SUBSCR_DICT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
+    [DELETE_SUBSCR] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [CALL_INTRINSIC_1] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [RAISE_VARARGS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [INTERPRETER_EXIT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [RETURN_VALUE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [GET_AITER] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [GET_ANEXT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [GET_AWAITABLE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [SEND] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [YIELD_VALUE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [POP_EXCEPT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [RERAISE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [PREP_RERAISE_STAR] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [END_ASYNC_FOR] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [CLEANUP_THROW] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [LOAD_ASSERTION_ERROR] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [LOAD_BUILD_CLASS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [STORE_NAME] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [DELETE_NAME] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [UNPACK_SEQUENCE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [UNPACK_SEQUENCE_TWO_TUPLE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [UNPACK_SEQUENCE_TUPLE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [UNPACK_SEQUENCE_LIST] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [UNPACK_EX] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [STORE_ATTR] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC000 },
+    [DELETE_ATTR] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [STORE_GLOBAL] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [DELETE_GLOBAL] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [LOAD_NAME] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [LOAD_GLOBAL] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [LOAD_GLOBAL_MODULE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [LOAD_GLOBAL_BUILTIN] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [DELETE_FAST] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [MAKE_CELL] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [DELETE_DEREF] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [LOAD_CLASSDEREF] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [LOAD_DEREF] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [STORE_DEREF] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [COPY_FREE_VARS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [BUILD_STRING] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [BUILD_TUPLE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [BUILD_LIST] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [LIST_EXTEND] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [SET_UPDATE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [BUILD_SET] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [BUILD_MAP] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [SETUP_ANNOTATIONS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [BUILD_CONST_KEY_MAP] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [DICT_UPDATE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [DICT_MERGE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [MAP_ADD] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [LOAD_ATTR] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [LOAD_ATTR_INSTANCE_VALUE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [LOAD_ATTR_MODULE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [LOAD_ATTR_WITH_HINT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [LOAD_ATTR_SLOT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [LOAD_ATTR_CLASS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [LOAD_ATTR_PROPERTY] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [STORE_ATTR_INSTANCE_VALUE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 },
+    [STORE_ATTR_WITH_HINT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC000 },
+    [STORE_ATTR_SLOT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 },
+    [COMPARE_OP] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC },
+    [COMPARE_AND_BRANCH] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC0 },
+    [COMPARE_AND_BRANCH_FLOAT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC0 },
+    [COMPARE_AND_BRANCH_INT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC0 },
+    [COMPARE_AND_BRANCH_STR] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC0 },
+    [IS_OP] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [CONTAINS_OP] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [CHECK_EG_MATCH] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [CHECK_EXC_MATCH] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [IMPORT_NAME] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [IMPORT_FROM] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [JUMP_FORWARD] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [JUMP_BACKWARD] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [POP_JUMP_IF_FALSE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [POP_JUMP_IF_TRUE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [POP_JUMP_IF_NOT_NONE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [POP_JUMP_IF_NONE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [JUMP_IF_FALSE_OR_POP] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [JUMP_IF_TRUE_OR_POP] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [JUMP_BACKWARD_NO_INTERRUPT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [GET_LEN] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [MATCH_CLASS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [MATCH_MAPPING] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [MATCH_SEQUENCE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [MATCH_KEYS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [GET_ITER] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [GET_YIELD_FROM_ITER] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [FOR_ITER] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [FOR_ITER_LIST] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [FOR_ITER_TUPLE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [FOR_ITER_RANGE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [FOR_ITER_GEN] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [BEFORE_ASYNC_WITH] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [BEFORE_WITH] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [WITH_EXCEPT_START] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [PUSH_EXC_INFO] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [LOAD_ATTR_METHOD_WITH_VALUES] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [LOAD_ATTR_METHOD_NO_DICT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [LOAD_ATTR_METHOD_LAZY_DICT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [CALL_BOUND_METHOD_EXACT_ARGS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [KW_NAMES] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [CALL] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [CALL_PY_EXACT_ARGS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [CALL_PY_WITH_DEFAULTS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [CALL_NO_KW_TYPE_1] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [CALL_NO_KW_STR_1] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [CALL_NO_KW_TUPLE_1] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [CALL_BUILTIN_CLASS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [CALL_NO_KW_BUILTIN_O] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [CALL_NO_KW_BUILTIN_FAST] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [CALL_BUILTIN_FAST_WITH_KEYWORDS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [CALL_NO_KW_LEN] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [CALL_NO_KW_ISINSTANCE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [CALL_NO_KW_LIST_APPEND] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [CALL_NO_KW_METHOD_DESCRIPTOR_O] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [CALL_NO_KW_METHOD_DESCRIPTOR_FAST] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [CALL_FUNCTION_EX] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [MAKE_FUNCTION] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [RETURN_GENERATOR] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
+    [BUILD_SLICE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [FORMAT_VALUE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [COPY] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [BINARY_OP] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC },
+    [SWAP] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [EXTENDED_ARG] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
+    [CACHE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
 };
index 429c9d34d60601b8ddc532b95c5e9d8ea1ac08cd..3e2ddaaf20063b655d2ce6ff44504e7bf4440c20 100644 (file)
@@ -734,6 +734,60 @@ class Analyzer:
         ]
         return stack, -lowest
 
+    def get_stack_effect_info(
+        self, thing: parser.InstDef | parser.Super | parser.Macro
+    ) -> tuple[Instruction, str, str]:
+
+        def effect_str(effect: list[StackEffect]) -> str:
+            if getattr(thing, 'kind', None) == 'legacy':
+                return str(-1)
+            n_effect, sym_effect = list_effect_size(effect)
+            if sym_effect:
+                return f"{sym_effect} + {n_effect}" if n_effect else sym_effect
+            return str(n_effect)
+
+        match thing:
+            case parser.InstDef():
+                if thing.kind != "op":
+                    instr = self.instrs[thing.name]
+                    popped = effect_str(instr.input_effects)
+                    pushed = effect_str(instr.output_effects)
+            case parser.Super():
+                instr = self.super_instrs[thing.name]
+                popped = '+'.join(effect_str(comp.instr.input_effects) for comp in instr.parts)
+                pushed = '+'.join(effect_str(comp.instr.output_effects) for comp in instr.parts)
+            case parser.Macro():
+                instr = self.macro_instrs[thing.name]
+                parts = [comp for comp in instr.parts if isinstance(comp, Component)]
+                popped = '+'.join(effect_str(comp.instr.input_effects) for comp in parts)
+                pushed = '+'.join(effect_str(comp.instr.output_effects) for comp in parts)
+            case _:
+                typing.assert_never(thing)
+        return instr, popped, pushed
+
+    def write_stack_effect_functions(self) -> None:
+        popped_data = []
+        pushed_data = []
+        for thing in self.everything:
+            instr, popped, pushed = self.get_stack_effect_info(thing)
+            popped_data.append( (instr, popped) )
+            pushed_data.append( (instr, pushed) )
+
+        def write_function(direction: str, data: list[tuple[Instruction, str]]) -> None:
+            self.out.emit("\nstatic int");
+            self.out.emit(f"_PyOpcode_num_{direction}(int opcode, int oparg) {{")
+            self.out.emit("    switch(opcode) {");
+            for instr, effect in data:
+                self.out.emit(f"        case {instr.name}:")
+                self.out.emit(f"            return {effect};")
+            self.out.emit("        default:")
+            self.out.emit("            Py_UNREACHABLE();")
+            self.out.emit("    }")
+            self.out.emit("}")
+
+        write_function('popped', popped_data)
+        write_function('pushed', pushed_data)
+
     def write_metadata(self) -> None:
         """Write instruction metadata to output file."""
 
@@ -762,13 +816,13 @@ class Analyzer:
             # Create formatter; the rest of the code uses this
             self.out = Formatter(f, 0)
 
+            self.write_stack_effect_functions()
+
             # Write variable definition
             self.out.emit("enum Direction { DIR_NONE, DIR_READ, DIR_WRITE };")
             self.out.emit(f"enum InstructionFormat {{ {', '.join(format_enums)} }};")
-            self.out.emit("static const struct {")
+            self.out.emit("struct opcode_metadata {")
             with self.out.indent():
-                self.out.emit("short n_popped;")
-                self.out.emit("short n_pushed;")
                 self.out.emit("enum Direction dir_op1;")
                 self.out.emit("enum Direction dir_op2;")
                 self.out.emit("enum Direction dir_op3;")
@@ -796,42 +850,30 @@ class Analyzer:
         """Write metadata for a single instruction."""
         dir_op1 = dir_op2 = dir_op3 = "DIR_NONE"
         if instr.kind == "legacy":
-            n_popped = n_pushed = -1
             assert not instr.register
         else:
-            n_popped, sym_popped = list_effect_size(instr.input_effects)
-            n_pushed, sym_pushed = list_effect_size(instr.output_effects)
-            if sym_popped or sym_pushed:
-                # TODO: Record symbolic effects (how?)
-                n_popped = n_pushed = -1
             if instr.register:
                 directions: list[str] = []
                 directions.extend("DIR_READ" for _ in instr.input_effects)
                 directions.extend("DIR_WRITE" for _ in instr.output_effects)
                 directions.extend("DIR_NONE" for _ in range(3))
                 dir_op1, dir_op2, dir_op3 = directions[:3]
-                n_popped = n_pushed = 0
         self.out.emit(
-            f'    [{instr.name}] = {{ {n_popped}, {n_pushed}, {dir_op1}, {dir_op2}, {dir_op3}, true, {INSTR_FMT_PREFIX}{instr.instr_fmt} }},'
+            f'    [{instr.name}] = {{ {dir_op1}, {dir_op2}, {dir_op3}, true, {INSTR_FMT_PREFIX}{instr.instr_fmt} }},'
         )
 
     def write_metadata_for_super(self, sup: SuperInstruction) -> None:
         """Write metadata for a super-instruction."""
-        n_popped = sum(len(comp.instr.input_effects) for comp in sup.parts)
-        n_pushed = sum(len(comp.instr.output_effects) for comp in sup.parts)
         dir_op1 = dir_op2 = dir_op3 = "DIR_NONE"
         self.out.emit(
-            f'    [{sup.name}] = {{ {n_popped}, {n_pushed}, {dir_op1}, {dir_op2}, {dir_op3}, true, {INSTR_FMT_PREFIX}{sup.instr_fmt} }},'
+            f'    [{sup.name}] = {{ {dir_op1}, {dir_op2}, {dir_op3}, true, {INSTR_FMT_PREFIX}{sup.instr_fmt} }},'
         )
 
     def write_metadata_for_macro(self, mac: MacroInstruction) -> None:
         """Write metadata for a macro-instruction."""
-        parts = [comp for comp in mac.parts if isinstance(comp, Component)]
-        n_popped = sum(len(comp.instr.input_effects) for comp in parts)
-        n_pushed = sum(len(comp.instr.output_effects) for comp in parts)
         dir_op1 = dir_op2 = dir_op3 = "DIR_NONE"
         self.out.emit(
-            f'    [{mac.name}] = {{ {n_popped}, {n_pushed}, {dir_op1}, {dir_op2}, {dir_op3}, true, {INSTR_FMT_PREFIX}{mac.instr_fmt} }},'
+            f'    [{mac.name}] = {{ {dir_op1}, {dir_op2}, {dir_op3}, true, {INSTR_FMT_PREFIX}{mac.instr_fmt} }},'
         )
 
     def write_instructions(self) -> None: