| 
									
										
										
										
											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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-19 01:23:18 +05:30
										 |  |  | header = """
 | 
					
						
							|  |  |  | /* Auto-generated by Tools/scripts/generate_opcode_h.py from Lib/opcode.py */ | 
					
						
							| 
									
										
										
										
											2014-04-15 23:50:06 +05:30
										 |  |  | #ifndef Py_OPCODE_H | 
					
						
							|  |  |  | #define Py_OPCODE_H | 
					
						
							|  |  |  | #ifdef __cplusplus | 
					
						
							|  |  |  | extern "C" { | 
					
						
							|  |  |  | #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 = """
 | 
					
						
							|  |  |  | #define HAS_ARG(op) ((op) >= HAVE_ARGUMENT) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-07 15:19:19 +01:00
										 |  |  | /* Reserve some bytecodes for internal use in the compiler. | 
					
						
							|  |  |  |  * The value of 240 is arbitrary. */ | 
					
						
							|  |  |  | #define IS_ARTIFICIAL(op) ((op) > 240) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-15 23:50:06 +05:30
										 |  |  | #ifdef __cplusplus | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif | 
					
						
							|  |  |  | #endif /* !Py_OPCODE_H */ | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def write_int_array_from_ops(name, ops, out): | 
					
						
							|  |  |  |     bits = 0 | 
					
						
							|  |  |  |     for op in ops: | 
					
						
							|  |  |  |         bits |= 1<<op | 
					
						
							| 
									
										
										
										
											2022-02-28 12:56:29 +00:00
										 |  |  |     out.write(f"static const uint32_t {name}[8] = {{\n") | 
					
						
							| 
									
										
										
										
											2020-08-04 17:30:11 +01:00
										 |  |  |     for i in range(8): | 
					
						
							|  |  |  |         out.write(f"    {bits & UINT32_MASK}U,\n") | 
					
						
							|  |  |  |         bits >>= 32 | 
					
						
							|  |  |  |     assert bits == 0 | 
					
						
							|  |  |  |     out.write(f"}};\n") | 
					
						
							| 
									
										
										
										
											2014-04-15 23:50:06 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-17 01:13:29 +02:00
										 |  |  | def main(opcode_py, outfile='Include/opcode.h'): | 
					
						
							|  |  |  |     opcode = {} | 
					
						
							| 
									
										
										
										
											2016-11-28 18:13:52 +01:00
										 |  |  |     if hasattr(tokenize, 'open'): | 
					
						
							|  |  |  |         fp = tokenize.open(opcode_py)   # Python 3.2+ | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         fp = open(opcode_py)            # Python 2.7 | 
					
						
							|  |  |  |     with fp: | 
					
						
							| 
									
										
										
										
											2016-11-25 11:59:52 +01:00
										 |  |  |         code = fp.read() | 
					
						
							|  |  |  |     exec(code, opcode) | 
					
						
							| 
									
										
										
										
											2014-04-17 01:13:29 +02:00
										 |  |  |     opmap = opcode['opmap'] | 
					
						
							| 
									
										
										
										
											2022-02-25 04:11:34 -08:00
										 |  |  |     opname = opcode['opname'] | 
					
						
							| 
									
										
										
										
											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'] | 
					
						
							| 
									
										
										
										
											2021-06-10 08:46:01 +01:00
										 |  |  |     used = [ False ] * 256 | 
					
						
							|  |  |  |     next_op = 1 | 
					
						
							|  |  |  |     for name, op in opmap.items(): | 
					
						
							|  |  |  |         used[op] = True | 
					
						
							| 
									
										
										
										
											2014-04-15 23:50:06 +05:30
										 |  |  |     with open(outfile, 'w') as fobj: | 
					
						
							|  |  |  |         fobj.write(header) | 
					
						
							| 
									
										
										
										
											2022-02-25 04:11:34 -08:00
										 |  |  |         for name in opname: | 
					
						
							| 
									
										
										
										
											2014-04-17 01:13:29 +02:00
										 |  |  |             if name in opmap: | 
					
						
							| 
									
										
										
										
											2021-11-10 22:56:22 -08:00
										 |  |  |                 fobj.write(DEFINE.format(name, opmap[name])) | 
					
						
							| 
									
										
										
										
											2014-04-15 23:50:06 +05:30
										 |  |  |             if name == 'POP_EXCEPT': # Special entry for HAVE_ARGUMENT | 
					
						
							| 
									
										
										
										
											2021-11-10 22:56:22 -08:00
										 |  |  |                 fobj.write(DEFINE.format("HAVE_ARGUMENT", opcode["HAVE_ARGUMENT"])) | 
					
						
							| 
									
										
										
										
											2021-09-14 09:53:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-10 08:46:01 +01:00
										 |  |  |         for name in opcode['_specialized_instructions']: | 
					
						
							|  |  |  |             while used[next_op]: | 
					
						
							|  |  |  |                 next_op += 1 | 
					
						
							| 
									
										
										
										
											2021-11-10 22:56:22 -08:00
										 |  |  |             fobj.write(DEFINE.format(name, next_op)) | 
					
						
							| 
									
										
										
										
											2021-06-10 08:46:01 +01:00
										 |  |  |             used[next_op] = True | 
					
						
							| 
									
										
										
										
											2021-11-10 22:56:22 -08:00
										 |  |  |         fobj.write(DEFINE.format('DO_TRACING', 255)) | 
					
						
							| 
									
										
										
										
											2022-03-21 04:11:17 -07:00
										 |  |  |         fobj.write("\nextern const uint8_t _PyOpcode_Caches[256];\n") | 
					
						
							|  |  |  |         fobj.write("\nextern const uint8_t _PyOpcode_Deopt[256];\n") | 
					
						
							| 
									
										
										
										
											2022-02-28 12:56:29 +00:00
										 |  |  |         fobj.write("\n#ifdef NEED_OPCODE_TABLES\n") | 
					
						
							| 
									
										
										
										
											2020-08-04 17:30:11 +01:00
										 |  |  |         write_int_array_from_ops("_PyOpcode_RelativeJump", opcode['hasjrel'], fobj) | 
					
						
							|  |  |  |         write_int_array_from_ops("_PyOpcode_Jump", opcode['hasjrel'] + opcode['hasjabs'], fobj) | 
					
						
							| 
									
										
										
										
											2022-02-28 12:56:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-21 04:11:17 -07:00
										 |  |  |         fobj.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: | 
					
						
							|  |  |  |                 fobj.write(f"    [{opname[i]}] = {entries},\n") | 
					
						
							|  |  |  |         fobj.write("};\n") | 
					
						
							| 
									
										
										
										
											2022-03-21 04:11:17 -07:00
										 |  |  |         deoptcodes = {} | 
					
						
							|  |  |  |         for basic in opmap: | 
					
						
							|  |  |  |             deoptcodes[basic] = basic | 
					
						
							|  |  |  |         for basic, family in opcode["_specializations"].items(): | 
					
						
							|  |  |  |             for specialized in family: | 
					
						
							|  |  |  |                 deoptcodes[specialized] = basic | 
					
						
							|  |  |  |         fobj.write("\nconst uint8_t _PyOpcode_Deopt[256] = {\n") | 
					
						
							|  |  |  |         for opt, deopt in sorted(deoptcodes.items()): | 
					
						
							|  |  |  |             fobj.write(f"    [{opt}] = {deopt},\n") | 
					
						
							|  |  |  |         fobj.write("};\n") | 
					
						
							| 
									
										
										
										
											2020-08-04 17:30:11 +01:00
										 |  |  |         fobj.write("#endif /* OPCODE_TABLES */\n") | 
					
						
							| 
									
										
										
										
											2021-09-14 09:53:32 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         fobj.write("\n") | 
					
						
							|  |  |  |         fobj.write("#define HAS_CONST(op) (false\\") | 
					
						
							|  |  |  |         for op in hasconst: | 
					
						
							|  |  |  |             fobj.write(f"\n    || ((op) == {op}) \\") | 
					
						
							|  |  |  |         fobj.write("\n    )\n") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-15 23:50:06 +05:30
										 |  |  |         fobj.write(footer) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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__': | 
					
						
							| 
									
										
										
										
											2014-04-17 01:13:29 +02:00
										 |  |  |     main(sys.argv[1], sys.argv[2]) |