public static VCExpr Block(Block b, VCExpr N, VCContext ctxt) //modifies ctxt.*; { Contract.Requires(b != null); Contract.Requires(N != null); Contract.Requires(ctxt != null); Contract.Ensures(Contract.Result<VCExpr>() != null); VCExpressionGenerator gen = ctxt.Ctxt.ExprGen; Contract.Assert(gen != null); VCExpr res = N; for (int i = b.Cmds.Count; --i >= 0; ) { res = Cmd(b, cce.NonNull( b.Cmds[i]), res, ctxt); } int id = b.UniqueId; if (ctxt.Label2absy != null) { ctxt.Label2absy[id] = b; } try { cce.BeginExpose(ctxt); if (ctxt.Label2absy == null) { return res; } else { return gen.Implies(gen.LabelPos(cce.NonNull(id.ToString()), VCExpressionGenerator.True), res); } } finally { cce.EndExpose(); } }
public static List<Block/*!*/>/*!*/ UnrollLoops(Block start, int unrollMaxDepth, bool soundLoopUnrolling) { Contract.Requires(start != null); Contract.Requires(0 <= unrollMaxDepth); Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>())); Dictionary<Block, GraphNode/*!*/> gd = new Dictionary<Block, GraphNode/*!*/>(); HashSet<Block> beingVisited = new HashSet<Block>(); GraphNode gStart = GraphNode.ComputeGraphInfo(null, start, gd, beingVisited); // Compute SCCs StronglyConnectedComponents<GraphNode/*!*/> sccs = new StronglyConnectedComponents<GraphNode/*!*/>(gd.Values, Preds, Succs); Contract.Assert(sccs != null); sccs.Compute(); Dictionary<GraphNode/*!*/, SCC<GraphNode/*!*/>> containingSCC = new Dictionary<GraphNode/*!*/, SCC<GraphNode/*!*/>>(); foreach (SCC<GraphNode/*!*/> scc in sccs) { foreach (GraphNode/*!*/ n in scc) { Contract.Assert(n != null); containingSCC[n] = scc; } } LoopUnroll lu = new LoopUnroll(unrollMaxDepth, soundLoopUnrolling, containingSCC, new List<Block/*!*/>()); lu.Visit(gStart); lu.newBlockSeqGlobal.Reverse(); return lu.newBlockSeqGlobal; }
void PredicateCmd(Expr p, Expr pDom, List<Block> blocks, Block block, Cmd cmd, out Block nextBlock) { var cCmd = cmd as CallCmd; if (cCmd != null && !useProcedurePredicates(cCmd.Proc)) { if (p == null) { block.Cmds.Add(cmd); nextBlock = block; return; } var trueBlock = new Block(); blocks.Add(trueBlock); trueBlock.Label = block.Label + ".call.true"; trueBlock.Cmds.Add(new AssumeCmd(Token.NoToken, p)); trueBlock.Cmds.Add(cmd); var falseBlock = new Block(); blocks.Add(falseBlock); falseBlock.Label = block.Label + ".call.false"; falseBlock.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.Not(p))); var contBlock = new Block(); blocks.Add(contBlock); contBlock.Label = block.Label + ".call.cont"; block.TransferCmd = new GotoCmd(Token.NoToken, new List<Block> { trueBlock, falseBlock }); trueBlock.TransferCmd = falseBlock.TransferCmd = new GotoCmd(Token.NoToken, new List<Block> { contBlock }); nextBlock = contBlock; } else { PredicateCmd(p, pDom, block.Cmds, cmd); nextBlock = block; } }
///////////////////////////////////////////////////////////////////////////////////// private BasicBlock addBlock(Block b) { // Console.WriteLine("\t\t\t\tAdding block: {0}",b.Label); var current = cfg.addNode(b.Label); // System.Console.Out.WriteLine("Adding block: \"" + basicBlock.LabelName + "\""); addStatementsToBasicBlock(current, b.Cmds); setControlStatement(current, b.TransferCmd, null); Debug.Assert(current.getControlStatement() != null); return(current); }
///////////////////////////////////////////////////////////////////////////////////// IList <Block> topoSort(IEnumerable <Block> blocks, Block initial) { var result = new List <Block>(); var blockPredsMissing = new Dictionary <string, int>(); foreach (var b in blocks) { blockPredsMissing[b.Label] = 0; } foreach (var b in blocks) { if (b.TransferCmd is GotoCmd) { foreach (var sb in (b.TransferCmd as GotoCmd).labelTargets) { blockPredsMissing[sb.Label]++; } } } var todo = new Queue <Block>(); var done = new HashSet <string>(); todo.Enqueue(initial); while (todo.Count > 0) { var b = todo.Dequeue(); Debug.Assert(!done.Contains(b.Label)); result.Add(b); var gotoCmd = b.TransferCmd as GotoCmd; if (gotoCmd != null) { foreach (var sb in gotoCmd.labelTargets) { Debug.Assert(!done.Contains(sb.Label)); Debug.Assert(!todo.Contains(sb)); blockPredsMissing[sb.Label]--; Debug.Assert(blockPredsMissing[sb.Label] >= 0); if (blockPredsMissing[sb.Label] == 0) { blockPredsMissing.Remove(sb.Label); todo.Enqueue(sb); } } } done.Add(b.Label); } return(result); }
static void Visit(Block b) { Contract.Requires(b != null); Contract.Assume(cce.IsExposable(b)); if (b.TraversingStatus == Block.VisitState.BeingVisited) { cce.BeginExpose(b); // we got here through a back-edge b.widenBlock = true; cce.EndExpose(); } else if (b.TraversingStatus == Block.VisitState.AlreadyVisited) { // do nothing... we already saw this node } else if (b.TransferCmd is GotoCmd) { Contract.Assert(b.TraversingStatus == Block.VisitState.ToVisit); GotoCmd g = (GotoCmd)b.TransferCmd; cce.BeginExpose(b); cce.BeginExpose(g); //PM: required for the subsequent expose (g.labelTargets) b.TraversingStatus = Block.VisitState.BeingVisited; // labelTargets is made non-null by Resolve, which we assume // has already called in a prior pass. Contract.Assume(g.labelTargets != null); cce.BeginExpose(g.labelTargets); foreach (Block succ in g.labelTargets) // invariant b.currentlyTraversed; //PM: The following loop invariant will work once properties are axiomatized //&& (g.labelNames != null && g.labelTargets != null ==> g.labelNames.Length == g.labelTargets.Length); { Contract.Assert(succ != null); Visit(succ); } cce.EndExpose(); Contract.Assert(b.TraversingStatus == Block.VisitState.BeingVisited); // System.Diagnostics.Debug.Assert(b.currentlyTraversed); b.TraversingStatus = Block.VisitState.AlreadyVisited; //PM: The folowing assumption is needed because we cannot prove that a simple field update //PM: leaves the value of a property unchanged. Contract.Assume(g.labelNames == null || g.labelNames.Count == g.labelTargets.Count); cce.EndExpose(); } else { Contract.Assert(b.TransferCmd == null || b.TransferCmd is ReturnCmd); // It must be a returnCmd; } }
/// <summary> /// Compute the blocks in the body loop. /// <param name ="block"> Tt is the head of the loop. It must be a widen block </param> /// <return> The blocks that are in the loop from block </return> /// </summary> public static List<Block> ComputeLoopBodyFrom(Block block) { Contract.Requires(block.widenBlock); Contract.Requires(block != null); Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>())); Contract.Assert(rootBlock == null); rootBlock = block; List<Block/*!*/> blocksInLoop = new List<Block/*!*/>(); // We use a list just because .net does not define a set List<Block/*!*/> visitingPath = new List<Block/*!*/>(); // The order is important, as we want paths blocksInLoop.Add(block); DoDFSVisit(block, visitingPath, blocksInLoop); visitingPath.Add(block); rootBlock = null; // We reset the invariant return blocksInLoop; }
// There is no default constructor, because these parameters are needed for most subclasses public DoomDetectionStrategy(Implementation imp, Block unifiedexit, List<Block> unreach) { m_BlockH = new BlockHierachy(imp, unifiedexit); __DEBUG_EQCLeaf = m_BlockH.Leaves.Count; //foreach (BlockHierachyNode bhn in m_BlockH.Leaves) //{ // if (bhn.Content.Count > 0) __DEBUG_minelements.Add(bhn.Content[0]); //} //if (imp.Blocks.Count>0) m_GatherInfo(imp.Blocks[0], 0, 0,0); if (__DEBUGOUT) { Console.WriteLine("MaBranchingDepth {0} MaxMinPP {1} ", m_MaxBranchingDepth, m_MaxK); Console.WriteLine("AvgLeaverPerPath {0} AvgPLen {1}", 0, 0); } MaxBlocks = imp.Blocks.Count; MinBlocks = imp.Blocks.Count; HACK_NewCheck = false; __DEBUG_BlocksTotal = imp.Blocks.Count; }
private void CreateYieldCheckerImpl(Implementation impl, List<List<Cmd>> yields) { if (yields.Count == 0) return; Dictionary<Variable, Expr> map = new Dictionary<Variable, Expr>(); foreach (Variable local in impl.LocVars) { var copy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, local.Name, local.TypedIdent.Type)); map[local] = Expr.Ident(copy); } Program program = linearTypeChecker.program; List<Variable> locals = new List<Variable>(); List<Variable> inputs = new List<Variable>(); foreach (IdentifierExpr ie in map.Values) { locals.Add(ie.Decl); } for (int i = 0; i < impl.InParams.Count - linearTypeChecker.linearDomains.Count; i++) { Variable inParam = impl.InParams[i]; Variable copy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, inParam.Name, inParam.TypedIdent.Type)); locals.Add(copy); map[impl.InParams[i]] = Expr.Ident(copy); } { int i = impl.InParams.Count - linearTypeChecker.linearDomains.Count; foreach (string domainName in linearTypeChecker.linearDomains.Keys) { Variable inParam = impl.InParams[i]; Variable copy = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, inParam.Name, inParam.TypedIdent.Type), true); inputs.Add(copy); map[impl.InParams[i]] = Expr.Ident(copy); i++; } } for (int i = 0; i < impl.OutParams.Count; i++) { Variable outParam = impl.OutParams[i]; var copy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, outParam.Name, outParam.TypedIdent.Type)); locals.Add(copy); map[impl.OutParams[i]] = Expr.Ident(copy); } Dictionary<Variable, Expr> ogOldLocalMap = new Dictionary<Variable, Expr>(); Dictionary<Variable, Expr> assumeMap = new Dictionary<Variable, Expr>(map); foreach (IdentifierExpr ie in globalMods) { Variable g = ie.Decl; var copy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_local_old_{0}", g.Name), g.TypedIdent.Type)); locals.Add(copy); ogOldLocalMap[g] = Expr.Ident(copy); Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_global_old_{0}", g.Name), g.TypedIdent.Type), true); inputs.Add(f); assumeMap[g] = Expr.Ident(f); } Substitution assumeSubst = Substituter.SubstitutionFromHashtable(assumeMap); Substitution oldSubst = Substituter.SubstitutionFromHashtable(ogOldLocalMap); Substitution subst = Substituter.SubstitutionFromHashtable(map); List<Block> yieldCheckerBlocks = new List<Block>(); List<String> labels = new List<String>(); List<Block> labelTargets = new List<Block>(); Block yieldCheckerBlock = new Block(Token.NoToken, "exit", new List<Cmd>(), new ReturnCmd(Token.NoToken)); labels.Add(yieldCheckerBlock.Label); labelTargets.Add(yieldCheckerBlock); yieldCheckerBlocks.Add(yieldCheckerBlock); int yieldCount = 0; foreach (List<Cmd> cs in yields) { List<Cmd> newCmds = new List<Cmd>(); foreach (Cmd cmd in cs) { PredicateCmd predCmd = (PredicateCmd)cmd; newCmds.Add(new AssumeCmd(Token.NoToken, Substituter.ApplyReplacingOldExprs(assumeSubst, oldSubst, predCmd.Expr))); } foreach (Cmd cmd in cs) { PredicateCmd predCmd = (PredicateCmd)cmd; var newExpr = Substituter.ApplyReplacingOldExprs(subst, oldSubst, predCmd.Expr); if (predCmd is AssertCmd) { AssertCmd assertCmd = new AssertCmd(predCmd.tok, newExpr, predCmd.Attributes); assertCmd.ErrorData = "Non-interference check failed"; newCmds.Add(assertCmd); } else { newCmds.Add(new AssumeCmd(Token.NoToken, newExpr)); } } newCmds.Add(new AssumeCmd(Token.NoToken, Expr.False)); yieldCheckerBlock = new Block(Token.NoToken, "L" + yieldCount++, newCmds, new ReturnCmd(Token.NoToken)); labels.Add(yieldCheckerBlock.Label); labelTargets.Add(yieldCheckerBlock); yieldCheckerBlocks.Add(yieldCheckerBlock); } yieldCheckerBlocks.Insert(0, new Block(Token.NoToken, "enter", new List<Cmd>(), new GotoCmd(Token.NoToken, labels, labelTargets))); // Create the yield checker procedure var yieldCheckerName = string.Format("{0}_YieldChecker_{1}", "Impl", impl.Name); var yieldCheckerProc = new Procedure(Token.NoToken, yieldCheckerName, impl.TypeParameters, inputs, new List<Variable>(), new List<Requires>(), new List<IdentifierExpr>(), new List<Ensures>()); yieldCheckerProc.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1))); yieldCheckerProcs.Add(yieldCheckerProc); // Create the yield checker implementation var yieldCheckerImpl = new Implementation(Token.NoToken, yieldCheckerName, impl.TypeParameters, inputs, new List<Variable>(), locals, yieldCheckerBlocks); yieldCheckerImpl.Proc = yieldCheckerProc; yieldCheckerImpl.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1))); yieldCheckerImpls.Add(yieldCheckerImpl); }
private void AddInitialBlock(Implementation impl, List<Variable> oldPcs, List<Variable> oldOks, Dictionary<string, Variable> domainNameToInputVar, Dictionary<string, Variable> domainNameToLocalVar, Dictionary<Variable, Variable> ogOldGlobalMap) { // Add initial block List<AssignLhs> lhss = new List<AssignLhs>(); List<Expr> rhss = new List<Expr>(); if (pc != null) { lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(pc))); rhss.Add(Expr.False); foreach (Variable oldPc in oldPcs) { lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(oldPc))); rhss.Add(Expr.False); } lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(ok))); rhss.Add(Expr.False); foreach (Variable oldOk in oldOks) { lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(oldOk))); rhss.Add(Expr.False); } } Dictionary<string, Expr> domainNameToExpr = new Dictionary<string, Expr>(); foreach (var domainName in linearTypeChecker.linearDomains.Keys) { domainNameToExpr[domainName] = Expr.Ident(domainNameToInputVar[domainName]); } for (int i = 0; i < impl.InParams.Count - linearTypeChecker.linearDomains.Count; i++) { Variable v = impl.InParams[i]; var domainName = linearTypeChecker.FindDomainName(v); if (domainName == null) continue; if (!linearTypeChecker.linearDomains.ContainsKey(domainName)) continue; var domain = linearTypeChecker.linearDomains[domainName]; if (!domain.collectors.ContainsKey(v.TypedIdent.Type)) continue; Expr ie = new NAryExpr(Token.NoToken, new FunctionCall(domain.collectors[v.TypedIdent.Type]), new List<Expr> { Expr.Ident(v) }); domainNameToExpr[domainName] = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapOrBool), new List<Expr> { ie, domainNameToExpr[domainName] }); } foreach (string domainName in linearTypeChecker.linearDomains.Keys) { lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(domainNameToLocalVar[domainName]))); rhss.Add(domainNameToExpr[domainName]); } foreach (Variable g in ogOldGlobalMap.Keys) { lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(ogOldGlobalMap[g]))); rhss.Add(Expr.Ident(g)); } if (lhss.Count > 0) { Block initBlock = new Block(Token.NoToken, "og_init", new List<Cmd> { new AssignCmd(Token.NoToken, lhss, rhss) }, new GotoCmd(Token.NoToken, new List<String> { impl.Blocks[0].Label }, new List<Block> { impl.Blocks[0] })); impl.Blocks.Insert(0, initBlock); } }
private void AddYieldProcAndImpl(List<Declaration> decls) { if (yieldProc == null) return; Program program = linearTypeChecker.program; List<Variable> inputs = new List<Variable>(); foreach (string domainName in linearTypeChecker.linearDomains.Keys) { var domain = linearTypeChecker.linearDomains[domainName]; Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "linear_" + domainName + "_in", new MapType(Token.NoToken, new List<TypeVariable>(), new List<Type> { domain.elementType }, Type.Bool)), true); inputs.Add(f); } foreach (IdentifierExpr ie in globalMods) { Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_global_old_{0}", ie.Decl.Name), ie.Decl.TypedIdent.Type), true); inputs.Add(f); } List<Block> blocks = new List<Block>(); TransferCmd transferCmd = new ReturnCmd(Token.NoToken); if (yieldCheckerProcs.Count > 0) { List<Block> blockTargets = new List<Block>(); List<String> labelTargets = new List<String>(); int labelCount = 0; foreach (Procedure proc in yieldCheckerProcs) { List<Expr> exprSeq = new List<Expr>(); foreach (Variable v in inputs) { exprSeq.Add(Expr.Ident(v)); } CallCmd callCmd = new CallCmd(Token.NoToken, proc.Name, exprSeq, new List<IdentifierExpr>()); callCmd.Proc = proc; string label = string.Format("L_{0}", labelCount++); Block block = new Block(Token.NoToken, label, new List<Cmd> { callCmd }, new ReturnCmd(Token.NoToken)); labelTargets.Add(label); blockTargets.Add(block); blocks.Add(block); } transferCmd = new GotoCmd(Token.NoToken, labelTargets, blockTargets); } blocks.Insert(0, new Block(Token.NoToken, "enter", new List<Cmd>(), transferCmd)); var yieldImpl = new Implementation(Token.NoToken, yieldProc.Name, new List<TypeVariable>(), inputs, new List<Variable>(), new List<Variable>(), blocks); yieldImpl.Proc = yieldProc; yieldImpl.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1))); decls.Add(yieldProc); decls.Add(yieldImpl); }
GraphNode(Block b, List<Cmd> body) { Contract.Requires(body != null); Contract.Requires(b != null); this.Block = b; this.Body = body; }
public override Procedure VisitProcedure(Procedure node) { if (!civlTypeChecker.procToActionInfo.ContainsKey(node)) return node; if (!procMap.ContainsKey(node)) { enclosingProc = node; Procedure proc = (Procedure)node.Clone(); proc.Name = string.Format("{0}_{1}", node.Name, layerNum); proc.InParams = this.VisitVariableSeq(node.InParams); proc.Modifies = this.VisitIdentifierExprSeq(node.Modifies); proc.OutParams = this.VisitVariableSeq(node.OutParams); ActionInfo actionInfo = civlTypeChecker.procToActionInfo[node]; if (actionInfo.createdAtLayerNum < layerNum) { proc.Requires = new List<Requires>(); proc.Ensures = new List<Ensures>(); Implementation impl; AtomicActionInfo atomicActionInfo = actionInfo as AtomicActionInfo; if (atomicActionInfo != null) { CodeExpr action = (CodeExpr)VisitCodeExpr(atomicActionInfo.action); List<Cmd> cmds = new List<Cmd>(); foreach (AssertCmd assertCmd in atomicActionInfo.gate) { cmds.Add(new AssumeCmd(Token.NoToken, (Expr)Visit(assertCmd.Expr))); } Block newInitBlock = new Block(Token.NoToken, "_init", cmds, new GotoCmd(Token.NoToken, new List<string>(new string[] { action.Blocks[0].Label }), new List<Block>(new Block[] { action.Blocks[0] }))); List<Block> newBlocks = new List<Block>(); newBlocks.Add(newInitBlock); newBlocks.AddRange(action.Blocks); impl = new Implementation(Token.NoToken, proc.Name, node.TypeParameters, node.InParams, node.OutParams, action.LocVars, newBlocks); } else { Block newInitBlock = new Block(Token.NoToken, "_init", new List<Cmd>(), new ReturnCmd(Token.NoToken)); List<Block> newBlocks = new List<Block>(); newBlocks.Add(newInitBlock); impl = new Implementation(Token.NoToken, proc.Name, node.TypeParameters, node.InParams, node.OutParams, new List<Variable>(), newBlocks); } impl.Proc = proc; impl.Proc.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1))); impl.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1))); impls.Add(impl); } else { yieldingProcs.Add(proc); proc.Requires = this.VisitRequiresSeq(node.Requires); proc.Ensures = this.VisitEnsuresSeq(node.Ensures); } procMap[node] = proc; proc.Modifies = new List<IdentifierExpr>(); civlTypeChecker.SharedVariables.Iter(x => proc.Modifies.Add(Expr.Ident(x))); } return procMap[node]; }
private HashSet<Variable> PropagateAvailableLinearVarsAcrossBlock(Block b) { HashSet<Variable> start = new HashSet<Variable>(availableLinearVars[b]); foreach (Cmd cmd in b.Cmds) { if (cmd is AssignCmd) { AssignCmd assignCmd = (AssignCmd)cmd; for (int i = 0; i < assignCmd.Lhss.Count; i++) { if (FindDomainName(assignCmd.Lhss[i].DeepAssignedVariable) == null) continue; IdentifierExpr ie = assignCmd.Rhss[i] as IdentifierExpr; if (!start.Contains(ie.Decl)) { Error(ie, "unavailable source for a linear read"); } else { start.Remove(ie.Decl); } } foreach (AssignLhs assignLhs in assignCmd.Lhss) { if (FindDomainName(assignLhs.DeepAssignedVariable) == null) continue; start.Add(assignLhs.DeepAssignedVariable); } } else if (cmd is CallCmd) { foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(start)) { Error(cmd, string.Format("Global variable {0} must be available at a call", g.Name)); } CallCmd callCmd = (CallCmd)cmd; for (int i = 0; i < callCmd.Proc.InParams.Count; i++) { Variable param = callCmd.Proc.InParams[i]; if (FindDomainName(param) == null) continue; IdentifierExpr ie = callCmd.Ins[i] as IdentifierExpr; LinearKind paramKind = FindLinearKind(param); if (start.Contains(ie.Decl)) { if (callCmd.IsAsync || paramKind == LinearKind.LINEAR_IN) { start.Remove(ie.Decl); } } else { if (paramKind == LinearKind.LINEAR_OUT) { start.Add(ie.Decl); } else { Error(ie, "unavailable source for a linear read"); } } } availableLinearVars[callCmd] = new HashSet<Variable>(start); AddAvailableVars(callCmd, start); } else if (cmd is ParCallCmd) { foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(start)) { Error(cmd, string.Format("Global variable {0} must be available at a call", g.Name)); } ParCallCmd parCallCmd = (ParCallCmd)cmd; foreach (CallCmd callCmd in parCallCmd.CallCmds) { for (int i = 0; i < callCmd.Proc.InParams.Count; i++) { Variable param = callCmd.Proc.InParams[i]; if (FindDomainName(param) == null) continue; IdentifierExpr ie = callCmd.Ins[i] as IdentifierExpr; LinearKind paramKind = FindLinearKind(param); if (start.Contains(ie.Decl)) { if (paramKind == LinearKind.LINEAR_IN) { start.Remove(ie.Decl); } } else { if (paramKind == LinearKind.LINEAR_OUT) { start.Add(ie.Decl); } else { Error(ie, "unavailable source for a linear read"); } } } } availableLinearVars[parCallCmd] = new HashSet<Variable>(start); AddAvailableVars(parCallCmd, start); } else if (cmd is HavocCmd) { HavocCmd havocCmd = (HavocCmd)cmd; foreach (IdentifierExpr ie in havocCmd.Vars) { if (FindDomainName(ie.Decl) == null) continue; start.Remove(ie.Decl); } } else if (cmd is YieldCmd) { foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(start)) { Error(cmd, string.Format("Global variable {0} must be available at a yield", g.Name)); } availableLinearVars[cmd] = new HashSet<Variable>(start); } } return start; }
public override Block VisitBlock(Block node) { //Contract.Requires(node != null); Contract.Ensures(Contract.Result<Block>() != null); return base.VisitBlock((Block) node.Clone()); }
private List<Block> CreateAssertsWithAssumes(List<List<Tuple<Variable, Expr, Expr>>> eqVarsGroups, List<Cmd> asserts) { int n = eqVarsGroups.Count(); if (n == 0) { var b = new Block { Label = SectionLabelPrefix + "_" + _labelCounter++ }; b.Cmds.AddRange(asserts); return new List<Block>() { b }; } var result = new List<Block>(); EnumerateAssumes(new List<Tuple<int, int>>(), n, asserts, eqVarsGroups, result); return result; }
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; }
private IEnumerable<Block> LoopsExitedForwardEdge(Block dest, IEnumerator<Tuple<Block, bool>> i) { var headsSeen = new HashSet<Block>(); while (i.MoveNext()) { var b = i.Current; if (b.Item1 == dest) yield break; else if (!b.Item2 && blockGraph.Headers.Contains(b.Item1)) headsSeen.Add(b.Item1); else if (b.Item2 && !headsSeen.Contains(b.Item1)) yield return b.Item1; } Debug.Assert(false); }
public PartInfo(Expr p, Block r) { pred = p; realDest = r; }
private IEnumerable<Block> LoopsExitedBackEdge(Block src, IEnumerator<Tuple<Block, bool>> i) { var headsSeen = new HashSet<Block>(); while (i.MoveNext()) { var b = i.Current; if (!b.Item2 && blockGraph.Headers.Contains(b.Item1)) headsSeen.Add(b.Item1); else if (b.Item2) headsSeen.Remove(b.Item1); if (b.Item1 == src) return headsSeen; } Debug.Assert(false); return null; }
IEnumerable<Block> LoopsExited(Block src, Block dest) { var i = sortedBlocks.GetEnumerator(); while (i.MoveNext()) { var b = i.Current; if (b.Item1 == src) { return LoopsExitedForwardEdge(dest, i); } else if (b.Item1 == dest) { return LoopsExitedBackEdge(src, i); } } Debug.Assert(false); return null; }
// hasPredicatedRegion is true iff the block or its targets are predicated // (i.e. we enter, stay within or exit a predicated region). void PredicateTransferCmd(Expr p, Block src, List<Cmd> cmdSeq, TransferCmd cmd, out bool hasPredicatedRegion) { hasPredicatedRegion = predMap.ContainsKey(src); if (cmd is GotoCmd) { var gCmd = (GotoCmd)cmd; hasPredicatedRegion = hasPredicatedRegion || gCmd.labelTargets.Cast<Block>().Any(b => predMap.ContainsKey(b)); if (gCmd.labelTargets.Count == 1) { if (defMap.ContainsKey(gCmd.labelTargets[0])) { PredicateCmd(p, Expr.True, cmdSeq, Cmd.SimpleAssign(Token.NoToken, Expr.Ident(predMap[gCmd.labelTargets[0]]), Expr.True)); } } else { Debug.Assert(gCmd.labelTargets.Count > 1); Debug.Assert(gCmd.labelTargets.Cast<Block>().All(t => uni.IsUniform(impl.Name, t) || partInfo.ContainsKey(t))); foreach (Block target in gCmd.labelTargets) { if (!partInfo.ContainsKey(target)) continue; // In this case we not only predicate with the current predicate p, // but also with the "part predicate"; this ensures that we do not // update a predicate twice when it occurs in both parts. var part = partInfo[target]; if (defMap.ContainsKey(part.realDest)) { PredicateCmd(p == null ? part.pred : Expr.And(p, part.pred), Expr.True, cmdSeq, Cmd.SimpleAssign(Token.NoToken, Expr.Ident(predMap[part.realDest]), part.pred)); } var predsExitingLoop = new Dictionary<Block, List<Expr>>(); foreach (Block exit in LoopsExited(src, target)) { List<Expr> predList; if (!predsExitingLoop.ContainsKey(exit)) predList = predsExitingLoop[exit] = new List<Expr>(); else predList = predsExitingLoop[exit]; predList.Add(part.pred); } foreach (var pred in predsExitingLoop) { PredicateCmd(p == null ? part.pred : Expr.And(p, part.pred), Expr.True, cmdSeq, Cmd.SimpleAssign(Token.NoToken, Expr.Ident(predMap[pred.Key]), Expr.Not(pred.Value.Aggregate(Expr.Or)))); } } } } else if (cmd is ReturnCmd) { // Blocks which end in a return will never share a predicate with a block // which appears after it. Furthermore, such a block cannot be part of a // loop. So it is safe to do nothing here. } else { Console.WriteLine("Unsupported cmd: " + cmd.GetType().ToString()); } }
private bool IsYieldingHeader(Graph<Block> graph, Block header) { foreach (Block backEdgeNode in graph.BackEdgeNodes(header)) { foreach (Block x in graph.NaturalLoops(header, backEdgeNode)) { foreach (Cmd cmd in x.Cmds) { if (cmd is YieldCmd) return true; if (cmd is ParCallCmd) return true; CallCmd callCmd = cmd as CallCmd; if (callCmd == null) continue; if (yieldingProcs.Contains(callCmd.Proc)) return true; } } } return false; }
void PredicateImplementation() { blockGraph = prog.ProcessLoops(impl); sortedBlocks = blockGraph.LoopyTopSort(); AssignPredicates(); partInfo = BuildPartitionInfo(); if (myUseProcedurePredicates) fp = Expr.Ident(impl.InParams[0]); var newBlocks = new List<Block>(); Block prevBlock = null; foreach (var n in sortedBlocks) { if (predMap.ContainsKey(n.Item1)) { var p = predMap[n.Item1]; var pExpr = Expr.Ident(p); if (n.Item2) { var dominator = FindImmediateDominator(n.Item1); if (dominator != null && predMap.ContainsKey(dominator)) { AssumeCmd aCmd = new AssumeCmd(Token.NoToken, Expr.True); aCmd.Attributes = new QKeyValue(Token.NoToken, "dominator_predicate", new List<object>() { predMap[dominator].ToString() }, aCmd.Attributes); aCmd.Attributes = new QKeyValue(Token.NoToken, "predicate", new List<object>() { predMap[n.Item1].ToString() }, aCmd.Attributes); n.Item1.Cmds.Insert(0, aCmd); } var backedgeBlock = new Block(); newBlocks.Add(backedgeBlock); backedgeBlock.Label = n.Item1.Label + ".backedge"; backedgeBlock.Cmds = new List<Cmd> { new AssumeCmd(Token.NoToken, pExpr, new QKeyValue(Token.NoToken, "backedge", new List<object>(), null)) }; backedgeBlock.TransferCmd = new GotoCmd(Token.NoToken, new List<Block> { n.Item1 }); var tailBlock = new Block(); newBlocks.Add(tailBlock); tailBlock.Label = n.Item1.Label + ".tail"; tailBlock.Cmds = new List<Cmd> { new AssumeCmd(Token.NoToken, Expr.Not(pExpr)) }; if (uni != null && !uni.IsUniform(impl.Name, n.Item1)) { uni.AddNonUniform(impl.Name, backedgeBlock); uni.AddNonUniform(impl.Name, tailBlock); } if (prevBlock != null) prevBlock.TransferCmd = new GotoCmd(Token.NoToken, new List<Block> { backedgeBlock, tailBlock }); prevBlock = tailBlock; } else { PredicateBlock(pExpr, n.Item1, newBlocks, ref prevBlock); } } else { if (!n.Item2) { PredicateBlock(null, n.Item1, newBlocks, ref prevBlock); } } } if (prevBlock != null) prevBlock.TransferCmd = new ReturnCmd(Token.NoToken); impl.Blocks = newBlocks; }
private void UnifyCallsToYieldProc(Implementation impl, Dictionary<Variable, Variable> ogOldGlobalMap, Dictionary<string, Variable> domainNameToLocalVar) { CallCmd yieldCallCmd = CallToYieldProc(Token.NoToken, ogOldGlobalMap, domainNameToLocalVar); Block yieldCheckBlock = new Block(Token.NoToken, "CallToYieldProc", new List<Cmd>(new Cmd[] { yieldCallCmd, new AssumeCmd(Token.NoToken, Expr.False) }), new ReturnCmd(Token.NoToken)); List<Block> newBlocks = new List<Block>(); foreach (Block b in impl.Blocks) { TransferCmd transferCmd = b.TransferCmd; List<Cmd> newCmds = new List<Cmd>(); for (int i = b.Cmds.Count-1; i >= 0; i--) { CallCmd callCmd = b.Cmds[i] as CallCmd; if (callCmd == null || callCmd.Proc != yieldProc) { newCmds.Insert(0, b.Cmds[i]); } else { Block newBlock = new Block(Token.NoToken, b.Label + i, newCmds, transferCmd); newCmds = new List<Cmd>(); transferCmd = new GotoCmd(Token.NoToken, new List<string>(new string[] { newBlock.Label, yieldCheckBlock.Label }), new List<Block>(new Block[] { newBlock, yieldCheckBlock })); newBlocks.Add(newBlock); } } b.Cmds = newCmds; b.TransferCmd = transferCmd; } impl.Blocks.AddRange(newBlocks); impl.Blocks.Add(yieldCheckBlock); }
private void PredicateBlock(Expr pExpr, Block block, List<Block> newBlocks, ref Block prevBlock) { var firstBlock = block; var oldCmdSeq = block.Cmds; block.Cmds = new List<Cmd>(); newBlocks.Add(block); if (prevBlock != null && !((prevBlock.TransferCmd is ReturnCmd) && uni != null && uni.IsUniform(impl.Name, block))) { prevBlock.TransferCmd = new GotoCmd(Token.NoToken, new List<Block> { block }); } Block currentBlock = block; Expr pCurrentExpr = pExpr; while (parentMap.ContainsKey(currentBlock)) { Block parent = parentMap[currentBlock]; Expr pParentExpr = null; if (predMap.ContainsKey(parent)) { var parentPred = predMap[parent]; if (parentPred != null) { pParentExpr = Expr.Ident(parentPred); block.Cmds.Add(new AssertCmd(Token.NoToken, pCurrentExpr != null ? (Expr)Expr.Imp(pCurrentExpr, pParentExpr) : pParentExpr)); } } currentBlock = parent; pCurrentExpr = pParentExpr; } Block dominator = FindImmediateDominator(block); Expr pDomExpr = Expr.True; if (dominator != null && predMap.ContainsKey(dominator)) pDomExpr = new IdentifierExpr(Token.NoToken, predMap[dominator]); var transferCmd = block.TransferCmd; foreach (Cmd cmd in oldCmdSeq) PredicateCmd(pExpr, pDomExpr, newBlocks, block, cmd, out block); if (ownedMap.ContainsKey(firstBlock)) { var owned = ownedMap[firstBlock]; foreach (var v in owned) block.Cmds.Add(Cmd.SimpleAssign(Token.NoToken, Expr.Ident(v), Expr.False)); } bool hasPredicatedRegion; PredicateTransferCmd(pExpr, block, block.Cmds, transferCmd, out hasPredicatedRegion); if (hasPredicatedRegion) prevBlock = block; else prevBlock = null; doneBlocks.Add(block); }
private void AddNonUniformCandidateInvariant(List<Cmd> cs, Block header) { var loopNodes = new HashSet<Block>(); foreach (var b in blockGraph.BackEdgeNodes(header)) loopNodes.UnionWith(blockGraph.NaturalLoops(header, b)); var exits = new HashSet<Expr>(); foreach (var ln in loopNodes) { if (ln.TransferCmd is GotoCmd) { var gCmd = (GotoCmd) ln.TransferCmd; foreach (var exit in gCmd.labelTargets.Cast<Block>() .Where(b => !loopNodes.Contains(b))) exits.Add(blockIds[exit]); } if (ln.TransferCmd is ReturnCmd) exits.Add(returnBlockId); } var curIsHeaderOrExit = exits.Aggregate((Expr)Expr.Eq(cur, blockIds[header]), (e, exit) => Expr.Or(e, Expr.Eq(cur, exit))); cs.Add(prog.CreateCandidateInvariant( CreateIfFPThenElse(curIsHeaderOrExit, Expr.Eq(cur, returnBlockId)), "non-uniform loop")); }
public override Block VisitBlock(Block node) { Block block = base.VisitBlock(node); absyMap[block] = node; return block; }
/// <summary> /// Requires there to be a procedure context. /// </summary> /// <param name="block"></param> public void AddBlock(Block block) { Contract.Requires(block != null); Contract.Requires(HasProcedureContext); Contract.Assert(procedureContext != null); // follows from precondition Hashtable/*!*/ /*string->Block!*/ blocks = procedureContext.Blocks; Contract.Assert(blocks != null); if (blocks[block.Label] != null) { Error(block, "more than one declaration of block name: {0}", block.Label); } else { blocks.Add(block.Label, block); } }
Block Visit(GraphNode node) { Contract.Requires(node != null); Contract.Ensures(Contract.Result<Block>() != null); Block orig = node.Block; Block nw; if (newBlocks.TryGetValue(orig, out 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 void EnumerateAssumes(List<Tuple<int, int>> pick, int depth, List<Cmd> asserts, List<List<Tuple<Variable, Expr, Expr>>> eqVarsGroups, List<Block> result) { // if we the number of asserts exceeds twice the maximum amount of asserts, the tracelet is hopeless, so generate empty output and don't try to solve if (_numOverallAsserts >= MaxAsserts) { // TODO: magic Utils.ErrorAndDie($"Sorry, can't handle very long programs (max {MaxAsserts} assertions allowed, {_numOverallAsserts} reached)"); } if (depth == 0) { var usedExprs = new HashSet<string>(); var eqVarsPick = new List<Variable>(); foreach (Tuple<int, int> t in pick) { var tuple = eqVarsGroups[t.Item1][t.Item2]; if (usedExprs.Contains(tuple.Item3.ToString())) return; usedExprs.Add(tuple.Item3.ToString()); eqVarsPick.Add(tuple.Item1); } var b = new Block { Label = SectionLabelPrefix + "_" + _labelCounter++ }; foreach (var eqv in eqVarsPick) b.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.Ident(eqv))); b.Cmds.AddRange(asserts); b.TransferCmd = new ReturnCmd(Token.NoToken); result.Add(b); return; } // always start from the next group for (var i = (pick.Count > 0) ? pick.Last().Item1 + 1 : 0; i < eqVarsGroups.Count; ++i) { // inside the group, try all candidates for (int j = 0; j < eqVarsGroups[i].Count; ++j) { var l = new List<Tuple<int, int>>(pick) { new Tuple<int, int>(i, j) }; EnumerateAssumes(l, depth - 1, asserts, eqVarsGroups, result); } } }
Block FindImmediateDominator(Block block) { Block predecessor = null; foreach(var pred in blockGraph.Predecessors(block)) { if (!blockGraph.DominatorMap.DominatedBy(pred, block)) { if (predecessor == null) predecessor = pred; else predecessor = blockGraph.DominatorMap.LeastCommonAncestor(pred, predecessor); } } return predecessor; }