Skip to content

Commit d3f6063

Browse files
authored
GH-131513: Cases generator: Allow dead inputs to be reassigned (GH-131515)
1 parent b70d45a commit d3f6063

File tree

4 files changed

+71
-17
lines changed

4 files changed

+71
-17
lines changed

Lib/test/test_generated_cases.py

+44
Original file line numberDiff line numberDiff line change
@@ -1838,6 +1838,50 @@ def test_multiple_labels(self):
18381838
"""
18391839
self.run_cases_test(input, output)
18401840

1841+
def test_reassigning_live_inputs(self):
1842+
input = """
1843+
inst(OP, (in -- )) {
1844+
in = 0;
1845+
DEAD(in);
1846+
}
1847+
"""
1848+
with self.assertRaises(SyntaxError):
1849+
self.run_cases_test(input, "")
1850+
1851+
def test_reassigning_dead_inputs(self):
1852+
input = """
1853+
inst(OP, (in -- )) {
1854+
temp = use(in);
1855+
DEAD(in);
1856+
in = temp;
1857+
PyStackRef_CLOSE(in);
1858+
}
1859+
"""
1860+
output = """
1861+
TARGET(OP) {
1862+
#if Py_TAIL_CALL_INTERP
1863+
int opcode = OP;
1864+
(void)(opcode);
1865+
#endif
1866+
frame->instr_ptr = next_instr;
1867+
next_instr += 1;
1868+
INSTRUCTION_STATS(OP);
1869+
_PyStackRef in;
1870+
in = stack_pointer[-1];
1871+
_PyFrame_SetStackPointer(frame, stack_pointer);
1872+
temp = use(in);
1873+
stack_pointer = _PyFrame_GetStackPointer(frame);
1874+
in = temp;
1875+
stack_pointer += -1;
1876+
assert(WITHIN_STACK_BOUNDS());
1877+
_PyFrame_SetStackPointer(frame, stack_pointer);
1878+
PyStackRef_CLOSE(in);
1879+
stack_pointer = _PyFrame_GetStackPointer(frame);
1880+
DISPATCH();
1881+
}
1882+
"""
1883+
self.run_cases_test(input, output)
1884+
18411885

18421886
class TestGeneratedAbstractCases(unittest.TestCase):
18431887
def setUp(self) -> None:

Tools/cases_generator/analyzer.py

+6-8
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ class Uop:
177177
stack: StackEffect
178178
caches: list[CacheEntry]
179179
deferred_refs: dict[lexer.Token, str | None]
180-
output_stores: list[lexer.Token]
180+
local_stores: list[lexer.Token]
181181
body: list[lexer.Token]
182182
properties: Properties
183183
_size: int = -1
@@ -236,7 +236,7 @@ def __init__(self, name: str, spilled: bool, body: list[lexer.Token], properties
236236
self.properties = properties
237237

238238
size:int = 0
239-
output_stores: list[lexer.Token] = []
239+
local_stores: list[lexer.Token] = []
240240
instruction_size = None
241241

242242
def __str__(self) -> str:
@@ -431,7 +431,7 @@ def find_assignment_target(node: parser.InstDef, idx: int) -> list[lexer.Token]:
431431
return []
432432

433433

434-
def find_stores_outputs(node: parser.InstDef) -> list[lexer.Token]:
434+
def find_variable_stores(node: parser.InstDef) -> list[lexer.Token]:
435435
res: list[lexer.Token] = []
436436
outnames = { out.name for out in node.outputs }
437437
innames = { out.name for out in node.inputs }
@@ -449,9 +449,7 @@ def find_stores_outputs(node: parser.InstDef) -> list[lexer.Token]:
449449
if len(lhs) != 1 or lhs[0].kind != "IDENTIFIER":
450450
continue
451451
name = lhs[0]
452-
if name.text in innames:
453-
raise analysis_error(f"Cannot assign to input variable '{name.text}'", name)
454-
if name.text in outnames:
452+
if name.text in outnames or name.text in innames:
455453
res.append(name)
456454
return res
457455

@@ -877,7 +875,7 @@ def make_uop(
877875
stack=analyze_stack(op),
878876
caches=analyze_caches(inputs),
879877
deferred_refs=analyze_deferred_refs(op),
880-
output_stores=find_stores_outputs(op),
878+
local_stores=find_variable_stores(op),
881879
body=op.block.tokens,
882880
properties=compute_properties(op),
883881
)
@@ -899,7 +897,7 @@ def make_uop(
899897
stack=analyze_stack(op),
900898
caches=analyze_caches(inputs),
901899
deferred_refs=analyze_deferred_refs(op),
902-
output_stores=find_stores_outputs(op),
900+
local_stores=find_variable_stores(op),
903901
body=op.block.tokens,
904902
properties=properties,
905903
)

Tools/cases_generator/generators_common.py

+17-9
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ def kill_inputs(
262262
next(tkn_iter)
263263
next(tkn_iter)
264264
for var in storage.inputs:
265-
var.defined = False
265+
var.kill()
266266
return True
267267

268268
def kill(
@@ -280,7 +280,7 @@ def kill(
280280
next(tkn_iter)
281281
for var in storage.inputs:
282282
if var.name == name:
283-
var.defined = False
283+
var.kill()
284284
break
285285
else:
286286
raise analysis_error(
@@ -301,7 +301,7 @@ def stackref_kill(
301301
raise analysis_error(
302302
f"Cannot close '{name.text}' when "
303303
f"'{live}' is still live", name)
304-
var.defined = False
304+
var.kill()
305305
break
306306
if var.defined:
307307
live = var.name
@@ -526,7 +526,7 @@ def _emit_block(
526526
) -> tuple[bool, Token, Storage]:
527527
""" Returns (reachable?, closing '}', stack)."""
528528
braces = 1
529-
out_stores = set(uop.output_stores)
529+
local_stores = set(uop.local_stores)
530530
tkn = next(tkn_iter)
531531
reload: Token | None = None
532532
try:
@@ -574,11 +574,19 @@ def _emit_block(
574574
if not self._replacers[tkn.text](tkn, tkn_iter, uop, storage, inst):
575575
reachable = False
576576
else:
577-
if tkn in out_stores:
578-
for out in storage.outputs:
579-
if out.name == tkn.text:
580-
out.defined = True
581-
out.in_memory = False
577+
if tkn in local_stores:
578+
for var in storage.inputs:
579+
if var.name == tkn.text:
580+
if var.defined or var.in_memory:
581+
msg = f"Cannot assign to already defined input variable '{tkn.text}'"
582+
raise analysis_error(msg, tkn)
583+
var.defined = True
584+
var.in_memory = False
585+
break
586+
for var in storage.outputs:
587+
if var.name == tkn.text:
588+
var.defined = True
589+
var.in_memory = False
582590
break
583591
if tkn.text.startswith("DISPATCH"):
584592
self._print_storage(storage)

Tools/cases_generator/stack.py

+4
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ def redefinition(var: StackItem, prev: "Local") -> "Local":
6363
def from_memory(defn: StackItem) -> "Local":
6464
return Local(defn, True, True, True)
6565

66+
def kill(self) -> None:
67+
self.defined = False
68+
self.in_memory = False
69+
6670
def copy(self) -> "Local":
6771
return Local(
6872
self.item,

0 commit comments

Comments
 (0)