gh-105481: reduce repetition in opcode metadata generation code (#107942)

This commit is contained in:
Irit Katriel 2023-08-14 19:36:29 +01:00 committed by GitHub
parent 6fbaba552a
commit 39745347f6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 61 additions and 76 deletions

View file

@ -56,11 +56,9 @@
#define _POP_JUMP_IF_TRUE 332 #define _POP_JUMP_IF_TRUE 332
#define JUMP_TO_TOP 333 #define JUMP_TO_TOP 333
#ifndef NEED_OPCODE_METADATA
extern int _PyOpcode_num_popped(int opcode, int oparg, bool jump); extern int _PyOpcode_num_popped(int opcode, int oparg, bool jump);
#else #ifdef NEED_OPCODE_METADATA
int int _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
_PyOpcode_num_popped(int opcode, int oparg, bool jump) {
switch(opcode) { switch(opcode) {
case NOP: case NOP:
return 0; return 0;
@ -500,13 +498,11 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
return -1; return -1;
} }
} }
#endif #endif // NEED_OPCODE_METADATA
#ifndef NEED_OPCODE_METADATA
extern int _PyOpcode_num_pushed(int opcode, int oparg, bool jump); extern int _PyOpcode_num_pushed(int opcode, int oparg, bool jump);
#else #ifdef NEED_OPCODE_METADATA
int int _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
_PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
switch(opcode) { switch(opcode) {
case NOP: case NOP:
return 0; return 0;
@ -946,7 +942,7 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
return -1; return -1;
} }
} }
#endif #endif // NEED_OPCODE_METADATA
enum InstructionFormat { enum InstructionFormat {
INSTR_FMT_IB, INSTR_FMT_IB,
@ -1004,11 +1000,8 @@ struct opcode_macro_expansion {
#define OPCODE_UOP_NAME_SIZE 512 #define OPCODE_UOP_NAME_SIZE 512
#define OPCODE_MACRO_EXPANSION_SIZE 256 #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_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE];
extern const struct opcode_macro_expansion _PyOpcode_macro_expansion[OPCODE_MACRO_EXPANSION_SIZE]; #ifdef NEED_OPCODE_METADATA
extern const char * const _PyOpcode_uop_name[OPCODE_UOP_NAME_SIZE];
#else // if NEED_OPCODE_METADATA
const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = { const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = {
[NOP] = { true, INSTR_FMT_IX, 0 }, [NOP] = { true, INSTR_FMT_IX, 0 },
[RESUME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, [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 }, [CACHE] = { true, INSTR_FMT_IX, 0 },
[RESERVED] = { 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] = { const struct opcode_macro_expansion _PyOpcode_macro_expansion[OPCODE_MACRO_EXPANSION_SIZE] = {
[NOP] = { .nuops = 1, .uops = { { NOP, 0, 0 } } }, [NOP] = { .nuops = 1, .uops = { { NOP, 0, 0 } } },
[LOAD_FAST_CHECK] = { .nuops = 1, .uops = { { LOAD_FAST_CHECK, 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 } } }, [BINARY_OP] = { .nuops = 1, .uops = { { BINARY_OP, 0, 0 } } },
[SWAP] = { .nuops = 1, .uops = { { SWAP, 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] = { const char * const _PyOpcode_uop_name[OPCODE_UOP_NAME_SIZE] = {
[EXIT_TRACE] = "EXIT_TRACE", [EXIT_TRACE] = "EXIT_TRACE",
[SAVE_IP] = "SAVE_IP", [SAVE_IP] = "SAVE_IP",

View file

@ -4,6 +4,7 @@ Writes the cases to generated_cases.c.h, which is #included in ceval.c.
""" """
import argparse import argparse
import contextlib
import os import os
import posixpath import posixpath
import sys import sys
@ -141,6 +142,15 @@ class Generator(Analyzer):
typing.assert_never(thing) typing.assert_never(thing)
return instr, popped, pushed 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: def write_stack_effect_functions(self) -> None:
popped_data: list[tuple[AnyInstruction, str]] = [] popped_data: list[tuple[AnyInstruction, str]] = []
pushed_data: list[tuple[AnyInstruction, str]] = [] pushed_data: list[tuple[AnyInstruction, str]] = []
@ -156,25 +166,16 @@ class Generator(Analyzer):
def write_function( def write_function(
direction: str, data: list[tuple[AnyInstruction, str]] direction: str, data: list[tuple[AnyInstruction, str]]
) -> None: ) -> None:
self.out.emit("")
self.out.emit("#ifndef NEED_OPCODE_METADATA") with self.metadata_item(
self.out.emit( f"int _PyOpcode_num_{direction}(int opcode, int oparg, bool jump)", "", ""
f"extern int _PyOpcode_num_{direction}(int opcode, int oparg, bool jump);" ):
) with self.out.block("switch(opcode)"):
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: for instr, effect in data:
self.out.emit(f"case {instr.name}:") self.out.emit(f"case {instr.name}:")
self.out.emit(f" return {effect};") self.out.emit(f" return {effect};")
self.out.emit("default:") self.out.emit("default:")
self.out.emit(" return -1;") self.out.emit(" return -1;")
self.out.emit(" }")
self.out.emit("}")
self.out.emit("#endif")
write_function("popped", popped_data) write_function("popped", popped_data)
write_function("pushed", pushed_data) write_function("pushed", pushed_data)
@ -290,26 +291,13 @@ class Generator(Analyzer):
self.out.emit("#define OPCODE_METADATA_SIZE 512") self.out.emit("#define OPCODE_METADATA_SIZE 512")
self.out.emit("#define OPCODE_UOP_NAME_SIZE 512") self.out.emit("#define OPCODE_UOP_NAME_SIZE 512")
self.out.emit("#define OPCODE_MACRO_EXPANSION_SIZE 256") 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 " "const struct opcode_metadata "
"_PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = {" "_PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE]",
) "=",
";"
):
# Write metadata for each instruction # Write metadata for each instruction
for thing in self.everything: for thing in self.everything:
match thing: match thing:
@ -325,13 +313,11 @@ class Generator(Analyzer):
case _: case _:
typing.assert_never(thing) typing.assert_never(thing)
# Write end of array with self.metadata_item(
self.out.emit("};")
with self.out.block(
"const struct opcode_macro_expansion " "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 # Write macro expansion for each non-pseudo instruction
for thing in self.everything: for thing in self.everything:
@ -360,13 +346,11 @@ class Generator(Analyzer):
case _: case _:
typing.assert_never(thing) typing.assert_never(thing)
with self.out.block( with self.metadata_item(
"const char * const _PyOpcode_uop_name[OPCODE_UOP_NAME_SIZE] =", ";" "const char * const _PyOpcode_uop_name[OPCODE_UOP_NAME_SIZE]", "=", ";"
): ):
self.write_uop_items(lambda name, counter: f'[{name}] = "{name}",') self.write_uop_items(lambda name, counter: f'[{name}] = "{name}",')
self.out.emit("#endif // NEED_OPCODE_METADATA")
with open(pymetadata_filename, "w") as f: with open(pymetadata_filename, "w") as f:
# Create formatter # Create formatter
self.out = Formatter(f, 0, comment="#") self.out = Formatter(f, 0, comment="#")