Skip to content

Commit de65f92

Browse files
authored
[Civl] Remove pending asyncs and inductive sequentialization (#1091)
This PR removes the implementation of pending asyncs and inductive sequentialization from Civl. The only aspect that remains is the notion of action refinement.
1 parent 4015635 commit de65f92

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+604
-2509
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
4+
namespace Microsoft.Boogie
5+
{
6+
public class ActionRefinement
7+
{
8+
private CivlTypeChecker civlTypeChecker;
9+
private Action targetAction;
10+
private Implementation inlinedImpl;
11+
12+
public static void AddCheckers(CivlTypeChecker civlTypeChecker, List<Declaration> decls)
13+
{
14+
foreach (var x in civlTypeChecker.ActionRefinements)
15+
{
16+
decls.AddRange([x.inlinedImpl, x.inlinedImpl.Proc]);
17+
}
18+
}
19+
20+
public ActionRefinement(CivlTypeChecker civlTypeChecker, Action targetAction)
21+
{
22+
this.civlTypeChecker = civlTypeChecker;
23+
this.targetAction = targetAction;
24+
inlinedImpl = CreateInlinedImplementation();
25+
var refinedAction = targetAction.RefinedAction;
26+
Dictionary<Variable, Expr> map = new Dictionary<Variable, Expr>();
27+
for (int i = 0; i < refinedAction.Impl.InParams.Count; i++)
28+
{
29+
map[refinedAction.Impl.InParams[i]] = Expr.Ident(inlinedImpl.Proc.InParams[i]);
30+
}
31+
for (int i = 0; i < refinedAction.Impl.OutParams.Count; i++)
32+
{
33+
map[refinedAction.Impl.OutParams[i]] = Expr.Ident(inlinedImpl.Proc.OutParams[i]);
34+
}
35+
var subst = Substituter.SubstitutionFromDictionary(map);
36+
inlinedImpl.Proc.Requires = refinedAction.Gate.Select(g => new Requires(false, Substituter.Apply(subst, g.Expr))).ToList();
37+
var frame = new HashSet<Variable>(civlTypeChecker.GlobalVariablesAtLayer(targetAction.LayerRange.UpperLayer));
38+
inlinedImpl.Proc.Ensures = new List<Ensures>(new[]
39+
{
40+
new Ensures(false, Substituter.Apply(subst, refinedAction.GetTransitionRelation(civlTypeChecker, frame)))
41+
{ Description = new FailureOnlyDescription($"Refinement check of {targetAction.Name} failed") }
42+
});
43+
}
44+
45+
private Implementation CreateInlinedImplementation()
46+
{
47+
var decls = new List<Declaration>();
48+
var inlinedImpl = Action.CreateDuplicateImplementation(targetAction.ActionDecl.Impl,
49+
$"{targetAction.ActionDecl.Name}_RefinementCheck");
50+
CivlAttributes.RemoveAttributes(inlinedImpl.Proc, new HashSet<string> { "inline" });
51+
decls.Add(inlinedImpl);
52+
decls.Add(inlinedImpl.Proc);
53+
var oldTopLevelDeclarations = new List<Declaration>(civlTypeChecker.program.TopLevelDeclarations);
54+
civlTypeChecker.program.AddTopLevelDeclarations(decls);
55+
decls.OfType<Implementation>().ForEach(impl =>
56+
{
57+
impl.OriginalBlocks = impl.Blocks;
58+
impl.OriginalLocVars = impl.LocVars;
59+
});
60+
Inliner.ProcessImplementation(civlTypeChecker.Options, civlTypeChecker.program, inlinedImpl);
61+
civlTypeChecker.program.TopLevelDeclarations = oldTopLevelDeclarations;
62+
decls.OfType<Implementation>().ForEach(impl =>
63+
{
64+
impl.OriginalBlocks = null;
65+
impl.OriginalLocVars = null;
66+
});
67+
return inlinedImpl;
68+
}
69+
}
70+
}

Source/Concurrency/CivlCoreTypes.cs

Lines changed: 1 addition & 198 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Collections.Generic;
2-
using System.Diagnostics;
32
using System.Linq;
43

54
namespace Microsoft.Boogie
@@ -20,36 +19,12 @@ public class Action
2019
public List<AssertCmd> SecondGate;
2120
public Implementation SecondImpl;
2221
public Dictionary<Variable, Function> TriggerFunctions;
23-
24-
public DatatypeTypeCtorDecl ChoiceDatatypeTypeCtorDecl;
25-
public Implementation ImplWithChoice;
26-
public Function InputOutputRelationWithChoice;
2722

28-
public Action(CivlTypeChecker civlTypeChecker, ActionDecl actionDecl, Action refinedAction, bool isInvariant)
23+
public Action(CivlTypeChecker civlTypeChecker, ActionDecl actionDecl, Action refinedAction)
2924
{
3025
ActionDecl = actionDecl;
3126
RefinedAction = refinedAction;
3227
Impl = CreateDuplicateImplementation(actionDecl.Impl, actionDecl.Name);
33-
if (PendingAsyncs.Any())
34-
{
35-
DesugarCreateAsyncs(civlTypeChecker, Impl, ActionDecl);
36-
if (isInvariant)
37-
{
38-
ImplWithChoice = CreateDuplicateImplementation(Impl, $"{Name}_With_Choice");
39-
var choiceDatatypeName = $"Choice_{Name}";
40-
ChoiceDatatypeTypeCtorDecl =
41-
new DatatypeTypeCtorDecl(Token.NoToken, choiceDatatypeName, new List<TypeVariable>(), null);
42-
PendingAsyncs.ForEach(elim =>
43-
{
44-
var field = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, elim.Name, elim.PendingAsyncType), true);
45-
ChoiceDatatypeTypeCtorDecl.AddConstructor(Token.NoToken, $"{choiceDatatypeName}_{elim.Name}",
46-
new List<Variable>() { field });
47-
});
48-
civlTypeChecker.program.AddTopLevelDeclaration(ChoiceDatatypeTypeCtorDecl);
49-
DesugarSetChoice(civlTypeChecker, ImplWithChoice);
50-
}
51-
DropSetChoice(Impl);
52-
}
5328

5429
AddGateSufficiencyCheckerAndHoistAsserts(civlTypeChecker);
5530

@@ -58,10 +33,6 @@ public Action(CivlTypeChecker civlTypeChecker, ActionDecl actionDecl, Action ref
5833
UsedGlobalVarsInAction = new HashSet<Variable>(VariableCollector.Collect(Impl).Where(x => x is GlobalVariable));
5934

6035
InputOutputRelation = ComputeInputOutputRelation(civlTypeChecker, Impl);
61-
if (ImplWithChoice != null)
62-
{
63-
InputOutputRelationWithChoice = ComputeInputOutputRelation(civlTypeChecker, ImplWithChoice);
64-
}
6536

6637
AtomicActionDuplicator.SetupCopy(this, ref FirstGate, ref FirstImpl, "first_");
6738
AtomicActionDuplicator.SetupCopy(this, ref SecondGate, ref SecondImpl, "second_");
@@ -76,10 +47,6 @@ public Action(CivlTypeChecker civlTypeChecker, ActionDecl actionDecl, Action ref
7647

7748
public LayerRange LayerRange => ActionDecl.LayerRange;
7849

79-
public IEnumerable<ActionDecl> PendingAsyncs => ActionDecl.CreateActionDecls;
80-
81-
public bool HasPendingAsyncs => PendingAsyncs.Any();
82-
8350
public bool IsRightMover => ActionDecl.MoverType == MoverType.Right || ActionDecl.MoverType == MoverType.Both;
8451

8552
public bool IsLeftMover => ActionDecl.MoverType == MoverType.Left || ActionDecl.MoverType == MoverType.Both;
@@ -88,27 +55,14 @@ public Action(CivlTypeChecker civlTypeChecker, ActionDecl actionDecl, Action ref
8855

8956
public bool IsUnconditionalLeftMover => IsLeftMover && !ActionDecl.HasPreconditions;
9057

91-
public int PendingAsyncStartIndex => ActionDecl.OutParams.Count;
92-
9358
public bool TriviallyCommutesWith(Action other)
9459
{
9560
return !this.ModifiedGlobalVars.Intersect(other.UsedGlobalVarsInAction).Any() &&
9661
!this.UsedGlobalVarsInAction.Intersect(other.ModifiedGlobalVars).Any();
9762
}
9863

99-
public Variable PAs(CtorType pendingAsyncType)
100-
{
101-
var pendingAsyncMultisetType = TypeHelper.MapType(pendingAsyncType, Type.Int);
102-
return Impl.OutParams.Skip(PendingAsyncStartIndex).First(v => v.TypedIdent.Type.Equals(pendingAsyncMultisetType));
103-
}
104-
10564
public bool HasAssumeCmd => Impl.Blocks.Any(b => b.Cmds.Any(c => c is AssumeCmd));
10665

107-
public DatatypeConstructor ChoiceConstructor(CtorType pendingAsyncType)
108-
{
109-
return ChoiceDatatypeTypeCtorDecl.Constructors.First(x => x.InParams[0].TypedIdent.Type.Equals(pendingAsyncType));
110-
}
111-
11266
public IEnumerable<AssertCmd> GetGateAsserts(Substitution subst, string msg)
11367
{
11468
foreach (var gate in Gate)
@@ -124,30 +78,6 @@ public Expr GetTransitionRelation(CivlTypeChecker civlTypeChecker, HashSet<Varia
12478
return TransitionRelationComputation.Refinement(civlTypeChecker, Impl, frame);
12579
}
12680

127-
public Substitution GetSubstitution(Action to)
128-
{
129-
Debug.Assert(PendingAsyncStartIndex == to.PendingAsyncStartIndex);
130-
Debug.Assert(Impl.InParams.Count == to.Impl.InParams.Count);
131-
Debug.Assert(Impl.OutParams.Count <= to.Impl.OutParams.Count);
132-
133-
Dictionary<Variable, Expr> map = new Dictionary<Variable, Expr>();
134-
for (int i = 0; i < Impl.InParams.Count; i++)
135-
{
136-
map[Impl.InParams[i]] = Expr.Ident(to.Impl.InParams[i]);
137-
}
138-
for (int i = 0; i < PendingAsyncStartIndex; i++)
139-
{
140-
map[Impl.OutParams[i]] = Expr.Ident(to.Impl.OutParams[i]);
141-
}
142-
for (int i = PendingAsyncStartIndex; i < Impl.OutParams.Count; i++)
143-
{
144-
var formal = Impl.OutParams[i];
145-
var pendingAsyncType = (CtorType)((MapType)formal.TypedIdent.Type).Arguments[0];
146-
map[formal] = Expr.Ident(to.PAs(pendingAsyncType));
147-
}
148-
return Substituter.SubstitutionFromDictionary(map);
149-
}
150-
15181
public IEnumerable<AssertCmd> Preconditions(int layerNum, Substitution subst)
15282
{
15383
var errorMessage = $"this precondition of {Name} could not be proved";
@@ -265,133 +195,6 @@ private Function ComputeInputOutputRelation(CivlTypeChecker civlTypeChecker, Imp
265195
CivlUtil.ResolveAndTypecheck(civlTypeChecker.Options, inputOutputRelation.Body);
266196
return inputOutputRelation;
267197
}
268-
269-
public static void DesugarCreateAsyncs(CivlTypeChecker civlTypeChecker, Implementation impl, ActionDecl actionDecl)
270-
{
271-
Debug.Assert(impl.OutParams.Count == actionDecl.OutParams.Count);
272-
var pendingAsyncTypeToActionDecl = new Dictionary<CtorType, ActionDecl>();
273-
var lhss = new List<IdentifierExpr>();
274-
var rhss = new List<Expr>();
275-
actionDecl.CreateActionDecls.ForEach(decl =>
276-
{
277-
pendingAsyncTypeToActionDecl[decl.PendingAsyncType] = decl;
278-
var pa = civlTypeChecker.Formal($"PAs_{decl.Name}", decl.PendingAsyncMultisetType, false);
279-
impl.Proc.OutParams.Add(pa);
280-
impl.OutParams.Add(pa);
281-
lhss.Add(Expr.Ident(pa));
282-
rhss.Add(ExprHelper.FunctionCall(decl.PendingAsyncConst, Expr.Literal(0)));
283-
});
284-
var tc = new TypecheckingContext(null, civlTypeChecker.Options);
285-
var initAssignCmd = CmdHelper.AssignCmd(lhss, rhss);
286-
initAssignCmd.Typecheck(tc);
287-
impl.Blocks[0].Cmds.Insert(0, initAssignCmd);
288-
impl.Blocks.ForEach(block =>
289-
{
290-
var newCmds = new List<Cmd>();
291-
foreach (var cmd in block.Cmds)
292-
{
293-
if (cmd is CallCmd callCmd)
294-
{
295-
var originalProc = (Procedure)Monomorphizer.GetOriginalDecl(callCmd.Proc);
296-
if (callCmd.IsAsync)
297-
{
298-
var actionDecl = (ActionDecl)callCmd.Proc;
299-
var pendingAsyncMultiset =
300-
Expr.Store(
301-
ExprHelper.FunctionCall(actionDecl.PendingAsyncConst, Expr.Literal(0)),
302-
ExprHelper.FunctionCall(actionDecl.PendingAsyncCtor, callCmd.Ins),
303-
Expr.Literal(1));
304-
var pendingAsyncMultisetType = TypeHelper.MapType(actionDecl.PendingAsyncType, Type.Int);
305-
var pendingAsyncCollector = impl.OutParams.Skip(actionDecl.OutParams.Count).First(v => v.TypedIdent.Type.Equals(pendingAsyncMultisetType));
306-
var updateAssignCmd = CmdHelper.AssignCmd(pendingAsyncCollector,
307-
ExprHelper.FunctionCall(actionDecl.PendingAsyncAdd, Expr.Ident(pendingAsyncCollector), pendingAsyncMultiset));
308-
updateAssignCmd.Typecheck(tc);
309-
newCmds.Add(updateAssignCmd);
310-
continue;
311-
}
312-
else if (originalProc.Name == "create_asyncs" || originalProc.Name == "create_multi_asyncs")
313-
{
314-
var pendingAsyncType =
315-
(CtorType)civlTypeChecker.program.monomorphizer.GetTypeInstantiation(callCmd.Proc)["T"];
316-
var pendingAsync = pendingAsyncTypeToActionDecl[pendingAsyncType];
317-
var pendingAsyncMultiset = originalProc.Name == "create_asyncs"
318-
? ExprHelper.FunctionCall(pendingAsync.PendingAsyncIte, callCmd.Ins[0],
319-
ExprHelper.FunctionCall(pendingAsync.PendingAsyncConst, Expr.Literal(1)),
320-
ExprHelper.FunctionCall(pendingAsync.PendingAsyncConst, Expr.Literal(0)))
321-
: callCmd.Ins[0];
322-
var pendingAsyncMultisetType = TypeHelper.MapType(pendingAsyncType, Type.Int);
323-
var pendingAsyncCollector = impl.OutParams.Skip(actionDecl.OutParams.Count).First(v => v.TypedIdent.Type.Equals(pendingAsyncMultisetType));
324-
var updateAssignCmd = CmdHelper.AssignCmd(pendingAsyncCollector,
325-
ExprHelper.FunctionCall(pendingAsync.PendingAsyncAdd, Expr.Ident(pendingAsyncCollector), pendingAsyncMultiset));
326-
updateAssignCmd.Typecheck(tc);
327-
newCmds.Add(updateAssignCmd);
328-
continue;
329-
}
330-
}
331-
newCmds.Add(cmd);
332-
}
333-
block.Cmds = newCmds;
334-
});
335-
}
336-
337-
private void DropSetChoice(Implementation impl)
338-
{
339-
impl.Blocks.ForEach(block =>
340-
{
341-
var newCmds = new List<Cmd>();
342-
foreach (var cmd in block.Cmds)
343-
{
344-
if (cmd is CallCmd callCmd)
345-
{
346-
var originalProcName = Monomorphizer.GetOriginalDecl(callCmd.Proc).Name;
347-
if (originalProcName == "set_choice")
348-
{
349-
continue;
350-
}
351-
}
352-
newCmds.Add(cmd);
353-
}
354-
block.Cmds = newCmds;
355-
});
356-
}
357-
358-
private void DesugarSetChoice(CivlTypeChecker civlTypeChecker, Implementation impl)
359-
{
360-
var choice = civlTypeChecker.Formal("choice", TypeHelper.CtorType(ChoiceDatatypeTypeCtorDecl), false);
361-
impl.Proc.OutParams.Add(choice);
362-
impl.OutParams.Add(choice);
363-
impl.Blocks.ForEach(block =>
364-
{
365-
var newCmds = new List<Cmd>();
366-
foreach (var cmd in block.Cmds)
367-
{
368-
if (cmd is CallCmd callCmd)
369-
{
370-
var originalProcName = Monomorphizer.GetOriginalDecl(callCmd.Proc).Name;
371-
if (originalProcName == "set_choice")
372-
{
373-
var pendingAsyncType = (CtorType)civlTypeChecker.program.monomorphizer.GetTypeInstantiation(callCmd.Proc)["T"];
374-
var pendingAsync = PendingAsyncs.First(decl => decl.PendingAsyncType.Equals(pendingAsyncType));
375-
var tc = new TypecheckingContext(null, civlTypeChecker.Options);
376-
var emptyExpr = Expr.Eq(Expr.Ident(PAs(pendingAsyncType)),
377-
ExprHelper.FunctionCall(pendingAsync.PendingAsyncConst, Expr.Literal(0)));
378-
var memberExpr = Expr.Gt(Expr.Select(Expr.Ident(PAs(pendingAsyncType)), callCmd.Ins[0]),
379-
Expr.Literal(0));
380-
var assertCmd = CmdHelper.AssertCmd(cmd.tok, Expr.Or(emptyExpr, memberExpr),
381-
"Choice is not a created pending async");
382-
assertCmd.Typecheck(tc);
383-
newCmds.Add(assertCmd);
384-
var assignCmd = CmdHelper.AssignCmd(CmdHelper.FieldAssignLhs(Expr.Ident(choice), pendingAsyncType.Decl.Name), callCmd.Ins[0]);
385-
assignCmd.Typecheck(tc);
386-
newCmds.Add(assignCmd);
387-
continue;
388-
}
389-
}
390-
newCmds.Add(cmd);
391-
}
392-
block.Cmds = newCmds;
393-
});
394-
}
395198

396199
private void DeclareTriggerFunctions()
397200
{

Source/Concurrency/CivlRewriter.cs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,6 @@ public static void Transform(ConcurrencyOptions options, CivlTypeChecker civlTyp
2929
civlTypeChecker.AtomicActions.ForEach(x =>
3030
{
3131
decls.AddRange(new Declaration[] { x.Impl, x.Impl.Proc, x.InputOutputRelation });
32-
if (x.ImplWithChoice != null)
33-
{
34-
decls.AddRange(new Declaration[]
35-
{ x.ImplWithChoice, x.ImplWithChoice.Proc, x.InputOutputRelationWithChoice });
36-
}
3732
});
3833

3934
// Commutativity checks
@@ -51,10 +46,7 @@ public static void Transform(ConcurrencyOptions options, CivlTypeChecker civlTyp
5146
if (!options.TrustRefinement)
5247
{
5348
YieldingProcChecker.AddRefinementCheckers(civlTypeChecker, decls);
54-
if (!options.TrustSequentialization)
55-
{
56-
Sequentialization.AddCheckers(civlTypeChecker, decls);
57-
}
49+
ActionRefinement.AddCheckers(civlTypeChecker, decls);
5850
}
5951

6052
foreach (var action in civlTypeChecker.AtomicActions)

0 commit comments

Comments
 (0)