Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Also validate sizes
  • Loading branch information
tomasr8 committed May 3, 2025
commit 8e5e19bccc837db9c191ff6013c2e1c504232cc2
46 changes: 45 additions & 1 deletion Lib/test/test_generated_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -2168,7 +2168,7 @@ def test_validate_uop_unused_input(self):
"""
self.run_cases_test(input, input2, output)

def test_validate_uop_unused_override(self):
def test_validate_uop_unused_output(self):
input = """
op(OP, ( -- unused)) {
}
Expand Down Expand Up @@ -2208,6 +2208,50 @@ def test_validate_uop_unused_override(self):
"""
self.run_cases_test(input, input2, output)

def test_validate_uop_input_size_mismatch(self):
input = """
op(OP, (arg1[2] -- )) {
}
"""
input2 = """
op(OP, (arg1[4] -- )) {
}
"""
output = """
"""
with self.assertRaisesRegex(SyntaxError,
"Inputs must have equal sizes"):
self.run_cases_test(input, input2, output)

def test_validate_uop_output_size_mismatch(self):
input = """
op(OP, ( -- out[2])) {
}
"""
input2 = """
op(OP, ( -- out[4])) {
}
"""
output = """
"""
with self.assertRaisesRegex(SyntaxError,
"Outputs must have equal sizes"):
self.run_cases_test(input, input2, output)

def test_validate_uop_unused_size_mismatch(self):
input = """
op(OP, (foo[2] -- )) {
}
"""
input2 = """
op(OP, (unused[4] -- )) {
}
"""
output = """
"""
with self.assertRaisesRegex(SyntaxError,
"Inputs must have equal sizes"):
self.run_cases_test(input, input2, output)

if __name__ == "__main__":
unittest.main()
2 changes: 1 addition & 1 deletion Python/optimizer_bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1088,7 +1088,7 @@ dummy_func(void) {
sym_set_const(callable, (PyObject *)&PyUnicode_Type);
}

op(_CALL_LEN, (callable[1], self_or_null[1], args[oparg] -- res)) {
op(_CALL_LEN, (callable, self_or_null, args[oparg] -- res)) {
res = sym_new_type(ctx, &PyLong_Type);
}

Expand Down
22 changes: 19 additions & 3 deletions Tools/cases_generator/optimizer_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@


def validate_uop(override: Uop, uop: Uop) -> None:
"""
Check that the overridden uop (defined in 'optimizer_bytecodes.c')
has the same stack effects as the original uop (defined in 'bytecodes.c').

Ensure that:
- The number of inputs and outputs is the same.
- The names of the inputs and outputs are the same
(except for 'unused' which is ignored).
- The sizes of the inputs and outputs are the same.
"""
for stack_effect in ('inputs', 'outputs'):
orig_effects = getattr(uop.stack, stack_effect)
new_effects = getattr(override.stack, stack_effect)
Expand All @@ -43,16 +53,22 @@ def validate_uop(override: Uop, uop: Uop) -> None:
raise analysis_error(msg, override.body.open)

for orig, new in zip(orig_effects, new_effects, strict=True):
if orig.name == 'unused' or new.name == 'unused':
continue
if orig.name != new.name:
if orig.name != new.name and orig.name != "unused" and new.name != "unused":
msg = (
f"{uop.name}: {stack_effect.capitalize()} must have "
"equal names in bytecodes.c and optimizer_bytecodes.c "
f"({orig.name} != {new.name})"
)
raise analysis_error(msg, override.body.open)

if orig.size != new.size:
msg = (
f"{uop.name}: {stack_effect.capitalize()} must have "
"equal sizes in bytecodes.c and optimizer_bytecodes.c "
f"({orig.size!r} != {new.size!r})"
)
raise analysis_error(msg, override.body.open)


def type_name(var: StackItem) -> str:
if var.is_array():
Expand Down