8000 GH-98831: Remove super-instruction definitions, use macro instructions instead by gvanrossum · Pull Request #100124 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

GH-98831: Remove super-instruction definitions, use macro instructions instead #100124

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Rip out parser and generator support for super()
  • Loading branch information
gvanrossum committed Dec 9, 2022
commit eadca5182a47d30324e6a8da6471a061165c665d
84 changes: 12 additions & 72 deletions Tools/cases_generator/generate_cases.py
8000
Original file line number Diff line number Diff line change
Expand Up @@ -260,27 +260,13 @@ def write_body(self, out: Formatter, cache_adjust: int) -> None:


@dataclasses.dataclass
class SuperOrMacroInstruction:
"""Common fields for super- and macro instructions."""
class MacroInstruction:
"""A macro instruction."""

name: str
stack: list[StackEffect]
initial_sp: int
final_sp: int


@dataclasses.dataclass
class SuperInstruction(SuperOrMacroInstruction):
"""A super-instruction."""

super: parser.Super
parts: list[Component]


@dataclasses.dataclass
class MacroInstruction(SuperOrMacroInstruction):
"""A macro instruction."""

macro: parser.Macro
parts: list[Component | parser.CacheEffect]

Expand Down Expand Up @@ -311,10 +297,8 @@ def error(self, msg: str, node: parser.Node) -> None:
print(f"{self.filename}:{lineno}: {msg}", file=sys.stderr)
self.errors += 1

everything: list[parser.InstDef | parser.Super | parser.Macro]
everything: list[parser.InstDef | parser.Macro]
instrs: dict[str, Instruction] # Includes ops
supers: dict[str, parser.Super]
super_instrs: dict[str, SuperInstruction]
macros: dict[str, parser.Macro]
macro_instrs: dict[str, MacroInstruction]
families: dict[str, parser.Family]
Expand Down Expand Up @@ -347,17 +331,13 @@ def parse(self) -> None:
psr.setpos(start)
self.everything = []
self.instrs = {}
self.supers = {}
self.macros = {}
self.families = {}
while thing := psr.definition():
match thing:
case parser.InstDef(name=name):
self.instrs[name] = Instruction(thing)
self.everything.append(thing)
case parser.Super(name):
self.supers[name] = thing
self.everything.append(thing)
case parser.Macro(name):
self.macros[name] = thing
self.everything.append(thing)
Expand All @@ -370,7 +350,7 @@ def parse(self) -> None:

print(
f"Read {len(self.instrs)} instructions/ops, "
f"{len(self.supers)} supers, {len(self.macros)} macros, "
f"{len(self.macros)} macros, "
f"and {len(self.families)} families from {self.filename}",
file=sys.stderr,
)
Expand All @@ -383,7 +363,7 @@ def analyze(self) -> None:
self.find_predictions()
self.map_families()
self.check_families()
self.analyze_supers_and_macros()
self.analyze_macros()

def find_predictions(self) -> None:
"""Find the instructions that need PREDICTED() labels."""
Expand Down Expand Up @@ -449,26 +429,12 @@ def check_families(self) -> None:
family,
)

def analyze_supers_and_macros(self) -> None:
"""Analyze each super- and macro instruction."""
self.super_instrs = {}
def analyze_macros(self) -> None:
"""Analyze each macro instruction."""
self.macro_instrs = {}
for name, super in self.supers.items():
self.super_instrs[name] = self.analyze_super(super)
for name, macro in self.macros.items():
self.macro_instrs[name] = self.analyze_macro(macro)

def analyze_super(self, super: parser.Super) -> SuperInstruction:
components = self.check_super_components(super)
stack, initial_sp = self.stack_analysis(components)
sp = initial_sp
parts: list[Component] = []
for instr in components:
part, sp = self.analyze_instruction(instr, stack, sp)
parts.append(part)
final_sp = sp
return SuperInstruction(super.name, stack, initial_sp, final_sp, super, parts)

def analyze_macro(self, macro: parser.Macro) -> MacroInstruction:
components = self.check_macro_components(macro)
stack, initial_sp = self.stack_analysis(components)
Expand Down Expand Up @@ -499,15 +465,6 @@ def analyze_instruction(
sp += 1
return Component(instr, input_mapping, output_mapping), sp

def check_super_components(self, super: parser.Super) -> list[Instruction]:
components: list[Instruction] = []
for op in super.ops:
if op.name not in self.instrs:
self.error(f"Unknown instruction {op.name!r}", super)
else:
components.append(self.instrs[op.name])
return components

def check_macro_components(
self, macro: parser.Macro
) -> list[InstructionOrCacheEffect]:
Expand All @@ -527,7 +484,7 @@ def check_macro_components(
def stack_analysis(
self, components: typing.Iterable[InstructionOrCacheEffect]
) -> tuple[list[StackEffect], int]:
"""Analyze a super-instruction or macro.
"""Analyze a macro instruction.

Print an error if there's a cache effect (which we don't support yet).

Expand Down Expand Up @@ -567,25 +524,21 @@ def write_instructions(self) -> None:

# Write and count instructions of all kinds
n_instrs = 0
n_supers = 0
n_macros = 0
for thing in self.everything:
match thing:
case parser.InstDef():
if thing.kind == "inst":
n_instrs += 1
self.write_instr(self.instrs[thing.name])
case parser.Super():
n_supers += 1
self.write_super(self.super_instrs[thing.name])
case parser.Macro():
n_macros += 1
self.write_macro(self.macro_instrs[thing.name])
case _:
typing.assert_never(thing)

print(
f"Wrote {n_instrs} instructions, {n_supers} supers, "
f"Wrote {n_instrs} instructions, "
f"and {n_macros} macros to {self.output_filename}",
file=sys.stderr,
)
Expand All @@ -602,22 +555,9 @@ def write_instr(self, instr: Instruction) -> None:
self.out.emit(f"PREDICT({prediction});")
self.out.emit(f"DISPATCH();")

def write_super(self, sup: SuperInstruction) -> None:
"""Write code for a super-instruction."""
with self.wrap_super_or_macro(sup):
first = True
for comp in sup.parts:
if not first:
self.out.emit("NEXTOPARG();")
self.out.emit("JUMPBY(1);")
first = False
comp.write_body(self.out, 0)
if comp.instr.cache_offset:
self.out.emit(f"JUMPBY({comp.instr.cache_offset});")

def write_macro(self, mac: MacroInstruction) -> None:
"""Write code for a macro instruction."""
with self.wrap_super_or_macro(mac):
with self.wrap_macro(mac):
cache_adjust = 0
for part in mac.parts:
match part:
Expand All @@ -631,8 +571,8 @@ def write_macro(self, mac: MacroInstruction) -> None:
self.out.emit(f"JUMPBY({cache_adjust});")

@contextlib.contextmanager
def wrap_super_or_macro(self, up: SuperOrMacroInstruction):
"""Shared boilerplate for super- and macro instructions."""
def wrap_macro(self, up: MacroInstruction):
"""Boilerplate for macro instructions."""
# TODO: Somewhere (where?) make it so that if one instruction
# has an output that is input to another, and the variable names
# and types match and don't conflict with other instructions,
Expand Down
22 changes: 1 addition & 21 deletions Tools/cases_generator/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,6 @@ class InstDef(Node):
block: Block


@dataclass
class Super(Node):
name: str
ops: list[OpName]


@dataclass
class Macro(Node):
name: str
Expand All @@ -120,11 +114,9 @@ class Family(Node):

class Parser(PLexer):
@contextual
def definition(self) -> InstDef | Super | Macro | Family | None:
def definition(self) -> InstDef | Macro | Family | None:
if inst := self.inst_def():
return inst
if super := self.super_def():
return super
if macro := self.macro_def():
return macro
if family := self.family_def():
Expand Down Expand Up @@ -224,18 +216,6 @@ def stack_effect(self) -> StackEffect | None:
type = self.require(lx.IDENTIFIER).text
return StackEffect(tkn.text, type)

@contextual
def super_def(self) -> Super | None:
if (tkn := self.expect(lx.IDENTIFIER)) and tkn.text == "super":
if self.expect(lx.LPAREN):
if tkn := self.expect(lx.IDENTIFIER):
if self.expect(lx.RPAREN):
if self.expect(lx.EQUALS):
if ops := self.ops():
Comment on lines -229 to -234
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kill it with fire! ;)

self.require(lx.SEMI)
res = Super(tkn.text, ops)
return res

def ops(self) -> list[OpName] | None:
if op := self.op():
ops = [op]
Expand Down
0