]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-103963: Make dis display names of args for intrinsics opcodes (#104029)
authorJuhi Chandalia <jkchandalia@gmail.com>
Wed, 3 May 2023 02:00:17 +0000 (19:00 -0700)
committerGitHub <noreply@github.com>
Wed, 3 May 2023 02:00:17 +0000 (19:00 -0700)
Include/internal/pycore_intrinsics.h
Lib/dis.py
Lib/opcode.py
Lib/test/test_dis.py
Misc/NEWS.d/next/Library/2023-05-01-17-58-28.gh-issue-103963.XWlHx7.rst [new file with mode: 0644]
Tools/build/generate_opcode_h.py

index 46a52740eb8a0c3ae8257c3bbadf01461af9e385..3902059a04b9da7a450bae7d5df88f76f40d456b 100644 (file)
@@ -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[];
-
index 85c109584bf94f126c4213ac5cc01e13f0f2ac6a..3a8e6ac3bf5ace8bdae534e689edc8c7e3af7bab 100644 (file)
@@ -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)
index aef8407948df15045d447ded69f40a2cac2dee3a..ad54bd27fba3d9aa57a4963f71484e5ddafdef76 100644 (file)
@@ -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",
index 5262c5c257cb895953b83613ebdd10d7498cbf7c..2f5d67fde861709b726f174f3dac9d806b69d9f6 100644 (file)
@@ -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 (file)
index 0000000..cb06ad5
--- /dev/null
@@ -0,0 +1 @@
+Make :mod:`dis` display the names of the args for :opcode:`CALL_INTRINSIC_*`.
index 645b9f1de1170bf95ef86ad5787833bd9e26f78b..adcbaf2b8e08bfd22fb328e2953ba0a24faab060 100644 (file)
@@ -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)}")