diff options
author | Juhi Chandalia <jkchandalia@gmail.com> | 2023-05-03 02:00:17 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-03 02:00:17 (GMT) |
commit | 872cbc613245db7a1fc5e6656ed0135d2e115f50 (patch) | |
tree | 130aa47855542bf7467ddc96e14008faf652f040 | |
parent | 65a49c6553a27cc36eebb4b79f409c3cb4450d8c (diff) | |
download | cpython-872cbc613245db7a1fc5e6656ed0135d2e115f50.zip cpython-872cbc613245db7a1fc5e6656ed0135d2e115f50.tar.gz cpython-872cbc613245db7a1fc5e6656ed0135d2e115f50.tar.bz2 |
GH-103963: Make dis display names of args for intrinsics opcodes (#104029)
-rw-r--r-- | Include/internal/pycore_intrinsics.h | 26 | ||||
-rw-r--r-- | Lib/dis.py | 8 | ||||
-rw-r--r-- | Lib/opcode.py | 15 | ||||
-rw-r--r-- | Lib/test/test_dis.py | 41 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2023-05-01-17-58-28.gh-issue-103963.XWlHx7.rst | 1 | ||||
-rw-r--r-- | Tools/build/generate_opcode_h.py | 36 |
6 files changed, 110 insertions, 17 deletions
diff --git a/Include/internal/pycore_intrinsics.h b/Include/internal/pycore_intrinsics.h index 46a5274..3902059 100644 --- a/Include/internal/pycore_intrinsics.h +++ b/Include/internal/pycore_intrinsics.h @@ -1,26 +1,24 @@ +// Auto-generated by Tools/build/generate_opcode_h.py from Lib/opcode.py /* Unary Functions: */ +#define INTRINSIC_1_INVALID 0 +#define INTRINSIC_PRINT 1 +#define INTRINSIC_IMPORT_STAR 2 +#define INTRINSIC_STOPITERATION_ERROR 3 +#define INTRINSIC_ASYNC_GEN_WRAP 4 +#define INTRINSIC_UNARY_POSITIVE 5 +#define INTRINSIC_LIST_TO_TUPLE 6 -#define INTRINSIC_PRINT 1 -#define INTRINSIC_IMPORT_STAR 2 -#define INTRINSIC_STOPITERATION_ERROR 3 -#define INTRINSIC_ASYNC_GEN_WRAP 4 -#define INTRINSIC_UNARY_POSITIVE 5 -#define INTRINSIC_LIST_TO_TUPLE 6 - -#define MAX_INTRINSIC_1 6 +#define MAX_INTRINSIC_1 6 /* Binary Functions: */ +#define INTRINSIC_2_INVALID 0 +#define INTRINSIC_PREP_RERAISE_STAR 1 -#define INTRINSIC_PREP_RERAISE_STAR 1 - -#define MAX_INTRINSIC_2 1 - +#define MAX_INTRINSIC_2 1 typedef PyObject *(*instrinsic_func1)(PyThreadState* tstate, PyObject *value); typedef PyObject *(*instrinsic_func2)(PyThreadState* tstate, PyObject *value1, PyObject *value2); - extern const instrinsic_func1 _PyIntrinsics_UnaryFunctions[]; extern const instrinsic_func2 _PyIntrinsics_BinaryFunctions[]; - @@ -11,6 +11,8 @@ from opcode import ( _cache_format, _inline_cache_entries, _nb_ops, + _intrinsic_1_descs, + _intrinsic_2_descs, _specializations, _specialized_instructions, ) @@ -42,6 +44,8 @@ FOR_ITER = opmap['FOR_ITER'] SEND = opmap['SEND'] LOAD_ATTR = opmap['LOAD_ATTR'] LOAD_SUPER_ATTR = opmap['LOAD_SUPER_ATTR'] +CALL_INTRINSIC_1 = opmap['CALL_INTRINSIC_1'] +CALL_INTRINSIC_2 = opmap['CALL_INTRINSIC_2'] CACHE = opmap["CACHE"] @@ -506,6 +510,10 @@ def _get_instructions_bytes(code, varname_from_oparg=None, if arg & (1<<i)) elif deop == BINARY_OP: _, argrepr = _nb_ops[arg] + elif deop == CALL_INTRINSIC_1: + argrepr = _intrinsic_1_descs[arg] + elif deop == CALL_INTRINSIC_2: + argrepr = _intrinsic_2_descs[arg] yield Instruction(_all_opname[op], op, arg, argval, argrepr, offset, starts_line, is_jump_target, positions) diff --git a/Lib/opcode.py b/Lib/opcode.py index aef8407..ad54bd2 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -306,6 +306,21 @@ _nb_ops = [ ("NB_INPLACE_XOR", "^="), ] +_intrinsic_1_descs = [ + "INTRINSIC_1_INVALID", + "INTRINSIC_PRINT", + "INTRINSIC_IMPORT_STAR", + "INTRINSIC_STOPITERATION_ERROR", + "INTRINSIC_ASYNC_GEN_WRAP", + "INTRINSIC_UNARY_POSITIVE", + "INTRINSIC_LIST_TO_TUPLE", +] + +_intrinsic_2_descs = [ + 'INTRINSIC_2_INVALID', + 'INTRINSIC_PREP_RERAISE_STAR', + ] + _specializations = { "BINARY_OP": [ "BINARY_OP_ADD_FLOAT", diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index 5262c5c..2f5d67f 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -247,6 +247,35 @@ dis_kw_names = """\ """ % (wrap_func_w_kwargs.__code__.co_firstlineno, wrap_func_w_kwargs.__code__.co_firstlineno + 1) +dis_intrinsic_1_2 = """\ + 0 RESUME 0 + + 1 LOAD_CONST 0 (0) + LOAD_CONST 1 (('*',)) + IMPORT_NAME 0 (math) + CALL_INTRINSIC_1 2 (INTRINSIC_IMPORT_STAR) + POP_TOP + RETURN_CONST 2 (None) +""" + +dis_intrinsic_1_5 = """\ + 0 RESUME 0 + + 1 LOAD_NAME 0 (a) + CALL_INTRINSIC_1 5 (INTRINSIC_UNARY_POSITIVE) + RETURN_VALUE +""" + +dis_intrinsic_1_6 = """\ + 0 RESUME 0 + + 1 BUILD_LIST 0 + LOAD_NAME 0 (a) + LIST_EXTEND 1 + CALL_INTRINSIC_1 6 (INTRINSIC_LIST_TO_TUPLE) + RETURN_VALUE +""" + _BIG_LINENO_FORMAT = """\ 1 RESUME 0 @@ -549,7 +578,7 @@ dis_asyncwith = """\ >> COPY 3 POP_EXCEPT RERAISE 1 - >> CALL_INTRINSIC_1 3 + >> CALL_INTRINSIC_1 3 (INTRINSIC_STOPITERATION_ERROR) RERAISE 1 ExceptionTable: 12 rows @@ -942,6 +971,16 @@ class DisTests(DisTestBase): # Test that value is displayed for KW_NAMES self.do_disassembly_test(wrap_func_w_kwargs, dis_kw_names) + def test_intrinsic_1(self): + # Test that argrepr is displayed for CALL_INTRINSIC_1 + self.do_disassembly_test("from math import *", dis_intrinsic_1_2) + self.do_disassembly_test("+a", dis_intrinsic_1_5) + self.do_disassembly_test("(*a,)", dis_intrinsic_1_6) + + def test_intrinsic_2(self): + self.assertIn("CALL_INTRINSIC_2 1 (INTRINSIC_PREP_RERAISE_STAR)", + self.get_disassembly("try: pass\nexcept* Exception: x")) + def test_big_linenos(self): def func(count): namespace = {} diff --git a/Misc/NEWS.d/next/Library/2023-05-01-17-58-28.gh-issue-103963.XWlHx7.rst b/Misc/NEWS.d/next/Library/2023-05-01-17-58-28.gh-issue-103963.XWlHx7.rst new file mode 100644 index 0000000..cb06ad5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-05-01-17-58-28.gh-issue-103963.XWlHx7.rst @@ -0,0 +1 @@ +Make :mod:`dis` display the names of the args for :opcode:`CALL_INTRINSIC_*`. diff --git a/Tools/build/generate_opcode_h.py b/Tools/build/generate_opcode_h.py index 645b9f1..adcbaf2 100644 --- a/Tools/build/generate_opcode_h.py +++ b/Tools/build/generate_opcode_h.py @@ -52,6 +52,18 @@ internal_footer = """ #endif // !Py_INTERNAL_OPCODE_H """ +intrinsic_header = f""" +// Auto-generated by {SCRIPT_NAME} from {PYTHON_OPCODE} + +""".lstrip() + +intrinsic_footer = """ +typedef PyObject *(*instrinsic_func1)(PyThreadState* tstate, PyObject *value); +typedef PyObject *(*instrinsic_func2)(PyThreadState* tstate, PyObject *value1, PyObject *value2); +extern const instrinsic_func1 _PyIntrinsics_UnaryFunctions[]; +extern const instrinsic_func2 _PyIntrinsics_BinaryFunctions[]; +""" + DEFINE = "#define {:<38} {:>3}\n" UINT32_MASK = (1<<32)-1 @@ -67,7 +79,9 @@ def write_int_array_from_ops(name, ops, out): assert bits == 0 out.write(f"}};\n") -def main(opcode_py, outfile='Include/opcode.h', internaloutfile='Include/internal/pycore_opcode.h'): +def main(opcode_py, outfile='Include/opcode.h', + internaloutfile='Include/internal/pycore_opcode.h', + intrinsicoutfile='Include/internal/pycore_intrinsics.h'): opcode = {} if hasattr(tokenize, 'open'): fp = tokenize.open(opcode_py) # Python 3.2+ @@ -107,9 +121,11 @@ def main(opcode_py, outfile='Include/opcode.h', internaloutfile='Include/interna opname_including_specialized[next_op] = name used[next_op] = True - with open(outfile, 'w') as fobj, open(internaloutfile, 'w') as iobj: + with open(outfile, 'w') as fobj, open(internaloutfile, 'w') as iobj, open( + intrinsicoutfile, "w") as nobj: fobj.write(header) iobj.write(internal_header) + nobj.write(intrinsic_header) for name in opname: if name in opmap: @@ -172,6 +188,22 @@ def main(opcode_py, outfile='Include/opcode.h', internaloutfile='Include/interna for i, (op, _) in enumerate(opcode["_nb_ops"]): fobj.write(DEFINE.format(op, i)) + nobj.write("/* Unary Functions: */") + nobj.write("\n") + for i, op in enumerate(opcode["_intrinsic_1_descs"]): + nobj.write(DEFINE.format(op, i)) + nobj.write("\n") + nobj.write(DEFINE.format("MAX_INTRINSIC_1", i)) + + nobj.write("\n\n") + nobj.write("/* Binary Functions: */\n") + for i, op in enumerate(opcode["_intrinsic_2_descs"]): + nobj.write(DEFINE.format(op, i)) + nobj.write("\n") + nobj.write(DEFINE.format("MAX_INTRINSIC_2", i)) + + nobj.write(intrinsic_footer) + fobj.write("\n") fobj.write("/* Defined in Lib/opcode.py */\n") fobj.write(f"#define ENABLE_SPECIALIZATION {int(ENABLE_SPECIALIZATION)}") |