https://github.com/python/cpython/commit/d3f6063af18a008e316e4342492e877ee51463e2
commit: d3f6063af18a008e316e4342492e877ee51463e2
branch: main
author: Mark Shannon <[email protected]>
committer: markshannon <[email protected]>
date: 2025-03-21T11:38:17Z
summary:
GH-131513: Cases generator: Allow dead inputs to be reassigned (GH-131515)
files:
M Lib/test/test_generated_cases.py
M Tools/cases_generator/analyzer.py
M Tools/cases_generator/generators_common.py
M Tools/cases_generator/stack.py
diff --git a/Lib/test/test_generated_cases.py b/Lib/test/test_generated_cases.py
index 3eb650bf3e6942..405c23ad96c414 100644
--- a/Lib/test/test_generated_cases.py
+++ b/Lib/test/test_generated_cases.py
@@ -1838,6 +1838,50 @@ def test_multiple_labels(self):
"""
self.run_cases_test(input, output)
+ def test_reassigning_live_inputs(self):
+ input = """
+ inst(OP, (in -- )) {
+ in = 0;
+ DEAD(in);
+ }
+ """
+ with self.assertRaises(SyntaxError):
+ self.run_cases_test(input, "")
+
+ def test_reassigning_dead_inputs(self):
+ input = """
+ inst(OP, (in -- )) {
+ temp = use(in);
+ DEAD(in);
+ in = temp;
+ PyStackRef_CLOSE(in);
+ }
+ """
+ output = """
+ TARGET(OP) {
+ #if Py_TAIL_CALL_INTERP
+ int opcode = OP;
+ (void)(opcode);
+ #endif
+ frame->instr_ptr = next_instr;
+ next_instr += 1;
+ INSTRUCTION_STATS(OP);
+ _PyStackRef in;
+ in = stack_pointer[-1];
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ temp = use(in);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ in = temp;
+ stack_pointer += -1;
+ assert(WITHIN_STACK_BOUNDS());
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyStackRef_CLOSE(in);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ DISPATCH();
+ }
+ """
+ self.run_cases_test(input, output)
+
class TestGeneratedAbstractCases(unittest.TestCase):
def setUp(self) -> None:
diff --git a/Tools/cases_generator/analyzer.py
b/Tools/cases_generator/analyzer.py
index ac2cfb7b50be40..491b5d127cf0f5 100644
--- a/Tools/cases_generator/analyzer.py
+++ b/Tools/cases_generator/analyzer.py
@@ -177,7 +177,7 @@ class Uop:
stack: StackEffect
caches: list[CacheEntry]
deferred_refs: dict[lexer.Token, str | None]
- output_stores: list[lexer.Token]
+ local_stores: list[lexer.Token]
body: list[lexer.Token]
properties: Properties
_size: int = -1
@@ -236,7 +236,7 @@ def __init__(self, name: str, spilled: bool, body:
list[lexer.Token], properties
self.properties = properties
size:int = 0
- output_stores: list[lexer.Token] = []
+ local_stores: list[lexer.Token] = []
instruction_size = None
def __str__(self) -> str:
@@ -431,7 +431,7 @@ def find_assignment_target(node: parser.InstDef, idx: int)
-> list[lexer.Token]:
return []
-def find_stores_outputs(node: parser.InstDef) -> list[lexer.Token]:
+def find_variable_stores(node: parser.InstDef) -> list[lexer.Token]:
res: list[lexer.Token] = []
outnames = { out.name for out in node.outputs }
innames = { out.name for out in node.inputs }
@@ -449,9 +449,7 @@ def find_stores_outputs(node: parser.InstDef) ->
list[lexer.Token]:
if len(lhs) != 1 or lhs[0].kind != "IDENTIFIER":
continue
name = lhs[0]
- if name.text in innames:
- raise analysis_error(f"Cannot assign to input variable
'{name.text}'", name)
- if name.text in outnames:
+ if name.text in outnames or name.text in innames:
res.append(name)
return res
@@ -877,7 +875,7 @@ def make_uop(
stack=analyze_stack(op),
caches=analyze_caches(inputs),
deferred_refs=analyze_deferred_refs(op),
- output_stores=find_stores_outputs(op),
+ local_stores=find_variable_stores(op),
body=op.block.tokens,
properties=compute_properties(op),
)
@@ -899,7 +897,7 @@ def make_uop(
stack=analyze_stack(op),
caches=analyze_caches(inputs),
deferred_refs=analyze_deferred_refs(op),
- output_stores=find_stores_outputs(op),
+ local_stores=find_variable_stores(op),
body=op.block.tokens,
properties=properties,
)
diff --git a/Tools/cases_generator/generators_common.py
b/Tools/cases_generator/generators_common.py
index fc0b468266078d..cc1ea5c7da5455 100644
--- a/Tools/cases_generator/generators_common.py
+++ b/Tools/cases_generator/generators_common.py
@@ -262,7 +262,7 @@ def kill_inputs(
next(tkn_iter)
next(tkn_iter)
for var in storage.inputs:
- var.defined = False
+ var.kill()
return True
def kill(
@@ -280,7 +280,7 @@ def kill(
next(tkn_iter)
for var in storage.inputs:
if var.name == name:
- var.defined = False
+ var.kill()
break
else:
raise analysis_error(
@@ -301,7 +301,7 @@ def stackref_kill(
raise analysis_error(
f"Cannot close '{name.text}' when "
f"'{live}' is still live", name)
- var.defined = False
+ var.kill()
break
if var.defined:
live = var.name
@@ -526,7 +526,7 @@ def _emit_block(
) -> tuple[bool, Token, Storage]:
""" Returns (reachable?, closing '}', stack)."""
braces = 1
- out_stores = set(uop.output_stores)
+ local_stores = set(uop.local_stores)
tkn = next(tkn_iter)
reload: Token | None = None
try:
@@ -574,11 +574,19 @@ def _emit_block(
if not self._replacers[tkn.text](tkn, tkn_iter, uop,
storage, inst):
reachable = False
else:
- if tkn in out_stores:
- for out in storage.outputs:
- if out.name == tkn.text:
- out.defined = True
- out.in_memory = False
+ if tkn in local_stores:
+ for var in storage.inputs:
+ if var.name == tkn.text:
+ if var.defined or var.in_memory:
+ msg = f"Cannot assign to already
defined input variable '{tkn.text}'"
+ raise analysis_error(msg, tkn)
+ var.defined = True
+ var.in_memory = False
+ break
+ for var in storage.outputs:
+ if var.name == tkn.text:
+ var.defined = True
+ var.in_memory = False
break
if tkn.text.startswith("DISPATCH"):
self._print_storage(storage)
diff --git a/Tools/cases_generator/stack.py b/Tools/cases_generator/stack.py
index 70fa8abe513953..67d0418a114977 100644
--- a/Tools/cases_generator/stack.py
+++ b/Tools/cases_generator/stack.py
@@ -63,6 +63,10 @@ def redefinition(var: StackItem, prev: "Local") -> "Local":
def from_memory(defn: StackItem) -> "Local":
return Local(defn, True, True, True)
+ def kill(self) -> None:
+ self.defined = False
+ self.in_memory = False
+
def copy(self) -> "Local":
return Local(
self.item,
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]