summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIrit Katriel <1055913+iritkatriel@users.noreply.github.com>2023-08-14 18:36:29 (GMT)
committerGitHub <noreply@github.com>2023-08-14 18:36:29 (GMT)
commit39745347f645ac99021f4ab981ff02ab5647b19c (patch)
tree1a31122d5e7a7850e834c5dfc065b47121336cd7
parent6fbaba552a52f93ecbe8be000888afa0b65b967e (diff)
downloadcpython-39745347f645ac99021f4ab981ff02ab5647b19c.zip
cpython-39745347f645ac99021f4ab981ff02ab5647b19c.tar.gz
cpython-39745347f645ac99021f4ab981ff02ab5647b19c.tar.bz2
gh-105481: reduce repetition in opcode metadata generation code (#107942)
-rw-r--r--Include/internal/pycore_opcode_metadata.h29
-rw-r--r--Tools/cases_generator/generate_cases.py108
2 files changed, 61 insertions, 76 deletions
diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h
index 9f4437c..c0a2e9d 100644
--- a/Include/internal/pycore_opcode_metadata.h
+++ b/Include/internal/pycore_opcode_metadata.h
@@ -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",
diff --git a/Tools/cases_generator/generate_cases.py b/Tools/cases_generator/generate_cases.py
index d35a16a..e78b0ed 100644
--- a/Tools/cases_generator/generate_cases.py
+++ b/Tools/cases_generator/generate_cases.py
@@ -4,6 +4,7 @@ Writes the cases to generated_cases.c.h, which is #included in ceval.c.
"""
import argparse
+import contextlib
import os
import posixpath
import sys
@@ -141,6 +142,15 @@ class Generator(Analyzer):
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 @@ class Generator(Analyzer):
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 @@ class Generator(Analyzer):
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] = {"
- )
-
- # 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("};")
+ "_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)
- 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 @@ class Generator(Analyzer):
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 @@ class Generator(Analyzer):
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)} }},"
)