public GotoInstructionStatistics(Microsoft.Boogie.GotoCmd gotoCmd) { TargetsVisited = new Dictionary <Block, int>(); foreach (var target in gotoCmd.labelTargets) { TargetsVisited[target] = 0; } }
public void GenerateDispatchContinuation(ITryCatchFinallyStatement tryCatchFinallyStatement) { string continuationLabel = this.sink.FindOrCreateContinuationLabel(tryCatchFinallyStatement); Bpl.IfCmd elseIfCmd = new Bpl.IfCmd(Bpl.Token.NoToken, Bpl.Expr.Literal(true), TranslationHelper.BuildStmtList(new Bpl.GotoCmd(Bpl.Token.NoToken, new List <string>(new string[] { continuationLabel }))), null, null); List <string> edges = sink.EscapingEdges(tryCatchFinallyStatement); Bpl.IdentifierExpr labelExpr = Bpl.Expr.Ident(this.sink.LabelVariable); for (int i = 0; i < edges.Count; i++) { string label = edges[i]; Bpl.GotoCmd gotoCmd = new Bpl.GotoCmd(Bpl.Token.NoToken, new List <string>(new string[] { label })); Bpl.Expr targetExpr = Bpl.Expr.Literal(i); elseIfCmd = new Bpl.IfCmd(Bpl.Token.NoToken, Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, labelExpr, targetExpr), TranslationHelper.BuildStmtList(gotoCmd), elseIfCmd, null); } this.StmtBuilder.Add(elseIfCmd); }
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; }
public override GotoCmd VisitGotoCmd(GotoCmd node) { Contract.Ensures(Contract.Result<GotoCmd>() == node); // do not visit the labelTargets, or control-flow loops will lead to a looping visitor return node; }
public virtual GotoCmd VisitGotoCmd(GotoCmd node) { Contract.Requires(node != null); Contract.Ensures(Contract.Result<GotoCmd>() != null); // do not visit the labelTargets, or control-flow loops will lead to a looping visitor return node; }
private List<Block> DeepCopyBlocks(List<Block> lb, List<Block> uncheckables) { List<Block> clones = new List<Block>(); List<Block> uncheck_ = new List<Block>(); Dictionary<Block, Block> clonemap = new Dictionary<Block, Block>(); foreach (Block b in lb) { Block clone = CloneBlock(b); clones.Add(clone); clonemap[b] = clone; if (uncheckables.Contains(b)) uncheck_.Add(clone); } uncheckables.Clear(); uncheckables.AddRange(uncheck_); // update the successors and predecessors foreach (Block b in lb) { List<Block> newpreds = new List<Block>(); foreach (Block b_ in b.Predecessors) { newpreds.Add(clonemap[b_]); } clonemap[b].Predecessors = newpreds; GotoCmd gc = b.TransferCmd as GotoCmd; ReturnCmd rc = b.TransferCmd as ReturnCmd; if (gc != null) { List<String> lseq = new List<String>(); List<Block> bseq = new List<Block>(); foreach (string s in gc.labelNames) lseq.Add(s); foreach (Block b_ in gc.labelTargets) bseq.Add(clonemap[b_]); GotoCmd tcmd = new GotoCmd(gc.tok, lseq, bseq); clonemap[b].TransferCmd = tcmd; } else if (rc != null) { clonemap[b].TransferCmd = new ReturnCmd(rc.tok); } } return clones; }
void TransferCmd(out TransferCmd/*!*/ tc) { Contract.Ensures(Contract.ValueAtReturn(out tc) != null); tc = dummyTransferCmd; Token y; List<IToken>/*!*/ xs; List<String> ss = new List<String>(); if (la.kind == 39) { Get(); y = t; Idents(out xs); foreach(IToken/*!*/ s in xs){ Contract.Assert(s != null); ss.Add(s.val); } tc = new GotoCmd(y, ss); } else if (la.kind == 40) { Get(); tc = new ReturnCmd(t); } else SynErr(108); Expect(9); }
public void GenerateDispatchContinuation(ITryCatchFinallyStatement tryCatchFinallyStatement) { string continuationLabel = this.sink.FindOrCreateContinuationLabel(tryCatchFinallyStatement); Bpl.IfCmd elseIfCmd = new Bpl.IfCmd(Bpl.Token.NoToken, Bpl.Expr.Literal(true), TranslationHelper.BuildStmtList(new Bpl.GotoCmd(Bpl.Token.NoToken, new List<string>(new string[] {continuationLabel}))), null, null); List<string> edges = sink.EscapingEdges(tryCatchFinallyStatement); Bpl.IdentifierExpr labelExpr = Bpl.Expr.Ident(this.sink.LabelVariable); for (int i = 0; i < edges.Count; i++) { string label = edges[i]; Bpl.GotoCmd gotoCmd = new Bpl.GotoCmd(Bpl.Token.NoToken, new List<string>(new string[] { label })); Bpl.Expr targetExpr = Bpl.Expr.Literal(i); elseIfCmd = new Bpl.IfCmd(Bpl.Token.NoToken, Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, labelExpr, targetExpr), TranslationHelper.BuildStmtList(gotoCmd), elseIfCmd, null); } this.StmtBuilder.Add(elseIfCmd); }
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); }
// 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.Subst != null); Contract.Requires(codeCopier.OldSubst != 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)cce.NonNull(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 = Substituter.Apply(codeCopier.Subst, 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 = Substituter.Apply(codeCopier.Subst, 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; }
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; }
// If the enclosing context is a loop, then "runOffTheEndLabel" is the loop head label; // otherwise, it is null. void CreateBlocks(StmtList stmtList, string runOffTheEndLabel) { Contract.Requires(stmtList != null); Contract.Requires(blocks != null); List<Cmd> cmdPrefixToApply = stmtList.PrefixCommands; int n = stmtList.BigBlocks.Count; foreach (BigBlock b in stmtList.BigBlocks) { n--; Contract.Assert(b.LabelName != null); List<Cmd> theSimpleCmds; if (cmdPrefixToApply == null) { theSimpleCmds = b.simpleCmds; } else { theSimpleCmds = new List<Cmd>(); theSimpleCmds.AddRange(cmdPrefixToApply); theSimpleCmds.AddRange(b.simpleCmds); cmdPrefixToApply = null; // now, we've used 'em up } if (b.tc != null) { // this BigBlock has the very same components as a Block Contract.Assert(b.ec == null); Block block = new Block(b.tok, b.LabelName, theSimpleCmds, b.tc); blocks.Add(block); } else if (b.ec == null) { TransferCmd trCmd; if (n == 0 && runOffTheEndLabel != null) { // goto the given label instead of the textual successor block trCmd = new GotoCmd(stmtList.EndCurly, new List<String> { runOffTheEndLabel }); } else { trCmd = GotoSuccessor(stmtList.EndCurly, b); } Block block = new Block(b.tok, b.LabelName, theSimpleCmds, trCmd); blocks.Add(block); } else if (b.ec is BreakCmd) { BreakCmd bcmd = (BreakCmd)b.ec; Contract.Assert(bcmd.BreakEnclosure != null); Block block = new Block(b.tok, b.LabelName, theSimpleCmds, GotoSuccessor(b.ec.tok, bcmd.BreakEnclosure)); blocks.Add(block); } else if (b.ec is WhileCmd) { WhileCmd wcmd = (WhileCmd)b.ec; string loopHeadLabel = prefix + anon + "_LoopHead"; string/*!*/ loopBodyLabel = prefix + anon + "_LoopBody"; string loopDoneLabel = prefix + anon + "_LoopDone"; anon++; List<Cmd> ssBody = new List<Cmd>(); List<Cmd> ssDone = new List<Cmd>(); if (wcmd.Guard != null) { var ac = new AssumeCmd(wcmd.tok, wcmd.Guard); ac.Attributes = new QKeyValue(wcmd.tok, "partition", new List<object>(), null); ssBody.Add(ac); ac = new AssumeCmd(wcmd.tok, Expr.Not(wcmd.Guard)); ac.Attributes = new QKeyValue(wcmd.tok, "partition", new List<object>(), null); ssDone.Add(ac); } // Try to squeeze in ssBody into the first block of wcmd.Body bool bodyGuardTakenCareOf = wcmd.Body.PrefixFirstBlock(ssBody, ref loopBodyLabel); // ... goto LoopHead; Block block = new Block(b.tok, b.LabelName, theSimpleCmds, new GotoCmd(wcmd.tok, new List<String> { loopHeadLabel })); blocks.Add(block); // LoopHead: assert/assume loop_invariant; goto LoopDone, LoopBody; List<Cmd> ssHead = new List<Cmd>(); foreach (PredicateCmd inv in wcmd.Invariants) { ssHead.Add(inv); } block = new Block(wcmd.tok, loopHeadLabel, ssHead, new GotoCmd(wcmd.tok, new List<String> { loopDoneLabel, loopBodyLabel })); blocks.Add(block); if (!bodyGuardTakenCareOf) { // LoopBody: assume guard; goto firstLoopBlock; block = new Block(wcmd.tok, loopBodyLabel, ssBody, new GotoCmd(wcmd.tok, new List<String> { wcmd.Body.BigBlocks[0].LabelName })); blocks.Add(block); } // recurse to create the blocks for the loop body CreateBlocks(wcmd.Body, loopHeadLabel); // LoopDone: assume !guard; goto loopSuccessor; TransferCmd trCmd; if (n == 0 && runOffTheEndLabel != null) { // goto the given label instead of the textual successor block trCmd = new GotoCmd(wcmd.tok, new List<String> { runOffTheEndLabel }); } else { trCmd = GotoSuccessor(wcmd.tok, b); } block = new Block(wcmd.tok, loopDoneLabel, ssDone, trCmd); blocks.Add(block); } else { IfCmd ifcmd = (IfCmd)b.ec; string predLabel = b.LabelName; List<Cmd> predCmds = theSimpleCmds; for (; ifcmd != null; ifcmd = ifcmd.elseIf) { string thenLabel = prefix + anon + "_Then"; Contract.Assert(thenLabel != null); string elseLabel = prefix + anon + "_Else"; Contract.Assert(elseLabel != null); anon++; List<Cmd> ssThen = new List<Cmd>(); List<Cmd> ssElse = new List<Cmd>(); if (ifcmd.Guard != null) { var ac = new AssumeCmd(ifcmd.tok, ifcmd.Guard); ac.Attributes = new QKeyValue(ifcmd.tok, "partition", new List<object>(), null); ssThen.Add(ac); ac = new AssumeCmd(ifcmd.tok, Expr.Not(ifcmd.Guard)); ac.Attributes = new QKeyValue(ifcmd.tok, "partition", new List<object>(), null); ssElse.Add(ac); } // Try to squeeze in ssThen/ssElse into the first block of ifcmd.thn/ifcmd.elseBlock bool thenGuardTakenCareOf = ifcmd.thn.PrefixFirstBlock(ssThen, ref thenLabel); bool elseGuardTakenCareOf = false; if (ifcmd.elseBlock != null) { elseGuardTakenCareOf = ifcmd.elseBlock.PrefixFirstBlock(ssElse, ref elseLabel); } // ... goto Then, Else; Block block = new Block(b.tok, predLabel, predCmds, new GotoCmd(ifcmd.tok, new List<String> { thenLabel, elseLabel })); blocks.Add(block); if (!thenGuardTakenCareOf) { // Then: assume guard; goto firstThenBlock; block = new Block(ifcmd.tok, thenLabel, ssThen, new GotoCmd(ifcmd.tok, new List<String> { ifcmd.thn.BigBlocks[0].LabelName })); blocks.Add(block); } // recurse to create the blocks for the then branch CreateBlocks(ifcmd.thn, n == 0 ? runOffTheEndLabel : null); if (ifcmd.elseBlock != null) { Contract.Assert(ifcmd.elseIf == null); if (!elseGuardTakenCareOf) { // Else: assume !guard; goto firstElseBlock; block = new Block(ifcmd.tok, elseLabel, ssElse, new GotoCmd(ifcmd.tok, new List<String> { ifcmd.elseBlock.BigBlocks[0].LabelName })); blocks.Add(block); } // recurse to create the blocks for the else branch CreateBlocks(ifcmd.elseBlock, n == 0 ? runOffTheEndLabel : null); } else if (ifcmd.elseIf != null) { // this is an "else if" predLabel = elseLabel; predCmds = new List<Cmd>(); if (ifcmd.Guard != null) { var ac = new AssumeCmd(ifcmd.tok, Expr.Not(ifcmd.Guard)); ac.Attributes = new QKeyValue(ifcmd.tok, "partition", new List<object>(), null); predCmds.Add(ac); } } else { // no else alternative is specified, so else branch is just "skip" // Else: assume !guard; goto ifSuccessor; TransferCmd trCmd; if (n == 0 && runOffTheEndLabel != null) { // goto the given label instead of the textual successor block trCmd = new GotoCmd(ifcmd.tok, new List<String> { runOffTheEndLabel }); } else { trCmd = GotoSuccessor(ifcmd.tok, b); } block = new Block(ifcmd.tok, elseLabel, ssElse, trCmd); blocks.Add(block); } } } } }
public Graph<Block> ProcessLoops(Implementation impl) { while (true) { impl.PruneUnreachableBlocks(); impl.ComputePredecessorsForBlocks(); Graph<Block/*!*/>/*!*/ g = GraphFromImpl(impl); g.ComputeLoops(); if (g.Reducible) { return g; } throw new IrreducibleLoopException(); #if USED_CODE System.Diagnostics.Debug.Assert(g.SplitCandidates.Count > 0); Block splitCandidate = null; foreach (Block b in g.SplitCandidates) { if (b.Predecessors.Length > 1) { splitCandidate = b; break; } } System.Diagnostics.Debug.Assert(splitCandidate != null); int count = 0; foreach (Block b in splitCandidate.Predecessors) { GotoCmd gotoCmd = (GotoCmd)b.TransferCmd; gotoCmd.labelNames.Remove(splitCandidate.Label); gotoCmd.labelTargets.Remove(splitCandidate); CodeCopier codeCopier = new CodeCopier(new Hashtable(), new Hashtable()); List<Cmd> newCmdSeq = codeCopier.CopyCmdSeq(splitCandidate.Cmds); TransferCmd newTransferCmd; GotoCmd splitGotoCmd = splitCandidate.TransferCmd as GotoCmd; if (splitGotoCmd == null) { newTransferCmd = new ReturnCmd(splitCandidate.tok); } else { List<String> newLabelNames = new List<String>(); newLabelNames.AddRange(splitGotoCmd.labelNames); List<Block> newLabelTargets = new List<Block>(); newLabelTargets.AddRange(splitGotoCmd.labelTargets); newTransferCmd = new GotoCmd(splitCandidate.tok, newLabelNames, newLabelTargets); } Block copy = new Block(splitCandidate.tok, splitCandidate.Label + count++, newCmdSeq, newTransferCmd); impl.Blocks.Add(copy); gotoCmd.AddTarget(copy); } #endif } }
void CreateProceduresForLoops(Implementation impl, Graph<Block/*!*/>/*!*/ g, List<Implementation/*!*/>/*!*/ loopImpls, Dictionary<string, Dictionary<string, Block>> fullMap) { Contract.Requires(impl != null); Contract.Requires(cce.NonNullElements(loopImpls)); // Enumerate the headers // for each header h: // create implementation p_h with // inputs = inputs, outputs, and locals of impl // outputs = outputs and locals of impl // locals = empty set // add call o := p_h(i) at the beginning of the header block // break the back edges whose target is h // Enumerate the headers again to create the bodies of p_h // for each header h: // compute the loop corresponding to h // make copies of all blocks in the loop for h // delete all target edges that do not go to a block in the loop // create a new entry block and a new return block // add edges from entry block to the loop header and the return block // add calls o := p_h(i) at the end of the blocks that are sources of back edges foreach (Block block in impl.Blocks) { AddToFullMap(fullMap, impl.Name, block.Label, block); } bool detLoopExtract = CommandLineOptions.Clo.DeterministicExtractLoops; Dictionary<Block/*!*/, List<Variable>/*!*/>/*!*/ loopHeaderToInputs = new Dictionary<Block/*!*/, List<Variable>/*!*/>(); Dictionary<Block/*!*/, List<Variable>/*!*/>/*!*/ loopHeaderToOutputs = new Dictionary<Block/*!*/, List<Variable>/*!*/>(); Dictionary<Block/*!*/, Dictionary<Variable, Expr>/*!*/>/*!*/ loopHeaderToSubstMap = new Dictionary<Block/*!*/, Dictionary<Variable, Expr>/*!*/>(); Dictionary<Block/*!*/, LoopProcedure/*!*/>/*!*/ loopHeaderToLoopProc = new Dictionary<Block/*!*/, LoopProcedure/*!*/>(); Dictionary<Block/*!*/, CallCmd/*!*/>/*!*/ loopHeaderToCallCmd1 = new Dictionary<Block/*!*/, CallCmd/*!*/>(); Dictionary<Block, CallCmd> loopHeaderToCallCmd2 = new Dictionary<Block, CallCmd>(); Dictionary<Block, AssignCmd> loopHeaderToAssignCmd = new Dictionary<Block, AssignCmd>(); foreach (Block/*!*/ header in g.Headers) { Contract.Assert(header != null); Contract.Assert(header != null); List<Variable> inputs = new List<Variable>(); List<Variable> outputs = new List<Variable>(); List<Expr> callInputs1 = new List<Expr>(); List<IdentifierExpr> callOutputs1 = new List<IdentifierExpr>(); List<Expr> callInputs2 = new List<Expr>(); List<IdentifierExpr> callOutputs2 = new List<IdentifierExpr>(); List<AssignLhs> lhss = new List<AssignLhs>(); List<Expr> rhss = new List<Expr>(); Dictionary<Variable, Expr> substMap = new Dictionary<Variable, Expr>(); // Variable -> IdentifierExpr List<Variable>/*!*/ targets = new List<Variable>(); HashSet<Variable> footprint = new HashSet<Variable>(); foreach (Block/*!*/ b in g.BackEdgeNodes(header)) { Contract.Assert(b != null); foreach (Block/*!*/ block in g.NaturalLoops(header, b)) { Contract.Assert(block != null); foreach (Cmd/*!*/ cmd in block.Cmds) { Contract.Assert(cmd != null); cmd.AddAssignedVariables(targets); VariableCollector c = new VariableCollector(); c.Visit(cmd); footprint.UnionWith(c.usedVars); } } } List<IdentifierExpr>/*!*/ globalMods = new List<IdentifierExpr>(); Set targetSet = new Set(); foreach (Variable/*!*/ v in targets) { Contract.Assert(v != null); if (targetSet.Contains(v)) continue; targetSet.Add(v); if (v is GlobalVariable) globalMods.Add(new IdentifierExpr(Token.NoToken, v)); } foreach (Variable v in impl.InParams) { Contract.Assert(v != null); if (!footprint.Contains(v)) continue; callInputs1.Add(new IdentifierExpr(Token.NoToken, v)); Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "in_" + v.Name, v.TypedIdent.Type), true); inputs.Add(f); callInputs2.Add(new IdentifierExpr(Token.NoToken, f)); substMap[v] = new IdentifierExpr(Token.NoToken, f); } foreach (Variable v in impl.OutParams) { Contract.Assert(v != null); if (!footprint.Contains(v)) continue; callInputs1.Add(new IdentifierExpr(Token.NoToken, v)); Formal f1 = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "in_" + v.Name, v.TypedIdent.Type), true); inputs.Add(f1); if (targetSet.Contains(v)) { callOutputs1.Add(new IdentifierExpr(Token.NoToken, v)); Formal f2 = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "out_" + v.Name, v.TypedIdent.Type), false); outputs.Add(f2); callInputs2.Add(new IdentifierExpr(Token.NoToken, f2)); callOutputs2.Add(new IdentifierExpr(Token.NoToken, f2)); lhss.Add(new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, f2))); rhss.Add(new IdentifierExpr(Token.NoToken, f1)); substMap[v] = new IdentifierExpr(Token.NoToken, f2); } else { callInputs2.Add(new IdentifierExpr(Token.NoToken, f1)); substMap[v] = new IdentifierExpr(Token.NoToken, f1); } } foreach (Variable v in impl.LocVars) { Contract.Assert(v != null); if (!footprint.Contains(v)) continue; callInputs1.Add(new IdentifierExpr(Token.NoToken, v)); Formal f1 = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "in_" + v.Name, v.TypedIdent.Type), true); inputs.Add(f1); if (targetSet.Contains(v)) { callOutputs1.Add(new IdentifierExpr(Token.NoToken, v)); Formal f2 = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "out_" + v.Name, v.TypedIdent.Type), false); outputs.Add(f2); callInputs2.Add(new IdentifierExpr(Token.NoToken, f2)); callOutputs2.Add(new IdentifierExpr(Token.NoToken, f2)); lhss.Add(new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, f2))); rhss.Add(new IdentifierExpr(Token.NoToken, f1)); substMap[v] = new IdentifierExpr(Token.NoToken, f2); } else { callInputs2.Add(new IdentifierExpr(Token.NoToken, f1)); substMap[v] = new IdentifierExpr(Token.NoToken, f1); } } loopHeaderToInputs[header] = inputs; loopHeaderToOutputs[header] = outputs; loopHeaderToSubstMap[header] = substMap; LoopProcedure loopProc = new LoopProcedure(impl, header, inputs, outputs, globalMods); loopHeaderToLoopProc[header] = loopProc; CallCmd callCmd1 = new CallCmd(Token.NoToken, loopProc.Name, callInputs1, callOutputs1); callCmd1.Proc = loopProc; loopHeaderToCallCmd1[header] = callCmd1; CallCmd callCmd2 = new CallCmd(Token.NoToken, loopProc.Name, callInputs2, callOutputs2); callCmd2.Proc = loopProc; loopHeaderToCallCmd2[header] = callCmd2; Debug.Assert(lhss.Count == rhss.Count); if (lhss.Count > 0) { AssignCmd assignCmd = new AssignCmd(Token.NoToken, lhss, rhss); loopHeaderToAssignCmd[header] = assignCmd; } } // Keep track of the new blocks created: maps a header node to the // header_last block that was created because of splitting header. Dictionary<Block, Block> newBlocksCreated = new Dictionary<Block, Block>(); bool headRecursion = false; // testing an option to put recursive call before loop body IEnumerable<Block> sortedHeaders = g.SortHeadersByDominance(); foreach (Block/*!*/ header in sortedHeaders) { Contract.Assert(header != null); LoopProcedure loopProc = loopHeaderToLoopProc[header]; Dictionary<Block, Block> blockMap = new Dictionary<Block, Block>(); HashSet<string> dummyBlocks = new HashSet<string>(); CodeCopier codeCopier = new CodeCopier(loopHeaderToSubstMap[header]); // fix me List<Variable> inputs = loopHeaderToInputs[header]; List<Variable> outputs = loopHeaderToOutputs[header]; int si_unique_loc = 1; // Added by AL: to distinguish the back edges foreach (Block/*!*/ source in g.BackEdgeNodes(header)) { Contract.Assert(source != null); foreach (Block/*!*/ block in g.NaturalLoops(header, source)) { Contract.Assert(block != null); if (blockMap.ContainsKey(block)) continue; Block newBlock = new Block(); newBlock.Label = block.Label; if (headRecursion && block == header) { CallCmd callCmd = (CallCmd)(loopHeaderToCallCmd2[header]).Clone(); addUniqueCallAttr(si_unique_loc, callCmd); si_unique_loc++; newBlock.Cmds.Add(callCmd); // add the recursive call at head of loop var rest = codeCopier.CopyCmdSeq(block.Cmds); newBlock.Cmds.AddRange(rest); } else newBlock.Cmds = codeCopier.CopyCmdSeq(block.Cmds); blockMap[block] = newBlock; if (newBlocksCreated.ContainsKey(block)) { Block newBlock2 = new Block(); newBlock2.Label = newBlocksCreated[block].Label; newBlock2.Cmds = codeCopier.CopyCmdSeq(newBlocksCreated[block].Cmds); blockMap[newBlocksCreated[block]] = newBlock2; } //for detLoopExtract, need the immediate successors even outside the loop if (detLoopExtract) { GotoCmd auxGotoCmd = block.TransferCmd as GotoCmd; Contract.Assert(auxGotoCmd != null && auxGotoCmd.labelNames != null && auxGotoCmd.labelTargets != null && auxGotoCmd.labelTargets.Count >= 1); foreach(var bl in auxGotoCmd.labelTargets) { bool found = false; foreach(var n in g.NaturalLoops(header, source)) { //very expensive, can we do a contains? if (bl == n) { //clarify: is this the right comparison? found = true; break; } } if (!found) { Block auxNewBlock = new Block(); auxNewBlock.Label = ((Block)bl).Label; auxNewBlock.Cmds = codeCopier.CopyCmdSeq(((Block)bl).Cmds); //add restoration code for such blocks if (loopHeaderToAssignCmd.ContainsKey(header)) { AssignCmd assignCmd = loopHeaderToAssignCmd[header]; auxNewBlock.Cmds.Add(assignCmd); } List<AssignLhs> lhsg = new List<AssignLhs>(); List<IdentifierExpr>/*!*/ globalsMods = loopHeaderToLoopProc[header].Modifies; foreach (IdentifierExpr gl in globalsMods) lhsg.Add(new SimpleAssignLhs(Token.NoToken, gl)); List<Expr> rhsg = new List<Expr>(); foreach (IdentifierExpr gl in globalsMods) rhsg.Add(new OldExpr(Token.NoToken, gl)); if (lhsg.Count != 0) { AssignCmd globalAssignCmd = new AssignCmd(Token.NoToken, lhsg, rhsg); auxNewBlock.Cmds.Add(globalAssignCmd); } blockMap[(Block)bl] = auxNewBlock; } } } } List<Cmd> cmdSeq; if (headRecursion) cmdSeq = new List<Cmd>(); else { CallCmd callCmd = (CallCmd)(loopHeaderToCallCmd2[header]).Clone(); addUniqueCallAttr(si_unique_loc, callCmd); si_unique_loc++; cmdSeq = new List<Cmd> { callCmd }; } Block/*!*/ block1 = new Block(Token.NoToken, source.Label + "_dummy", new List<Cmd>{ new AssumeCmd(Token.NoToken, Expr.False) }, new ReturnCmd(Token.NoToken)); Block/*!*/ block2 = new Block(Token.NoToken, block1.Label, cmdSeq, new ReturnCmd(Token.NoToken)); impl.Blocks.Add(block1); dummyBlocks.Add(block1.Label); GotoCmd gotoCmd = source.TransferCmd as GotoCmd; Contract.Assert(gotoCmd != null && gotoCmd.labelNames != null && gotoCmd.labelTargets != null && gotoCmd.labelTargets.Count >= 1); List<String>/*!*/ newLabels = new List<String>(); List<Block>/*!*/ newTargets = new List<Block>(); for (int i = 0; i < gotoCmd.labelTargets.Count; i++) { if (gotoCmd.labelTargets[i] == header) continue; newTargets.Add(gotoCmd.labelTargets[i]); newLabels.Add(gotoCmd.labelNames[i]); } newTargets.Add(block1); newLabels.Add(block1.Label); gotoCmd.labelNames = newLabels; gotoCmd.labelTargets = newTargets; blockMap[block1] = block2; } List<Block/*!*/>/*!*/ blocks = new List<Block/*!*/>(); Block exit = new Block(Token.NoToken, "exit", new List<Cmd>(), new ReturnCmd(Token.NoToken)); GotoCmd cmd = new GotoCmd(Token.NoToken, new List<String> { cce.NonNull(blockMap[header]).Label, exit.Label }, new List<Block> { blockMap[header], exit }); if (detLoopExtract) //cutting the non-determinism cmd = new GotoCmd(Token.NoToken, new List<String> { cce.NonNull(blockMap[header]).Label }, new List<Block> { blockMap[header] }); Block entry; List<Cmd> initCmds = new List<Cmd>(); if (loopHeaderToAssignCmd.ContainsKey(header)) { AssignCmd assignCmd = loopHeaderToAssignCmd[header]; initCmds.Add(assignCmd); } entry = new Block(Token.NoToken, "entry", initCmds, cmd); blocks.Add(entry); foreach (Block/*!*/ block in blockMap.Keys) { Contract.Assert(block != null); Block/*!*/ newBlock = cce.NonNull(blockMap[block]); GotoCmd gotoCmd = block.TransferCmd as GotoCmd; if (gotoCmd == null) { newBlock.TransferCmd = new ReturnCmd(Token.NoToken); } else { Contract.Assume(gotoCmd.labelNames != null && gotoCmd.labelTargets != null); List<String> newLabels = new List<String>(); List<Block> newTargets = new List<Block>(); for (int i = 0; i < gotoCmd.labelTargets.Count; i++) { Block target = gotoCmd.labelTargets[i]; if (blockMap.ContainsKey(target)) { newLabels.Add(gotoCmd.labelNames[i]); newTargets.Add(blockMap[target]); } } if (newTargets.Count == 0) { if (!detLoopExtract) newBlock.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.False)); newBlock.TransferCmd = new ReturnCmd(Token.NoToken); } else { newBlock.TransferCmd = new GotoCmd(Token.NoToken, newLabels, newTargets); } } blocks.Add(newBlock); } blocks.Add(exit); Implementation loopImpl = new Implementation(Token.NoToken, loopProc.Name, new List<TypeVariable>(), inputs, outputs, new List<Variable>(), blocks); loopImpl.Proc = loopProc; loopImpls.Add(loopImpl); // Make a (shallow) copy of the header before splitting it Block origHeader = new Block(header.tok, header.Label, header.Cmds, header.TransferCmd); // Finally, add call to the loop in the containing procedure string lastIterBlockName = header.Label + "_last"; Block lastIterBlock = new Block(Token.NoToken, lastIterBlockName, header.Cmds, header.TransferCmd); newBlocksCreated[header] = lastIterBlock; header.Cmds = new List<Cmd> { loopHeaderToCallCmd1[header] }; header.TransferCmd = new GotoCmd(Token.NoToken, new List<String> { lastIterBlockName }, new List<Block> { lastIterBlock }); impl.Blocks.Add(lastIterBlock); blockMap[origHeader] = blockMap[header]; blockMap.Remove(header); Contract.Assert(fullMap[impl.Name][header.Label] == header); fullMap[impl.Name][header.Label] = origHeader; foreach (Block block in blockMap.Keys) { // Don't add dummy blocks to the map if (dummyBlocks.Contains(blockMap[block].Label)) continue; // Following two statements are for nested loops: compose map if (!fullMap[impl.Name].ContainsKey(block.Label)) continue; var target = fullMap[impl.Name][block.Label]; AddToFullMap(fullMap, loopProc.Name, blockMap[block].Label, target); } fullMap[impl.Name].Remove(header.Label); fullMap[impl.Name][lastIterBlockName] = origHeader; } }
protected TransferCmd CreateInlinedTransferCmd(TransferCmd transferCmd, string procLabel) { Contract.Requires(procLabel != null); Contract.Requires(transferCmd != null); TransferCmd newTransferCmd; GotoCmd gotoCmd = transferCmd as GotoCmd; if (gotoCmd != null) { List<String> gotoSeq = gotoCmd.labelNames; List<String> newGotoSeq = new List<String>(); foreach (string/*!*/ blockLabel in cce.NonNull(gotoSeq)) { Contract.Assert(blockLabel != null); newGotoSeq.Add(procLabel + "$" + blockLabel); } newTransferCmd = new GotoCmd(transferCmd.tok, newGotoSeq); } else { newTransferCmd = new GotoCmd(transferCmd.tok, new List<String> { procLabel + "$Return" }); } return newTransferCmd; }
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); }
public TransferCmd CopyTransferCmd(TransferCmd cmd) { Contract.Requires(cmd != null); Contract.Ensures(Contract.Result<TransferCmd>() != null); TransferCmd transferCmd; GotoCmd gotocmd = cmd as GotoCmd; if (gotocmd != null) { Contract.Assert(gotocmd.labelNames != null); List<String> labels = new List<String>(); labels.AddRange(gotocmd.labelNames); transferCmd = new GotoCmd(cmd.tok, labels); } else { ReturnExprCmd returnExprCmd = cmd as ReturnExprCmd; if (returnExprCmd != null) { transferCmd = new ReturnExprCmd(cmd.tok, CopyExpr(returnExprCmd.Expr)); } else { transferCmd = new ReturnCmd(cmd.tok); } } return transferCmd; }
public override GotoCmd VisitGotoCmd(GotoCmd node) { //Contract.Requires(node != null); Contract.Ensures(Contract.Result<GotoCmd>() != null); // NOTE: This doesn't duplicate the labelTarget basic blocks // or resolve them to the new blocks // VisitImplementation() and VisitBlock() handle this return base.VisitGotoCmd( (GotoCmd)node.Clone()); }
public override GotoCmd VisitGotoCmd(GotoCmd node) { //Contract.Requires(node != null); Contract.Ensures(Contract.Result<GotoCmd>() != null); return base.VisitGotoCmd((GotoCmd)node.Clone()); }