Skip to content

GH-118926: Better distinguish between pointer and arrays in interpreter generator #121496

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

Merged
merged 3 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
44 changes: 43 additions & 1 deletion Lib/test/test_generated_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -815,7 +815,6 @@ def test_annotated_op(self):
"""
self.run_cases_test(input, output)


def test_deopt_and_exit(self):
input = """
pure op(OP, (arg1 -- out)) {
Expand All @@ -827,6 +826,49 @@ def test_deopt_and_exit(self):
with self.assertRaises(Exception):
self.run_cases_test(input, output)

def test_array_of_one(self):
input = """
inst(OP, (arg[1] -- out[1])) {
out[0] = arg[0];
}
"""
output = """
TARGET(OP) {
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(OP);
_PyStackRef *arg;
_PyStackRef *out;
arg = &stack_pointer[-1];
out = &stack_pointer[-1];
out[0] = arg[0];
DISPATCH();
}
"""
self.run_cases_test(input, output)

def test_pointer_to_stackref(self):
input = """
inst(OP, (arg: _PyStackRef * -- out)) {
out = *arg;
}
"""
output = """
TARGET(OP) {
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(OP);
_PyStackRef *arg;
_PyStackRef out;
arg = (_PyStackRef *)stack_pointer[-1].bits;
out = *arg;
stack_pointer[-1] = out;
DISPATCH();
}
"""
self.run_cases_test(input, output)


class TestGeneratedAbstractCases(unittest.TestCase):
def setUp(self) -> None:
super().setUp()
Expand Down
8 changes: 5 additions & 3 deletions Tools/cases_generator/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,15 @@ class StackItem:

def __str__(self) -> str:
cond = f" if ({self.condition})" if self.condition else ""
size = f"[{self.size}]" if self.size != "1" else ""
size = f"[{self.size}]" if self.size else ""
type = "" if self.type is None else f"{self.type} "
return f"{type}{self.name}{size}{cond} {self.peek}"

def is_array(self) -> bool:
return self.type == "_PyStackRef *"
return self.size != ""

def get_size(self) -> str:
return self.size if self.size else "1"

@dataclass
class StackEffect:
Expand Down Expand Up @@ -293,7 +295,7 @@ def convert_stack_item(item: parser.StackEffect, replace_op_arg_1: str | None) -
if replace_op_arg_1 and OPARG_AND_1.match(item.cond):
cond = replace_op_arg_1
return StackItem(
item.name, item.type, cond, (item.size or "1")
item.name, item.type, cond, item.size
)

def analyze_stack(op: parser.InstDef | parser.Pseudo, replace_op_arg_1: str | None = None) -> StackEffect:
Expand Down
14 changes: 12 additions & 2 deletions Tools/cases_generator/generators_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
Instruction,
Uop,
Properties,
StackItem,
)
from cwriter import CWriter
from typing import Callable, Mapping, TextIO, Iterator
from typing import Callable, Mapping, TextIO, Iterator, Tuple
from lexer import Token
from stack import Stack

Expand All @@ -24,6 +25,15 @@ def root_relative_path(filename: str) -> str:
return filename


def type_and_null(var: StackItem) -> Tuple[str, str]:
if var.type:
return var.type, "NULL"
elif var.is_array():
return "_PyStackRef *", "NULL"
else:
return "_PyStackRef", "PyStackRef_NULL"


def write_header(
generator: str, sources: list[str], outfile: TextIO, comment: str = "//"
) -> None:
Expand Down Expand Up @@ -126,7 +136,7 @@ def replace_decrefs(
for var in uop.stack.inputs:
if var.name == "unused" or var.name == "null" or var.peek:
continue
if var.size != "1":
if var.size:
out.emit(f"for (int _i = {var.size}; --_i >= 0;) {{\n")
out.emit(f"PyStackRef_CLOSE({var.name}[_i]);\n")
out.emit("}\n")
Expand Down
1 change: 0 additions & 1 deletion Tools/cases_generator/parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,6 @@ def stack_effect(self) -> StackEffect | None:
if not (size := self.expression()):
raise self.make_syntax_error("Expected expression")
self.require(lx.RBRACKET)
type_text = "_PyStackRef *"
size_text = size.text.strip()
return StackEffect(tkn.text, type_text, cond_text, size_text)
return None
Expand Down
11 changes: 6 additions & 5 deletions Tools/cases_generator/stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,15 @@ def var_size(var: StackItem) -> str:
if var.condition == "0":
return "0"
elif var.condition == "1":
return var.size
elif var.condition == "oparg & 1" and var.size == "1":
return var.get_size()
elif var.condition == "oparg & 1" and not var.size:
return f"({var.condition})"
else:
return f"(({var.condition}) ? {var.size} : 0)"
else:
return f"(({var.condition}) ? {var.get_size()} : 0)"
elif var.size:
return var.size

else:
return "1"

@dataclass
class StackOffset:
Expand Down
11 changes: 5 additions & 6 deletions Tools/cases_generator/tier1_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@
analyze_files,
Skip,
analysis_error,
StackItem,
)
from generators_common import (
DEFAULT_INPUT,
ROOT,
write_header,
emit_tokens,
type_and_null,
)
from cwriter import CWriter
from typing import TextIO
Expand All @@ -38,19 +40,16 @@ def declare_variables(inst: Instruction, out: CWriter) -> None:
for var in reversed(uop.stack.inputs):
if var.name not in variables:
variables.add(var.name)
type, null = (var.type, "NULL") if var.type else ("_PyStackRef", "PyStackRef_NULL")
type, null = type_and_null(var)
space = " " if type[-1].isalnum() else ""
if var.condition:
out.emit(f"{type}{space}{var.name} = {null};\n")
else:
if var.is_array():
out.emit(f"{var.type}{space}{var.name};\n")
else:
out.emit(f"{type}{space}{var.name};\n")
out.emit(f"{type}{space}{var.name};\n")
for var in uop.stack.outputs:
if var.name not in variables:
variables.add(var.name)
type, null = (var.type, "NULL") if var.type else ("_PyStackRef", "PyStackRef_NULL")
type, null = type_and_null(var)
space = " " if type[-1].isalnum() else ""
if var.condition:
out.emit(f"{type}{space}{var.name} = {null};\n")
Expand Down
3 changes: 2 additions & 1 deletion Tools/cases_generator/tier2_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
emit_tokens,
emit_to,
REPLACEMENT_FUNCTIONS,
type_and_null,
)
from cwriter import CWriter
from typing import TextIO, Iterator
Expand All @@ -35,7 +36,7 @@ def declare_variable(
if var.name in variables:
return
variables.add(var.name)
type, null = (var.type, "NULL") if var.type else ("_PyStackRef", "PyStackRef_NULL")
type, null = type_and_null(var)
space = " " if type[-1].isalnum() else ""
if var.condition:
out.emit(f"{type}{space}{var.name} = {null};\n")
Expand Down
Loading