| 
									
										
										
										
											2014-04-15 23:50:06 +05:30
										 |  |  | # This script generates the opcode.h header file. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import sys | 
					
						
							| 
									
										
										
										
											2016-11-28 18:13:52 +01:00
										 |  |  | import tokenize | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-17 12:01:00 +02:00
										 |  |  | SCRIPT_NAME = "Tools/build/generate_opcode_h.py" | 
					
						
							| 
									
										
										
										
											2022-04-26 00:14:30 +02:00
										 |  |  | PYTHON_OPCODE = "Lib/opcode.py" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | header = f"""
 | 
					
						
							|  |  |  | // Auto-generated by {SCRIPT_NAME} from {PYTHON_OPCODE} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-15 23:50:06 +05:30
										 |  |  | #ifndef Py_OPCODE_H | 
					
						
							|  |  |  | #define Py_OPCODE_H | 
					
						
							|  |  |  | #ifdef __cplusplus | 
					
						
							| 
									
										
										
										
											2022-04-26 00:14:30 +02:00
										 |  |  | extern "C" {{ | 
					
						
							| 
									
										
										
										
											2014-04-15 23:50:06 +05:30
										 |  |  | #endif | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-10 22:56:22 -08:00
										 |  |  | /* Instruction opcodes for compiled code */ | 
					
						
							| 
									
										
										
										
											2018-10-19 01:23:18 +05:30
										 |  |  | """.lstrip()
 | 
					
						
							| 
									
										
										
										
											2014-04-15 23:50:06 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  | footer = """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef __cplusplus | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | #endif /* !Py_OPCODE_H */ | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-26 00:14:30 +02:00
										 |  |  | internal_header = f"""
 | 
					
						
							|  |  |  | // Auto-generated by {SCRIPT_NAME} from {PYTHON_OPCODE} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef Py_INTERNAL_OPCODE_H | 
					
						
							|  |  |  | #define Py_INTERNAL_OPCODE_H | 
					
						
							|  |  |  | #ifdef __cplusplus | 
					
						
							|  |  |  | extern "C" {{ | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef Py_BUILD_CORE | 
					
						
							|  |  |  | #  error "this header requires Py_BUILD_CORE define" | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "opcode.h" | 
					
						
							|  |  |  | """.lstrip()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | internal_footer = """
 | 
					
						
							|  |  |  | #ifdef __cplusplus | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | #endif  // !Py_INTERNAL_OPCODE_H | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-02 19:00:17 -07:00
										 |  |  | 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[]; | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-21 04:11:17 -07:00
										 |  |  | DEFINE = "#define {:<38} {:>3}\n" | 
					
						
							| 
									
										
										
										
											2021-11-10 22:56:22 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-04 17:30:11 +01:00
										 |  |  | UINT32_MASK = (1<<32)-1 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-19 23:47:04 +01:00
										 |  |  | def get_python_module_dict(filename): | 
					
						
							|  |  |  |     mod = {} | 
					
						
							|  |  |  |     with tokenize.open(filename) as fp: | 
					
						
							|  |  |  |         code = fp.read() | 
					
						
							|  |  |  |     exec(code, mod) | 
					
						
							|  |  |  |     return mod | 
					
						
							| 
									
										
										
										
											2014-04-15 23:50:06 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-19 23:47:04 +01:00
										 |  |  | def main(opcode_py, | 
					
						
							|  |  |  |          _opcode_metadata_py='Lib/_opcode_metadata.py', | 
					
						
							|  |  |  |          outfile='Include/opcode.h', | 
					
						
							| 
									
										
										
										
											2023-05-02 19:00:17 -07:00
										 |  |  |          internaloutfile='Include/internal/pycore_opcode.h', | 
					
						
							|  |  |  |          intrinsicoutfile='Include/internal/pycore_intrinsics.h'): | 
					
						
							| 
									
										
										
										
											2023-06-19 23:47:04 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     _opcode_metadata = get_python_module_dict(_opcode_metadata_py) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     opcode = get_python_module_dict(opcode_py) | 
					
						
							| 
									
										
										
										
											2014-04-17 01:13:29 +02:00
										 |  |  |     opmap = opcode['opmap'] | 
					
						
							| 
									
										
										
										
											2022-02-25 04:11:34 -08:00
										 |  |  |     opname = opcode['opname'] | 
					
						
							| 
									
										
										
										
											2022-07-01 15:33:35 +01:00
										 |  |  |     hasarg = opcode['hasarg'] | 
					
						
							| 
									
										
										
										
											2021-09-14 09:53:32 +01:00
										 |  |  |     hasconst = opcode['hasconst'] | 
					
						
							| 
									
										
										
										
											2020-08-04 17:30:11 +01:00
										 |  |  |     hasjrel = opcode['hasjrel'] | 
					
						
							|  |  |  |     hasjabs = opcode['hasjabs'] | 
					
						
							| 
									
										
										
										
											2022-07-01 15:33:35 +01:00
										 |  |  |     is_pseudo = opcode['is_pseudo'] | 
					
						
							|  |  |  |     _pseudo_ops = opcode['_pseudo_ops'] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-19 23:47:04 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-19 18:14:55 +00:00
										 |  |  |     ENABLE_SPECIALIZATION = opcode["ENABLE_SPECIALIZATION"] | 
					
						
							| 
									
										
										
										
											2022-07-01 15:33:35 +01:00
										 |  |  |     MIN_PSEUDO_OPCODE = opcode["MIN_PSEUDO_OPCODE"] | 
					
						
							|  |  |  |     MAX_PSEUDO_OPCODE = opcode["MAX_PSEUDO_OPCODE"] | 
					
						
							| 
									
										
										
										
											2023-04-12 12:04:55 +01:00
										 |  |  |     MIN_INSTRUMENTED_OPCODE = opcode["MIN_INSTRUMENTED_OPCODE"] | 
					
						
							| 
									
										
										
										
											2022-07-01 15:33:35 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     NUM_OPCODES = len(opname) | 
					
						
							|  |  |  |     used = [ False ] * len(opname) | 
					
						
							| 
									
										
										
										
											2021-06-10 08:46:01 +01:00
										 |  |  |     next_op = 1 | 
					
						
							| 
									
										
										
										
											2022-04-14 16:00:58 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-10 08:46:01 +01:00
										 |  |  |     for name, op in opmap.items(): | 
					
						
							|  |  |  |         used[op] = True | 
					
						
							| 
									
										
										
										
											2022-04-14 16:00:58 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     specialized_opmap = {} | 
					
						
							|  |  |  |     opname_including_specialized = opname.copy() | 
					
						
							| 
									
										
										
										
											2023-06-19 23:47:04 +01:00
										 |  |  |     for name in _opcode_metadata['_specialized_instructions']: | 
					
						
							| 
									
										
										
										
											2022-04-14 16:00:58 -04:00
										 |  |  |         while used[next_op]: | 
					
						
							|  |  |  |             next_op += 1 | 
					
						
							|  |  |  |         specialized_opmap[name] = next_op | 
					
						
							|  |  |  |         opname_including_specialized[next_op] = name | 
					
						
							|  |  |  |         used[next_op] = True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-02 19:00:17 -07:00
										 |  |  |     with open(outfile, 'w') as fobj, open(internaloutfile, 'w') as iobj, open( | 
					
						
							|  |  |  |             intrinsicoutfile, "w") as nobj: | 
					
						
							| 
									
										
										
										
											2014-04-15 23:50:06 +05:30
										 |  |  |         fobj.write(header) | 
					
						
							| 
									
										
										
										
											2022-04-26 00:14:30 +02:00
										 |  |  |         iobj.write(internal_header) | 
					
						
							| 
									
										
										
										
											2023-05-02 19:00:17 -07:00
										 |  |  |         nobj.write(intrinsic_header) | 
					
						
							| 
									
										
										
										
											2022-04-26 00:14:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-25 04:11:34 -08:00
										 |  |  |         for name in opname: | 
					
						
							| 
									
										
										
										
											2014-04-17 01:13:29 +02:00
										 |  |  |             if name in opmap: | 
					
						
							| 
									
										
										
										
											2022-07-01 15:33:35 +01:00
										 |  |  |                 op = opmap[name] | 
					
						
							|  |  |  |                 if op == MIN_PSEUDO_OPCODE: | 
					
						
							|  |  |  |                     fobj.write(DEFINE.format("MIN_PSEUDO_OPCODE", MIN_PSEUDO_OPCODE)) | 
					
						
							| 
									
										
										
										
											2023-04-12 12:04:55 +01:00
										 |  |  |                 if op == MIN_INSTRUMENTED_OPCODE: | 
					
						
							|  |  |  |                     fobj.write(DEFINE.format("MIN_INSTRUMENTED_OPCODE", MIN_INSTRUMENTED_OPCODE)) | 
					
						
							| 
									
										
										
										
											2022-07-01 15:33:35 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 fobj.write(DEFINE.format(name, op)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if op == MAX_PSEUDO_OPCODE: | 
					
						
							|  |  |  |                     fobj.write(DEFINE.format("MAX_PSEUDO_OPCODE", MAX_PSEUDO_OPCODE)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-14 09:53:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-14 16:00:58 -04:00
										 |  |  |         for name, op in specialized_opmap.items(): | 
					
						
							|  |  |  |             fobj.write(DEFINE.format(name, op)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-26 00:14:30 +02:00
										 |  |  |         iobj.write("\nextern const uint8_t _PyOpcode_Caches[256];\n") | 
					
						
							|  |  |  |         iobj.write("\nextern const uint8_t _PyOpcode_Deopt[256];\n") | 
					
						
							|  |  |  |         iobj.write("\n#ifdef NEED_OPCODE_TABLES\n") | 
					
						
							| 
									
										
										
										
											2022-02-28 12:56:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-26 00:14:30 +02:00
										 |  |  |         iobj.write("\nconst uint8_t _PyOpcode_Caches[256] = {\n") | 
					
						
							| 
									
										
										
										
											2022-02-28 12:56:29 +00:00
										 |  |  |         for i, entries in enumerate(opcode["_inline_cache_entries"]): | 
					
						
							|  |  |  |             if entries: | 
					
						
							| 
									
										
										
										
											2022-04-26 00:14:30 +02:00
										 |  |  |                 iobj.write(f"    [{opname[i]}] = {entries},\n") | 
					
						
							|  |  |  |         iobj.write("};\n") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-21 04:11:17 -07:00
										 |  |  |         deoptcodes = {} | 
					
						
							| 
									
										
										
										
											2022-07-01 15:33:35 +01:00
										 |  |  |         for basic, op in opmap.items(): | 
					
						
							|  |  |  |             if not is_pseudo(op): | 
					
						
							|  |  |  |                 deoptcodes[basic] = basic | 
					
						
							| 
									
										
										
										
											2023-06-19 23:47:04 +01:00
										 |  |  |         for basic, family in _opcode_metadata["_specializations"].items(): | 
					
						
							| 
									
										
										
										
											2022-03-21 04:11:17 -07:00
										 |  |  |             for specialized in family: | 
					
						
							|  |  |  |                 deoptcodes[specialized] = basic | 
					
						
							| 
									
										
										
										
											2022-04-26 00:14:30 +02:00
										 |  |  |         iobj.write("\nconst uint8_t _PyOpcode_Deopt[256] = {\n") | 
					
						
							| 
									
										
										
										
											2022-03-21 04:11:17 -07:00
										 |  |  |         for opt, deopt in sorted(deoptcodes.items()): | 
					
						
							| 
									
										
										
										
											2022-04-26 00:14:30 +02:00
										 |  |  |             iobj.write(f"    [{opt}] = {deopt},\n") | 
					
						
							|  |  |  |         iobj.write("};\n") | 
					
						
							|  |  |  |         iobj.write("#endif   // NEED_OPCODE_TABLES\n") | 
					
						
							| 
									
										
										
										
											2021-09-14 09:53:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-10 22:56:22 -08:00
										 |  |  |         fobj.write("\n") | 
					
						
							|  |  |  |         for i, (op, _) in enumerate(opcode["_nb_ops"]): | 
					
						
							|  |  |  |             fobj.write(DEFINE.format(op, i)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-02 19:00:17 -07:00
										 |  |  |         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) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-19 18:14:55 +00:00
										 |  |  |         fobj.write("\n") | 
					
						
							|  |  |  |         fobj.write("/* Defined in Lib/opcode.py */\n") | 
					
						
							|  |  |  |         fobj.write(f"#define ENABLE_SPECIALIZATION {int(ENABLE_SPECIALIZATION)}") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-26 00:14:30 +02:00
										 |  |  |         iobj.write("\n") | 
					
						
							|  |  |  |         iobj.write("#ifdef Py_DEBUG\n") | 
					
						
							| 
									
										
										
										
											2022-07-01 15:33:35 +01:00
										 |  |  |         iobj.write(f"static const char *const _PyOpcode_OpName[{NUM_OPCODES}] = {{\n") | 
					
						
							| 
									
										
										
										
											2022-04-14 16:00:58 -04:00
										 |  |  |         for op, name in enumerate(opname_including_specialized): | 
					
						
							|  |  |  |             if name[0] != "<": | 
					
						
							|  |  |  |                 op = name | 
					
						
							| 
									
										
										
										
											2022-04-26 00:14:30 +02:00
										 |  |  |             iobj.write(f'''    [{op}] = "{name}",\n''') | 
					
						
							|  |  |  |         iobj.write("};\n") | 
					
						
							|  |  |  |         iobj.write("#endif\n") | 
					
						
							| 
									
										
										
										
											2022-04-11 18:33:00 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-26 00:14:30 +02:00
										 |  |  |         iobj.write("\n") | 
					
						
							|  |  |  |         iobj.write("#define EXTRA_CASES \\\n") | 
					
						
							| 
									
										
										
										
											2022-04-21 11:53:57 -07:00
										 |  |  |         for i, flag in enumerate(used): | 
					
						
							|  |  |  |             if not flag: | 
					
						
							| 
									
										
										
										
											2022-04-26 00:14:30 +02:00
										 |  |  |                 iobj.write(f"    case {i}: \\\n") | 
					
						
							|  |  |  |         iobj.write("        ;\n") | 
					
						
							| 
									
										
										
										
											2022-04-21 11:53:57 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-15 23:50:06 +05:30
										 |  |  |         fobj.write(footer) | 
					
						
							| 
									
										
										
										
											2022-04-26 00:14:30 +02:00
										 |  |  |         iobj.write(internal_footer) | 
					
						
							| 
									
										
										
										
											2014-04-15 23:50:06 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-04 17:30:11 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-10 22:56:22 -08:00
										 |  |  |     print(f"{outfile} regenerated from {opcode_py}") | 
					
						
							| 
									
										
										
										
											2016-11-28 18:13:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-15 23:50:06 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  | if __name__ == '__main__': | 
					
						
							| 
									
										
										
										
											2023-06-19 23:47:04 +01:00
										 |  |  |     main(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5]) |