Skip to content

Commit

Permalink
[Civl] Turn modset analysis on (#987)
Browse files Browse the repository at this point in the history
This PR makes specification of modifies clauses optional on atomic
actions. It also makes it possible to optionally specify a name for an
atomic action defined in a refines specification.
  • Loading branch information
shazqadeer authored Nov 21, 2024
1 parent e7695f0 commit 0089082
Show file tree
Hide file tree
Showing 15 changed files with 54 additions and 82 deletions.
6 changes: 0 additions & 6 deletions Source/Core/AST/Absy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2951,12 +2951,6 @@ public override void Resolve(ResolutionContext rc)

public override void Typecheck(TypecheckingContext tc)
{
if (IsAnonymous)
{
var modSetCollector = new ModSetCollector(tc.Options);
modSetCollector.DoModSetAnalysis(this.Impl);
}

var oldProc = tc.Proc;
tc.Proc = this;
base.Typecheck(tc);
Expand Down
59 changes: 19 additions & 40 deletions Source/Core/Analysis/ModSetCollector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,39 +26,10 @@ public ModSetCollector(CoreOptions options)

private bool moreProcessingRequired;

public void DoModSetAnalysis(Implementation impl)
{
this.VisitImplementation(impl);
var proc = impl.Proc;
if (modSets.ContainsKey(proc))
{
proc.Modifies = new List<IdentifierExpr>(modSets[proc].Select(v => new IdentifierExpr(v.tok, v)));
}
else
{
proc.Modifies = new List<IdentifierExpr>();
}
}

public void DoModSetAnalysis(Program program)
{
Contract.Requires(program != null);

if (options.Trace)
{
// Console.WriteLine();
// Console.WriteLine("Running modset analysis ...");
// int procCount = 0;
// foreach (Declaration/*!*/ decl in program.TopLevelDeclarations)
// {
// Contract.Assert(decl != null);
// if (decl is Procedure)
// procCount++;
// }
// Console.WriteLine("Number of procedures = {0}", procCount);*/
}

HashSet<Procedure /*!*/> implementedProcs = new HashSet<Procedure /*!*/>();
var implementedProcs = new HashSet<Procedure>();
foreach (var impl in program.Implementations)
{
if (impl.Proc != null)
Expand All @@ -67,7 +38,7 @@ public void DoModSetAnalysis(Program program)
}
}

foreach (var proc in program.Procedures)
foreach (var proc in program.Procedures.Where(x => x is not YieldProcedureDecl))
{
if (!implementedProcs.Contains(proc))
{
Expand Down Expand Up @@ -104,30 +75,33 @@ public void DoModSetAnalysis(Program program)

#if DEBUG_PRINT
options.OutputWriter.WriteLine("Number of procedures with nonempty modsets = {0}", modSets.Keys.Count);
foreach (Procedure/*!*/ x in modSets.Keys) {
foreach (Procedure x in modSets.Keys)
{
Contract.Assert(x != null);
options.OutputWriter.Write("{0} : ", x.Name);
bool first = true;
foreach (Variable/*!*/ y in modSets[x]) {
Contract.Assert(y != null);
foreach (var y in modSets[x])
{
if (first)
{
first = false;
}
else
{
options.OutputWriter.Write(", ");
}
options.OutputWriter.Write("{0}", y.Name);
}
options.OutputWriter.WriteLine("");
options.OutputWriter
}
#endif
}

public override Implementation VisitImplementation(Implementation node)
{
//Contract.Requires(node != null);
Contract.Ensures(Contract.Result<Implementation>() != null);
enclosingProc = node.Proc;
Implementation /*!*/
ret = base.VisitImplementation(node);
Implementation ret = base.VisitImplementation(node);
Contract.Assert(ret != null);
enclosingProc = null;

Expand Down Expand Up @@ -173,9 +147,14 @@ public override Cmd VisitHavocCmd(HavocCmd havocCmd)

public override Cmd VisitCallCmd(CallCmd callCmd)
{
//Contract.Requires(callCmd != null);
Contract.Ensures(Contract.Result<Cmd>() != null);
Cmd ret = base.VisitCallCmd(callCmd);

if (callCmd.IsAsync)
{
return ret;
}

foreach (IdentifierExpr ie in callCmd.Outs)
{
if (ie != null)
Expand Down Expand Up @@ -219,7 +198,7 @@ private void ProcessVariable(Variable var)
return;
}

if (!(var is GlobalVariable))
if (var is not GlobalVariable)
{
return;
}
Expand Down
7 changes: 3 additions & 4 deletions Source/Core/BoogiePL.atg
Original file line number Diff line number Diff line change
Expand Up @@ -769,10 +769,9 @@ SpecRefinedActionForYieldProcedure<.ref ActionDeclRef refinedAction, IToken name
Ident<out m>
ImplBody<out locals, out stmtList>
(.
if (m.val != "_") {
this.SemErr("expected _ for name of anoonymous action");
} else if (refinedAction == null) {
var actionDecl = new ActionDecl(tok, null, moverType, Formal.StripWhereClauses(ins), Formal.StripWhereClauses(outs),
if (refinedAction == null) {
var actionName = m.val == "_" ? null : m.val;
var actionDecl = new ActionDecl(tok, actionName, moverType, Formal.StripWhereClauses(ins), Formal.StripWhereClauses(outs),
false, new List<ActionDeclRef>(), null, null,
new List<Requires>(), new List<CallCmd>(), new List<AssertCmd>(), new List<IdentifierExpr>(), null, akv);
Pgm.AddTopLevelDeclaration(actionDecl);
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/CoreOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public enum VerbosityLevel
bool OverlookBoogieTypeErrors { get; }
uint TimeLimit { get; }
uint ResourceLimit { get; }
bool DoModSetAnalysis { get; }
bool DoModSetAnalysis { get; set; }
bool DebugStagedHoudini { get; }
int LoopUnrollCount { get; }
bool DeterministicExtractLoops { get; }
Expand Down
7 changes: 3 additions & 4 deletions Source/Core/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1235,10 +1235,9 @@ void SpecRefinedActionForYieldProcedure(ref ActionDeclRef refinedAction, IToken
}
Ident(out m);
ImplBody(out locals, out stmtList);
if (m.val != "_") {
this.SemErr("expected _ for name of anoonymous action");
} else if (refinedAction == null) {
var actionDecl = new ActionDecl(tok, null, moverType, Formal.StripWhereClauses(ins), Formal.StripWhereClauses(outs),
if (refinedAction == null) {
var actionName = m.val == "_" ? null : m.val;
var actionDecl = new ActionDecl(tok, actionName, moverType, Formal.StripWhereClauses(ins), Formal.StripWhereClauses(outs),
false, new List<ActionDeclRef>(), null, null,
new List<Requires>(), new List<CallCmd>(), new List<AssertCmd>(), new List<IdentifierExpr>(), null, akv);
Pgm.AddTopLevelDeclaration(actionDecl);
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/ResolutionContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,7 @@ public class TypecheckingContext : CheckingContext
public LayerRange ExpectedLayerRange;
public bool GlobalAccessOnlyInOld;
public int InsideOld;
public bool CheckModifies => Proc != null && (Proc.IsPure || (!Options?.DoModSetAnalysis ?? true));
public bool CheckModifies => Proc != null && (!Options?.DoModSetAnalysis ?? true);

public TypecheckingContext(IErrorSink errorSink, CoreOptions options)
: base(errorSink)
Expand Down
1 change: 1 addition & 0 deletions Source/ExecutionEngine/ExecutionEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ public Program ParseBoogieProgram(IList<string> fileNames, bool suppressTraceOut
if (program.TopLevelDeclarations.Any(d => d.HasCivlAttribute()))
{
Options.Libraries.Add("base");
Options.DoModSetAnalysis = true;
}

foreach (var libraryName in Options.Libraries)
Expand Down
12 changes: 11 additions & 1 deletion Test/civl/regression-tests/Pure1.bpl
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,14 @@ async atomic action A()
pure action F()
creates A;
{
}
}

pure action G(d: int)
{
x := d;
}

pure action H() returns (d: int)
{
d := x;
}
4 changes: 3 additions & 1 deletion Test/civl/regression-tests/Pure1.bpl.expect
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
Pure1.bpl(6,12): Error: unnecessary modifies clause for pure action
Pure1.bpl(10,9): Error: cannot refer to a global variable in this context: x
Pure1.bpl(17,12): Error: unnecessary creates clause for pure action
3 name resolution errors detected in Pure1.bpl
Pure1.bpl(24,4): Error: cannot refer to a global variable in this context: x
Pure1.bpl(29,9): Error: cannot refer to a global variable in this context: x
5 name resolution errors detected in Pure1.bpl
10 changes: 0 additions & 10 deletions Test/civl/regression-tests/Pure2.bpl

This file was deleted.

2 changes: 0 additions & 2 deletions Test/civl/regression-tests/Pure2.bpl.expect

This file was deleted.

9 changes: 0 additions & 9 deletions Test/civl/regression-tests/anonymous-action-fail.bpl

This file was deleted.

2 changes: 0 additions & 2 deletions Test/civl/regression-tests/anonymous-action-fail.bpl.expect

This file was deleted.

11 changes: 11 additions & 0 deletions Test/civl/regression-tests/anonymous-action.bpl
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,15 @@ refines both action {:layer 2} _ {
}
{
call j := A(i);
}

yield procedure {:layer 0} C(i: int) returns (j: int);
refines both action {:layer 1} AC {
call Incr();
}

action {:layer 1} Incr()
modifies x;
{
x := x + 1;
}
2 changes: 1 addition & 1 deletion Test/civl/regression-tests/anonymous-action.bpl.expect
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@

Boogie program verifier finished with 3 verified, 0 errors
Boogie program verifier finished with 6 verified, 0 errors

0 comments on commit 0089082

Please sign in to comment.