quebex

A software analysis framework built around the QBE intermediate language

git clone https://git.8pit.net/quebex.git

 1-- SPDX-FileCopyrightText: 2024 University of Bremen
 2-- SPDX-FileCopyrightText: 2025 Sören Tempel <soeren+git@soeren-tempel.net>
 3--
 4-- SPDX-License-Identifier: MIT AND GPL-3.0-only
 5
 6module Language.QBE.Simulator.Symbolic.Tracer
 7  ( Branch (Branch),
 8    newBranch,
 9    fromBranch,
10    ExecTrace,
11    newExecTrace,
12    toSExprs,
13    appendBranch,
14    appendCons,
15  )
16where
17
18import Language.QBE.Simulator.Symbolic.Expression qualified as SE
19import SimpleSMT qualified as SMT
20
21-- Represents a branch condition in the executed code
22data Branch
23  = Branch
24      Bool -- Whether negation of the branch was attempted
25      SE.BitVector -- The symbolic branch condition
26  deriving (Show, Eq)
27
28-- Create a new branch condition.
29newBranch :: SE.BitVector -> Branch
30newBranch = Branch False
31
32-- Create a new branch from an existing branch, thereby updating its metadata.
33-- It is assumed that the condition, encoded in the branches, is equal.
34fromBranch :: Branch -> Branch -> Branch
35fromBranch (Branch wasNeg' _) (Branch wasNeg ast) =
36  Branch (wasNeg || wasNeg') ast
37
38------------------------------------------------------------------------
39
40-- Represents a single execution through a program, tracking for each
41-- symbolic branch condition if it was 'True' or 'False'.
42type ExecTrace = [(Bool, Branch)]
43
44-- Create a new empty execution tree.
45newExecTrace :: ExecTrace
46newExecTrace = []
47
48-- Return all branch conditions of an 'ExecTrace'.
49toSExprs :: ExecTrace -> [SMT.SExpr]
50toSExprs = map (\(_, Branch _ bv) -> SE.toSExpr bv)
51
52-- Append a branch to the execution trace, denoting via a 'Bool'
53-- if the branch was taken or if it was not taken.
54appendBranch :: ExecTrace -> Bool -> Branch -> ExecTrace
55appendBranch trace wasTrue branch = trace ++ [(wasTrue, branch)]
56
57-- Append a constraint to the execution tree. This constraint must
58-- be true and, contrary to appendBranch, negation will not be
59-- attempted for it.
60appendCons :: ExecTrace -> SE.BitVector -> ExecTrace
61appendCons trace cons = trace ++ [(True, Branch True cons)]