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

Turn into passive cmd splitup #746

Draft
wants to merge 29 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
49d5d23
Recognize {:id ...} attributes on assignments
atomb May 9, 2023
0ac0824
Recognize {:id ...} on requires clauses
atomb May 10, 2023
32398ee
Recognize {:id ...} on loop invariants
atomb May 10, 2023
5c4afaf
Add a field to VCResult to track unsat cores
atomb May 10, 2023
e945230
Basic support for labeled assertions
atomb May 15, 2023
ac56302
Fix concurrency bug accidentally discovered
atomb May 31, 2023
a97032b
Mostly complete verification coverage tracking
atomb May 31, 2023
5919289
Add initial test for verification coverage
atomb Jun 1, 2023
8ad7c16
Tweak RUN commands for verification coverage test
atomb Jun 1, 2023
e95aab5
Verification coverage unsupported in batch mode
atomb Jun 1, 2023
3ce4244
Attempt to make timeouts test more robust
atomb Jun 1, 2023
950080b
Another try for more deterministic timeout testing
atomb Jun 1, 2023
7b6679b
Tiny tweaks to coverage tests
atomb Jun 1, 2023
b67d227
Merge remote-tracking branch 'upstream/master' into broader-unsat-cores
atomb Jun 1, 2023
20e06a0
Rename variables
atomb Jun 2, 2023
abcae74
Adjust how IDs (and other attributes) are tracked
atomb Jun 2, 2023
6b48078
Remove `/printNecessaryAssumes` option
atomb Jun 2, 2023
d1861c0
Typo in comment
atomb Jun 2, 2023
a07fe28
Documentation for /printVerificationCoverage, :id
atomb Jun 2, 2023
82e7e24
Remove conditionals on magic variable prefixes
atomb Jun 2, 2023
98dcf9f
Copy `:id` attributes unconditionally
atomb Jun 2, 2023
d68b1f9
Rename variable for `id` on `CallCmd`s
atomb Jun 5, 2023
6d48d32
Add comment about dummy operators
atomb Jun 5, 2023
e43e4f2
PrintVerificationCoverage -> TrackVerificationCoverage
atomb Jun 5, 2023
94cf1ea
CurrentCoveredElements -> ProofRun.CoveredElements
atomb Jun 5, 2023
449364c
Rename command variables in VCGen for loops
atomb Jun 5, 2023
725fe2d
Update verification coverage test
atomb Jun 5, 2023
cd50eef
Remove uses of /printVerificationCoverage
atomb Jun 5, 2023
20eace9
Extract outer methods from turnIntoPassiveCmd
keyboardDrummer Jun 5, 2023
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
38 changes: 29 additions & 9 deletions Source/Core/AST/Absy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,33 @@ public List<int> FindLayers()
}
return layers.Distinct().OrderBy(l => l).ToList();
}

// Look for {:name string} in list of attributes.
public string FindStringAttribute(string name)
{
return QKeyValue.FindStringAttribute(Attributes, name);
}

public void AddStringAttribute(IToken tok, string name, string parameter)
{
Attributes = new QKeyValue(tok, name, new List<object>() {parameter}, Attributes);
}

public void CopyIdFrom(IToken tok, ICarriesAttributes src)
{
var id = src.FindStringAttribute("id");
if (id is not null) {
AddStringAttribute(tok, "id", id);
}
}

public void CopyIdWithSuffixFrom(IToken tok, ICarriesAttributes src, string suffix)
{
var id = src.FindStringAttribute("id");
if (id is not null) {
AddStringAttribute(tok, "id", id + suffix);
}
}
}

[ContractClassFor(typeof(Absy))]
Expand Down Expand Up @@ -410,13 +437,6 @@ public Expr FindExprAttribute(string name)
return res;
}

// Look for {:name string} in list of attributes.
public string FindStringAttribute(string name)
{
Contract.Requires(name != null);
return QKeyValue.FindStringAttribute(this.Attributes, name);
}

// Look for {:name N} in list of attributes. Return false if attribute
// 'name' does not exist or if N is not an integer constant. Otherwise,
// return true and update 'result' with N.
Expand Down Expand Up @@ -1810,7 +1830,7 @@ public byte[] MD5DependencyChecksum

public string Checksum
{
get { return FindStringAttribute("checksum"); }
get { return (this as ICarriesAttributes).FindStringAttribute("checksum"); }
}

string dependencyChecksum;
Expand Down Expand Up @@ -3616,7 +3636,7 @@ public string Id
{
get
{
var id = FindStringAttribute("id");
var id = (this as ICarriesAttributes).FindStringAttribute("id");
if (id == null)
{
id = Name + GetHashCode().ToString() + ":0";
Expand Down
19 changes: 19 additions & 0 deletions Source/Core/AST/AbsyCmd.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3720,6 +3720,7 @@ protected override Cmd ComputeDesugaring(PrintOptions options)
Dictionary<Variable, Expr> substMapBound = new Dictionary<Variable, Expr>();
List<Variable> /*!*/
tempVars = new List<Variable>();
string callId = (this as ICarriesAttributes).FindStringAttribute("id");

// proc P(ins) returns (outs)
// requires Pre
Expand Down Expand Up @@ -3838,6 +3839,7 @@ protected override Cmd ComputeDesugaring(PrintOptions options)
AssertCmd /*!*/
a = new AssertRequiresCmd(this, reqCopy);
Contract.Assert(a != null);

if (Attributes != null)
{
// Inherit attributes of call.
Expand All @@ -3846,6 +3848,11 @@ protected override Cmd ComputeDesugaring(PrintOptions options)
a.Attributes = attrCopy;
}

// Do this after copying the attributes so it doesn't get overwritten
if (callId is not null) {
(a as ICarriesAttributes).CopyIdWithSuffixFrom(tok, req, $"${callId}$requires");
}

a.ErrorDataEnhanced = reqCopy.ErrorDataEnhanced;
newBlockBody.Add(a);
}
Expand All @@ -3857,6 +3864,11 @@ protected override Cmd ComputeDesugaring(PrintOptions options)
AssumeCmd /*!*/
a = new AssumeCmd(req.tok, Substituter.Apply(s, req.Condition));
Contract.Assert(a != null);
// These probably won't have IDs, but copy if they do.
if (callId is not null) {
(a as ICarriesAttributes).CopyIdWithSuffixFrom(tok, req, $"${callId}$requires_assumed");
}

newBlockBody.Add(a);
}
}
Expand Down Expand Up @@ -4019,6 +4031,10 @@ protected override Cmd ComputeDesugaring(PrintOptions options)

#endregion

if (callId is not null) {
(assume as ICarriesAttributes).CopyIdWithSuffixFrom(tok, e, $"${callId}$ensures");
}

newBlockBody.Add(assume);
}

Expand All @@ -4036,6 +4052,9 @@ protected override Cmd ComputeDesugaring(PrintOptions options)
cout_exp = new IdentifierExpr(cce.NonNull(couts[i]).tok, cce.NonNull(couts[i]));
Contract.Assert(cout_exp != null);
AssignCmd assign = Cmd.SimpleAssign(param_i.tok, cce.NonNull(this.Outs[i]), cout_exp);
if (callId is not null) {
Attributes = new QKeyValue(param_i.tok, "id", new List<object>(){ $"{callId}$out{i}" }, Attributes);
}
newBlockBody.Add(assign);
}
}
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/AST/AbsyType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3604,7 +3604,7 @@ public override bool IsSeq
// be represented using the provided string (and also does not need to be explicitly declared).
public string GetBuiltin()
{
return this.Decl.FindStringAttribute("builtin");
return (this.Decl as ICarriesAttributes).FindStringAttribute("builtin");
}

//----------- Cloning ----------------------------------
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/AST/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ public List<GlobalVariable /*!*/> /*!*/ GlobalVariables
}
}

public readonly ISet<string> NecessaryAssumes = new HashSet<string>();
public readonly ISet<string> AllCoveredElements = new HashSet<string>();

public IEnumerable<Block> Blocks()
{
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Monomorphization.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class MonomorphismChecker : ReadOnlyVisitor

public static bool DoesTypeCtorDeclNeedMonomorphization(TypeCtorDecl typeCtorDecl)
{
return typeCtorDecl.Arity > 0 && typeCtorDecl.FindStringAttribute("builtin") == null;
return typeCtorDecl.Arity > 0 && (typeCtorDecl as ICarriesAttributes).FindStringAttribute("builtin") == null;
}

public static bool IsMonomorphic(Program program)
Expand Down
26 changes: 18 additions & 8 deletions Source/ExecutionEngine/CommandLineOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,8 @@ public bool NormalizeDeclarationOrder

public bool ImmediatelyAcceptCommands => StratifiedInlining > 0 || ContractInfer;

public bool ProduceUnsatCores => PrintNecessaryAssumes || EnableUnSatCoreExtract == 1 ||
public bool ProduceUnsatCores => TrackVerificationCoverage ||
EnableUnSatCoreExtract == 1 ||
ContractInfer && (UseUnsatCoreForContractInfer || ExplainHoudini);

public bool BatchModeSolver { get; set; }
Expand Down Expand Up @@ -279,10 +280,9 @@ public bool UseUnsatCoreForContractInfer {

public bool PrintAssignment { get; set; }

// TODO(wuestholz): Add documentation for this flag.
public bool PrintNecessaryAssumes {
get => printNecessaryAssumes;
set => printNecessaryAssumes = value;
public bool TrackVerificationCoverage {
get => trackVerificationCoverage;
set => trackVerificationCoverage = value;
}

public int InlineDepth { get; set; } = -1;
Expand Down Expand Up @@ -544,7 +544,7 @@ void ObjectInvariant5()
private bool reverseHoudiniWorklist = false;
private bool houdiniUseCrossDependencies = false;
private bool useUnsatCoreForContractInfer = false;
private bool printNecessaryAssumes = false;
private bool trackVerificationCoverage = false;
private bool useProverEvaluate;
private bool trustMoverTypes = false;
private bool trustNoninterference = false;
Expand Down Expand Up @@ -1297,7 +1297,7 @@ protected override bool ParseOption(string name, CommandLineParseState ps)
ps.CheckBooleanFlag("crossDependencies", x => houdiniUseCrossDependencies = x) ||
ps.CheckBooleanFlag("useUnsatCoreForContractInfer", x => useUnsatCoreForContractInfer = x) ||
ps.CheckBooleanFlag("printAssignment", x => PrintAssignment = x) ||
ps.CheckBooleanFlag("printNecessaryAssumes", x => printNecessaryAssumes = x) ||
ps.CheckBooleanFlag("trackVerificationCoverage", x => trackVerificationCoverage = x) ||
ps.CheckBooleanFlag("useProverEvaluate", x => useProverEvaluate = x) ||
ps.CheckBooleanFlag("deterministicExtractLoops", x => DeterministicExtractLoops = x) ||
ps.CheckBooleanFlag("verifySeparately", x => VerifySeparately = x) ||
Expand Down Expand Up @@ -1508,7 +1508,10 @@ order in which implementations are verified (default: N = 1).

{:id <string>}
Assign a unique ID to an implementation to be used for verification
result caching (default: ""<impl. name>:0"").
result caching (default: ""<impl. name>:0""), or assign a unique ID
to a statement or contract clause for use in identifying which program
elements were necessary to complete verification. The latter form is
used by the `/trackVerificationCoverage` option.

{:timeLimit N}
Set the time limit for verifying a given implementation.
Expand Down Expand Up @@ -1896,6 +1899,13 @@ without requiring the user to actually make those changes.
This option is implemented by renaming variables and reordering
declarations in the input, and by setting solver options that have
similar effects.
/trackVerificationCoverage
Track and report which program elements labeled with an
`{:id ...}` attribute were necessary to complete verification.
Assumptions, assertions, requires clauses, ensures clauses,
assignments, and calls can be labeled for inclusion in this
report. This generalizes and replaces the previous
(undocumented) `/printNecessaryAssertions` option.

---- Verification-condition splitting --------------------------------------

Expand Down
4 changes: 2 additions & 2 deletions Source/ExecutionEngine/ExecutionEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -673,8 +673,8 @@ private async Task<PipelineOutcome> VerifyEachImplementation(TextWriter output,
CleanupRequest(requestId);
}

if (Options.PrintNecessaryAssumes && processedProgram.Program.NecessaryAssumes.Any()) {
Options.OutputWriter.WriteLine("Necessary assume command(s): {0}", string.Join(", ", processedProgram.Program.NecessaryAssumes.OrderBy(s => s)));
if (Options.TrackVerificationCoverage && processedProgram.Program.AllCoveredElements.Any()) {
Options.OutputWriter.WriteLine("Elements covered by verification: {0}", string.Join(", ", processedProgram.Program.AllCoveredElements.OrderBy(s => s)));
}

cce.NonNull(Options.TheProverFactory).Close();
Expand Down
1 change: 1 addition & 0 deletions Source/ExecutionEngine/ExecutionEngine.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<ProjectReference Include="..\Houdini\Houdini.csproj" />
<ProjectReference Include="..\Model\Model.csproj" />
<ProjectReference Include="..\VCGeneration\VCGeneration.csproj" />
<ProjectReference Include="..\Provers\SMTLib\SMTLib.csproj" />
</ItemGroup>

</Project>
2 changes: 1 addition & 1 deletion Source/ExecutionEngine/VerificationResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public sealed class VerificationResult
{
private readonly Implementation implementation;
public readonly string ProgramId;
public string MessageIfVerifies => implementation.FindStringAttribute("msg_if_verifies");
public string MessageIfVerifies => (implementation as ICarriesAttributes).FindStringAttribute("msg_if_verifies");
public string Checksum => implementation.Checksum;
public string DependenciesChecksum => implementation.DependencyChecksum;

Expand Down
1 change: 1 addition & 0 deletions Source/Houdini/HoudiniSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ public class HoudiniStatistics
private readonly Houdini houdini;
public HoudiniStatistics stats;
public List<Counterexample> Counterexamples { get; } = new();
public HashSet<string> CoveredElements { get; } = new();
private VCExpr conjecture;
private ProverInterface.ErrorHandler handler;
ConditionGeneration.VerificationResultCollector collector;
Expand Down
2 changes: 1 addition & 1 deletion Source/Provers/SMTLib/ProverInterface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ protected ErrorHandler(SMTLibOptions options)
this.options = options;
}

public virtual void AddNecessaryAssume(string id)
public virtual void AddCoveredElement(string id)
{
throw new System.NotImplementedException();
}
Expand Down
8 changes: 4 additions & 4 deletions Source/Provers/SMTLib/SMTLibInteractiveTheoremProver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -223,18 +223,18 @@ public async Task<Outcome> CheckSat(CancellationToken cancellationToken,
if (resp.Name != "")
{
usedNamedAssumes.Add(resp.Name);
if (libOptions.PrintNecessaryAssumes)
if (libOptions.TrackVerificationCoverage)
{
reporter.AddNecessaryAssume(resp.Name.Substring("aux$$assume$$".Length));
reporter.AddCoveredElement(resp.Name.Substring("aux$$assume$$".Length));
}
}

foreach (var arg in resp.Arguments)
{
usedNamedAssumes.Add(arg.Name);
if (libOptions.PrintNecessaryAssumes)
if (libOptions.TrackVerificationCoverage)
{
reporter.AddNecessaryAssume(arg.Name.Substring("aux$$assume$$".Length));
reporter.AddCoveredElement(arg.Name.Substring("aux$$assume$$".Length));
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions Source/Provers/SMTLib/SMTLibLineariser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ public string ExtractBuiltin(Function f)
{
Contract.Requires(f != null);
string retVal = null;
retVal = f.FindStringAttribute("bvbuiltin");
retVal = (f as ICarriesAttributes).FindStringAttribute("bvbuiltin");

// It used to be "sign_extend 12" in Simplify, and is "(_ sign_extend 12)" with SMT
if (retVal != null && (retVal.StartsWith("sign_extend ") || retVal.StartsWith("zero_extend ")))
Expand All @@ -249,7 +249,7 @@ public string ExtractBuiltin(Function f)

if (retVal == null)
{
retVal = f.FindStringAttribute("builtin");
retVal = (f as ICarriesAttributes).FindStringAttribute("builtin");
}

if (retVal != null && !LibOptions.UseArrayTheory && SMTLibOpLineariser.ArrayOps.Contains(retVal))
Expand Down Expand Up @@ -398,7 +398,7 @@ public bool Visit(VCExprNAry node, LineariserOptions options)
return true;
}

if (node.Op.Equals(VCExpressionGenerator.NamedAssumeOp))
if (node.Op.Equals(VCExpressionGenerator.NamedAssumeOp) || node.Op.Equals(VCExpressionGenerator.NamedAssertOp))
{
var exprVar = node[0] as VCExprVar;
NamedAssumes.Add(exprVar);
Expand Down
2 changes: 1 addition & 1 deletion Source/Provers/SMTLib/SMTLibOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public interface SMTLibOptions : CoreOptions
bool ProduceUnsatCores { get; }
bool ImmediatelyAcceptCommands { get; }
bool RunningBoogieFromCommandLine { get; }
bool PrintNecessaryAssumes { get; }
bool TrackVerificationCoverage { get; }
string ProverPreamble { get; }
bool TraceDiagnosticsOnTimeout { get; }
uint TimeLimitPerAssertionInPercent { get; }
Expand Down
7 changes: 3 additions & 4 deletions Source/Provers/SMTLib/TypeDeclCollector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -212,11 +212,11 @@ public override bool Visit(VCExprNAry node, bool arg)
AddDeclaration(string.Format("(declare-fun {0} () Bool)", exprVar.Name));
AddDeclaration(string.Format("(assert-soft {0} :weight {1})", exprVar.Name, ((VCExprSoftOp) node.Op).Weight));
}
else if (node.Op.Equals(VCExpressionGenerator.NamedAssumeOp))
else if (node.Op.Equals(VCExpressionGenerator.NamedAssumeOp) || node.Op.Equals(VCExpressionGenerator.NamedAssertOp))
{
var exprVar = node[0] as VCExprVar;
AddDeclaration(string.Format("(declare-fun {0} () Bool)", exprVar.Name));
if (options.PrintNecessaryAssumes)
if (options.TrackVerificationCoverage)
{
AddDeclaration(string.Format("(assert (! {0} :named {1}))", exprVar.Name, "aux$$" + exprVar.Name));
}
Expand Down Expand Up @@ -270,8 +270,7 @@ public override bool Visit(VCExprVar node, bool arg)
RegisterType(node.Type);
string decl =
"(declare-fun " + printedName + " () " + TypeToString(node.Type) + ")";
if (!(printedName.StartsWith("assume$$") || printedName.StartsWith("soft$$") ||
printedName.StartsWith("try$$")))
if (node.VarKind == VCExprVarKind.Normal)
{
AddDeclaration(decl);
}
Expand Down
3 changes: 2 additions & 1 deletion Source/VCExpr/QuantifierInstantiationEngine.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
Expand Down Expand Up @@ -50,7 +51,7 @@ public QuantifierInstantiationInfo(Dictionary<VCExprVar, HashSet<string>> boundV
private string skolemConstantNamePrefix;
internal VCExpressionGenerator vcExprGen;
private Boogie2VCExprTranslator exprTranslator;
internal static Dictionary<string, Type> labelToType = new();
internal static ConcurrentDictionary<string, Type> labelToType = new();

public static VCExpr Instantiate(Implementation impl, VCExpressionGenerator vcExprGen, Boogie2VCExprTranslator exprTranslator, VCExpr vcExpr)
{
Expand Down
Loading