Skip to content

Commit 1242036

Browse files
markshannonnoahbkim
authored andcommitted
pythonGH-118926: Better distinguish between pointer and arrays in interpreter generator (pythonGH-121496)
1 parent 4187f2a commit 1242036

File tree

7 files changed

+73
-19
lines changed

7 files changed

+73
-19
lines changed

Lib/test/test_generated_cases.py

+43-1
Original file line numberDiff line numberDiff line change
@@ -815,7 +815,6 @@ def test_annotated_op(self):
815815
"""
816816
self.run_cases_test(input, output)
817817

818-
819818
def test_deopt_and_exit(self):
820819
input = """
821820
pure op(OP, (arg1 -- out)) {
@@ -827,6 +826,49 @@ def test_deopt_and_exit(self):
827826
with self.assertRaises(Exception):
828827
self.run_cases_test(input, output)
829828

829+
def test_array_of_one(self):
830+
input = """
831+
inst(OP, (arg[1] -- out[1])) {
832+
out[0] = arg[0];
833+
}
834+
"""
835+
output = """
836+
TARGET(OP) {
837+
frame->instr_ptr = next_instr;
838+
next_instr += 1;
839+
INSTRUCTION_STATS(OP);
840+
_PyStackRef *arg;
841+
_PyStackRef *out;
842+
arg = &stack_pointer[-1];
843+
out = &stack_pointer[-1];
844+
out[0] = arg[0];
845+
DISPATCH();
846+
}
847+
"""
848+
self.run_cases_test(input, output)
849+
850+
def test_pointer_to_stackref(self):
851+
input = """
852+
inst(OP, (arg: _PyStackRef * -- out)) {
853+
out = *arg;
854+
}
855+
"""
856+
output = """
857+
TARGET(OP) {
858+
frame->instr_ptr = next_instr;
859+
next_instr += 1;
860+
INSTRUCTION_STATS(OP);
861+
_PyStackRef *arg;
862+
_PyStackRef out;
863+
arg = (_PyStackRef *)stack_pointer[-1].bits;
864+
out = *arg;
865+
stack_pointer[-1] = out;
866+
DISPATCH();
867+
}
868+
"""
869+
self.run_cases_test(input, output)
870+
871+
830872
class TestGeneratedAbstractCases(unittest.TestCase):
831873
def setUp(self) -> None:
832874
super().setUp()

Tools/cases_generator/analyzer.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,15 @@ class StackItem:
106106

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

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

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

117119
@dataclass
118120
class StackEffect:
@@ -293,7 +295,7 @@ def convert_stack_item(item: parser.StackEffect, replace_op_arg_1: str | None) -
293295
if replace_op_arg_1 and OPARG_AND_1.match(item.cond):
294296
cond = replace_op_arg_1
295297
return StackItem(
296-
item.name, item.type, cond, (item.size or "1")
298+
item.name, item.type, cond, item.size
297299
)
298300

299301
def analyze_stack(op: parser.InstDef | parser.Pseudo, replace_op_arg_1: str | None = None) -> StackEffect:

Tools/cases_generator/generators_common.py

+12-2
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
Instruction,
66
Uop,
77
Properties,
8+
StackItem,
89
)
910
from cwriter import CWriter
10-
from typing import Callable, Mapping, TextIO, Iterator
11+
from typing import Callable, Mapping, TextIO, Iterator, Tuple
1112
from lexer import Token
1213
from stack import Stack
1314

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

2627

28+
def type_and_null(var: StackItem) -> Tuple[str, str]:
29+
if var.type:
30+
return var.type, "NULL"
31+
elif var.is_array():
32+
return "_PyStackRef *", "NULL"
33+
else:
34+
return "_PyStackRef", "PyStackRef_NULL"
35+
36+
2737
def write_header(
2838
generator: str, sources: list[str], outfile: TextIO, comment: str = "//"
2939
) -> None:
@@ -126,7 +136,7 @@ def replace_decrefs(
126136
for var in uop.stack.inputs:
127137
if var.name == "unused" or var.name == "null" or var.peek:
128138
continue
129-
if var.size != "1":
139+
if var.size:
130140
out.emit(f"for (int _i = {var.size}; --_i >= 0;) {{\n")
131141
out.emit(f"PyStackRef_CLOSE({var.name}[_i]);\n")
132142
out.emit("}\n")

Tools/cases_generator/parsing.py

-1
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,6 @@ def stack_effect(self) -> StackEffect | None:
285285
if not (size := self.expression()):
286286
raise self.make_syntax_error("Expected expression")
287287
self.require(lx.RBRACKET)
288-
type_text = "_PyStackRef *"
289288
size_text = size.text.strip()
290289
return StackEffect(tkn.text, type_text, cond_text, size_text)
291290
return None

Tools/cases_generator/stack.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,15 @@ def var_size(var: StackItem) -> str:
2828
if var.condition == "0":
2929
return "0"
3030
elif var.condition == "1":
31-
return var.size
32-
elif var.condition == "oparg & 1" and var.size == "1":
31+
return var.get_size()
32+
elif var.condition == "oparg & 1" and not var.size:
3333
return f"({var.condition})"
3434
else:
35-
return f"(({var.condition}) ? {var.size} : 0)"
36-
else:
35+
return f"(({var.condition}) ? {var.get_size()} : 0)"
36+
elif var.size:
3737
return var.size
38-
38+
else:
39+
return "1"
3940

4041
@dataclass
4142
class StackOffset:

Tools/cases_generator/tier1_generator.py

+5-6
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@
1313
analyze_files,
1414
Skip,
1515
analysis_error,
16+
StackItem,
1617
)
1718
from generators_common import (
1819
DEFAULT_INPUT,
1920
ROOT,
2021
write_header,
2122
emit_tokens,
23+
type_and_null,
2224
)
2325
from cwriter import CWriter
2426
from typing import TextIO
@@ -38,19 +40,16 @@ def declare_variables(inst: Instruction, out: CWriter) -> None:
3840
for var in reversed(uop.stack.inputs):
3941
if var.name not in variables:
4042
variables.add(var.name)
41-
type, null = (var.type, "NULL") if var.type else ("_PyStackRef", "PyStackRef_NULL")
43+
type, null = type_and_null(var)
4244
space = " " if type[-1].isalnum() else ""
4345
if var.condition:
4446
out.emit(f"{type}{space}{var.name} = {null};\n")
4547
else:
46-
if var.is_array():
47-
out.emit(f"{var.type}{space}{var.name};\n")
48-
else:
49-
out.emit(f"{type}{space}{var.name};\n")
48+
out.emit(f"{type}{space}{var.name};\n")
5049
for var in uop.stack.outputs:
5150
if var.name not in variables:
5251
variables.add(var.name)
53-
type, null = (var.type, "NULL") if var.type else ("_PyStackRef", "PyStackRef_NULL")
52+
type, null = type_and_null(var)
5453
space = " " if type[-1].isalnum() else ""
5554
if var.condition:
5655
out.emit(f"{type}{space}{var.name} = {null};\n")

Tools/cases_generator/tier2_generator.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
emit_tokens,
2121
emit_to,
2222
REPLACEMENT_FUNCTIONS,
23+
type_and_null,
2324
)
2425
from cwriter import CWriter
2526
from typing import TextIO, Iterator
@@ -35,7 +36,7 @@ def declare_variable(
3536
if var.name in variables:
3637
return
3738
variables.add(var.name)
38-
type, null = (var.type, "NULL") if var.type else ("_PyStackRef", "PyStackRef_NULL")
39+
type, null = type_and_null(var)
3940
space = " " if type[-1].isalnum() else ""
4041
if var.condition:
4142
out.emit(f"{type}{space}{var.name} = {null};\n")

0 commit comments

Comments
 (0)