• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"""Generate the list of opcode IDs.
2Reads the instruction definitions from bytecodes.c.
3Writes the IDs to opcode_ids.h by default.
4"""
5
6import argparse
7import os.path
8import sys
9
10from analyzer import (
11    Analysis,
12    Instruction,
13    analyze_files,
14)
15from generators_common import (
16    DEFAULT_INPUT,
17    ROOT,
18    write_header,
19)
20from cwriter import CWriter
21from typing import TextIO
22
23
24DEFAULT_OUTPUT = ROOT / "Include/opcode_ids.h"
25
26
27def generate_opcode_header(
28    filenames: list[str], analysis: Analysis, outfile: TextIO
29) -> None:
30    write_header(__file__, filenames, outfile)
31    out = CWriter(outfile, 0, False)
32    with out.header_guard("Py_OPCODE_IDS_H"):
33        out.emit("/* Instruction opcodes for compiled code */\n")
34
35        def write_define(name: str, op: int) -> None:
36            out.emit(f"#define {name:<38} {op:>3}\n")
37
38        for op, name in sorted([(op, name) for (name, op) in analysis.opmap.items()]):
39            write_define(name, op)
40
41        out.emit("\n")
42        write_define("HAVE_ARGUMENT", analysis.have_arg)
43        write_define("MIN_INSTRUMENTED_OPCODE", analysis.min_instrumented)
44
45
46arg_parser = argparse.ArgumentParser(
47    description="Generate the header file with all opcode IDs.",
48    formatter_class=argparse.ArgumentDefaultsHelpFormatter,
49)
50
51arg_parser.add_argument(
52    "-o", "--output", type=str, help="Generated code", default=DEFAULT_OUTPUT
53)
54
55arg_parser.add_argument(
56    "input", nargs=argparse.REMAINDER, help="Instruction definition file(s)"
57)
58
59if __name__ == "__main__":
60    args = arg_parser.parse_args()
61    if len(args.input) == 0:
62        args.input.append(DEFAULT_INPUT)
63    data = analyze_files(args.input)
64    with open(args.output, "w") as outfile:
65        generate_opcode_header(args.input, data, outfile)
66