Skip to content

Commit 16cddd4

Browse files
author
Aaron Tomb
committed
Check VCs one-by-one in crucible_llvm_verify
This is probably slightly slower in some cases, but allows us to add a specific message to each goal, and identify which one failed, which should help a lot with debugging failed proofs.
1 parent cc9f45b commit 16cddd4

File tree

1 file changed

+27
-20
lines changed

1 file changed

+27
-20
lines changed

src/SAWScript/CrucibleBuiltins.hs

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -155,26 +155,28 @@ verifyObligations :: CrucibleContext
155155
-> CrucibleMethodSpecIR
156156
-> ProofScript SatResult
157157
-> [Term]
158-
-> [Term]
158+
-> [(String, Term)]
159159
-> TopLevel ()
160160
verifyObligations cc mspec tactic assumes asserts = do
161161
let sym = ccBackend cc
162162
st <- io $ readIORef $ Crucible.sbStateManager sym
163163
let sc = Crucible.saw_ctx st
164164
t <- io $ scBool sc True
165165
assume <- io $ foldM (scAnd sc) t assumes
166-
assert <- io $ foldM (scAnd sc) t asserts
167-
goal <- io $ scImplies sc assume assert
168-
goal' <- io $ scAbstractExts sc (getAllExts goal) goal
169166
let nm = show (L.ppSymbol (csName mspec))
170-
r <- evalStateT tactic (startProof (ProofGoal Universal nm goal'))
171-
case r of
172-
Unsat _stats -> do
173-
io $ putStrLn $ unwords ["Proof succeeded!", nm]
174-
SatMulti stats vals -> do
175-
io $ putStrLn $ unwords ["Proof failed!", nm]
176-
io $ print stats
177-
io $ mapM_ print vals
167+
r <- forM asserts $ \(msg, assert) -> do
168+
goal <- io $ scImplies sc assume assert
169+
goal' <- io $ scAbstractExts sc (getAllExts goal) goal
170+
r <- evalStateT tactic (startProof (ProofGoal Universal nm goal'))
171+
case r of
172+
Unsat _stats -> return True
173+
SatMulti stats vals -> do
174+
io $ putStrLn $ unwords ["Subgoal failed:", nm, msg]
175+
io $ print stats
176+
io $ mapM_ print vals
177+
return False
178+
let msg = if and r then "Proof succeeded!" else "Proof failed!"
179+
io $ putStrLn $ unwords [msg, nm]
178180

179181
-- | Evaluate the precondition part of a Crucible method spec:
180182
--
@@ -477,7 +479,7 @@ verifyPoststate ::
477479
Map AllocIndex LLVMVal ->
478480
MemImpl ->
479481
Maybe LLVMVal ->
480-
IO [Term]
482+
IO [(String, Term)]
481483
verifyPoststate sc cc mspec env mem ret =
482484
do postconds <- mapM verifyPostCond (csPostconditions mspec)
483485
obligations <- Crucible.getProofObligations (ccBackend cc)
@@ -490,19 +492,20 @@ verifyPoststate sc cc mspec env mem ret =
490492
(Just ret', Just val) ->
491493
do val' <- resolveSetupVal cc env tyenv val
492494
goal <- assertEqualVals cc ret' val'
493-
return (goal : goals)
495+
return (("return value", goal) : goals)
494496
where
495497
dl = TyCtx.llvmDataLayout (Crucible.llvmTypeCtx (ccLLVMContext cc))
496498
tyenv = csAllocations mspec
497499
sym = ccBackend cc
498500

499501
verifyObligation (_, (Crucible.Assertion _ _ Nothing)) =
500502
fail "Found an assumption in final proof obligation list"
501-
verifyObligation (hyps, (Crucible.Assertion _ concl (Just _))) = do
503+
verifyObligation (hyps, (Crucible.Assertion _ concl (Just err))) = do
502504
true <- scBool sc True
503505
hypTerm <- foldM (scAnd sc) true =<< mapM (Crucible.toSC sym) hyps
504506
conclTerm <- Crucible.toSC sym concl
505-
scImplies sc hypTerm conclTerm
507+
obligation <- scImplies sc hypTerm conclTerm
508+
return ("safety assertion: " ++ Crucible.simErrorReasonMsg err, obligation)
506509

507510
verifyPostCond (SetupCond_PointsTo lhs val) = do
508511
lhs' <- resolveSetupVal cc env tyenv lhs
@@ -516,19 +519,23 @@ verifyPoststate sc cc mspec env mem ret =
516519
cty <- maybe (fail "can't translate type") return (memTypeToType tp)
517520
x <- Crucible.loadRaw sym mem ptr cty
518521
tVal <- valueToSC sym x
519-
scEq sc tVal (ttTerm tm)
522+
g <- scEq sc tVal (ttTerm tm)
523+
return ("points-to assertion", g)
520524
_ -> do
521525
val' <- resolveSetupVal cc env tyenv val
522526
let tp' = typeOfLLVMVal dl val'
523527
x <- Crucible.loadRaw sym mem ptr tp'
524-
assertEqualVals cc x val'
528+
g <- assertEqualVals cc x val'
529+
return ("points-to assertion", g)
525530

526531
verifyPostCond (SetupCond_Equal val1 val2) = do
527532
val1' <- resolveSetupVal cc env tyenv val1
528533
val2' <- resolveSetupVal cc env tyenv val2
529-
assertEqualVals cc val1' val2'
534+
g <- assertEqualVals cc val1' val2'
535+
return ("equality assertion", g)
530536

531-
verifyPostCond (SetupCond_Pred tm) = return (ttTerm tm)
537+
verifyPostCond (SetupCond_Pred tm) =
538+
return ("predicate assertion", ttTerm tm)
532539

533540
--------------------------------------------------------------------------------
534541

0 commit comments

Comments
 (0)