17db96d56Sopenharmony_ci# This script generates the opcode.h header file.
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_ciimport sys
47db96d56Sopenharmony_ciimport tokenize
57db96d56Sopenharmony_ci
67db96d56Sopenharmony_ciSCRIPT_NAME = "Tools/scripts/generate_opcode_h.py"
77db96d56Sopenharmony_ciPYTHON_OPCODE = "Lib/opcode.py"
87db96d56Sopenharmony_ci
97db96d56Sopenharmony_ciheader = f"""
107db96d56Sopenharmony_ci// Auto-generated by {SCRIPT_NAME} from {PYTHON_OPCODE}
117db96d56Sopenharmony_ci
127db96d56Sopenharmony_ci#ifndef Py_OPCODE_H
137db96d56Sopenharmony_ci#define Py_OPCODE_H
147db96d56Sopenharmony_ci#ifdef __cplusplus
157db96d56Sopenharmony_ciextern "C" {{
167db96d56Sopenharmony_ci#endif
177db96d56Sopenharmony_ci
187db96d56Sopenharmony_ci
197db96d56Sopenharmony_ci/* Instruction opcodes for compiled code */
207db96d56Sopenharmony_ci""".lstrip()
217db96d56Sopenharmony_ci
227db96d56Sopenharmony_cifooter = """
237db96d56Sopenharmony_ci#define HAS_ARG(op) ((op) >= HAVE_ARGUMENT)
247db96d56Sopenharmony_ci
257db96d56Sopenharmony_ci/* Reserve some bytecodes for internal use in the compiler.
267db96d56Sopenharmony_ci * The value of 240 is arbitrary. */
277db96d56Sopenharmony_ci#define IS_ARTIFICIAL(op) ((op) > 240)
287db96d56Sopenharmony_ci
297db96d56Sopenharmony_ci#ifdef __cplusplus
307db96d56Sopenharmony_ci}
317db96d56Sopenharmony_ci#endif
327db96d56Sopenharmony_ci#endif /* !Py_OPCODE_H */
337db96d56Sopenharmony_ci"""
347db96d56Sopenharmony_ci
357db96d56Sopenharmony_ciinternal_header = f"""
367db96d56Sopenharmony_ci// Auto-generated by {SCRIPT_NAME} from {PYTHON_OPCODE}
377db96d56Sopenharmony_ci
387db96d56Sopenharmony_ci#ifndef Py_INTERNAL_OPCODE_H
397db96d56Sopenharmony_ci#define Py_INTERNAL_OPCODE_H
407db96d56Sopenharmony_ci#ifdef __cplusplus
417db96d56Sopenharmony_ciextern "C" {{
427db96d56Sopenharmony_ci#endif
437db96d56Sopenharmony_ci
447db96d56Sopenharmony_ci#ifndef Py_BUILD_CORE
457db96d56Sopenharmony_ci#  error "this header requires Py_BUILD_CORE define"
467db96d56Sopenharmony_ci#endif
477db96d56Sopenharmony_ci
487db96d56Sopenharmony_ci#include "opcode.h"
497db96d56Sopenharmony_ci""".lstrip()
507db96d56Sopenharmony_ci
517db96d56Sopenharmony_ciinternal_footer = """
527db96d56Sopenharmony_ci#ifdef __cplusplus
537db96d56Sopenharmony_ci}
547db96d56Sopenharmony_ci#endif
557db96d56Sopenharmony_ci#endif  // !Py_INTERNAL_OPCODE_H
567db96d56Sopenharmony_ci"""
577db96d56Sopenharmony_ci
587db96d56Sopenharmony_ciDEFINE = "#define {:<38} {:>3}\n"
597db96d56Sopenharmony_ci
607db96d56Sopenharmony_ciUINT32_MASK = (1<<32)-1
617db96d56Sopenharmony_ci
627db96d56Sopenharmony_cidef write_int_array_from_ops(name, ops, out):
637db96d56Sopenharmony_ci    bits = 0
647db96d56Sopenharmony_ci    for op in ops:
657db96d56Sopenharmony_ci        bits |= 1<<op
667db96d56Sopenharmony_ci    out.write(f"static const uint32_t {name}[8] = {{\n")
677db96d56Sopenharmony_ci    for i in range(8):
687db96d56Sopenharmony_ci        out.write(f"    {bits & UINT32_MASK}U,\n")
697db96d56Sopenharmony_ci        bits >>= 32
707db96d56Sopenharmony_ci    assert bits == 0
717db96d56Sopenharmony_ci    out.write(f"}};\n")
727db96d56Sopenharmony_ci
737db96d56Sopenharmony_cidef main(opcode_py, outfile='Include/opcode.h', internaloutfile='Include/internal/pycore_opcode.h'):
747db96d56Sopenharmony_ci    opcode = {}
757db96d56Sopenharmony_ci    if hasattr(tokenize, 'open'):
767db96d56Sopenharmony_ci        fp = tokenize.open(opcode_py)   # Python 3.2+
777db96d56Sopenharmony_ci    else:
787db96d56Sopenharmony_ci        fp = open(opcode_py)            # Python 2.7
797db96d56Sopenharmony_ci    with fp:
807db96d56Sopenharmony_ci        code = fp.read()
817db96d56Sopenharmony_ci    exec(code, opcode)
827db96d56Sopenharmony_ci    opmap = opcode['opmap']
837db96d56Sopenharmony_ci    opname = opcode['opname']
847db96d56Sopenharmony_ci    hasconst = opcode['hasconst']
857db96d56Sopenharmony_ci    hasjrel = opcode['hasjrel']
867db96d56Sopenharmony_ci    hasjabs = opcode['hasjabs']
877db96d56Sopenharmony_ci    used = [ False ] * 256
887db96d56Sopenharmony_ci    next_op = 1
897db96d56Sopenharmony_ci
907db96d56Sopenharmony_ci    for name, op in opmap.items():
917db96d56Sopenharmony_ci        used[op] = True
927db96d56Sopenharmony_ci
937db96d56Sopenharmony_ci    specialized_opmap = {}
947db96d56Sopenharmony_ci    opname_including_specialized = opname.copy()
957db96d56Sopenharmony_ci    for name in opcode['_specialized_instructions']:
967db96d56Sopenharmony_ci        while used[next_op]:
977db96d56Sopenharmony_ci            next_op += 1
987db96d56Sopenharmony_ci        specialized_opmap[name] = next_op
997db96d56Sopenharmony_ci        opname_including_specialized[next_op] = name
1007db96d56Sopenharmony_ci        used[next_op] = True
1017db96d56Sopenharmony_ci    specialized_opmap['DO_TRACING'] = 255
1027db96d56Sopenharmony_ci    opname_including_specialized[255] = 'DO_TRACING'
1037db96d56Sopenharmony_ci    used[255] = True
1047db96d56Sopenharmony_ci
1057db96d56Sopenharmony_ci    with open(outfile, 'w') as fobj, open(internaloutfile, 'w') as iobj:
1067db96d56Sopenharmony_ci        fobj.write(header)
1077db96d56Sopenharmony_ci        iobj.write(internal_header)
1087db96d56Sopenharmony_ci
1097db96d56Sopenharmony_ci        for name in opname:
1107db96d56Sopenharmony_ci            if name in opmap:
1117db96d56Sopenharmony_ci                fobj.write(DEFINE.format(name, opmap[name]))
1127db96d56Sopenharmony_ci            if name == 'POP_EXCEPT': # Special entry for HAVE_ARGUMENT
1137db96d56Sopenharmony_ci                fobj.write(DEFINE.format("HAVE_ARGUMENT", opcode["HAVE_ARGUMENT"]))
1147db96d56Sopenharmony_ci
1157db96d56Sopenharmony_ci        for name, op in specialized_opmap.items():
1167db96d56Sopenharmony_ci            fobj.write(DEFINE.format(name, op))
1177db96d56Sopenharmony_ci
1187db96d56Sopenharmony_ci        iobj.write("\nextern const uint8_t _PyOpcode_Caches[256];\n")
1197db96d56Sopenharmony_ci        iobj.write("\nextern const uint8_t _PyOpcode_Deopt[256];\n")
1207db96d56Sopenharmony_ci        iobj.write("\n#ifdef NEED_OPCODE_TABLES\n")
1217db96d56Sopenharmony_ci        write_int_array_from_ops("_PyOpcode_RelativeJump", opcode['hasjrel'], iobj)
1227db96d56Sopenharmony_ci        write_int_array_from_ops("_PyOpcode_Jump", opcode['hasjrel'] + opcode['hasjabs'], iobj)
1237db96d56Sopenharmony_ci
1247db96d56Sopenharmony_ci        iobj.write("\nconst uint8_t _PyOpcode_Caches[256] = {\n")
1257db96d56Sopenharmony_ci        for i, entries in enumerate(opcode["_inline_cache_entries"]):
1267db96d56Sopenharmony_ci            if entries:
1277db96d56Sopenharmony_ci                iobj.write(f"    [{opname[i]}] = {entries},\n")
1287db96d56Sopenharmony_ci        iobj.write("};\n")
1297db96d56Sopenharmony_ci
1307db96d56Sopenharmony_ci        deoptcodes = {}
1317db96d56Sopenharmony_ci        for basic in opmap:
1327db96d56Sopenharmony_ci            deoptcodes[basic] = basic
1337db96d56Sopenharmony_ci        for basic, family in opcode["_specializations"].items():
1347db96d56Sopenharmony_ci            for specialized in family:
1357db96d56Sopenharmony_ci                deoptcodes[specialized] = basic
1367db96d56Sopenharmony_ci        iobj.write("\nconst uint8_t _PyOpcode_Deopt[256] = {\n")
1377db96d56Sopenharmony_ci        for opt, deopt in sorted(deoptcodes.items()):
1387db96d56Sopenharmony_ci            iobj.write(f"    [{opt}] = {deopt},\n")
1397db96d56Sopenharmony_ci        iobj.write("};\n")
1407db96d56Sopenharmony_ci        iobj.write("#endif   // NEED_OPCODE_TABLES\n")
1417db96d56Sopenharmony_ci
1427db96d56Sopenharmony_ci        fobj.write("\n")
1437db96d56Sopenharmony_ci        fobj.write("#define HAS_CONST(op) (false\\")
1447db96d56Sopenharmony_ci        for op in hasconst:
1457db96d56Sopenharmony_ci            fobj.write(f"\n    || ((op) == {op}) \\")
1467db96d56Sopenharmony_ci        fobj.write("\n    )\n")
1477db96d56Sopenharmony_ci
1487db96d56Sopenharmony_ci        fobj.write("\n")
1497db96d56Sopenharmony_ci        for i, (op, _) in enumerate(opcode["_nb_ops"]):
1507db96d56Sopenharmony_ci            fobj.write(DEFINE.format(op, i))
1517db96d56Sopenharmony_ci
1527db96d56Sopenharmony_ci        iobj.write("\n")
1537db96d56Sopenharmony_ci        iobj.write("#ifdef Py_DEBUG\n")
1547db96d56Sopenharmony_ci        iobj.write("static const char *const _PyOpcode_OpName[256] = {\n")
1557db96d56Sopenharmony_ci        for op, name in enumerate(opname_including_specialized):
1567db96d56Sopenharmony_ci            if name[0] != "<":
1577db96d56Sopenharmony_ci                op = name
1587db96d56Sopenharmony_ci            iobj.write(f'''    [{op}] = "{name}",\n''')
1597db96d56Sopenharmony_ci        iobj.write("};\n")
1607db96d56Sopenharmony_ci        iobj.write("#endif\n")
1617db96d56Sopenharmony_ci
1627db96d56Sopenharmony_ci        iobj.write("\n")
1637db96d56Sopenharmony_ci        iobj.write("#define EXTRA_CASES \\\n")
1647db96d56Sopenharmony_ci        for i, flag in enumerate(used):
1657db96d56Sopenharmony_ci            if not flag:
1667db96d56Sopenharmony_ci                iobj.write(f"    case {i}: \\\n")
1677db96d56Sopenharmony_ci        iobj.write("        ;\n")
1687db96d56Sopenharmony_ci
1697db96d56Sopenharmony_ci        fobj.write(footer)
1707db96d56Sopenharmony_ci        iobj.write(internal_footer)
1717db96d56Sopenharmony_ci
1727db96d56Sopenharmony_ci
1737db96d56Sopenharmony_ci    print(f"{outfile} regenerated from {opcode_py}")
1747db96d56Sopenharmony_ci
1757db96d56Sopenharmony_ci
1767db96d56Sopenharmony_ciif __name__ == '__main__':
1777db96d56Sopenharmony_ci    main(sys.argv[1], sys.argv[2], sys.argv[3])
178