Skip to content
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: 44 additions & 0 deletions Lib/test/test_generated_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
14 changes: 6 additions & 8 deletions Tools/cases_generator/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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 }
Expand All @@ -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

Expand Down Expand Up @@ -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),
)
Expand All @@ -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,
)
Expand Down
26 changes: 17 additions & 9 deletions Tools/cases_generator/generators_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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(
Expand All @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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)
Expand Down
4 changes: 4 additions & 0 deletions Tools/cases_generator/stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading