1-- SPDX-FileCopyrightText: 2025 Sören Tempel <soeren+git@soeren-tempel.net>2--3-- SPDX-License-Identifier: GPL-3.0-only4module Language.QBE.Simulator.Explorer5 ( newEngine,6 explore,7 defSolver,8 logSolver,9 )10where1112import Language.QBE.Backend.DFS (PathSel, findUnexplored, newPathSel, trackTrace)13import Language.QBE.Backend.Model (Model)14import Language.QBE.Backend.Store qualified as ST15import Language.QBE.Backend.Tracer qualified as T16import Language.QBE.Simulator (execFunc)17import Language.QBE.Simulator.Concolic.State (Env (envStore), makeConcolic, run)18import Language.QBE.Types qualified as QBE19import SimpleBV qualified as SMT20import System.IO (Handle)2122logic :: String23logic = "QF_BV"2425defSolver :: IO SMT.Solver26defSolver = do27 -- l <- SMT.newLogger 028 s <- SMT.newSolver "bitwuzla" [] Nothing29 SMT.setLogic s logic30 return s3132logSolver :: Handle -> IO SMT.Solver33logSolver handle = do34 l <- SMT.newLoggerWithHandle handle 035 s <-36 SMT.newSolverWithConfig37 (SMT.defaultConfig "bitwuzla" [])38 { SMT.solverLogger = SMT.smtSolverLogger l39 }40 SMT.setLogic s logic41 return s4243------------------------------------------------------------------------4445data Engine46 = Engine47 { expSolver :: SMT.Solver,48 expPathSel :: PathSel49 }5051newEngine :: SMT.Solver -> Engine52newEngine solver = Engine solver newPathSel5354findNext :: Engine -> [SMT.SExpr] -> T.ExecTrace -> IO (Maybe Model, Engine)55findNext e symVars eTrace = do56 let pathSel = trackTrace (expPathSel e) eTrace57 (model, nextPathSel) <- findUnexplored (expSolver e) symVars pathSel5859 let ne = e {expPathSel = nextPathSel}60 case model of61 Nothing ->62 pure (model, ne)63 Just nm ->64 pure (Just nm, ne)6566explore ::67 Engine ->68 Env ->69 QBE.FuncDef ->70 [(String, QBE.ExtType)] ->71 IO [(ST.Assign, T.ExecTrace)]72explore engine@(Engine {expSolver = solver}) env entry params = do73 (eTrace, nStore) <- run env (mapM (uncurry makeConcolic) params >>= execFunc entry)7475 -- Before finalizing the store, we can extract the variables we encountered76 -- during this concrete execution, as well as the concrete values used for77 -- these variables during the execution.78 let inputVars = ST.sexprs nStore79 varAssign = ST.cValues nStore80 finalStore <- ST.finalize solver nStore8182 (model, nEngine) <- findNext engine inputVars eTrace83 case model of84 Nothing -> pure [(varAssign, eTrace)]85 Just newModel -> do86 let nEnv = env {envStore = ST.setModel finalStore newModel}87 (:) (varAssign, eTrace) <$> explore nEngine nEnv entry params