mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	gh-105481: reduce repetition in opcode metadata generation code (#107942)
This commit is contained in:
		
							parent
							
								
									6fbaba552a
								
							
						
					
					
						commit
						39745347f6
					
				
					 2 changed files with 61 additions and 76 deletions
				
			
		
							
								
								
									
										29
									
								
								Include/internal/pycore_opcode_metadata.h
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										29
									
								
								Include/internal/pycore_opcode_metadata.h
									
										
									
										generated
									
									
									
								
							|  | @ -56,11 +56,9 @@ | |||
| #define _POP_JUMP_IF_TRUE 332 | ||||
| #define JUMP_TO_TOP 333 | ||||
| 
 | ||||
| #ifndef NEED_OPCODE_METADATA | ||||
| extern int _PyOpcode_num_popped(int opcode, int oparg, bool jump); | ||||
| #else | ||||
| int | ||||
| _PyOpcode_num_popped(int opcode, int oparg, bool jump) { | ||||
| #ifdef NEED_OPCODE_METADATA | ||||
| int _PyOpcode_num_popped(int opcode, int oparg, bool jump)  { | ||||
|     switch(opcode) { | ||||
|         case NOP: | ||||
|             return 0; | ||||
|  | @ -500,13 +498,11 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) { | |||
|             return -1; | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #endif // NEED_OPCODE_METADATA
 | ||||
| 
 | ||||
| #ifndef NEED_OPCODE_METADATA | ||||
| extern int _PyOpcode_num_pushed(int opcode, int oparg, bool jump); | ||||
| #else | ||||
| int | ||||
| _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { | ||||
| #ifdef NEED_OPCODE_METADATA | ||||
| int _PyOpcode_num_pushed(int opcode, int oparg, bool jump)  { | ||||
|     switch(opcode) { | ||||
|         case NOP: | ||||
|             return 0; | ||||
|  | @ -946,7 +942,7 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { | |||
|             return -1; | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #endif // NEED_OPCODE_METADATA
 | ||||
| 
 | ||||
| enum InstructionFormat { | ||||
|     INSTR_FMT_IB, | ||||
|  | @ -1004,11 +1000,8 @@ struct opcode_macro_expansion { | |||
| #define OPCODE_UOP_NAME_SIZE 512 | ||||
| #define OPCODE_MACRO_EXPANSION_SIZE 256 | ||||
| 
 | ||||
| #ifndef NEED_OPCODE_METADATA | ||||
| extern const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE]; | ||||
| extern const struct opcode_macro_expansion _PyOpcode_macro_expansion[OPCODE_MACRO_EXPANSION_SIZE]; | ||||
| extern const char * const _PyOpcode_uop_name[OPCODE_UOP_NAME_SIZE]; | ||||
| #else // if NEED_OPCODE_METADATA
 | ||||
| #ifdef NEED_OPCODE_METADATA | ||||
| const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = { | ||||
|     [NOP] = { true, INSTR_FMT_IX, 0 }, | ||||
|     [RESUME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, | ||||
|  | @ -1228,6 +1221,10 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = { | |||
|     [CACHE] = { true, INSTR_FMT_IX, 0 }, | ||||
|     [RESERVED] = { true, INSTR_FMT_IX, 0 }, | ||||
| }; | ||||
| #endif // NEED_OPCODE_METADATA
 | ||||
| 
 | ||||
| extern const struct opcode_macro_expansion _PyOpcode_macro_expansion[OPCODE_MACRO_EXPANSION_SIZE]; | ||||
| #ifdef NEED_OPCODE_METADATA | ||||
| const struct opcode_macro_expansion _PyOpcode_macro_expansion[OPCODE_MACRO_EXPANSION_SIZE] = { | ||||
|     [NOP] = { .nuops = 1, .uops = { { NOP, 0, 0 } } }, | ||||
|     [LOAD_FAST_CHECK] = { .nuops = 1, .uops = { { LOAD_FAST_CHECK, 0, 0 } } }, | ||||
|  | @ -1357,6 +1354,10 @@ const struct opcode_macro_expansion _PyOpcode_macro_expansion[OPCODE_MACRO_EXPAN | |||
|     [BINARY_OP] = { .nuops = 1, .uops = { { BINARY_OP, 0, 0 } } }, | ||||
|     [SWAP] = { .nuops = 1, .uops = { { SWAP, 0, 0 } } }, | ||||
| }; | ||||
| #endif // NEED_OPCODE_METADATA
 | ||||
| 
 | ||||
| extern const char * const _PyOpcode_uop_name[OPCODE_UOP_NAME_SIZE]; | ||||
| #ifdef NEED_OPCODE_METADATA | ||||
| const char * const _PyOpcode_uop_name[OPCODE_UOP_NAME_SIZE] = { | ||||
|     [EXIT_TRACE] = "EXIT_TRACE", | ||||
|     [SAVE_IP] = "SAVE_IP", | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ | |||
| """ | ||||
| 
 | ||||
| import argparse | ||||
| import contextlib | ||||
| import os | ||||
| import posixpath | ||||
| import sys | ||||
|  | @ -141,6 +142,15 @@ def effect_str(effects: list[StackEffect]) -> str: | |||
|                 typing.assert_never(thing) | ||||
|         return instr, popped, pushed | ||||
| 
 | ||||
|     @contextlib.contextmanager | ||||
|     def metadata_item(self, signature, open, close): | ||||
|         self.out.emit("") | ||||
|         self.out.emit(f"extern {signature};") | ||||
|         self.out.emit("#ifdef NEED_OPCODE_METADATA") | ||||
|         with self.out.block(f"{signature} {open}", close): | ||||
|             yield | ||||
|         self.out.emit("#endif // NEED_OPCODE_METADATA") | ||||
| 
 | ||||
|     def write_stack_effect_functions(self) -> None: | ||||
|         popped_data: list[tuple[AnyInstruction, str]] = [] | ||||
|         pushed_data: list[tuple[AnyInstruction, str]] = [] | ||||
|  | @ -156,25 +166,16 @@ def write_stack_effect_functions(self) -> None: | |||
|         def write_function( | ||||
|             direction: str, data: list[tuple[AnyInstruction, str]] | ||||
|         ) -> None: | ||||
|             self.out.emit("") | ||||
|             self.out.emit("#ifndef NEED_OPCODE_METADATA") | ||||
|             self.out.emit( | ||||
|                 f"extern int _PyOpcode_num_{direction}(int opcode, int oparg, bool jump);" | ||||
|             ) | ||||
|             self.out.emit("#else") | ||||
|             self.out.emit("int") | ||||
|             self.out.emit( | ||||
|                 f"_PyOpcode_num_{direction}(int opcode, int oparg, bool jump) {{" | ||||
|             ) | ||||
|             self.out.emit("    switch(opcode) {") | ||||
|             for instr, effect in data: | ||||
|                 self.out.emit(f"        case {instr.name}:") | ||||
|                 self.out.emit(f"            return {effect};") | ||||
|             self.out.emit("        default:") | ||||
|             self.out.emit("            return -1;") | ||||
|             self.out.emit("    }") | ||||
|             self.out.emit("}") | ||||
|             self.out.emit("#endif") | ||||
| 
 | ||||
|             with self.metadata_item( | ||||
|                 f"int _PyOpcode_num_{direction}(int opcode, int oparg, bool jump)", "", "" | ||||
|             ): | ||||
|                 with self.out.block("switch(opcode)"): | ||||
|                     for instr, effect in data: | ||||
|                         self.out.emit(f"case {instr.name}:") | ||||
|                         self.out.emit(f"    return {effect};") | ||||
|                     self.out.emit("default:") | ||||
|                     self.out.emit("    return -1;") | ||||
| 
 | ||||
|         write_function("popped", popped_data) | ||||
|         write_function("pushed", pushed_data) | ||||
|  | @ -290,48 +291,33 @@ def write_metadata(self, metadata_filename: str, pymetadata_filename: str) -> No | |||
|             self.out.emit("#define OPCODE_METADATA_SIZE 512") | ||||
|             self.out.emit("#define OPCODE_UOP_NAME_SIZE 512") | ||||
|             self.out.emit("#define OPCODE_MACRO_EXPANSION_SIZE 256") | ||||
|             self.out.emit("") | ||||
|             self.out.emit("#ifndef NEED_OPCODE_METADATA") | ||||
|             self.out.emit( | ||||
|                 "extern const struct opcode_metadata " | ||||
|                 "_PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE];" | ||||
|             ) | ||||
|             self.out.emit( | ||||
|                 "extern const struct opcode_macro_expansion " | ||||
|                 "_PyOpcode_macro_expansion[OPCODE_MACRO_EXPANSION_SIZE];" | ||||
|             ) | ||||
|             self.out.emit( | ||||
|                 "extern const char * const _PyOpcode_uop_name[OPCODE_UOP_NAME_SIZE];" | ||||
|             ) | ||||
|             self.out.emit("#else // if NEED_OPCODE_METADATA") | ||||
| 
 | ||||
|             self.out.emit( | ||||
|             with self.metadata_item( | ||||
|                 "const struct opcode_metadata " | ||||
|                 "_PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = {" | ||||
|             ) | ||||
|                 "_PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE]", | ||||
|                 "=", | ||||
|                 ";" | ||||
|             ): | ||||
|                 # Write metadata for each instruction | ||||
|                 for thing in self.everything: | ||||
|                     match thing: | ||||
|                         case OverriddenInstructionPlaceHolder(): | ||||
|                             continue | ||||
|                         case parsing.InstDef(): | ||||
|                             if thing.kind != "op": | ||||
|                                 self.write_metadata_for_inst(self.instrs[thing.name]) | ||||
|                         case parsing.Macro(): | ||||
|                             self.write_metadata_for_macro(self.macro_instrs[thing.name]) | ||||
|                         case parsing.Pseudo(): | ||||
|                             self.write_metadata_for_pseudo(self.pseudo_instrs[thing.name]) | ||||
|                         case _: | ||||
|                             typing.assert_never(thing) | ||||
| 
 | ||||
|             # Write metadata for each instruction | ||||
|             for thing in self.everything: | ||||
|                 match thing: | ||||
|                     case OverriddenInstructionPlaceHolder(): | ||||
|                         continue | ||||
|                     case parsing.InstDef(): | ||||
|                         if thing.kind != "op": | ||||
|                             self.write_metadata_for_inst(self.instrs[thing.name]) | ||||
|                     case parsing.Macro(): | ||||
|                         self.write_metadata_for_macro(self.macro_instrs[thing.name]) | ||||
|                     case parsing.Pseudo(): | ||||
|                         self.write_metadata_for_pseudo(self.pseudo_instrs[thing.name]) | ||||
|                     case _: | ||||
|                         typing.assert_never(thing) | ||||
| 
 | ||||
|             # Write end of array | ||||
|             self.out.emit("};") | ||||
| 
 | ||||
|             with self.out.block( | ||||
|             with self.metadata_item( | ||||
|                 "const struct opcode_macro_expansion " | ||||
|                 "_PyOpcode_macro_expansion[OPCODE_MACRO_EXPANSION_SIZE] =", | ||||
|                 ";", | ||||
|                 "_PyOpcode_macro_expansion[OPCODE_MACRO_EXPANSION_SIZE]", | ||||
|                 "=", | ||||
|                 ";" | ||||
|             ): | ||||
|                 # Write macro expansion for each non-pseudo instruction | ||||
|                 for thing in self.everything: | ||||
|  | @ -360,13 +346,11 @@ def write_metadata(self, metadata_filename: str, pymetadata_filename: str) -> No | |||
|                         case _: | ||||
|                             typing.assert_never(thing) | ||||
| 
 | ||||
|             with self.out.block( | ||||
|                 "const char * const _PyOpcode_uop_name[OPCODE_UOP_NAME_SIZE] =", ";" | ||||
|             with self.metadata_item( | ||||
|                 "const char * const _PyOpcode_uop_name[OPCODE_UOP_NAME_SIZE]", "=", ";" | ||||
|             ): | ||||
|                 self.write_uop_items(lambda name, counter: f'[{name}] = "{name}",') | ||||
| 
 | ||||
|             self.out.emit("#endif // NEED_OPCODE_METADATA") | ||||
| 
 | ||||
|         with open(pymetadata_filename, "w") as f: | ||||
|             # Create formatter | ||||
|             self.out = Formatter(f, 0, comment="#") | ||||
|  | @ -511,7 +495,7 @@ def emit_metadata_entry(self, name: str, fmt: str, flags: InstructionFlags) -> N | |||
|         if not flag_names: | ||||
|             flag_names.append("0") | ||||
|         self.out.emit( | ||||
|             f"    [{name}] = {{ true, {INSTR_FMT_PREFIX}{fmt}," | ||||
|             f"[{name}] = {{ true, {INSTR_FMT_PREFIX}{fmt}," | ||||
|             f" {' | '.join(flag_names)} }}," | ||||
|         ) | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Irit Katriel
						Irit Katriel