mirror of
https://github.com/python/cpython.git
synced 2025-09-23 00:43:12 +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 _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",
|
||||||
|
|
|
@ -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")
|
for instr, effect in data:
|
||||||
self.out.emit("int")
|
self.out.emit(f"case {instr.name}:")
|
||||||
self.out.emit(
|
self.out.emit(f" return {effect};")
|
||||||
f"_PyOpcode_num_{direction}(int opcode, int oparg, bool jump) {{"
|
self.out.emit("default:")
|
||||||
)
|
self.out.emit(" return -1;")
|
||||||
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")
|
|
||||||
|
|
||||||
write_function("popped", popped_data)
|
write_function("popped", popped_data)
|
||||||
write_function("pushed", pushed_data)
|
write_function("pushed", pushed_data)
|
||||||
|
@ -290,48 +291,33 @@ 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
|
||||||
|
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
|
with self.metadata_item(
|
||||||
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(
|
|
||||||
"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="#")
|
||||||
|
@ -511,7 +495,7 @@ class Generator(Analyzer):
|
||||||
if not flag_names:
|
if not flag_names:
|
||||||
flag_names.append("0")
|
flag_names.append("0")
|
||||||
self.out.emit(
|
self.out.emit(
|
||||||
f" [{name}] = {{ true, {INSTR_FMT_PREFIX}{fmt},"
|
f"[{name}] = {{ true, {INSTR_FMT_PREFIX}{fmt},"
|
||||||
f" {' | '.join(flag_names)} }},"
|
f" {' | '.join(flag_names)} }},"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue