private List <Block> SubstituteBlocks(List <Block> blocks, Substitution subst, string blockLabelPrefix) { Dictionary <Block, Block> blockMap = new Dictionary <Block, Block>(); List <Block> otherBlocks = new List <Block>(); foreach (Block block in blocks) { List <Cmd> otherCmds = new List <Cmd>(); foreach (Cmd cmd in block.Cmds) { otherCmds.Add(Substituter.Apply(subst, cmd)); } Block otherBlock = new Block(); otherBlock.Cmds = otherCmds; otherBlock.Label = blockLabelPrefix + block.Label; otherBlocks.Add(otherBlock); blockMap[block] = otherBlock; } foreach (Block block in blocks) { if (block.TransferCmd is ReturnCmd) { blockMap[block].TransferCmd = new ReturnCmd(block.TransferCmd.tok); continue; } List <Block> otherGotoCmdLabelTargets = new List <Block>(); List <string> otherGotoCmdLabelNames = new List <string>(); GotoCmd gotoCmd = block.TransferCmd as GotoCmd; foreach (Block target in gotoCmd.labelTargets) { otherGotoCmdLabelTargets.Add(blockMap[target]); otherGotoCmdLabelNames.Add(blockMap[target].Label); } blockMap[block].TransferCmd = new GotoCmd(block.TransferCmd.tok, otherGotoCmdLabelNames, otherGotoCmdLabelTargets); } return(otherBlocks); }
private void Search(Block b, bool inFirst) { dfsStack.Push(b); if (b.TransferCmd is ReturnCmd) { if (first == null || inFirst) { transitionRelation = Expr.Or(transitionRelation, CalculatePathCondition()); } else { Search(first.thisAction.Blocks[0], true); } } else { GotoCmd gotoCmd = b.TransferCmd as GotoCmd; foreach (Block target in gotoCmd.labelTargets) { Search(target, inFirst); } } dfsStack.Pop(); }
private static List <Block> CloneBlocks(List <Block> blocks) { Dictionary <Block, Block> blockMap = new Dictionary <Block, Block>(); List <Block> otherBlocks = new List <Block>(); foreach (Block block in blocks) { List <Cmd> otherCmds = new List <Cmd>(); foreach (Cmd cmd in block.Cmds) { otherCmds.Add(cmd); } Block otherBlock = new Block(); otherBlock.Cmds = otherCmds; otherBlock.Label = block.Label; otherBlocks.Add(otherBlock); blockMap[block] = otherBlock; } foreach (Block block in blocks) { if (block.TransferCmd is ReturnCmd) { continue; } List <Block> otherGotoCmdLabelTargets = new List <Block>(); List <string> otherGotoCmdLabelNames = new List <string>(); GotoCmd gotoCmd = block.TransferCmd as GotoCmd; foreach (Block target in gotoCmd.labelTargets) { otherGotoCmdLabelTargets.Add(blockMap[target]); otherGotoCmdLabelNames.Add(blockMap[target].Label); } blockMap[block].TransferCmd = new GotoCmd(block.TransferCmd.tok, otherGotoCmdLabelNames, otherGotoCmdLabelTargets); } return(otherBlocks); }
/// <summary> /// Instrument the if-else block. /// </summary> /// <param name="node">The lca node.</param> private void InstrumentIfElse(ProgramNode node) { ProgramNode next = node.Successors.First(); // the block should have source location information for instrumentation to work if (next.Block.Cmds.Count > 1 && next.Block.Cmds[1] is AssertCmd) { AssertCmd assert = next.Block.Cmds[1] as AssertCmd; assert = DuplicateAssertCmd(assert); if (assert != null) { Block lca = null; foreach (Block block in program.Implementations.SelectMany(x => x.Blocks)) { if (block.TransferCmd is GotoCmd) { GotoCmd gotoCmd = block.TransferCmd as GotoCmd; if (gotoCmd.labelTargets.Contains(next.Block)) { lca = block; break; } } } int index = lca.Cmds.Count; lca.Cmds.Insert(index, assert); Implementation implementation = program.Implementations.First(x => x.Blocks.Contains(lca)); // insert a barrier at the end of the header block AddBarrier(implementation, lca, index + 1); } } }
List <Block> getTheFFinalBlock(Block b) { List <Block> lb = new List <Block>(); GotoCmd gc = b.TransferCmd as GotoCmd; if (gc == null) { lb.Add(b); } else { foreach (Block s in gc.labelTargets) { foreach (Block r in getTheFFinalBlock(s)) { if (!lb.Contains(r)) { lb.Add(r); } } } } return(lb); }
void ComputeBestSplit() { if (scoreComputed) { return; } scoreComputed = true; assertionCount = 0; foreach (Block b in blocks) { Contract.Assert(b != null); CountAssertions(b); } foreach (Block b in blocks) { Contract.Assert(b != null); BlockStats bs = GetBlockStats(b); if (bs.bigBlock) { bigBlocks.Add(b); foreach (Block ch in bs.virtualSuccessors) { Contract.Assert(ch != null); BlockStats chs = GetBlockStats(ch); if (!chs.bigBlock) { Console.WriteLine("non-big {0} accessed from {1}", ch, b); DumpDot(-1); Contract.Assert(false); throw new cce.UnreachableException(); } chs.virtualPredecessors.Add(b); } } } assumizedBranches.Clear(); totalCost = ProverCost(DoComputeScore(false)); score = double.PositiveInfinity; Block bestSplit = null; List <Block> savedBranches = new List <Block>(); foreach (Block b in bigBlocks) { Contract.Assert(b != null); GotoCmd gt = b.TransferCmd as GotoCmd; if (gt == null) { continue; } List <Block> targ = cce.NonNull(gt.labelTargets); if (targ.Count < 2) { continue; } // caution, we only consider two first exits double left0, right0, left1, right1; splitBlock = b; assumizedBranches.Clear(); assumizedBranches.Add(cce.NonNull(targ[0])); left0 = DoComputeScore(true); right0 = DoComputeScore(false); assumizedBranches.Clear(); for (int idx = 1; idx < targ.Count; idx++) { assumizedBranches.Add(cce.NonNull(targ[idx])); } left1 = DoComputeScore(true); right1 = DoComputeScore(false); double currentScore = ProverCost(left1) + ProverCost(right1); double otherScore = ProverCost(left0) + ProverCost(right0); if (otherScore < currentScore) { currentScore = otherScore; assumizedBranches.Clear(); assumizedBranches.Add(cce.NonNull(targ[0])); } if (currentScore < score) { score = currentScore; bestSplit = splitBlock; savedBranches.Clear(); savedBranches.AddRange(assumizedBranches); } } if (CommandLineOptions.Clo.VcsPathSplitMult * score > totalCost) { splitBlock = null; score = -1; } else { assumizedBranches = savedBranches; splitBlock = bestSplit; } }
public ActionInfo(Procedure proc, CodeExpr codeExpr, MoverType moverType, int phaseNum) { this.proc = proc; this.moverType = moverType; this.phaseNum = phaseNum; this.callerPhaseNums = new HashSet <int>(); this.thisGate = new List <AssertCmd>(); this.thisAction = codeExpr; this.thisInParams = new List <Variable>(); this.thisOutParams = new List <Variable>(); this.thatGate = new List <AssertCmd>(); this.thatInParams = new List <Variable>(); this.thatOutParams = new List <Variable>(); var cmds = thisAction.Blocks[0].Cmds; for (int i = 0; i < cmds.Count; i++) { AssertCmd assertCmd = cmds[i] as AssertCmd; if (assertCmd == null) { break; } thisGate.Add(assertCmd); cmds[i] = new AssumeCmd(assertCmd.tok, assertCmd.Expr); } Dictionary <Variable, Expr> map = new Dictionary <Variable, Expr>(); foreach (Variable x in proc.InParams) { this.thisInParams.Add(x); Variable y = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "that_" + x.Name, x.TypedIdent.Type), true); this.thatInParams.Add(y); map[x] = new IdentifierExpr(Token.NoToken, y); } foreach (Variable x in proc.OutParams) { this.thisOutParams.Add(x); Variable y = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "that_" + x.Name, x.TypedIdent.Type), false); this.thatOutParams.Add(y); map[x] = new IdentifierExpr(Token.NoToken, y); } List <Variable> otherLocVars = new List <Variable>(); foreach (Variable x in thisAction.LocVars) { Variable y = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "that_" + x.Name, x.TypedIdent.Type), false); map[x] = new IdentifierExpr(Token.NoToken, y); otherLocVars.Add(y); } Contract.Assume(proc.TypeParameters.Count == 0); Substitution subst = Substituter.SubstitutionFromHashtable(map); foreach (AssertCmd assertCmd in thisGate) { thatGate.Add((AssertCmd)Substituter.Apply(subst, assertCmd)); } Dictionary <Block, Block> blockMap = new Dictionary <Block, Block>(); List <Block> otherBlocks = new List <Block>(); foreach (Block block in thisAction.Blocks) { List <Cmd> otherCmds = new List <Cmd>(); foreach (Cmd cmd in block.Cmds) { otherCmds.Add(Substituter.Apply(subst, cmd)); } Block otherBlock = new Block(); otherBlock.Cmds = otherCmds; otherBlock.Label = "that_" + block.Label; block.Label = "this_" + block.Label; otherBlocks.Add(otherBlock); blockMap[block] = otherBlock; if (block.TransferCmd is GotoCmd) { GotoCmd gotoCmd = block.TransferCmd as GotoCmd; for (int i = 0; i < gotoCmd.labelNames.Count; i++) { gotoCmd.labelNames[i] = "this_" + gotoCmd.labelNames[i]; } } } foreach (Block block in thisAction.Blocks) { if (block.TransferCmd is ReturnExprCmd) { block.TransferCmd = new ReturnCmd(block.TransferCmd.tok); blockMap[block].TransferCmd = new ReturnCmd(block.TransferCmd.tok); continue; } List <Block> otherGotoCmdLabelTargets = new List <Block>(); List <string> otherGotoCmdLabelNames = new List <string>(); GotoCmd gotoCmd = block.TransferCmd as GotoCmd; foreach (Block target in gotoCmd.labelTargets) { otherGotoCmdLabelTargets.Add(blockMap[target]); otherGotoCmdLabelNames.Add(blockMap[target].Label); } blockMap[block].TransferCmd = new GotoCmd(block.TransferCmd.tok, otherGotoCmdLabelNames, otherGotoCmdLabelTargets); } this.thatAction = new CodeExpr(otherLocVars, otherBlocks); }
public override GotoCmd VisitGotoCmd(GotoCmd node) { //Contract.Requires(node != null); Contract.Ensures(Contract.Result <GotoCmd>() != null); return(base.VisitGotoCmd((GotoCmd)node.Clone())); }
public override Implementation VisitImplementation(Implementation node) { HashSet <Variable> start = new HashSet <Variable>(globalVarToDomainName.Keys); for (int i = 0; i < node.InParams.Count; i++) { string domainName = FindDomainName(node.Proc.InParams[i]); if (domainName != null) { inoutParamToDomainName[node.InParams[i]] = domainName; start.Add(node.InParams[i]); } } for (int i = 0; i < node.OutParams.Count; i++) { string domainName = FindDomainName(node.Proc.OutParams[i]); if (domainName != null) { inoutParamToDomainName[node.OutParams[i]] = domainName; } } var oldErrorCount = this.errorCount; var impl = base.VisitImplementation(node); if (oldErrorCount < this.errorCount) { return(impl); } Stack <Block> dfsStack = new Stack <Block>(); HashSet <Block> dfsStackAsSet = new HashSet <Block>(); availableLinearVars[node.Blocks[0]] = start; dfsStack.Push(node.Blocks[0]); dfsStackAsSet.Add(node.Blocks[0]); while (dfsStack.Count > 0) { Block b = dfsStack.Pop(); dfsStackAsSet.Remove(b); HashSet <Variable> end = PropagateAvailableLinearVarsAcrossBlock(b); if (b.TransferCmd is ReturnCmd) { foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(end)) { Error(b.TransferCmd, string.Format("Global variable {0} must be available at a return", g.Name)); } foreach (Variable v in node.OutParams) { if (FindDomainName(v) == null || end.Contains(v)) { continue; } Error(b.TransferCmd, string.Format("Output variable {0} must be available at a return", v.Name)); } continue; } GotoCmd gotoCmd = b.TransferCmd as GotoCmd; foreach (Block target in gotoCmd.labelTargets) { if (!availableLinearVars.ContainsKey(target)) { availableLinearVars[target] = new HashSet <Variable>(end); dfsStack.Push(target); dfsStackAsSet.Add(target); } else { var savedAvailableVars = new HashSet <Variable>(availableLinearVars[target]); availableLinearVars[target].IntersectWith(end); if (savedAvailableVars.IsProperSupersetOf(availableLinearVars[target]) && !dfsStackAsSet.Contains(target)) { dfsStack.Push(target); dfsStackAsSet.Add(target); } } } } return(impl); }
private string CreateNewImplementation(Implementation impl, List <Block> blocks) { if (!this.NameCounter.ContainsKey(impl.Name)) { this.NameCounter.Add(impl.Name, 0); } this.NameCounter[impl.Name]++; var newInParams = new List <Variable>(); foreach (var v in impl.Proc.InParams) { newInParams.Add(new Duplicator().VisitVariable(v.Clone() as Variable) as Variable); } var newOutParams = new List <Variable>(); foreach (var v in impl.Proc.OutParams) { newOutParams.Add(new Duplicator().VisitVariable(v.Clone() as Variable) as Variable); } var newLocalParams = new List <Variable>(); foreach (var v in impl.LocVars) { newLocalParams.Add(new Duplicator().VisitVariable(v.Clone() as Variable) as Variable); } var newBlocks = new List <Block>(); foreach (var b in impl.Blocks) { if (blocks.Any(val => val.Label.Equals(b.Label))) { continue; } var newCmds = new List <Cmd>(); foreach (var cmd in b.Cmds) { newCmds.Add(new Duplicator().Visit(cmd.Clone()) as Cmd); } TransferCmd transferCmd = null; if (b.TransferCmd is GotoCmd) { transferCmd = new GotoCmd(Token.NoToken, new List <string>(), new List <Block>()); } else { transferCmd = new ReturnCmd(Token.NoToken); } newBlocks.Add(new Block(Token.NoToken, b.Label, newCmds, transferCmd)); } foreach (var b in newBlocks) { if (!(b.TransferCmd is GotoCmd)) { continue; } var originalBlock = impl.Blocks.Find(val => val.Label.Equals(b.Label)); var originalTransfer = originalBlock.TransferCmd as GotoCmd; var gotoCmd = b.TransferCmd as GotoCmd; foreach (var target in originalTransfer.labelTargets) { if (blocks.Any(val => val.Label.Equals(target.Label))) { continue; } var newTarget = newBlocks.Find(val => val.Label.Equals(target.Label)); gotoCmd.labelTargets.Add(newTarget); gotoCmd.labelNames.Add(newTarget.Label); } } var newImpl = new Implementation(Token.NoToken, impl.Name + "#" + this.NameCounter[impl.Name], new List <TypeVariable>(), newInParams, newOutParams, newLocalParams, newBlocks, impl.Attributes); var newProc = this.CreateNewProcedure(newImpl, impl.Proc.Modifies); var newCons = this.CreateNewConstant(newImpl); this.AC.TopLevelDeclarations.Add(newProc); this.AC.TopLevelDeclarations.Add(newImpl); this.AC.TopLevelDeclarations.Add(newCons); return(newImpl.Name); }
public override GotoCmd VisitGotoCmd(GotoCmd node) { return(base.VisitGotoCmd((GotoCmd)node.Clone())); }
public override GotoCmd VisitGotoCmd(GotoCmd node) { add(node); return(base.VisitGotoCmd(node)); }
private void AddEdge(GotoCmd gotoCmd, Block b) { gotoCmd.AddTarget(b); }
public static void ProcessCounterexamplesWOSymbolicOut(SDiffCounterexamples errors, List <Variable> globals, List <Variable> eqLocVars, Implementation vtLeftProcImpl, Implementation vtRightProcImpl, List <Declaration> consts, List <Model> errModelList, string v1Name, string v2Name) { List <Expr> constraintExprs = new List <Expr>(); List <Block> listBlocksV1 = new List <Block>(); List <Block> listBlocksV2 = new List <Block>(); Model[] errModelArray = errModelList.ToArray(); var label = new GotoCmd(Token.NoToken, new List <String>() { "DONE" }); label.labelNames = new List <string>(); // label.labelTargets = new List<Block>(); label.labelNames.Add("DONE"); //label.labelTargets.Add("DONE"); // First block var labels = new List <String>(); for (int j = 0; j < errors.Count; j++) { labels.Add("Cex" + j); } labels.Add("ELSE"); var labelEntry = new GotoCmd(Token.NoToken, labels); labelEntry.labelTargets = new List <Block>(); for (int j = 0; j < errors.Count; j++) { labelEntry.labelNames.Add("Cex" + j);//labelEntry.labelTargets.Add("Cex" + j); } for (int i = 0; i < errors.Count; i++) { var impl = errors[i].Impl; var trace = errors[i].Trace; //Log.Out(Log.Normal, "Attempting symbolic execution of [" + i + "] $ " + impl.Name); if (Options.GenerateCTrace) { Log.Out(Log.Normal, "Constructing metatrace from location annotations"); var extractor = new SDiff.SymEx.TraceExtractor(); extractor.VisitTrace(trace); //Log.Out(Log.CTrace, CTrace.Make(extractor.metaTrace)); var cTrace = CTrace.Make(extractor.metaTrace, consts, errModelArray[i], v1Name, v2Name); //var cTrace = ""; if (cTrace.Trim() != "") { //note that the index for cex on the output shows 1,2,..., instead of 0,1,2.... var fname = impl.Name + "_cex_" + (i + 1) + "_out.c"; var cexOut = new TokenTextWriter(impl.Name + "_cex_" + (i + 1) + "_out.c", true); cexOut.WriteLine(cTrace); cexOut.Close(); Log.Out(Log.CTrace, "n:" + (i + 1) + ":" + fname); Log.Out(Log.CTrace, "w:" + fname); } } Log.Out(Log.Normal, "Desugaring calls"); //HACK!!!: changes havoc x; assume (x= uf(..)); --> x := uf(...) var deCall = new SDiff.SymEx.DesugarCallCmds(); trace = deCall.VisitTrace(trace); //symbolic constants var symInParams = new List <Variable>(impl.InParams); foreach (var g in globals) { symInParams.Add(g); } Log.Out(Log.Normal, "Executing trace downward"); //symbolic stores (look at symex.cs for the datastructure) // var sTrace = SDiff.SymEx.Cexecutor.ExecDown(trace, symInParams); Log.Out(Log.Normal, "Executing trace upward"); //looks at each assume to create the path constants //clean up the duplication of assignments //SDiff.SymEx.Cexecutor.ExecUp(sTrace); Log.Out(Log.Normal, "Grabbing final execution values"); // var lastStore = sTrace.LastSCmd().Gammas.Last(); // var firstCons = sTrace.FirstSCmd().Cons; // constraintExprs.Add(firstCons.Conjoin()); //#hemr - generating new strategy right here with inlining counterexamples! // Second block List <Cmd> cmdsV1_Diff_inline = new List <Cmd>(); List <Cmd> cmdsV2_Diff_inline = new List <Cmd>(); Substitution replaceScopeV1 = delegate(Variable x) { return(replaceScopeGeneric(vtLeftProcImpl, x)); }; Substitution replaceScopeV2 = delegate(Variable x) { return(replaceScopeGeneric(vtRightProcImpl, x)); }; foreach (Block currentBlock in trace) { if (currentBlock.ToString().Contains("inline$" + v1Name)) { foreach (Cmd currentCmd in currentBlock.Cmds) { Cmd newCmd = Substituter.Apply(replaceScopeV1, currentCmd); cmdsV1_Diff_inline.Add(newCmd); } } else if (currentBlock.ToString().Contains("inline$" + v2Name)) { foreach (Cmd currentCmd in currentBlock.Cmds) { Cmd newCmd = Substituter.Apply(replaceScopeV2, currentCmd); cmdsV2_Diff_inline.Add(newCmd); } } } Block blockV1 = new Block(Token.NoToken, "Cex" + i, cmdsV1_Diff_inline, label); Block blockV2 = new Block(Token.NoToken, "Cex" + i, cmdsV2_Diff_inline, label); listBlocksV1.Add(blockV1); listBlocksV2.Add(blockV2); //#hemr - displaying values related to error model (at console level) Model currentModel = errModelArray[i]; //var keys = currentModel.identifierToPartition.Keys; var keys = currentModel.Functions.Where(f => f.Arity == 0).Select(f => f.GetConstant()); } Expr disjunctionDiffCond = Expr.False; foreach (Expr currentExpr in constraintExprs) { disjunctionDiffCond = Expr.Or(disjunctionDiffCond, currentExpr); } ProcessCounterexampleForDiffInliningWOSymbolicOut(eqLocVars, vtLeftProcImpl, vtRightProcImpl, v1Name, v2Name, listBlocksV1, listBlocksV2, labelEntry); }
private void Transform4DoomedCheck(Implementation impl) { variable2SequenceNumber = new Dictionary <Variable, int>(); incarnationOriginMap = new Dictionary <Incarnation, Absy>(); if (impl.Blocks.Count < 1) { return; } impl.PruneUnreachableBlocks(); AddBlocksBetween(impl.Blocks); ResetPredecessors(impl.Blocks); GraphAnalyzer ga = new GraphAnalyzer(impl.Blocks); LoopRemover lr = new LoopRemover(ga); lr.AbstractLoopUnrolling(); impl.Blocks = ga.ToImplementation(out m_UncheckableBlocks); ResetPredecessors(impl.Blocks); // Check for the "BlocksBetween" if all their successors are in m_UncheckableBlocks List <Block> oldblocks = new List <Block>(); oldblocks.AddRange(impl.Blocks); GenerateHelperBlocks(impl); #region Check for the "BlocksBetween" if all their successors are in m_UncheckableBlocks foreach (Block b in impl.Blocks) { if (oldblocks.Contains(b)) { continue; } GotoCmd gc = b.TransferCmd as GotoCmd; if (gc != null) { bool allsuccUncheckable = true; foreach (Block _b in gc.labelTargets) { if (!m_UncheckableBlocks.Contains(_b)) { allsuccUncheckable = false; break; } } if (allsuccUncheckable && !m_UncheckableBlocks.Contains(b)) { m_UncheckableBlocks.Add(b); } } } #endregion impl.Blocks = DeepCopyBlocks(impl.Blocks, m_UncheckableBlocks); m_BlockReachabilityMap = new Dictionary <Block, Variable>(); List <Cmd> cs = GenerateReachabilityPredicates(impl); //foreach (Block test in getTheFFinalBlock(impl.Blocks[0])) //{ // test.Cmds.AddRange(cs); //} ResetPredecessors(impl.Blocks); //EmitImpl(impl,false); Dictionary <Variable, Expr> var2Expr = PassifyProgram(impl, new ModelViewInfo(program, impl)); // Collect the last incarnation of each reachability variable in the passive program foreach (KeyValuePair <Block, Variable> kvp in m_BlockReachabilityMap) { if (var2Expr.ContainsKey(kvp.Value)) { m_LastReachVarIncarnation[kvp.Value] = (Expr)var2Expr[kvp.Value]; } } }
public AtomicActionInfo(Procedure proc, Ensures ensures, MoverType moverType, int layerNum, int availableUptoLayerNum) : base(proc, layerNum, availableUptoLayerNum) { CodeExpr codeExpr = ensures.Condition as CodeExpr; this.ensures = ensures; this.moverType = moverType; this.thisGate = new List <AssertCmd>(); this.thisAction = codeExpr; this.thisInParams = new List <Variable>(); this.thisOutParams = new List <Variable>(); this.thatGate = new List <AssertCmd>(); this.thatInParams = new List <Variable>(); this.thatOutParams = new List <Variable>(); this.hasAssumeCmd = false; foreach (Block block in codeExpr.Blocks) { block.Cmds.ForEach(x => this.hasAssumeCmd = this.hasAssumeCmd || x is AssumeCmd); } var cmds = thisAction.Blocks[0].Cmds; for (int i = 0; i < cmds.Count; i++) { AssertCmd assertCmd = cmds[i] as AssertCmd; if (assertCmd == null) { break; } thisGate.Add(assertCmd); cmds[i] = new AssumeCmd(assertCmd.tok, Expr.True); } Dictionary <Variable, Expr> map = new Dictionary <Variable, Expr>(); foreach (Variable x in proc.InParams) { this.thisInParams.Add(x); Variable y = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "that_" + x.Name, x.TypedIdent.Type), true, x.Attributes); this.thatInParams.Add(y); map[x] = Expr.Ident(y); } foreach (Variable x in proc.OutParams) { this.thisOutParams.Add(x); Variable y = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "that_" + x.Name, x.TypedIdent.Type), false, x.Attributes); this.thatOutParams.Add(y); map[x] = Expr.Ident(y); } List <Variable> thatLocVars = new List <Variable>(); foreach (Variable x in thisAction.LocVars) { Variable y = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "that_" + x.Name, x.TypedIdent.Type), false); map[x] = Expr.Ident(y); thatLocVars.Add(y); } Contract.Assume(proc.TypeParameters.Count == 0); Substitution subst = Substituter.SubstitutionFromHashtable(map); foreach (AssertCmd assertCmd in thisGate) { thatGate.Add((AssertCmd)Substituter.Apply(subst, assertCmd)); } Dictionary <Block, Block> blockMap = new Dictionary <Block, Block>(); List <Block> thatBlocks = new List <Block>(); foreach (Block block in thisAction.Blocks) { List <Cmd> otherCmds = new List <Cmd>(); foreach (Cmd cmd in block.Cmds) { otherCmds.Add(Substituter.Apply(subst, cmd)); } Block thatBlock = new Block(); thatBlock.Cmds = otherCmds; thatBlock.Label = "that_" + block.Label; block.Label = "this_" + block.Label; thatBlocks.Add(thatBlock); blockMap[block] = thatBlock; if (block.TransferCmd is GotoCmd) { GotoCmd gotoCmd = block.TransferCmd as GotoCmd; for (int i = 0; i < gotoCmd.labelNames.Count; i++) { gotoCmd.labelNames[i] = "this_" + gotoCmd.labelNames[i]; } } } foreach (Block block in thisAction.Blocks) { if (block.TransferCmd is ReturnExprCmd) { block.TransferCmd = new ReturnCmd(block.TransferCmd.tok); blockMap[block].TransferCmd = new ReturnCmd(block.TransferCmd.tok); continue; } List <Block> thatGotoCmdLabelTargets = new List <Block>(); List <string> thatGotoCmdLabelNames = new List <string>(); GotoCmd gotoCmd = block.TransferCmd as GotoCmd; foreach (Block target in gotoCmd.labelTargets) { thatGotoCmdLabelTargets.Add(blockMap[target]); thatGotoCmdLabelNames.Add(blockMap[target].Label); } blockMap[block].TransferCmd = new GotoCmd(block.TransferCmd.tok, thatGotoCmdLabelNames, thatGotoCmdLabelTargets); } this.thatAction = new CodeExpr(thatLocVars, thatBlocks); { VariableCollector collector = new VariableCollector(); collector.Visit(codeExpr); this.actionUsedGlobalVars = new HashSet <Variable>(collector.usedVars.Where(x => x is GlobalVariable)); } List <Variable> modifiedVars = new List <Variable>(); foreach (Block block in codeExpr.Blocks) { block.Cmds.ForEach(cmd => cmd.AddAssignedVariables(modifiedVars)); } this.modifiedGlobalVars = new HashSet <Variable>(modifiedVars.Where(x => x is GlobalVariable)); { VariableCollector collector = new VariableCollector(); this.thisGate.ForEach(assertCmd => collector.Visit(assertCmd)); this.gateUsedGlobalVars = new HashSet <Variable>(collector.usedVars.Where(x => x is GlobalVariable)); } }
VCExpr LetVC(Block block, Dictionary <int, Absy> label2absy, Hashtable /*<Block, VCExprVar!>*/ blockVariables, List <VCExprLetBinding> bindings, ProverContext proverCtxt, out int assertionCount) { Contract.Requires(label2absy != null); Contract.Requires(blockVariables != null); Contract.Requires(proverCtxt != null); Contract.Requires(cce.NonNullElements(bindings)); Contract.Ensures(Contract.Result <VCExpr>() != null); assertionCount = 0; VCExpressionGenerator gen = proverCtxt.ExprGen; Contract.Assert(gen != null); VCExprVar v = (VCExprVar)blockVariables[block]; if (v == null) { /* * For block A (= block), generate: * LET_binding A_correct = wp(A_body, (/\ S \in Successors(A) :: S_correct)) * with the side effect of adding the let bindings to "bindings" for any * successor not yet visited. */ VCExpr SuccCorrect; GotoCmd gotocmd = block.TransferCmd as GotoCmd; if (gotocmd == null) { if (CommandLineOptions.Clo.vcVariety == CommandLineOptions.VCVariety.Doomed) { SuccCorrect = VCExpressionGenerator.False; } else { SuccCorrect = VCExpressionGenerator.True; } } else { Contract.Assert(gotocmd.labelTargets != null); List <VCExpr> SuccCorrectVars = new List <VCExpr>(gotocmd.labelTargets.Count); foreach (Block successor in gotocmd.labelTargets) { Contract.Assert(successor != null); int ac; VCExpr s = LetVC(successor, label2absy, blockVariables, bindings, proverCtxt, out ac); assertionCount += ac; SuccCorrectVars.Add(s); } SuccCorrect = gen.NAry(VCExpressionGenerator.AndOp, SuccCorrectVars); } VCContext context = new VCContext(label2absy, proverCtxt); // m_Context = context; VCExpr vc = Wlp.Block(block, SuccCorrect, context); assertionCount += context.AssertionCount; v = gen.Variable(block.Label + "_correct", Microsoft.Boogie.Type.Bool); bindings.Add(gen.LetBinding(v, vc)); blockVariables.Add(block, v); } return(v); }
public static List <Split /*!*/> /*!*/ DoSplit(Split initial, double maxCost, int max) { Contract.Requires(initial != null); Contract.Ensures(cce.NonNullElements(Contract.Result <List <Split> >())); List <Split> res = new List <Split>(); res.Add(initial); while (res.Count < max) { Split best = null; int bestIdx = 0, pos = 0; foreach (Split s in res) { Contract.Assert(s != null); s.ComputeBestSplit(); // TODO check totalCost first if (s.totalCost > maxCost && (best == null || best.totalCost < s.totalCost) && (s.assertionCount > 1 || s.splitBlock != null)) { best = s; bestIdx = pos; } pos++; } if (best == null) { break; // no split found } Split s0, s1; bool splitStats = CommandLineOptions.Clo.TraceVerify; if (splitStats) { Console.WriteLine("{0} {1} -->", best.splitBlock == null ? "SLICE" : ("SPLIT@" + best.splitBlock.Label), best.Stats); if (best.splitBlock != null) { GotoCmd g = best.splitBlock.TransferCmd as GotoCmd; if (g != null) { Console.Write(" exits: "); foreach (Block b in cce.NonNull(g.labelTargets)) { Contract.Assert(b != null); Console.Write("{0} ", b.Label); } Console.WriteLine(""); Console.Write(" assumized: "); foreach (Block b in best.assumizedBranches) { Contract.Assert(b != null); Console.Write("{0} ", b.Label); } Console.WriteLine(""); } } } if (best.splitBlock != null) { s0 = best.SplitAt(0); s1 = best.SplitAt(1); } else { best.splitBlock = null; s0 = best.SliceAsserts(best.assertionCost / 2, true); s1 = best.SliceAsserts(best.assertionCost / 2, false); } if (true) { List <Block> ss = new List <Block>(); ss.Add(s0.blocks[0]); ss.Add(s1.blocks[0]); try { best.SoundnessCheck(new HashSet <List <Block> >(new BlockListComparer()), best.blocks[0], ss); } catch (System.Exception e) { Console.WriteLine(e); best.DumpDot(-1); s0.DumpDot(-2); s1.DumpDot(-3); Contract.Assert(false); throw new cce.UnreachableException(); } } if (splitStats) { s0.ComputeBestSplit(); s1.ComputeBestSplit(); Console.WriteLine(" --> {0}", s0.Stats); Console.WriteLine(" --> {0}", s1.Stats); } if (CommandLineOptions.Clo.TraceVerify) { best.Print(); } res[bestIdx] = s0; res.Add(s1); } return(res); }
///////////////////////////////////////////////////////////////////////////////////// private void setControlStatement(BasicBlock current, GotoCmd gotoCmd, BasicBlock next) { if (gotoCmd.labelNames.Count == 0) { current.setControlStatement(new Programs.Statements.Block(current)); } else if (gotoCmd.labelNames.Count == 1) { BasicBlock target = cfg.lookupOrAddNode(gotoCmd.labelNames[0]); current.setControlStatement(new UnconditionalBranch(current, target)); } else { var conditionVariables = new List <ProgramVariable>(); while ((1 << conditionVariables.Count) < gotoCmd.labelNames.Count) { ProgramVariable nd = scope.makeFreshProgramVariable(pathConditionPrefix, makeBooleanType()); conditionVariables.Add(nd); nondeterministicConditionVariables.Add(nd); } string basicLabel = "$cascade_" + labelIndex.ToString(); labelIndex++; int currentTarget = 0; for (int i = 0; (1 << i) <= gotoCmd.labelNames.Count; i++) { for (int j = 0; (j < (1 << i)) && ((1 << i) + j < gotoCmd.labelNames.Count); j += 2) { int index = (1 << i) + j; string label = basicLabel + "_$" + i.ToString() + "_$" + j.ToString(); BasicBlock block = (i == 0) ? current : cfg.lookupOrAddNode(label); string targetLabel1 = (index * 2 < gotoCmd.labelNames.Count) ? basicLabel + "_$" + (i + 1).ToString() + "_$" + (j * 2).ToString() : gotoCmd.labelNames[currentTarget++]; string targetLabel2 = (index * 2 + 1 < gotoCmd.labelNames.Count) ? basicLabel + "_$" + (i + 1).ToString() + "_$" + (j * 2 + 1).ToString() : ( (currentTarget < gotoCmd.labelNames.Count) ? gotoCmd.labelNames[currentTarget++] : null ); BasicBlock target1 = cfg.lookupOrAddNode(targetLabel1); BasicBlock target2 = (targetLabel2 == null) ? null : cfg.lookupOrAddNode(targetLabel2); if (target2 != null) { block.setControlStatement(new ConditionalBranch(block, conditionVariables[i], target1, target2)); } else { block.setControlStatement(new UnconditionalBranch(block, target1)); } } } } }
Block Visit(GraphNode node) { Contract.Requires(node != null); Contract.Ensures(Contract.Result <Block>() != null); Block orig = node.Block; if (newBlocks.TryGetValue(orig, out var nw)) { Contract.Assert(nw != null); } else { List <Cmd> body; TransferCmd tcmd; Contract.Assert(orig.TransferCmd != null); if (next == null && node.IsCutPoint) { // as the body, use the assert/assume commands that make up the loop invariant body = new List <Cmd>(); foreach (Cmd /*!*/ c in node.Body) { Contract.Assert(c != null); if (c is PredicateCmd || c is CommentCmd) { body.Add(c); } else { break; } } if (soundLoopUnrolling) { body.Add(new AssertCmd(orig.tok, Bpl.Expr.False)); } else { body.Add(new AssumeCmd(orig.tok, Bpl.Expr.False)); } tcmd = new ReturnCmd(orig.TransferCmd.tok); } else { body = node.Body; List <Block> newSuccs = new List <Block>(); foreach (GraphNode succ in node.ForwardEdges) { Block s; if (containingSCC[node] == containingSCC[succ]) { s = Visit(succ); } else { Contract.Assert(head != null); // follows from object invariant s = head.Visit(succ); } newSuccs.Add(s); } Contract.Assert(next != null || node.BackEdges.Count == 0); // follows from if-else test above and the GraphNode invariant foreach (GraphNode succ in node.BackEdges) { Contract.Assert(next != null); // since if we get here, node.BackEdges.Count != 0 Block s = next.Visit(succ); newSuccs.Add(s); } if (newSuccs.Count == 0) { tcmd = new ReturnCmd(orig.TransferCmd.tok); } else { tcmd = new GotoCmd(orig.TransferCmd.tok, newSuccs); } } nw = new Block(orig.tok, orig.Label + "#" + this.c, body, tcmd); newBlocks.Add(orig, nw); newBlockSeqGlobal.Add(nw); } return(nw); }
private int InlineCallCmd(Block block, CallCmd callCmd, Implementation impl, List<Cmd> newCmds, List<Block> newBlocks, int lblCount) { Contract.Assume(impl != null); Contract.Assert(cce.NonNull(impl.OriginalBlocks).Count > 0); // do inline now int nextlblCount = lblCount + 1; string nextBlockLabel = block.Label + "$" + nextlblCount; // run the callback before each inline if (inlineCallback != null) { inlineCallback(impl); } // increment the counter for the procedure to be used in constructing the locals and formals NextInlinedProcLabel(impl.Proc.Name); BeginInline(impl); List<Block /*!*/> /*!*/ inlinedBlocks = CreateInlinedBlocks(callCmd, impl, nextBlockLabel); Contract.Assert(cce.NonNullElements(inlinedBlocks)); EndInline(); if (inlineDepth >= 0) { Debug.Assert(inlineDepth > 0); inlineDepth = inlineDepth - 1; } else { recursiveProcUnrollMap[impl.Name] = recursiveProcUnrollMap[impl.Name] - 1; } bool inlinedSomething = true; inlinedBlocks = DoInlineBlocks(inlinedBlocks, ref inlinedSomething); if (inlineDepth >= 0) { inlineDepth = inlineDepth + 1; } else { recursiveProcUnrollMap[impl.Name] = recursiveProcUnrollMap[impl.Name] + 1; } Block /*!*/ startBlock = inlinedBlocks[0]; Contract.Assert(startBlock != null); GotoCmd gotoCmd = new GotoCmd(Token.NoToken, new List<String> {startBlock.Label}); Block newBlock = new Block(block.tok, ((lblCount == 0) ? (block.Label) : (block.Label + "$" + lblCount)), newCmds, gotoCmd); newBlocks.Add(newBlock); newBlocks.AddRange(inlinedBlocks); return nextlblCount; }
public override GotoCmd VisitGotoCmd(GotoCmd node) { node.labelTargets = null; return(node); }
private static void ProcessCounterexampleForDiffInliningWOSymbolicOut(List <Variable> eqLocVars, Implementation vtLeftProcImpl, Implementation vtRightProcImpl, string v1Name, string v2Name, List <Block> listBlocksV1, List <Block> listBlocksV2, GotoCmd labelEntry) { if (vtLeftProcImpl != null && vtRightProcImpl != null) //only when diff inlining is on { var blocksLeftProcImpl = vtLeftProcImpl.Blocks.ToArray(); var blocksRightProcImpl = vtRightProcImpl.Blocks.ToArray(); var firstCmdThirdBlockLeft = new AssumeCmd(Token.NoToken, Expr.Not(Expr.True)); var firstCmdThirdBlockRight = new AssumeCmd(Token.NoToken, Expr.Not(Expr.True)); var leftThirdBlockCmdElems = blocksLeftProcImpl[2].Cmds; var rightThirdBlockCmdElems = blocksRightProcImpl[2].Cmds; leftThirdBlockCmdElems[0] = firstCmdThirdBlockLeft; rightThirdBlockCmdElems[0] = firstCmdThirdBlockRight; blocksLeftProcImpl[2].Cmds = leftThirdBlockCmdElems; blocksRightProcImpl[2].Cmds = rightThirdBlockCmdElems; // re-building the first block (only the goto cmds) blocksLeftProcImpl[0].TransferCmd = labelEntry; blocksRightProcImpl[0].TransferCmd = labelEntry; // removing the second block vtLeftProcImpl.Blocks.RemoveAt(1); vtRightProcImpl.Blocks.RemoveAt(1); foreach (Block currentBlockV1 in listBlocksV1) { vtLeftProcImpl.Blocks.Add(currentBlockV1); } foreach (Block currentBlockV2 in listBlocksV2) { vtRightProcImpl.Blocks.Add(currentBlockV2); } //vtLeftProcImpl.Blocks.Add(blockV1); //vtRightProcImpl.Blocks.Add(blockV2); //hemr - handling local variable declarations List <Variable> locVarsV1_diff_inline = new List <Variable>(); List <Variable> locVarsV2_diff_inline = new List <Variable>(); foreach (Variable currentVariable in eqLocVars) { if (currentVariable.ToString().Contains("inline$" + v1Name)) { locVarsV1_diff_inline.Add(currentVariable); } else if (currentVariable.ToString().Contains("inline$" + v2Name)) { locVarsV2_diff_inline.Add(currentVariable); } } vtLeftProcImpl.LocVars = locVarsV1_diff_inline; vtRightProcImpl.LocVars = locVarsV2_diff_inline; } }
private void AddEdge(GotoCmd gotoCmd, Block b) { gotoCmd.labelNames.Add(b.Label); gotoCmd.labelTargets.Add(b); }
public static GraphNode ComputeGraphInfo(GraphNode from, Block b, Dictionary <Block /*!*/, GraphNode /*!*/> /*!*/ gd, HashSet <Block> beingVisited) { Contract.Requires(beingVisited != null); Contract.Requires(b != null); Contract.Requires(cce.NonNullDictionaryAndValues(gd)); Contract.Ensures(Contract.Result <GraphNode>() != null); GraphNode g; if (gd.TryGetValue(b, out g)) { Contract.Assume(from != null); Contract.Assert(g != null); if (beingVisited.Contains(b)) { // it's a cut point g.isCutPoint = true; from.BackEdges.Add(g); g.Predecessors.Add(from); } else { from.ForwardEdges.Add(g); g.Predecessors.Add(from); } } else { List <Cmd> body = GetOptimizedBody(b.Cmds); g = new GraphNode(b, body); gd.Add(b, g); if (from != null) { from.ForwardEdges.Add(g); g.Predecessors.Add(from); } if (body != b.Cmds) { // the body was optimized -- there is no way through this block } else { beingVisited.Add(b); GotoCmd gcmd = b.TransferCmd as GotoCmd; if (gcmd != null) { Contract.Assume(gcmd.labelTargets != null); foreach (Block /*!*/ succ in gcmd.labelTargets) { Contract.Assert(succ != null); ComputeGraphInfo(g, succ, gd, beingVisited); } } beingVisited.Remove(b); } } return(g); }
public override Implementation VisitImplementation(Implementation node) { if (civlTypeChecker.procToAtomicAction.ContainsKey(node.Proc) || civlTypeChecker.procToIntroductionAction.ContainsKey(node.Proc) || civlTypeChecker.procToLemmaProc.ContainsKey(node.Proc)) return node; node.PruneUnreachableBlocks(); node.ComputePredecessorsForBlocks(); GraphUtil.Graph<Block> graph = Program.GraphFromImpl(node); graph.ComputeLoops(); HashSet<Variable> start = new HashSet<Variable>(globalVarToDomainName.Keys); for (int i = 0; i < node.InParams.Count; i++) { Variable v = node.Proc.InParams[i]; string domainName = FindDomainName(v); if (domainName != null) { var kind = FindLinearKind(v); inParamToLinearQualifier[node.InParams[i]] = new LinearQualifier(domainName, kind); if (kind == LinearKind.LINEAR || kind == LinearKind.LINEAR_IN) { start.Add(node.InParams[i]); } } } for (int i = 0; i < node.OutParams.Count; i++) { string domainName = FindDomainName(node.Proc.OutParams[i]); if (domainName != null) { outParamToDomainName[node.OutParams[i]] = domainName; } } var oldErrorCount = checkingContext.ErrorCount; var impl = base.VisitImplementation(node); if (oldErrorCount < checkingContext.ErrorCount) return impl; Stack<Block> dfsStack = new Stack<Block>(); HashSet<Block> dfsStackAsSet = new HashSet<Block>(); availableLinearVars[node.Blocks[0]] = start; dfsStack.Push(node.Blocks[0]); dfsStackAsSet.Add(node.Blocks[0]); while (dfsStack.Count > 0) { Block b = dfsStack.Pop(); dfsStackAsSet.Remove(b); HashSet<Variable> end = PropagateAvailableLinearVarsAcrossBlock(b); if (b.TransferCmd is ReturnCmd) { foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(end)) { Error(b.TransferCmd, $"Global variable {g.Name} must be available at a return"); } foreach (Variable v in node.InParams) { if (FindDomainName(v) == null || FindLinearKind(v) == LinearKind.LINEAR_IN || end.Contains(v)) continue; Error(b.TransferCmd, $"Input variable {v.Name} must be available at a return"); } foreach (Variable v in node.OutParams) { if (FindDomainName(v) == null || end.Contains(v)) continue; Error(b.TransferCmd, $"Output variable {v.Name} must be available at a return"); } continue; } GotoCmd gotoCmd = b.TransferCmd as GotoCmd; foreach (Block target in gotoCmd.labelTargets) { if (!availableLinearVars.ContainsKey(target)) { availableLinearVars[target] = new HashSet<Variable>(end); dfsStack.Push(target); dfsStackAsSet.Add(target); } else { var savedAvailableVars = new HashSet<Variable>(availableLinearVars[target]); availableLinearVars[target].IntersectWith(end); if (savedAvailableVars.IsProperSupersetOf(availableLinearVars[target]) && !dfsStackAsSet.Contains(target)) { dfsStack.Push(target); dfsStackAsSet.Add(target); } } } } if (graph.Reducible) { foreach (Block header in graph.Headers) { foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(availableLinearVars[header])) { Error(header, $"Global variable {g.Name} must be available at a loop head"); } } } return impl; }
public TerminatedAtGotoWithUnsatisfiableTargets(GotoCmd gotoCmd) { this.ExitLocation = gotoCmd.GetProgramLocation(); }
// result[0] is the entry block protected List<Block /*!*/> /*!*/ CreateInlinedBlocks(CallCmd callCmd, Implementation impl, string nextBlockLabel) { Contract.Requires(nextBlockLabel != null); Contract.Requires(impl != null); Contract.Requires(impl.Proc != null); Contract.Requires(callCmd != null); Contract.Requires(codeCopier.substMap != null); Contract.Requires(codeCopier.oldSubstMap != null); Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>())); List<Block /*!*/> /*!*/ implBlocks = cce.NonNull(impl.OriginalBlocks); Contract.Assert(implBlocks.Count > 0); Procedure proc = impl.Proc; string startLabel = implBlocks[0].Label; List<Block /*!*/> /*!*/ inlinedBlocks = new List<Block /*!*/>(); // create in block List<Cmd> inCmds = new List<Cmd>(); // assign in parameters for (int i = 0; i < impl.InParams.Count; ++i) { Cmd cmd = Cmd.SimpleAssign(impl.tok, (IdentifierExpr) codeCopier.Subst(cce.NonNull(impl.InParams[i])), cce.NonNull(callCmd.Ins[i])); inCmds.Add(cmd); } // inject requires for (int i = 0; i < proc.Requires.Count; i++) { Requires /*!*/ req = cce.NonNull(proc.Requires[i]); inCmds.Add(InlinedRequires(callCmd, req)); } List<Variable> locVars = cce.NonNull(impl.OriginalLocVars); // havoc locals and out parameters in case procedure is invoked in a loop List<IdentifierExpr> havocVars = new List<IdentifierExpr>(); foreach (Variable v in locVars) { havocVars.Add((IdentifierExpr) codeCopier.Subst(v)); } foreach (Variable v in impl.OutParams) { havocVars.Add((IdentifierExpr) codeCopier.Subst(v)); } if (havocVars.Count > 0) { inCmds.Add(new HavocCmd(Token.NoToken, havocVars)); } // add where clauses of local vars as assume for (int i = 0; i < locVars.Count; ++i) { Expr whereExpr = (cce.NonNull(locVars[i])).TypedIdent.WhereExpr; if (whereExpr != null) { whereExpr = codeCopier.CopyExpr(whereExpr); // FIXME we cannot overwrite it, can we?! (cce.NonNull(locVars[i])).TypedIdent.WhereExpr = whereExpr; AssumeCmd /*!*/ a = new AssumeCmd(Token.NoToken, whereExpr); Contract.Assert(a != null); inCmds.Add(a); } } // add where clauses of output params as assume for (int i = 0; i < impl.OutParams.Count; ++i) { Expr whereExpr = (cce.NonNull(impl.OutParams[i])).TypedIdent.WhereExpr; if (whereExpr != null) { whereExpr = codeCopier.CopyExpr(whereExpr); // FIXME likewise (cce.NonNull(impl.OutParams[i])).TypedIdent.WhereExpr = whereExpr; AssumeCmd /*!*/ a = new AssumeCmd(Token.NoToken, whereExpr); Contract.Assert(a != null); inCmds.Add(a); } } // assign modifies old values foreach (IdentifierExpr /*!*/ mie in proc.Modifies) { Contract.Assert(mie != null); Variable /*!*/ mvar = cce.NonNull(mie.Decl); AssignCmd assign = Cmd.SimpleAssign(impl.tok, (IdentifierExpr) cce.NonNull(codeCopier.OldSubst(mvar)), mie); inCmds.Add(assign); } GotoCmd inGotoCmd = new GotoCmd(callCmd.tok, new List<String> {GetInlinedProcLabel(proc.Name) + "$" + startLabel}); Block inBlock = new Block(impl.tok, GetInlinedProcLabel(proc.Name) + "$Entry", inCmds, inGotoCmd); inlinedBlocks.Add(inBlock); // inject the blocks of the implementation Block intBlock; foreach (Block block in implBlocks) { List<Cmd> copyCmds = codeCopier.CopyCmdSeq(block.Cmds); if (0 <= inlineDepth) { copyCmds = RemoveAsserts(copyCmds); } TransferCmd transferCmd = CreateInlinedTransferCmd(cce.NonNull(block.TransferCmd), GetInlinedProcLabel(proc.Name)); intBlock = new Block(block.tok, GetInlinedProcLabel(proc.Name) + "$" + block.Label, copyCmds, transferCmd); inlinedBlocks.Add(intBlock); } // create out block List<Cmd> outCmds = new List<Cmd>(); // inject ensures for (int i = 0; i < proc.Ensures.Count; i++) { Ensures /*!*/ ens = cce.NonNull(proc.Ensures[i]); outCmds.Add(InlinedEnsures(callCmd, ens)); } // assign out params for (int i = 0; i < impl.OutParams.Count; ++i) { Expr /*!*/ cout_exp = (IdentifierExpr) cce.NonNull(codeCopier.Subst(cce.NonNull(impl.OutParams[i]))); Cmd cmd = Cmd.SimpleAssign(impl.tok, cce.NonNull(callCmd.Outs[i]), cout_exp); outCmds.Add(cmd); } // create out block GotoCmd outGotoCmd = new GotoCmd(Token.NoToken, new List<String> {nextBlockLabel}); Block outBlock = new Block(impl.tok, GetInlinedProcLabel(proc.Name) + "$Return", outCmds, outGotoCmd); inlinedBlocks.Add(outBlock); return inlinedBlocks; }
/// <summary> /// Instrument the loop. /// </summary> /// <param name="node">The merge node.</param> private void InstrumentLoop(ProgramNode node) { // skips asserts to preserve the invariants at the loop head int i = 1; while (node.Block.Cmds.Count > i && node.Block.Cmds[i] is AssertCmd) { AssertCmd assert = node.Block.Cmds[i] as AssertCmd; if (!ContainsAttribute(assert, "originated_from_invariant")) { break; } i = i + 1; } // the block should have source location information for instrumentation to work if (node.Block.Cmds[0] is AssertCmd) { AssertCmd assert = node.Block.Cmds[0] as AssertCmd; if (ContainsAttribute(assert, SourceLocationKey)) { node.Block.Cmds.Insert(i, assert); node.Block.Cmds.RemoveAt(0); // insert a barrier at the beginning of the merge block AddBarrier(node.Implementation, node.Block, i); // get the header nodes in the loop List <Block> predecessors = new List <Block>(); foreach (Block block in program.Implementations.SelectMany(x => x.Blocks)) { if (block.TransferCmd is GotoCmd) { GotoCmd gotoCmd = block.TransferCmd as GotoCmd; if (gotoCmd.labelTargets.Contains(node.Block)) { predecessors.Add(block); } } } foreach (Block predecessor in predecessors) { if (analyzer.Graph.BackEdges.Any(x => x.Destination == node && x.Source.Block == predecessor)) { continue; } // identify the location of the initialize statement of the loop int index = predecessor.Cmds.Count - 1; while (index >= 0) { if (predecessor.Cmds[index] is AssertCmd) { break; } index = index - 1; } if (index != -1) { // create an assert from the block source location since initializers don't have source locations int location = QKeyValue.FindIntAttribute(assert.Attributes, SourceLocationKey, -1); if (location != -1) { assert = predecessor.Cmds[index] as AssertCmd; // becomes true when there is only one command in the block // in those cases, we don't need to need to add a new assert attribute if (!ContainsAttribute(assert, BlockSourceKey)) { // create a new assert to store the location information LiteralExpr locationValue = new LiteralExpr(Token.NoToken, BigNum.FromInt(location)); QKeyValue sourceLocationKey = new QKeyValue(Token.NoToken, SourceLocationKey, new List <object>() { locationValue }, null); LiteralExpr literal = new LiteralExpr(Token.NoToken, true); assert = new AssertCmd(Token.NoToken, literal); assert.Attributes = sourceLocationKey; index = index + 2; predecessor.Cmds.Insert(index, assert); } Implementation implementation = program.Implementations.First(x => x.Blocks.Contains(predecessor)); // insert a barrier at the end of the header block AddBarrier(implementation, predecessor, index + 1); } } } } } }