mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
gh-107557: Setup abstract interpretation (#107847)
Co-authored-by: Guido van Rossum <gvanrossum@users.noreply.github.com> Co-authored-by: Jules <57632293+juliapoo@users.noreply.github.com>
This commit is contained in:
parent
34e1917912
commit
e28b0dc86d
21 changed files with 1118 additions and 9 deletions
|
@ -16,6 +16,7 @@ from formatting import Formatter, list_effect_size
|
|||
from flags import InstructionFlags, variable_used
|
||||
from instructions import (
|
||||
AnyInstruction,
|
||||
AbstractInstruction,
|
||||
Component,
|
||||
Instruction,
|
||||
MacroInstruction,
|
||||
|
@ -44,6 +45,9 @@ DEFAULT_PYMETADATA_OUTPUT = os.path.relpath(
|
|||
DEFAULT_EXECUTOR_OUTPUT = os.path.relpath(
|
||||
os.path.join(ROOT, "Python/executor_cases.c.h")
|
||||
)
|
||||
DEFAULT_ABSTRACT_INTERPRETER_OUTPUT = os.path.relpath(
|
||||
os.path.join(ROOT, "Python/abstract_interp_cases.c.h")
|
||||
)
|
||||
|
||||
# Constants used instead of size for macro expansions.
|
||||
# Note: 1, 2, 4 must match actual cache entry sizes.
|
||||
|
@ -58,6 +62,23 @@ OPARG_SIZES = {
|
|||
|
||||
INSTR_FMT_PREFIX = "INSTR_FMT_"
|
||||
|
||||
# TODO: generate all these after updating the DSL
|
||||
SPECIALLY_HANDLED_ABSTRACT_INSTR = {
|
||||
"LOAD_FAST",
|
||||
"LOAD_FAST_CHECK",
|
||||
"LOAD_FAST_AND_CLEAR",
|
||||
"LOAD_CONST",
|
||||
"STORE_FAST",
|
||||
"STORE_FAST_MAYBE_NULL",
|
||||
"COPY",
|
||||
|
||||
# Arithmetic
|
||||
"_BINARY_OP_MULTIPLY_INT",
|
||||
"_BINARY_OP_ADD_INT",
|
||||
"_BINARY_OP_SUBTRACT_INT",
|
||||
|
||||
}
|
||||
|
||||
arg_parser = argparse.ArgumentParser(
|
||||
description="Generate the code for the interpreter switch.",
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
|
@ -92,7 +113,13 @@ arg_parser.add_argument(
|
|||
help="Write executor cases to this file",
|
||||
default=DEFAULT_EXECUTOR_OUTPUT,
|
||||
)
|
||||
|
||||
arg_parser.add_argument(
|
||||
"-a",
|
||||
"--abstract-interpreter-cases",
|
||||
type=str,
|
||||
help="Write abstract interpreter cases to this file",
|
||||
default=DEFAULT_ABSTRACT_INTERPRETER_OUTPUT,
|
||||
)
|
||||
|
||||
class Generator(Analyzer):
|
||||
def get_stack_effect_info(
|
||||
|
@ -109,7 +136,7 @@ class Generator(Analyzer):
|
|||
pushed: str | None
|
||||
match thing:
|
||||
case parsing.InstDef():
|
||||
if thing.kind != "op":
|
||||
if thing.kind != "op" or self.instrs[thing.name].is_viable_uop():
|
||||
instr = self.instrs[thing.name]
|
||||
popped = effect_str(instr.input_effects)
|
||||
pushed = effect_str(instr.output_effects)
|
||||
|
@ -588,6 +615,35 @@ class Generator(Analyzer):
|
|||
file=sys.stderr,
|
||||
)
|
||||
|
||||
def write_abstract_interpreter_instructions(
|
||||
self, abstract_interpreter_filename: str, emit_line_directives: bool
|
||||
) -> None:
|
||||
"""Generate cases for the Tier 2 abstract interpreter/analzyer."""
|
||||
with open(abstract_interpreter_filename, "w") as f:
|
||||
self.out = Formatter(f, 8, emit_line_directives)
|
||||
self.write_provenance_header()
|
||||
for thing in self.everything:
|
||||
match thing:
|
||||
case OverriddenInstructionPlaceHolder():
|
||||
pass
|
||||
case parsing.InstDef():
|
||||
instr = AbstractInstruction(self.instrs[thing.name].inst)
|
||||
if instr.is_viable_uop() and instr.name not in SPECIALLY_HANDLED_ABSTRACT_INSTR:
|
||||
self.out.emit("")
|
||||
with self.out.block(f"case {thing.name}:"):
|
||||
instr.write(self.out, tier=TIER_TWO)
|
||||
self.out.emit("break;")
|
||||
case parsing.Macro():
|
||||
pass
|
||||
case parsing.Pseudo():
|
||||
pass
|
||||
case _:
|
||||
typing.assert_never(thing)
|
||||
print(
|
||||
f"Wrote some stuff to {abstract_interpreter_filename}",
|
||||
file=sys.stderr,
|
||||
)
|
||||
|
||||
def write_overridden_instr_place_holder(
|
||||
self, place_holder: OverriddenInstructionPlaceHolder
|
||||
) -> None:
|
||||
|
@ -629,6 +685,8 @@ def main():
|
|||
a.write_instructions(args.output, args.emit_line_directives)
|
||||
a.write_metadata(args.metadata, args.pymetadata)
|
||||
a.write_executor_instructions(args.executor_cases, args.emit_line_directives)
|
||||
a.write_abstract_interpreter_instructions(args.abstract_interpreter_cases,
|
||||
args.emit_line_directives)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue