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