private static void setupPrint(PersistentCBAProgram program, ErrorTrace trace, string file) { // Set output files pathFile = file == null ? null : new TokenTextWriter(file + "_trace.txt"); if (pathFile != null) { program.writeToFile(file + ".bpl"); } Program prog = program.getProgram(); // Initialization initialize(prog, trace, file == null ? null : file + ".bpl"); if (pathFile != null) { if (traceFormat == TraceFormat.ConcurrencyExplorer) { pathFile.WriteLine("s"); pathFile.WriteLine("#"); } else if (traceFormat == TraceFormat.SDV) { pathFile.WriteLine("0 \"?\" 0 false ^ Call \"OS\" \"main\""); } } }
private PersistentCBAProgram instrument(PersistentCBAProgram pprogram, HashSet <string> candidates) { var program = pprogram.getProgram(); foreach (var decl in program.TopLevelDeclarations) { if (!(decl is Implementation)) { continue; } var impl = decl as Implementation; // Create two blocks at the start of the implementation: // newStart: // goto lab,origStart; // // lab: // assert false; // return; // var lab = getNewLabel(); var targets1 = new List <String>(); targets1.Add(lab); targets1.Add(impl.Blocks[0].Label); var blk1 = new Block(Token.NoToken, getNewLabel(), new List <Cmd>(), new GotoCmd(Token.NoToken, targets1)); var blk2cmds = new List <Cmd>(); blk2cmds.Add(new AssertCmd(Token.NoToken, Expr.Literal(false))); var blk2 = new Block(Token.NoToken, lab, blk2cmds, new ReturnCmd(Token.NoToken)); // Get rid of original asserts // TODO: This works with the CBA reduction?? foreach (var blk in impl.Blocks) { for (int i = 0, n = blk.Cmds.Count; i < n; i++) { if (blk.Cmds[i] is AssertCmd) { var c = (blk.Cmds[i] as AssertCmd).Expr; blk.Cmds[i] = new AssumeCmd(Token.NoToken, c); } } } // Put in the new blocks var newBlocks = new List <Block>(); newBlocks.Add(blk1); newBlocks.AddRange(impl.Blocks); newBlocks.Add(blk2); impl.Blocks = newBlocks; } return(new PersistentCBAProgram(program, pprogram.mainProcName, pprogram.contextBound)); }
private static void setupPrint(PersistentCBAProgram program, ErrorTrace trace, string file) { // Set output files pathFile = file == null ? null : new TokenTextWriter(file + "_trace.txt"); if (pathFile != null) { program.writeToFile(file + ".bpl"); } Program prog = program.getProgram(); // Initialization initialize(prog, trace, file == null ? null : file + ".bpl"); if (pathFile != null) { pathFile.WriteLine("s"); } if (pathFile != null) { pathFile.WriteLine("#"); } }
private PersistentCBAProgram instrument(PersistentCBAProgram pprogram, HashSet <string> candidates) { Debug.Assert(candidates.Count != 0); labelProcMap = new Dictionary <string, string>(); var program = pprogram.getProgram(); var nameImplMap = BoogieUtil.nameImplMapping(program); // Each candidate gets its own variable var procVars = new Dictionary <string, Variable>(); foreach (var str in candidates) { procVars.Add(str, new GlobalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "ep_var_" + str, Microsoft.Boogie.Type.Bool))); program.AddTopLevelDeclaration(procVars[str]); } // Add the new variables to each procedures' modifies clause foreach (var decl in program.TopLevelDeclarations) { if (decl is Implementation) { var impl = decl as Implementation; foreach (var str in candidates) { impl.Proc.Modifies.Add(new IdentifierExpr(Token.NoToken, procVars[str])); } } } // Instrument program foreach (var str in candidates) { var impl = nameImplMap[str]; var ncmds = new List <Cmd>(); ncmds.Add(BoogieAstFactory.MkVarEqConst(procVars[str], false)); ncmds.AddRange(impl.Blocks[0].Cmds); impl.Blocks[0].Cmds = ncmds; } // Instrument main. // -- Assign true to the new variables // -- Change the assert // (We assume that main only has one assert) var mainImpl = nameImplMap[pprogram.mainProcName]; var newCmds = new List <Cmd>(); foreach (var str in candidates) { newCmds.Add(BoogieAstFactory.MkVarEqConst(procVars[str], true)); } newCmds.AddRange(mainImpl.Blocks[0].Cmds); mainImpl.Blocks[0].Cmds = newCmds; // Find the assert Block blkWithAssert = null; AssertCmd assertCmd = null; bool found = false; foreach (var blk in mainImpl.Blocks) { found = false; foreach (var cmd in blk.Cmds) { if (cmd is AssertCmd) { assertCmd = cmd as AssertCmd; found = true; break; } } if (found) { blkWithAssert = blk; break; } } Debug.Assert(blkWithAssert != null); // Construct the new blocks var newLabs = new Dictionary <string, string>(); var restLab = getNewLabel(); foreach (var str in candidates) { newLabs.Add(str, getNewLabel()); var tcmds = new List <Cmd>(); tcmds.Add(new AssertCmd(Token.NoToken, Expr.Or(Expr.Ident(procVars[str]), assertCmd.Expr))); mainImpl.Blocks.Add(new Block(Token.NoToken, newLabs[str], tcmds, BoogieAstFactory.MkGotoCmd(restLab))); } // change blkWithAssert to include only commands upto the assert // Add the rest of commands to a new block found = false; newCmds = new List <Cmd>(); var newBlk = new Block(Token.NoToken, restLab, new List <Cmd>(), blkWithAssert.TransferCmd); foreach (Cmd cmd in blkWithAssert.Cmds) { if (cmd is AssertCmd) { found = true; continue; } if (!found) { newCmds.Add(cmd); } else { newBlk.Cmds.Add(cmd); } } blkWithAssert.Cmds = newCmds; var targets = new List <String>(newLabs.Values.ToArray()); blkWithAssert.TransferCmd = new GotoCmd(Token.NoToken, targets); mainImpl.Blocks.Add(newBlk); var ret = new PersistentCBAProgram(program, pprogram.mainProcName, pprogram.contextBound); //ret.writeToFile("ep_instrumented.bpl"); return(ret); }
private ErrorTrace mapBackTraceInline(ErrorTrace trace) { Debug.Assert(trace.isIntra()); Program inputProg = inlineInput.getProgram(); var nameImplMap = BoogieUtil.nameImplMapping(inputProg); var traceLabels = trace.getBlockLabels(); var stack = new List <WorkItemR>(); Implementation startImpl = getImpl(trace.procName, nameImplMap); Debug.Assert(traceLabels[0] == startImpl.Blocks[0].Label); var curr = new WorkItemR(startImpl, traceLabels[0]); // This variable keeps our current position in traceLabels int ecount = 0; // This variable keeps our current position in traceLabels[ecount].Cmds int icount = 0; var ret = new ErrorTrace(trace.procName); ret.addBlock(new ErrorTraceBlock(traceLabels[0])); // We will walk over the input program, trying to cover the same path as // trace, knowing that trace represents an inlined path while (true) { // Reached the end of the path? if (ecount == traceLabels.Count) { break; } //Console.WriteLine(curr.impl.Name + ": " + curr.label); // Reached the end of the current block? if (curr.count == curr.block.Cmds.Count) { ecount++; icount = 0; if (ecount == traceLabels.Count) { break; } // Move onto the next block TransferCmd tc = curr.block.TransferCmd; if (tc is ReturnCmd) { ret.addReturn(); if (stack.Count == 0) { // We're done Debug.Assert(ecount == traceLabels.Count); break; } curr = stack[0]; stack.RemoveAt(0); // An inlined procedure ends with "Return" label Debug.Assert(inlinedLabelMatches("Return", traceLabels[ecount])); ecount++; icount = 0; Debug.Assert(traceLabels[ecount].Contains(curr.block.Label)); continue; } if (tc is GotoCmd) { List <String> targets = (tc as GotoCmd).labelNames; string target = matchInlinedLabelNames(targets, traceLabels[ecount]); curr = new WorkItemR(curr.impl, target); ret.addBlock(new ErrorTraceBlock(curr.label)); continue; } // Unknown transfer command Debug.Assert(false); } // We have to continue in the same block Cmd c = curr.block.Cmds[curr.count]; curr.count++; if (!(c is CallCmd)) { ret.addInstr(new IntraInstr(getInfo(trace, ecount, icount))); icount++; continue; } // We're at a procedure call CallCmd cc = c as CallCmd; // If this is a call to a procedure without implementation, then skip if (!nameImplMap.ContainsKey(cc.Proc.Name)) { ret.addInstr(new CallInstr(cc.Proc.Name, null, false, getInfo(trace, ecount, icount))); icount++; continue; } Implementation callee = getImpl(cc.Proc.Name, nameImplMap); string label = callee.Blocks[0].Label; // The first label in a inlined procedure is always called Entry ecount++; Debug.Assert(inlinedLabelMatches("Entry", traceLabels[ecount])); ecount++; icount = 0; Debug.Assert(inlinedLabelMatches(label, traceLabels[ecount])); WorkItemR next = new WorkItemR(callee, label); stack.Insert(0, curr); curr = next; ret.addCall(callee.Name); ret.addBlock(new ErrorTraceBlock(curr.label)); } return(ret); }