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 let store = envStore env74 let varAssign = ST.cValues store75 (eTrace, nStore) <- run env (mapM (uncurry makeConcolic) params >>= execFunc entry)7677 let inputVars = ST.sexprs nStore78 finalStore <- ST.finalize solver nStore7980 (model, nEngine) <- findNext engine inputVars eTrace81 case model of82 Nothing -> pure [(varAssign, eTrace)]83 Just newModel -> do84 let nEnv = env {envStore = ST.setModel finalStore newModel}85 (:) (varAssign, eTrace) <$> explore nEngine nEnv entry params