https://github.com/python/cpython/commit/d3f6063af18a008e316e4342492e877ee51463e2 commit: d3f6063af18a008e316e4342492e877ee51463e2 branch: main author: Mark Shannon <m...@hotpy.org> committer: markshannon <m...@hotpy.org> 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 -- python-checkins@python.org To unsubscribe send an email to python-checkins-le...@python.org https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: arch...@mail-archive.com