[llvm] [Dexter] Add ability to rewrite scripts to fill-in unknown values (PR #202799)
Jeremy Morse via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 22 05:59:39 PDT 2026
================
@@ -0,0 +1,201 @@
+# DExTer : Debugging Experience Tester
+# ~~~~~~ ~ ~~ ~ ~~
+#
+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+"""Utilities for using debugger output to generate expected values that match that output."""
+
+from collections import Counter, OrderedDict, defaultdict
+from copy import deepcopy
+from enum import Enum, IntEnum
+from typing import Any, Dict, List, Optional, Set, Tuple, Union
+
+from dex.dextIR import DextIR, StepIR, ValueIR
+from dex.evaluation.StateMatch import get_active_where_matches
+from dex.test_script.Nodes import Expect, Then, Value, Where
+from dex.test_script.Script import DexterScript, Scope
+from dex.tools.Main import Context
+
+
+class ExpectedValueWriter:
+ """Given a ValueIR for an Expect, generates a complete expected value that matches that value if one can be
+ provided."""
+
+ def __init__(self, expect: Expect, value: ValueIR):
+ self.expect = expect
+ self.root_value = value
+ self.expected_value = expect.get_variable_result(value)
+
+
+def unique_expected_values(elements: List[ExpectedValueWriter]):
+ """Given a list of ExpectedValueWriters, and returns either a list containing the unique set of non-None expected
+ values, or a single item if there is only one non-duplicated expected value in the list, or None if there are no
+ valid expected values."""
+
+ unique_set = set()
+ result = []
+ for element in elements:
+ expected_value = element.expected_value
+ if expected_value is None:
+ continue
+ if expected_value not in unique_set:
+ unique_set.add(expected_value)
+ result.append(expected_value)
+ if not result:
+ return None
+ if len(result) == 1:
+ return result[0]
+ return result
+
+
+class StepExpectWriter:
+ """Processes all active, unknown expects at a given debugger step and produces ExpectedValueWriter results for
+ each."""
+
+ def __init__(self, step: StepIR, script: DexterScript):
+ self.step = step
+ self.script = script
+ self.state_match = get_active_where_matches(script, step)
+ active_expects = {
+ expect
+ for where_match in self.state_match.values()
+ for expect in where_match.active_expects
+ }
+ self.expect_matches: Dict[Expect, ExpectedValueWriter] = {}
+
+ def add_expected_values(expect: Expect, expected_value: Any, scope: Scope):
+ assert isinstance(expect, Value), "Non-Value expects currently unsupported"
+ if expect in active_expects and expected_value is None:
+ self.expect_matches[expect] = ExpectedValueWriter(
+ expect, step.watches[expect.get_watched_expr()]
+ )
+
+ script.visit_script(visit_expect=add_expected_values)
+
+
+class ScriptExpectWriter:
+ """Given the full output from a debugger run and a script with missing expected values, returns a script with
+ filled-in expected values that match the debugger output."""
+
+ def __init__(self, context: Context, dext_ir: DextIR):
+ self.context = context
+ self.dext_ir = dext_ir
+ self.unknown_expect_rewrites: Dict[
+ Expect, List[Tuple[int, ExpectedValueWriter]]
+ ] = {}
+ self.new_script: Optional[DexterScript] = None
+ self.new_expected_values: Dict[Expect, Any] = {}
+ self.missing_expect_rewrites: List[Expect] = []
+
+ def collect_unknown_expects(expect: Expect, expected_value: Any, scope: Scope):
+ assert isinstance(expect, Value), "Non-Value expects currently unsupported"
+ if expected_value is None:
+ self.unknown_expect_rewrites[expect] = []
+
+ script = dext_ir.script
+ assert (
+ script is not None
+ ), "Cannot use ScriptExpectWriter on a non-script Dexter test."
+ script.visit_script(visit_expect=collect_unknown_expects)
+
+ # If there are no expects to update, then there is no rewriting to be done - exit early.
+ if not self.unknown_expect_rewrites:
+ return
+
+ self.step_writers = [StepExpectWriter(step, script) for step in dext_ir.steps]
----------------
jmorse wrote:
A comment along the lines of "groups x by somethingorother" for each of these collections would be useful.
https://github.com/llvm/llvm-project/pull/202799
More information about the llvm-commits
mailing list