Skip to content

Commit 872cbc6

Browse files
authored
GH-103963: Make dis display names of args for intrinsics opcodes (#104029)
1 parent 65a49c6 commit 872cbc6

File tree

6 files changed

+110
-17
lines changed

6 files changed

+110
-17
lines changed

Diff for: Include/internal/pycore_intrinsics.h

+12-14
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,24 @@
1+
// Auto-generated by Tools/build/generate_opcode_h.py from Lib/opcode.py
12

23
/* Unary Functions: */
4+
#define INTRINSIC_1_INVALID 0
5+
#define INTRINSIC_PRINT 1
6+
#define INTRINSIC_IMPORT_STAR 2
7+
#define INTRINSIC_STOPITERATION_ERROR 3
8+
#define INTRINSIC_ASYNC_GEN_WRAP 4
9+
#define INTRINSIC_UNARY_POSITIVE 5
10+
#define INTRINSIC_LIST_TO_TUPLE 6
311

4-
#define INTRINSIC_PRINT 1
5-
#define INTRINSIC_IMPORT_STAR 2
6-
#define INTRINSIC_STOPITERATION_ERROR 3
7-
#define INTRINSIC_ASYNC_GEN_WRAP 4
8-
#define INTRINSIC_UNARY_POSITIVE 5
9-
#define INTRINSIC_LIST_TO_TUPLE 6
10-
11-
#define MAX_INTRINSIC_1 6
12+
#define MAX_INTRINSIC_1 6
1213

1314

1415
/* Binary Functions: */
16+
#define INTRINSIC_2_INVALID 0
17+
#define INTRINSIC_PREP_RERAISE_STAR 1
1518

16-
#define INTRINSIC_PREP_RERAISE_STAR 1
17-
18-
#define MAX_INTRINSIC_2 1
19-
19+
#define MAX_INTRINSIC_2 1
2020

2121
typedef PyObject *(*instrinsic_func1)(PyThreadState* tstate, PyObject *value);
2222
typedef PyObject *(*instrinsic_func2)(PyThreadState* tstate, PyObject *value1, PyObject *value2);
23-
2423
extern const instrinsic_func1 _PyIntrinsics_UnaryFunctions[];
2524
extern const instrinsic_func2 _PyIntrinsics_BinaryFunctions[];
26-

Diff for: Lib/dis.py

+8
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
_cache_format,
1212
_inline_cache_entries,
1313
_nb_ops,
14+
_intrinsic_1_descs,
15+
_intrinsic_2_descs,
1416
_specializations,
1517
_specialized_instructions,
1618
)
@@ -42,6 +44,8 @@
4244
SEND = opmap['SEND']
4345
LOAD_ATTR = opmap['LOAD_ATTR']
4446
LOAD_SUPER_ATTR = opmap['LOAD_SUPER_ATTR']
47+
CALL_INTRINSIC_1 = opmap['CALL_INTRINSIC_1']
48+
CALL_INTRINSIC_2 = opmap['CALL_INTRINSIC_2']
4549

4650
CACHE = opmap["CACHE"]
4751

@@ -506,6 +510,10 @@ def _get_instructions_bytes(code, varname_from_oparg=None,
506510
if arg & (1<<i))
507511
elif deop == BINARY_OP:
508512
_, argrepr = _nb_ops[arg]
513+
elif deop == CALL_INTRINSIC_1:
514+
argrepr = _intrinsic_1_descs[arg]
515+
elif deop == CALL_INTRINSIC_2:
516+
argrepr = _intrinsic_2_descs[arg]
509517
yield Instruction(_all_opname[op], op,
510518
arg, argval, argrepr,
511519
offset, starts_line, is_jump_target, positions)

Diff for: Lib/opcode.py

+15
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,21 @@ def pseudo_op(name, op, real_ops):
306306
("NB_INPLACE_XOR", "^="),
307307
]
308308

309+
_intrinsic_1_descs = [
310+
"INTRINSIC_1_INVALID",
311+
"INTRINSIC_PRINT",
312+
"INTRINSIC_IMPORT_STAR",
313+
"INTRINSIC_STOPITERATION_ERROR",
314+
"INTRINSIC_ASYNC_GEN_WRAP",
315+
"INTRINSIC_UNARY_POSITIVE",
316+
"INTRINSIC_LIST_TO_TUPLE",
317+
]
318+
319+
_intrinsic_2_descs = [
320+
'INTRINSIC_2_INVALID',
321+
'INTRINSIC_PREP_RERAISE_STAR',
322+
]
323+
309324
_specializations = {
310325
"BINARY_OP": [
311326
"BINARY_OP_ADD_FLOAT",

Diff for: Lib/test/test_dis.py

+40-1
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,35 @@ def wrap_func_w_kwargs():
247247
""" % (wrap_func_w_kwargs.__code__.co_firstlineno,
248248
wrap_func_w_kwargs.__code__.co_firstlineno + 1)
249249

250+
dis_intrinsic_1_2 = """\
251+
0 RESUME 0
252+
253+
1 LOAD_CONST 0 (0)
254+
LOAD_CONST 1 (('*',))
255+
IMPORT_NAME 0 (math)
256+
CALL_INTRINSIC_1 2 (INTRINSIC_IMPORT_STAR)
257+
POP_TOP
258+
RETURN_CONST 2 (None)
259+
"""
260+
261+
dis_intrinsic_1_5 = """\
262+
0 RESUME 0
263+
264+
1 LOAD_NAME 0 (a)
265+
CALL_INTRINSIC_1 5 (INTRINSIC_UNARY_POSITIVE)
266+
RETURN_VALUE
267+
"""
268+
269+
dis_intrinsic_1_6 = """\
270+
0 RESUME 0
271+
272+
1 BUILD_LIST 0
273+
LOAD_NAME 0 (a)
274+
LIST_EXTEND 1
275+
CALL_INTRINSIC_1 6 (INTRINSIC_LIST_TO_TUPLE)
276+
RETURN_VALUE
277+
"""
278+
250279
_BIG_LINENO_FORMAT = """\
251280
1 RESUME 0
252281
@@ -549,7 +578,7 @@ async def _asyncwith(c):
549578
>> COPY 3
550579
POP_EXCEPT
551580
RERAISE 1
552-
>> CALL_INTRINSIC_1 3
581+
>> CALL_INTRINSIC_1 3 (INTRINSIC_STOPITERATION_ERROR)
553582
RERAISE 1
554583
ExceptionTable:
555584
12 rows
@@ -942,6 +971,16 @@ def test_kw_names(self):
942971
# Test that value is displayed for KW_NAMES
943972
self.do_disassembly_test(wrap_func_w_kwargs, dis_kw_names)
944973

974+
def test_intrinsic_1(self):
975+
# Test that argrepr is displayed for CALL_INTRINSIC_1
976+
self.do_disassembly_test("from math import *", dis_intrinsic_1_2)
977+
self.do_disassembly_test("+a", dis_intrinsic_1_5)
978+
self.do_disassembly_test("(*a,)", dis_intrinsic_1_6)
979+
980+
def test_intrinsic_2(self):
981+
self.assertIn("CALL_INTRINSIC_2 1 (INTRINSIC_PREP_RERAISE_STAR)",
982+
self.get_disassembly("try: pass\nexcept* Exception: x"))
983+
945984
def test_big_linenos(self):
946985
def func(count):
947986
namespace = {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Make :mod:`dis` display the names of the args for :opcode:`CALL_INTRINSIC_*`.

Diff for: Tools/build/generate_opcode_h.py

+34-2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,18 @@
5252
#endif // !Py_INTERNAL_OPCODE_H
5353
"""
5454

55+
intrinsic_header = f"""
56+
// Auto-generated by {SCRIPT_NAME} from {PYTHON_OPCODE}
57+
58+
""".lstrip()
59+
60+
intrinsic_footer = """
61+
typedef PyObject *(*instrinsic_func1)(PyThreadState* tstate, PyObject *value);
62+
typedef PyObject *(*instrinsic_func2)(PyThreadState* tstate, PyObject *value1, PyObject *value2);
63+
extern const instrinsic_func1 _PyIntrinsics_UnaryFunctions[];
64+
extern const instrinsic_func2 _PyIntrinsics_BinaryFunctions[];
65+
"""
66+
5567
DEFINE = "#define {:<38} {:>3}\n"
5668

5769
UINT32_MASK = (1<<32)-1
@@ -67,7 +79,9 @@ def write_int_array_from_ops(name, ops, out):
6779
assert bits == 0
6880
out.write(f"}};\n")
6981

70-
def main(opcode_py, outfile='Include/opcode.h', internaloutfile='Include/internal/pycore_opcode.h'):
82+
def main(opcode_py, outfile='Include/opcode.h',
83+
internaloutfile='Include/internal/pycore_opcode.h',
84+
intrinsicoutfile='Include/internal/pycore_intrinsics.h'):
7185
opcode = {}
7286
if hasattr(tokenize, 'open'):
7387
fp = tokenize.open(opcode_py) # Python 3.2+
@@ -107,9 +121,11 @@ def main(opcode_py, outfile='Include/opcode.h', internaloutfile='Include/interna
107121
opname_including_specialized[next_op] = name
108122
used[next_op] = True
109123

110-
with open(outfile, 'w') as fobj, open(internaloutfile, 'w') as iobj:
124+
with open(outfile, 'w') as fobj, open(internaloutfile, 'w') as iobj, open(
125+
intrinsicoutfile, "w") as nobj:
111126
fobj.write(header)
112127
iobj.write(internal_header)
128+
nobj.write(intrinsic_header)
113129

114130
for name in opname:
115131
if name in opmap:
@@ -172,6 +188,22 @@ def main(opcode_py, outfile='Include/opcode.h', internaloutfile='Include/interna
172188
for i, (op, _) in enumerate(opcode["_nb_ops"]):
173189
fobj.write(DEFINE.format(op, i))
174190

191+
nobj.write("/* Unary Functions: */")
192+
nobj.write("\n")
193+
for i, op in enumerate(opcode["_intrinsic_1_descs"]):
194+
nobj.write(DEFINE.format(op, i))
195+
nobj.write("\n")
196+
nobj.write(DEFINE.format("MAX_INTRINSIC_1", i))
197+
198+
nobj.write("\n\n")
199+
nobj.write("/* Binary Functions: */\n")
200+
for i, op in enumerate(opcode["_intrinsic_2_descs"]):
201+
nobj.write(DEFINE.format(op, i))
202+
nobj.write("\n")
203+
nobj.write(DEFINE.format("MAX_INTRINSIC_2", i))
204+
205+
nobj.write(intrinsic_footer)
206+
175207
fobj.write("\n")
176208
fobj.write("/* Defined in Lib/opcode.py */\n")
177209
fobj.write(f"#define ENABLE_SPECIALIZATION {int(ENABLE_SPECIALIZATION)}")

0 commit comments

Comments
 (0)