Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 448 #450

Merged
merged 36 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
9620ea8
add FnBindings module representing post-hoc defined functions
danmatichuk Sep 20, 2024
8016376
overhaul the control flow sync/merge logic to use uninterpreted funct…
danmatichuk Sep 25, 2024
cd2100c
Use BoundVars in FnBindings rather than SymFn to work around groundin…
danmatichuk Sep 25, 2024
6f3c8bb
FnBindings: use bound variables instead of functions
danmatichuk Oct 2, 2024
206e308
WIP: handleProcessMerge is over-widening at the moment, see TODO
danmatichuk Oct 2, 2024
0af3e98
FnBindings: don't generate uninterpreted functions for concrete values
danmatichuk Oct 31, 2024
e3df8b8
drop implicit SimSpec wrapping from 'withFreshScope'
danmatichuk Oct 31, 2024
92813a6
remove deprecaded 'scopeAsm' field from 'SimScope'
danmatichuk Oct 31, 2024
45e49ba
add "composite" scopes to handle mixing variables from
danmatichuk Nov 6, 2024
d688d9e
WIP: rework control flow merge logic to use mixed scopes
danmatichuk Nov 6, 2024
a01f3ba
add desync-assert tests
danmatichuk Nov 14, 2024
0f3ab93
resolve merge artifacts from Data.Quant
danmatichuk Dec 11, 2024
d49e7c5
more Node generalizations
danmatichuk Dec 11, 2024
5a6d730
WIP: transplant function binding propagation
danmatichuk Dec 11, 2024
8157622
more Quant refinements
danmatichuk Dec 12, 2024
1ed1b2c
pull in rewriteStrategy
danmatichuk Dec 12, 2024
43c8754
Data.Quant: misc interface changes
danmatichuk Dec 13, 2024
d652078
properly track divergence points for single-sided nodes
danmatichuk Dec 18, 2024
89fa195
use global uninterpreted function to define "caller" stack base for r…
danmatichuk Jan 6, 2025
8d6da88
always add divergence point when combining single-sided nodes
danmatichuk Jan 6, 2025
66ed8ef
avoid scheduling loop when re-processing control flow divergence
danmatichuk Jan 6, 2025
c9937d6
rewrite propagated assertion using function bindings
danmatichuk Jan 6, 2025
eab0181
add debugging information when function bindings need to be propagated
danmatichuk Jan 6, 2025
6b4b247
add type-level case distinction for QuantK
danmatichuk Jan 7, 2025
ba4e782
drop divergence point from two-sided nodes
danmatichuk Jan 7, 2025
47ab6aa
avoid implicit condition propagation when widening between one and tw…
danmatichuk Jan 7, 2025
9132cfe
queue ancestors of divergence point when propagating assertions
danmatichuk Jan 8, 2025
7f1839b
ensure that fresh domains have the expected original/patched shape
danmatichuk Jan 8, 2025
adb874a
desync-zerostep: set desync to be before pushing any arguents to the …
danmatichuk Jan 8, 2025
739dc5d
fix symbolic pointer support when adding domain refinements
danmatichuk Jan 10, 2025
023739c
queueSyncNodeMerge: fix after dropping diverge points from two-sided …
danmatichuk Jan 10, 2025
79732d9
use a runtime error when expected quantifier convertion fails
danmatichuk Jan 10, 2025
ad19598
ignore "handleMerge" flag when scheduling single-sided sync points
danmatichuk Jan 10, 2025
9dd8ad8
add informative error message when a scheduled node has no domain
danmatichuk Jan 10, 2025
3111d0a
give Inequivalent result when entry point has unsolved assertions
danmatichuk Jan 10, 2025
65e5208
add desync-assert test
danmatichuk Jan 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pate.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ library
Pate.Verification.DemandDiscovery,
Pate.Verification.Domain,
Pate.Verification.ExternalCall,
Pate.Verification.FnBindings,
Pate.Verification.InlineCallee,
Pate.Verification.MemoryLog,
Pate.Verification.Override,
Expand Down
7 changes: 7 additions & 0 deletions src/Data/Parameterized/SetF.hs
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,14 @@ module Data.Parameterized.SetF
, fromSet
, map
, ppSetF
, asSet
) where

import Prelude hiding (filter, null, map)
import qualified Data.List as List
import Data.Parameterized.Classes
import qualified Data.Foldable as Foldable
import qualified Control.Lens as L

import qualified Prettyprinter as PP
import Prettyprinter ( (<+>) )
Expand Down Expand Up @@ -150,6 +152,11 @@ toSet (SetF s) = unsafeCoerce s
fromSet :: (OrdF f, Ord (f tp)) => Set (f tp) -> SetF f tp
fromSet s = SetF (unsafeCoerce s)

asSet ::
(OrdF f, Ord (f tp)) =>
L.Lens' (SetF f tp) (Set (f tp))
asSet f sf = fmap fromSet (f (toSet sf))

map ::
(OrdF g) => (f tp -> g tp) -> SetF f tp -> SetF g tp
map f (SetF s) = SetF (S.map (\(AsOrd v) -> AsOrd (f v)) s)
Expand Down
1 change: 1 addition & 0 deletions src/Data/Parameterized/TotalMapF.hs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ module Data.Parameterized.TotalMapF
, zip
, mapWithKey
, traverseWithKey
, toList
) where

import Prelude hiding ( zip )
Expand Down
351 changes: 302 additions & 49 deletions src/Data/Quant.hs

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions src/Pate/AssumptionSet.hs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ instance OrdF (W4.SymExpr sym) => PEM.ExprMappable sym (AssumptionSet sym) where
return $ MapF.singleton k' v'
return $ mkAssumptionSet sym ps' (foldr (mergeExprSetFMap (Proxy @sym)) MapF.empty bs')

instance PEM.ExprFoldable sym (AssumptionSet sym) where
foldExpr sym f (AssumptionSet ps bs) acc =
PEM.withSymExprFoldable @W4.BaseBoolType sym $
PEM.foldExpr sym f ps acc >>= PEM.foldExpr sym f bs

instance forall sym. W4S.SerializableExprs sym => W4S.W4Serializable sym (AssumptionSet sym) where
w4Serialize (AssumptionSet ps bs) | SetF.null ps, MapF.null bs = W4S.w4Serialize True
w4Serialize (AssumptionSet ps bs) | [p] <- SetF.toList ps, MapF.null bs = W4S.w4SerializeF p
Expand Down Expand Up @@ -166,6 +171,11 @@ data NamedAsms sym (nm :: Symbol) =
instance W4S.SerializableExprs sym => W4S.W4Serializable sym (NamedAsms sym nm) where
w4Serialize (NamedAsms asm) = W4S.w4Serialize asm

instance PEM.ExprFoldable sym (NamedAsms sym nm) where
foldExpr sym f (NamedAsms asm) acc = PEM.foldExpr sym f asm acc

instance PEM.ExprFoldableF sym (NamedAsms sym)

instance PEM.ExprMappable sym (NamedAsms sym nm) where
mapExpr sym f (NamedAsms asm) = NamedAsms <$> PEM.mapExpr sym f asm

Expand Down
11 changes: 11 additions & 0 deletions src/Pate/Equivalence/Condition.hs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,13 @@ instance PEM.ExprMappable sym (EquivalenceCondition sym arch v) where
<*> PEM.mapExpr sym f c
<*> PEM.mapExpr sym f d

instance PEM.ExprFoldableF sym (MM.ArchReg arch) => PEM.ExprFoldable sym (EquivalenceCondition sym arch v) where
foldExpr sym f (EquivalenceCondition a b c d) acc =
PEM.foldExpr sym f a acc
>>= PEM.foldExpr sym f b
>>= PEM.foldExpr sym f c
>>= PEM.foldExpr sym f d

instance PS.Scoped (EquivalenceCondition sym arch) where
unsafeCoerceScope (EquivalenceCondition a b c d) = EquivalenceCondition a (PS.unsafeCoerceScope b) c d

Expand Down Expand Up @@ -234,6 +241,10 @@ instance PS.Scoped (RegisterCondition sym arch) where
instance PEM.ExprMappable sym (RegisterCondition sym arch v) where
mapExpr sym f (RegisterCondition cond) = RegisterCondition <$> MM.traverseRegsWith (\_ -> PEM.mapExpr sym f) cond

instance PEM.ExprFoldableF sym (MM.ArchReg arch) => PEM.ExprFoldable sym (RegisterCondition sym arch v) where
foldExpr sym f (RegisterCondition cond) = PEM.foldExpr sym f (MM.regStateMap cond)


trueRegCond ::
W4.IsSymExprBuilder sym =>
PA.ValidArch arch =>
Expand Down
41 changes: 37 additions & 4 deletions src/Pate/ExprMappable.hs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ module Pate.ExprMappable (
, withExprFoldable
, ExprFoldableFC
, ExprFoldableIO(..)
, withSymExprFoldable
, SkipTransformation(..)
, ToExprMappable(..)
, SymExprMappable(..)
Expand Down Expand Up @@ -70,6 +71,7 @@ import qualified Lang.Crucible.Utils.MuxTree as MT
import Data.Parameterized.Map (MapF)
import qualified Data.Parameterized.Map as MapF
import qualified Data.Parameterized.TraversableF as TF
import qualified Data.Parameterized.TraversableFC as TFC
import Data.Text
import Control.Monad (forM, foldM)
import Data.Kind (Type)
Expand Down Expand Up @@ -414,6 +416,9 @@ withExprFoldable ::
(ExprFoldable sym (f tp) => a) -> a
withExprFoldable f = withExprFoldable_ (Proxy @sym) (Proxy @f) (Proxy @tp) f

instance forall sym f. ExprFoldableF sym f => ExprFoldable sym (Some f) where
foldExpr sym f (Some (a :: f tp)) b = withExprFoldable @sym @f @tp $ foldExpr sym f a b

class (forall sym. ExprFoldableF sym f) => ExprFoldableFC f where

instance (Ord f, ExprMappable sym f) => ExprMappable sym (MT.MuxTree sym f) where
Expand Down Expand Up @@ -456,15 +461,37 @@ instance ExprFoldable sym f => ExprFoldable sym (Maybe f) where
foldExpr sym f (Just e) b0 = foldExpr sym f e b0
foldExpr _ _ Nothing b0 = return b0

instance (ExprFoldable sym f) => ExprFoldable sym (MT.MuxTree sym f) where
foldExpr sym f mt b0 | SymExprFoldable aEF <- symExprFoldable sym = aEF @WI.BaseBoolType $ foldExpr sym f (MT.viewMuxTree mt) b0
instance forall sym f. (ExprFoldable sym f) => ExprFoldable sym (MT.MuxTree sym f) where
foldExpr sym f mt b0 | SymExprFoldable aEF <- symExprFoldable sym =
aEF $ withExprFoldable @sym @(WI.SymExpr sym) @WI.BaseBoolType $ foldExpr sym f (MT.viewMuxTree mt) b0

instance forall sym f ctx. ExprFoldableF sym f => ExprFoldable sym (Ctx.Assignment f ctx) where
foldExpr sym f asn b0 = TFC.foldrMFC (\(a :: f x) b -> withExprFoldable @sym @f @x $ foldExpr sym f a b) b0 asn

instance forall sym f k. (ExprFoldable sym f) => ExprFoldable sym (WPM.PredMap sym f k) where
foldExpr sym f pm b = withSymExprFoldable @WI.BaseBoolType sym $
WPM.foldMWithKey pm (\k v b_ -> foldExpr sym f k b_ >>= foldExpr sym f v) b

instance ExprFoldable sym f => ExprFoldable sym ((Const f) tp) where
foldExpr sym f (Const e) b = foldExpr sym f e b

instance ExprFoldable sym f => ExprFoldableF sym (Const f)

instance ExprFoldable sym (f tp) => ExprFoldable sym (SetF.SetF f tp) where
foldExpr sym f s b = foldExpr sym f (SetF.toList s) b

instance forall sym f. ExprFoldableF sym f => ExprFoldableF sym (SetF.SetF f) where
withExprFoldable_ psym _pf ptp f =
withExprFoldable_ psym (Proxy @f) ptp f

newtype ToExprFoldable sym tp = ToExprFoldable { unEF :: WI.SymExpr sym tp }

instance ExprFoldable sym (ToExprFoldable sym tp) where
foldExpr _sym f (ToExprFoldable e) b = f e b

newtype SymExprFoldable sym f = SymExprFoldable (forall tp a. ((ExprFoldable sym (f tp)) => a) -> a)
instance ExprFoldableF sym (ToExprFoldable sym)

newtype SymExprFoldable sym f = SymExprFoldable (forall a. ((ExprFoldableF sym f) => a) -> a)

-- Same approach for 'symExprMappable' to create ExprFoldable instances for SymExpr
symExprFoldable ::
Expand All @@ -474,4 +501,10 @@ symExprFoldable ::
symExprFoldable _sym =
unsafeCoerce r
where r :: SymExprFoldable sym (ToExprFoldable sym)
r = SymExprFoldable (\a -> a)
r = SymExprFoldable (\a -> a)

withSymExprFoldable ::
forall tp sym a.
sym ->
((ExprFoldableF sym (WI.SymExpr sym), ExprFoldable sym (WI.SymExpr sym tp)) => a) -> a
withSymExprFoldable sym f | SymExprFoldable aEF <- symExprFoldable sym = aEF $ withExprFoldable @sym @(WI.SymExpr sym) @tp f
3 changes: 3 additions & 0 deletions src/Pate/Location.hs
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,9 @@ instance Ord (SomeLocation sym arch) where
LTF -> LT
GTF -> GT

instance forall sym arch. PEM.ExprMappable sym (SomeLocation sym arch) where
mapExpr sym f (SomeLocation l) = SomeLocation <$> PEM.mapExpr sym f l

instance (W4.IsSymExprBuilder sym, MM.RegisterInfo (MM.ArchReg arch)) => IsTraceNode '(sym :: DK.Type,arch :: DK.Type) "loc" where
type TraceNodeType '(sym,arch) "loc" = SomeLocation sym arch
prettyNode () (SomeLocation l) = PP.pretty (showLoc l) PP.<> ":" PP.<+> PP.pretty l
Expand Down
6 changes: 6 additions & 0 deletions src/Pate/MemCell.hs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,12 @@ instance PEM.ExprMappable sym (MemCell sym arch w) where
ptr' <- WEH.mapExprPtr sym f ptr
return $ MemCell ptr' w end

instance PEM.ExprFoldable sym (MemCell sym arch w) where
foldExpr _sym f (MemCell (CLM.LLVMPointer reg off) _w _end) b =
f (WI.natToIntegerPure reg) b >>= f off

instance PEM.ExprFoldableF sym (MemCell sym arch)

ppCell :: (WI.IsExprBuilder sym) => MemCell sym arch w -> PP.Doc a
ppCell cell =
let CLM.LLVMPointer reg off = cellPtr cell
Expand Down
14 changes: 6 additions & 8 deletions src/Pate/Monad.hs
Original file line number Diff line number Diff line change
Expand Up @@ -613,8 +613,7 @@ withSimSpec ::
EquivM sym arch (SimSpec sym arch g)
withSimSpec blocks spec f = withSym $ \sym -> do
spec_fresh <- withFreshVars blocks $ \vars -> liftIO $ bindSpec sym vars spec
forSpec spec_fresh $ \scope body ->
withAssumptionSet (scopeAsm scope) (f scope body)
forSpec spec_fresh $ \scope body -> (f scope body)

lookupArgumentNamesSingle
:: PBi.WhichBinaryRepr bin
Expand Down Expand Up @@ -654,14 +653,13 @@ currentAsm = CMR.asks envCurrentFrame

withFreshScope ::
forall sym arch f.
Scoped f =>
PB.BlockPair arch ->
(forall v. SimScope sym arch v -> EquivM sym arch (f v)) ->
EquivM sym arch (SimSpec sym arch f)
(forall v. SimScope sym arch v -> EquivM sym arch f) ->
EquivM sym arch f
withFreshScope bPair f = do
dummy_spec <- withFreshVars @sym @arch @(WithScope ()) bPair $ \_ -> do
return (mempty, WithScope ())
forSpec dummy_spec $ \scope _ -> f scope
return (WithScope ())
fmap (\x -> viewSpecBody x unWS) $ forSpec dummy_spec $ \scope _ -> WithScope <$> f scope

-- | Create a new 'SimSpec' by evaluating the given function under a fresh set
-- of bound variables. The returned 'AssumptionSet' is set as the assumption
Expand All @@ -670,7 +668,7 @@ withFreshVars ::
forall sym arch f.
Scoped f =>
PB.BlockPair arch ->
(forall v. (SimVars sym arch v PBi.Original, SimVars sym arch v PBi.Patched) -> EquivM sym arch (AssumptionSet sym,(f v))) ->
(forall v. (SimVars sym arch v PBi.Original, SimVars sym arch v PBi.Patched) -> EquivM sym arch (f v)) ->
EquivM sym arch (SimSpec sym arch f)
withFreshVars blocks f = do
argNames <- lookupArgumentNames blocks
Expand Down
29 changes: 22 additions & 7 deletions src/Pate/Monad/PairGraph.hs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ module Pate.Monad.PairGraph
, runPG
, execPG
, liftPartEqM_
, lookupFnBindings
) where

import Control.Monad.State.Strict
Expand All @@ -42,8 +43,10 @@ import Control.Monad (foldM, forM_)
import qualified Control.Monad.IO.Unlift as IO
import Data.Functor.Const
import Data.Maybe (fromMaybe)
import Control.Lens ( (&), (.~), (^.), (%~) )

import qualified Data.Parameterized.TraversableF as TF
import qualified Data.Parameterized.Map as MapF
import Data.Parameterized.Some

import SemMC.Formula.Env (SomeSome(..))
Expand All @@ -65,6 +68,10 @@ import qualified Pate.Equivalence.Error as PEE
import GHC.Stack (HasCallStack)
import qualified Prettyprinter as PP
import qualified What4.Interface as W4
import qualified Pate.Verification.FnBindings as PFn
import qualified What4.Concrete as W4
import qualified Data.Quant as Qu


instance IsTraceNode (k :: l) "pg_trace" where
type TraceNodeType k "pg_trace" = [String]
Expand Down Expand Up @@ -201,14 +208,11 @@ initialDomainSpec ::
GraphNode arch ->
EquivM sym arch (PAD.AbstractDomainSpec sym arch)
initialDomainSpec (GraphNodeEntry blocks) = withTracing @"function_name" "initialDomainSpec" $
withFreshVars blocks $ \_vars -> do
dom <- initialDomain
return (mempty, dom)
withFreshVars blocks $ \_vars -> initialDomain
initialDomainSpec (GraphNodeReturn fPair) = withTracing @"function_name" "initialDomainSpec" $ do
let blocks = PPa.map PB.functionEntryToConcreteBlock fPair
withFreshVars blocks $ \_vars -> do
dom <- initialDomain
return (mempty, dom)
withFreshVars blocks $ \_vars -> initialDomain


getScopedCondition ::
PS.SimScope sym arch v ->
Expand All @@ -218,7 +222,7 @@ getScopedCondition ::
EquivM sym arch (PEC.EquivalenceCondition sym arch v)
getScopedCondition scope pg nd condK = withSym $ \sym -> case getCondition pg nd condK of
Just condSpec -> do
(_, eqCond) <- liftIO $ PS.bindSpec sym (PS.scopeVarsPair scope) condSpec
eqCond <- liftIO $ PS.bindSpec sym (PS.scopeVarsPair scope) condSpec
return eqCond
Nothing -> return $ PEC.universal sym

Expand Down Expand Up @@ -324,3 +328,14 @@ runPendingActions lens edge result pg0 = do
case didchange of
True -> return $ Just pg1
False -> return Nothing

lookupFnBindings ::
PS.SimScope sym arch v ->
SingleGraphNode arch bin ->
PairGraph sym arch ->
EquivM sym arch (Maybe (PFn.FnBindings sym bin v))
lookupFnBindings scope sne pg = withSym $ \sym -> case MapF.lookup (Qu.AsSingle sne) (pg ^. (syncData dp . syncBindings)) of
Just (PS.AbsT bindsSpec) -> Just <$> (IO.liftIO $ PS.bindSpec sym (PS.scopeVarsPair scope) bindsSpec)
Nothing -> return Nothing
where
dp = singleNodeDivergePoint sne
Loading
Loading