]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-111485: Test the new cases generator (GH-113252)
authorMark Shannon <mark@hotpy.org>
Mon, 18 Dec 2023 11:14:40 +0000 (11:14 +0000)
committerGitHub <noreply@github.com>
Mon, 18 Dec 2023 11:14:40 +0000 (11:14 +0000)
Lib/test/test_generated_cases.py
Python/executor_cases.c.h
Python/generated_cases.c.h
Tools/cases_generator/analyzer.py
Tools/cases_generator/cwriter.py
Tools/cases_generator/generators_common.py
Tools/cases_generator/stack.py
Tools/cases_generator/tier1_generator.py

index de96a8764594bae24cce8208814f618a45556492..74cebbe469d794043100fb300a0b4185a2b67ce7 100644 (file)
@@ -32,6 +32,7 @@ with test_tools.imports_under_tool('cases_generator'):
     import analysis
     import formatting
     from parsing import StackEffect
+    import tier1_generator
 
 
 def handle_stderr():
@@ -108,13 +109,12 @@ class TestGeneratedCases(unittest.TestCase):
             temp_input.write(analysis.END_MARKER)
             temp_input.flush()
 
-        a = generate_cases.Generator([self.temp_input_filename])
         with handle_stderr():
-            a.parse()
-            a.analyze()
-            if a.errors:
-                raise RuntimeError(f"Found {a.errors} errors")
-            a.write_instructions(self.temp_output_filename, False)
+            tier1_generator.generate_tier1_from_files(
+                [self.temp_input_filename],
+                self.temp_output_filename,
+                False
+            )
 
         with open(self.temp_output_filename) as temp_output:
             lines = temp_output.readlines()
@@ -163,7 +163,7 @@ class TestGeneratedCases(unittest.TestCase):
             PyObject *value;
             value = stack_pointer[-1];
             spam();
-            STACK_SHRINK(1);
+            stack_pointer += -1;
             DISPATCH();
         }
     """
@@ -182,8 +182,8 @@ class TestGeneratedCases(unittest.TestCase):
             INSTRUCTION_STATS(OP);
             PyObject *res;
             spam();
-            STACK_GROW(1);
-            stack_pointer[-1] = res;
+            stack_pointer[0] = res;
+            stack_pointer += 1;
             DISPATCH();
         }
     """
@@ -227,8 +227,8 @@ class TestGeneratedCases(unittest.TestCase):
             right = stack_pointer[-1];
             left = stack_pointer[-2];
             spam();
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            stack_pointer[-2] = res;
+            stack_pointer += -1;
             DISPATCH();
         }
     """
@@ -273,7 +273,6 @@ class TestGeneratedCases(unittest.TestCase):
             next_instr += 1;
             INSTRUCTION_STATS(OP1);
             PREDICTED(OP1);
-            static_assert(INLINE_CACHE_ENTRIES_OP1 == 0, "incorrect cache size");
             PyObject *arg;
             PyObject *rest;
             arg = stack_pointer[-1];
@@ -285,6 +284,7 @@ class TestGeneratedCases(unittest.TestCase):
             frame->instr_ptr = next_instr;
             next_instr += 1;
             INSTRUCTION_STATS(OP3);
+            static_assert(INLINE_CACHE_ENTRIES_OP1 == 0, "incorrect cache size");
             PyObject *arg;
             PyObject *res;
             arg = stack_pointer[-1];
@@ -325,6 +325,7 @@ class TestGeneratedCases(unittest.TestCase):
             next_instr += 1;
             INSTRUCTION_STATS(OP);
             if (cond) goto label;
+            // Comment is ok
             DISPATCH();
         }
     """
@@ -347,8 +348,8 @@ class TestGeneratedCases(unittest.TestCase):
             right = stack_pointer[-1];
             left = stack_pointer[-2];
             if (cond) goto pop_2_label;
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            stack_pointer[-2] = res;
+            stack_pointer += -1;
             DISPATCH();
         }
     """
@@ -368,7 +369,7 @@ class TestGeneratedCases(unittest.TestCase):
             value = stack_pointer[-1];
             uint16_t counter = read_u16(&this_instr[1].cache);
             uint32_t extra = read_u32(&this_instr[2].cache);
-            STACK_SHRINK(1);
+            stack_pointer += -1;
             DISPATCH();
         }
     """
@@ -411,26 +412,26 @@ class TestGeneratedCases(unittest.TestCase):
             INSTRUCTION_STATS(OP);
             PREDICTED(OP);
             _Py_CODEUNIT *this_instr = next_instr - 6;
-            static_assert(INLINE_CACHE_ENTRIES_OP == 5, "incorrect cache size");
             PyObject *right;
             PyObject *left;
             PyObject *arg2;
             PyObject *res;
-            // OP1
+            // _OP1
             right = stack_pointer[-1];
             left = stack_pointer[-2];
             {
                 uint16_t counter = read_u16(&this_instr[1].cache);
                 op1(left, right);
             }
+            /* Skip 2 cache entries */
             // OP2
             arg2 = stack_pointer[-3];
             {
                 uint32_t extra = read_u32(&this_instr[4].cache);
                 res = op2(arg2, left, right);
             }
-            STACK_SHRINK(2);
-            stack_pointer[-1] = res;
+            stack_pointer[-3] = res;
+            stack_pointer += -2;
             DISPATCH();
         }
 
@@ -451,6 +452,7 @@ class TestGeneratedCases(unittest.TestCase):
             frame->instr_ptr = next_instr;
             next_instr += 6;
             INSTRUCTION_STATS(OP3);
+            static_assert(INLINE_CACHE_ENTRIES_OP == 5, "incorrect cache size");
             PyObject *right;
             PyObject *left;
             PyObject *arg2;
@@ -459,8 +461,24 @@ class TestGeneratedCases(unittest.TestCase):
             left = stack_pointer[-2];
             arg2 = stack_pointer[-3];
             res = op3(arg2, left, right);
-            STACK_SHRINK(2);
-            stack_pointer[-1] = res;
+            stack_pointer[-3] = res;
+            stack_pointer += -2;
+            DISPATCH();
+        }
+    """
+        self.run_cases_test(input, output)
+    def test_unused_caches(self):
+        input = """
+        inst(OP, (unused/1, unused/2 --)) {
+            body();
+        }
+    """
+        output = """
+        TARGET(OP) {
+            frame->instr_ptr = next_instr;
+            next_instr += 4;
+            INSTRUCTION_STATS(OP);
+            body();
             DISPATCH();
         }
     """
@@ -519,11 +537,10 @@ class TestGeneratedCases(unittest.TestCase):
             PyObject **values;
             PyObject *below;
             above = stack_pointer[-1];
-            values = stack_pointer - 1 - oparg*2;
+            values = &stack_pointer[-1 - oparg*2];
             below = stack_pointer[-2 - oparg*2];
             spam();
-            STACK_SHRINK(oparg*2);
-            STACK_SHRINK(2);
+            stack_pointer += -2 - oparg*2;
             DISPATCH();
         }
     """
@@ -543,11 +560,11 @@ class TestGeneratedCases(unittest.TestCase):
             PyObject *below;
             PyObject **values;
             PyObject *above;
-            values = stack_pointer - 1;
+            values = &stack_pointer[-1];
             spam(values, oparg);
-            STACK_GROW(oparg*3);
-            stack_pointer[-2 - oparg*3] = below;
-            stack_pointer[-1] = above;
+            stack_pointer[-2] = below;
+            stack_pointer[-1 + oparg*3] = above;
+            stack_pointer += oparg*3;
             DISPATCH();
         }
     """
@@ -566,10 +583,10 @@ class TestGeneratedCases(unittest.TestCase):
             INSTRUCTION_STATS(OP);
             PyObject **values;
             PyObject *above;
-            values = stack_pointer - oparg;
+            values = &stack_pointer[-oparg];
             spam(values, oparg);
-            STACK_GROW(1);
-            stack_pointer[-1] = above;
+            stack_pointer[0] = above;
+            stack_pointer += 1;
             DISPATCH();
         }
     """
@@ -588,11 +605,10 @@ class TestGeneratedCases(unittest.TestCase):
             INSTRUCTION_STATS(OP);
             PyObject **values;
             PyObject *extra;
-            values = stack_pointer - oparg;
+            values = &stack_pointer[-oparg];
             extra = stack_pointer[-1 - oparg];
-            if (oparg == 0) { STACK_SHRINK(oparg); goto pop_1_somewhere; }
-            STACK_SHRINK(oparg);
-            STACK_SHRINK(1);
+            if (oparg == 0) { stack_pointer += -1 - oparg; goto somewhere; }
+            stack_pointer += -1 - oparg;
             DISPATCH();
         }
     """
@@ -616,14 +632,13 @@ class TestGeneratedCases(unittest.TestCase):
             PyObject *output = NULL;
             PyObject *zz;
             cc = stack_pointer[-1];
-            if ((oparg & 1) == 1) { input = stack_pointer[-1 - ((oparg & 1) == 1 ? 1 : 0)]; }
-            aa = stack_pointer[-2 - ((oparg & 1) == 1 ? 1 : 0)];
+            if ((oparg & 1) == 1) { input = stack_pointer[-1 - ((((oparg & 1) == 1) ? 1 : 0))]; }
+            aa = stack_pointer[-2 - ((((oparg & 1) == 1) ? 1 : 0))];
             output = spam(oparg, input);
-            STACK_SHRINK((((oparg & 1) == 1) ? 1 : 0));
-            STACK_GROW(((oparg & 2) ? 1 : 0));
-            stack_pointer[-2 - (oparg & 2 ? 1 : 0)] = xx;
-            if (oparg & 2) { stack_pointer[-1 - (oparg & 2 ? 1 : 0)] = output; }
-            stack_pointer[-1] = zz;
+            stack_pointer[-2 - ((((oparg & 1) == 1) ? 1 : 0))] = xx;
+            if (oparg & 2) stack_pointer[-1 - ((((oparg & 1) == 1) ? 1 : 0))] = output;
+            stack_pointer[-1 - ((((oparg & 1) == 1) ? 1 : 0)) + (((oparg & 2) ? 1 : 0))] = zz;
+            stack_pointer += -((((oparg & 1) == 1) ? 1 : 0)) + (((oparg & 2) ? 1 : 0));
             DISPATCH();
         }
     """
@@ -661,11 +676,10 @@ class TestGeneratedCases(unittest.TestCase):
             {
                 # Body of B
             }
-            STACK_SHRINK(1);
-            STACK_GROW((oparg ? 1 : 0));
-            stack_pointer[-2 - (oparg ? 1 : 0)] = deep;
-            if (oparg) { stack_pointer[-1 - (oparg ? 1 : 0)] = extra; }
-            stack_pointer[-1] = res;
+            stack_pointer[-3] = deep;
+            if (oparg) stack_pointer[-2] = extra;
+            stack_pointer[-2 + (((oparg) ? 1 : 0))] = res;
+            stack_pointer += -1 + (((oparg) ? 1 : 0));
             DISPATCH();
         }
     """
@@ -696,9 +710,9 @@ class TestGeneratedCases(unittest.TestCase):
             {
                 val2 = spam();
             }
-            STACK_GROW(2);
-            stack_pointer[-2] = val1;
-            stack_pointer[-1] = val2;
+            stack_pointer[0] = val1;
+            stack_pointer[1] = val2;
+            stack_pointer += 2;
             DISPATCH();
         }
         """
index 7cb60cbc1dd3ff8ba9e6527e115597dfcb5430b7..7cc29c8e644d8d6b96b3585507d69bd3e59696b6 100644 (file)
             }
             null = NULL;
             stack_pointer[0] = res;
-             if (oparg & 1) stack_pointer[1] = null;
+            if (oparg & 1) stack_pointer[1] = null;
             stack_pointer += 1 + ((oparg & 1));
             break;
         }
             STAT_INC(LOAD_GLOBAL, hit);
             null = NULL;
             stack_pointer[0] = res;
-             if (oparg & 1) stack_pointer[1] = null;
+            if (oparg & 1) stack_pointer[1] = null;
             stack_pointer += 1 + ((oparg & 1));
             break;
         }
             STAT_INC(LOAD_GLOBAL, hit);
             null = NULL;
             stack_pointer[0] = res;
-             if (oparg & 1) stack_pointer[1] = null;
+            if (oparg & 1) stack_pointer[1] = null;
             stack_pointer += 1 + ((oparg & 1));
             break;
         }
                 if (attr == NULL) goto pop_1_error_tier_two;
             }
             stack_pointer[-1] = attr;
-             if (oparg & 1) stack_pointer[0] = self_or_null;
+            if (oparg & 1) stack_pointer[0] = self_or_null;
             stack_pointer += ((oparg & 1));
             break;
         }
             null = NULL;
             Py_DECREF(owner);
             stack_pointer[-1] = attr;
-             if (oparg & 1) stack_pointer[0] = null;
+            if (oparg & 1) stack_pointer[0] = null;
             stack_pointer += ((oparg & 1));
             break;
         }
             null = NULL;
             Py_DECREF(owner);
             stack_pointer[-1] = attr;
-             if (oparg & 1) stack_pointer[0] = null;
+            if (oparg & 1) stack_pointer[0] = null;
             stack_pointer += ((oparg & 1));
             break;
         }
             null = NULL;
             Py_DECREF(owner);
             stack_pointer[-1] = attr;
-             if (oparg & 1) stack_pointer[0] = null;
+            if (oparg & 1) stack_pointer[0] = null;
             stack_pointer += ((oparg & 1));
             break;
         }
             null = NULL;
             Py_DECREF(owner);
             stack_pointer[-1] = attr;
-             if (oparg & 1) stack_pointer[0] = null;
+            if (oparg & 1) stack_pointer[0] = null;
             stack_pointer += ((oparg & 1));
             break;
         }
             null = NULL;
             Py_DECREF(owner);
             stack_pointer[-1] = attr;
-             if (oparg & 1) stack_pointer[0] = null;
+            if (oparg & 1) stack_pointer[0] = null;
             stack_pointer += ((oparg & 1));
             break;
         }
             assert(_PyType_HasFeature(Py_TYPE(attr), Py_TPFLAGS_METHOD_DESCRIPTOR));
             self = owner;
             stack_pointer[-1] = attr;
-             if (1) stack_pointer[0] = self;
+            if (1) stack_pointer[0] = self;
             stack_pointer += (((1) ? 1 : 0));
             break;
         }
             attr = Py_NewRef(descr);
             self = owner;
             stack_pointer[-1] = attr;
-             if (1) stack_pointer[0] = self;
+            if (1) stack_pointer[0] = self;
             stack_pointer += (((1) ? 1 : 0));
             break;
         }
             attr = Py_NewRef(descr);
             self = owner;
             stack_pointer[-1] = attr;
-             if (1) stack_pointer[0] = self;
+            if (1) stack_pointer[0] = self;
             stack_pointer += (((1) ? 1 : 0));
             break;
         }
             PyObject *start;
             PyObject *slice;
             oparg = CURRENT_OPARG();
-        if (oparg == 3) { step = stack_pointer[-(((oparg == 3) ? 1 : 0))]; }
+            if (oparg == 3) { step = stack_pointer[-(((oparg == 3) ? 1 : 0))]; }
             stop = stack_pointer[-1 - (((oparg == 3) ? 1 : 0))];
             start = stack_pointer[-2 - (((oparg == 3) ? 1 : 0))];
             slice = PySlice_New(start, stop, step);
index 24f26722d7a7453ecaa15785674a9aa340a3cca3..b202d141b36f4fca13ee27c0f68c84771084780b 100644 (file)
             PyObject *stop;
             PyObject *start;
             PyObject *slice;
-        if (oparg == 3) { step = stack_pointer[-(((oparg == 3) ? 1 : 0))]; }
+            if (oparg == 3) { step = stack_pointer[-(((oparg == 3) ? 1 : 0))]; }
             stop = stack_pointer[-1 - (((oparg == 3) ? 1 : 0))];
             start = stack_pointer[-2 - (((oparg == 3) ? 1 : 0))];
             slice = PySlice_New(start, stop, step);
             PyObject *callargs;
             PyObject *func;
             PyObject *result;
-        if (oparg & 1) { kwargs = stack_pointer[-((oparg & 1))]; }
+            if (oparg & 1) { kwargs = stack_pointer[-((oparg & 1))]; }
             callargs = stack_pointer[-1 - ((oparg & 1))];
             func = stack_pointer[-3 - ((oparg & 1))];
             // DICT_MERGE is called before this opcode if there are kwargs.
                 }
             }
             stack_pointer[-1] = attr;
-             if (oparg & 1) stack_pointer[0] = self_or_null;
+            if (oparg & 1) stack_pointer[0] = self_or_null;
             stack_pointer += ((oparg & 1));
             DISPATCH();
         }
                 Py_DECREF(owner);
             }
             stack_pointer[-1] = attr;
-             if (oparg & 1) stack_pointer[0] = null;
+            if (oparg & 1) stack_pointer[0] = null;
             stack_pointer += ((oparg & 1));
             DISPATCH();
         }
             }
             /* Skip 5 cache entries */
             stack_pointer[-1] = attr;
-             if (oparg & 1) stack_pointer[0] = null;
+            if (oparg & 1) stack_pointer[0] = null;
             stack_pointer += ((oparg & 1));
             DISPATCH();
         }
                 self = owner;
             }
             stack_pointer[-1] = attr;
-             if (1) stack_pointer[0] = self;
+            if (1) stack_pointer[0] = self;
             stack_pointer += (((1) ? 1 : 0));
             DISPATCH();
         }
                 self = owner;
             }
             stack_pointer[-1] = attr;
-             if (1) stack_pointer[0] = self;
+            if (1) stack_pointer[0] = self;
             stack_pointer += (((1) ? 1 : 0));
             DISPATCH();
         }
                 self = owner;
             }
             stack_pointer[-1] = attr;
-             if (1) stack_pointer[0] = self;
+            if (1) stack_pointer[0] = self;
             stack_pointer += (((1) ? 1 : 0));
             DISPATCH();
         }
             }
             /* Skip 5 cache entries */
             stack_pointer[-1] = attr;
-             if (oparg & 1) stack_pointer[0] = null;
+            if (oparg & 1) stack_pointer[0] = null;
             stack_pointer += ((oparg & 1));
             DISPATCH();
         }
             }
             /* Skip 5 cache entries */
             stack_pointer[-1] = attr;
-             if (oparg & 1) stack_pointer[0] = null;
+            if (oparg & 1) stack_pointer[0] = null;
             stack_pointer += ((oparg & 1));
             DISPATCH();
         }
             }
             /* Skip 5 cache entries */
             stack_pointer[-1] = attr;
-             if (oparg & 1) stack_pointer[0] = null;
+            if (oparg & 1) stack_pointer[0] = null;
             stack_pointer += ((oparg & 1));
             DISPATCH();
         }
                 null = NULL;
             }
             stack_pointer[0] = res;
-             if (oparg & 1) stack_pointer[1] = null;
+            if (oparg & 1) stack_pointer[1] = null;
             stack_pointer += 1 + ((oparg & 1));
             DISPATCH();
         }
                 null = NULL;
             }
             stack_pointer[0] = res;
-             if (oparg & 1) stack_pointer[1] = null;
+            if (oparg & 1) stack_pointer[1] = null;
             stack_pointer += 1 + ((oparg & 1));
             DISPATCH();
         }
                 null = NULL;
             }
             stack_pointer[0] = res;
-             if (oparg & 1) stack_pointer[1] = null;
+            if (oparg & 1) stack_pointer[1] = null;
             stack_pointer += 1 + ((oparg & 1));
             DISPATCH();
         }
                 null = NULL;
             }
             stack_pointer[-3] = attr;
-             if (oparg & 1) stack_pointer[-2] = null;
+            if (oparg & 1) stack_pointer[-2] = null;
             stack_pointer += -2 + ((oparg & 1));
             DISPATCH();
         }
index bcc13538e51d9be8ea8f37766c50a383eea79715..2147f6f25b8a6f5fd08481d11164f5f370545c46 100644 (file)
@@ -444,7 +444,8 @@ def analyze_forest(forest: list[parser.AstNode]) -> Analysis:
                 if target.text in instructions:
                     instructions[target.text].is_target = True
     # Hack
-    instructions["BINARY_OP_INPLACE_ADD_UNICODE"].family = families["BINARY_OP"]
+    if "BINARY_OP_INPLACE_ADD_UNICODE" in instructions:
+        instructions["BINARY_OP_INPLACE_ADD_UNICODE"].family = families["BINARY_OP"]
     return Analysis(instructions, uops, families, pseudos)
 
 
index 34e39855a9b40a6cfba0bf642a42dcab77f3485e..67b1c9a169024ce8bb48bd0182d235b117132adb 100644 (file)
@@ -38,7 +38,8 @@ class CWriter:
         parens = txt.count("(") - txt.count(")")
         if parens < 0:
             self.indents.pop()
-        elif "}" in txt or is_label(txt):
+        braces = txt.count("{") - txt.count("}")
+        if braces < 0 or is_label(txt):
             self.indents.pop()
 
     def maybe_indent(self, txt: str) -> None:
@@ -50,11 +51,13 @@ class CWriter:
             self.indents.append(offset)
         if is_label(txt):
             self.indents.append(self.indents[-1] + 4)
-        elif "{" in txt:
-            if 'extern "C"' in txt:
-                self.indents.append(self.indents[-1])
-            else:
-                self.indents.append(self.indents[-1] + 4)
+        else:
+            braces = txt.count("{") - txt.count("}")
+            if braces > 0:
+                if 'extern "C"' in txt:
+                    self.indents.append(self.indents[-1])
+                else:
+                    self.indents.append(self.indents[-1] + 4)
 
     def emit_text(self, txt: str) -> None:
         self.out.write(txt)
index e0674a7343498d5b0753994b62570e2cc6ca3351..1b565bff2c56f60a3e6bd4580a88e9bf63aab119 100644 (file)
@@ -22,8 +22,10 @@ DEFAULT_INPUT = (ROOT / "Python/bytecodes.c").absolute().as_posix()
 
 
 def root_relative_path(filename: str) -> str:
-    return Path(filename).absolute().relative_to(ROOT).as_posix()
-
+    try:
+        return Path(filename).absolute().relative_to(ROOT).as_posix()
+    except ValueError:
+        return filename
 
 def write_header(generator: str, sources: list[str], outfile: TextIO) -> None:
     outfile.write(
index c36a56ebf2d38166256e2692eb99179827d8ba7a..0b31ce4090f552a516704e82876153de56a7e0ed 100644 (file)
@@ -148,7 +148,7 @@ class Stack:
                 cast = "(PyObject *)" if var.type else ""
                 if var.name != "unused" and not var.is_array():
                     if var.condition:
-                        out.emit(f" if ({var.condition}) ")
+                        out.emit(f"if ({var.condition}) ")
                     out.emit(
                         f"stack_pointer[{self.base_offset.to_c()}] = {cast}{var.name};\n"
                     )
index 11885dca6fe1a2286f60e9b586b73379b6c8fbbf..bcfd2d88ecd734905295383fe3e07f7f37601575 100644 (file)
@@ -181,6 +181,14 @@ arg_parser.add_argument(
     "input", nargs=argparse.REMAINDER, help="Instruction definition file(s)"
 )
 
+
+def generate_tier1_from_files(
+    filenames: list[str], outfilename: str, lines: bool
+) -> None:
+    data = analyze_files(filenames)
+    with open(outfilename, "w") as outfile:
+        generate_tier1(filenames, data, outfile, lines)
+
 if __name__ == "__main__":
     args = arg_parser.parse_args()
     if len(args.input) == 0: