// Adds a new main: // assertsPassed := true; // call main(); // assert assertsPassed; string addMain(CBAProgram program) { var dup = new FixedDuplicator(); var origMain = BoogieUtil.findProcedureImpl(program.TopLevelDeclarations, program.mainProcName); var newMain = dup.VisitImplementation(origMain); var newProc = dup.VisitProcedure(origMain.Proc); newMain.Name += "_SeqInstr"; newProc.Name += "_SeqInstr"; newMain.Proc = newProc; var mainIns = new List <Expr>(); foreach (Variable v in newMain.InParams) { mainIns.Add(Expr.Ident(v)); } var mainOuts = new List <IdentifierExpr>(); foreach (Variable v in newMain.OutParams) { mainOuts.Add(Expr.Ident(v)); } var callMain = new CallCmd(Token.NoToken, program.mainProcName, mainIns, mainOuts); callMain.Proc = origMain.Proc; var cmds = new List <Cmd>(); cmds.Add(BoogieAstFactory.MkVarEqConst(assertsPassed, true)); cmds.Add(callMain); cmds.Add(new AssertCmd(Token.NoToken, Expr.Ident(assertsPassed))); var blk = new Block(Token.NoToken, "start", cmds, new ReturnCmd(Token.NoToken)); newMain.Blocks = new List <Block>(); newMain.Blocks.Add(blk); program.AddTopLevelDeclaration(newProc); program.AddTopLevelDeclaration(newMain); program.mainProcName = newMain.Name; // Set entrypoint origMain.Attributes = BoogieUtil.removeAttr("entrypoint", origMain.Attributes); origMain.Proc.Attributes = BoogieUtil.removeAttr("entrypoint", origMain.Proc.Attributes); newMain.AddAttribute("entrypoint"); return(newMain.Name); }
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 string addTraceRec(ErrorTrace trace) { Debug.Assert(trace.Blocks.Count != 0); // First, construct the procedure declaration: only a name change required string newName = getNewName(trace.procName); Procedure proc = nameToProc[trace.procName]; output.AddTopLevelDeclaration( new Procedure(Token.NoToken, newName, proc.TypeParameters, proc.InParams, proc.OutParams, proc.Requires, proc.Modifies, proc.Ensures, proc.Attributes)); // Now to peice together the commands from the implementation. We keep around // multiple blocks to make sure that trace mapping works out. var traceBlocks = new List <Block>(); Implementation impl = nameToImpl[trace.procName]; var labelToBlock = BoogieUtil.labelBlockMapping(impl); // These two need not agree. This happens when impl.Block[0] has // no commands. // Debug.Assert(impl.Blocks[0].Label == trace.Blocks[0].blockName); Debug.Assert(reachableViaEmptyBlocks(impl.Blocks[0].Label, labelToBlock).Contains(trace.Blocks[0].blockName)); for (int i = 0, n = trace.Blocks.Count; i < n; i++) { Block curr = labelToBlock[trace.Blocks[i].blockName]; Block traceBlock = new Block(); traceBlock.Cmds = new List <Cmd>(); traceBlock.Label = addIntToString(trace.Blocks[i].blockName, i); // (The "i" is to deal with loops) if (i != n - 1) { traceBlock.TransferCmd = BoogieAstFactory.MkGotoCmd(addIntToString(trace.Blocks[i + 1].blockName, i + 1)); } else { traceBlock.TransferCmd = new ReturnCmd(Token.NoToken); } tinfo.addTrans(newName, trace.Blocks[i].blockName, traceBlock.Label); #region Check consistency Debug.Assert(curr.Cmds.Count >= trace.Blocks[i].Cmds.Count); if (trace.Blocks[i].Cmds.Count != curr.Cmds.Count) { Debug.Assert((i == n - 1)); } if (curr.TransferCmd is ReturnCmd) { Debug.Assert(i == n - 1); } else if (curr.TransferCmd is GotoCmd) { List <String> targets = (curr.TransferCmd as GotoCmd).labelNames; // one of these targets should be the next label if (i != n - 1) { Debug.Assert(reachableViaEmptyBlocks(targets, labelToBlock).Contains(trace.Blocks[i + 1].blockName)); } } else { throw new InternalError("Unknown transfer command"); } #endregion // Index into trace.Blocks[i].Cmds int instrCount = -1; foreach (Cmd c in curr.Cmds) { instrCount++; if (instrCount == trace.Blocks[i].Cmds.Count) { break; } ErrorTraceInstr curr_instr = trace.Blocks[i].Cmds[instrCount]; if (curr_instr.info.isValid) { traceBlock.Cmds.Add(InstrumentationConfig.getFixedContextProc(curr_instr.info.executionContext)); newFixedContextProcs.Add(curr_instr.info.executionContext); } // Don't keep "fix context value" procs from the input program if (InstrumentationConfig.getFixedContextValue(c) != -1) { traceBlock.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.True)); addedTrans(newName, curr.Label, instrCount, c, traceBlock.Label, traceBlock.Cmds); continue; } // Don't keep "fix raise exception" procs from the input program if (InstrumentationConfig.isFixedRaiseExceptionProc(c)) { traceBlock.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.True)); addedTrans(newName, curr.Label, instrCount, c, traceBlock.Label, traceBlock.Cmds); continue; } if (addConcretization && c is HavocCmd && curr_instr.info != null && curr_instr.info.hasIntVar("si_arg") && (c as HavocCmd).Vars.Count > 0 && (c as HavocCmd).Vars[0].Decl.TypedIdent.Type.IsInt) { // concretize havoc-ed variable var val = curr_instr.info.getIntVal("si_arg"); traceBlock.Cmds.Add(BoogieAstFactory.MkVarEqConst((c as HavocCmd).Vars[0].Decl, val)); addedTrans(newName, curr.Label, instrCount, c, traceBlock.Label, traceBlock.Cmds); continue; } if (!(c is CallCmd)) { if (convertNonFailingAssertsToAssumes && c is AssertCmd && !(curr_instr.info is AssertFailInstrInfo)) { traceBlock.Cmds.Add(new AssumeCmd(c.tok, (c as AssertCmd).Expr, (c as AssertCmd).Attributes)); } else { traceBlock.Cmds.Add(c); } Debug.Assert(!curr_instr.isCall()); addedTrans(newName, curr.Label, instrCount, c, traceBlock.Label, traceBlock.Cmds); continue; } Debug.Assert(curr_instr.isCall()); CallCmd cc = c as CallCmd; CallInstr call_instr = curr_instr as CallInstr; if (!nameToImpl.ContainsKey(cc.Proc.Name) || !call_instr.hasCalledTrace) { // This is a call to a procedure without implementation; skip; calledProcsNoImpl.Add(cc.Proc.Name); traceBlock.Cmds.Add(c); Debug.Assert(!call_instr.hasCalledTrace); if (addConcretization && cc.Outs.Count == 1 && call_instr.info.hasVar("si_arg")) { if (!addConcretizationAsConstants) { if (call_instr.info.hasBoolVar("si_arg")) { traceBlock.Cmds.Add(BoogieAstFactory.MkVarEqConst(cc.Outs[0].Decl, call_instr.info.getBoolVal("si_arg"))); } else if (call_instr.info.hasIntVar("si_arg")) { traceBlock.Cmds.Add(BoogieAstFactory.MkVarEqConst(cc.Outs[0].Decl, call_instr.info.getIntVal("si_arg"))); } else { Debug.Assert(false); } } else { // create a constant that is equal to this literal, then use the constant // for concretization // do we use a specific name for the constant? var constantName = QKeyValue.FindStringAttribute(cc.Attributes, ConcretizeConstantNameAttr); if (constantName == null) { constantName = ""; } var constant = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("alloc_{0}__{1}", constantName, const_counter), cc.Outs[0].Decl.TypedIdent.Type), false); const_counter++; traceBlock.Cmds.Add(BoogieAstFactory.MkVarEqVar(cc.Outs[0].Decl, constant)); output.AddTopLevelDeclaration(constant); if (call_instr.info.hasIntVar("si_arg")) { output.AddTopLevelDeclaration(new Axiom(Token.NoToken, Expr.Eq(Expr.Ident(constant), Expr.Literal(call_instr.info.getIntVal("si_arg"))))); } else if (call_instr.info.hasVar("si_arg") && cc.Outs[0].Decl.TypedIdent.Type.IsCtor) { uvalueToConstants.InitAndAdd(call_instr.info.getVal("si_arg").ToString(), constant); } var id = QKeyValue.FindIntAttribute(cc.Attributes, ConcretizeCallIdAttr, -1); concretizeConstantToCall.Add(constant.Name, id); } } addedTrans(newName, curr.Label, instrCount, c, traceBlock.Label, traceBlock.Cmds); continue; } Debug.Assert(call_instr.calleeTrace.procName == cc.Proc.Name); var callee = addTraceRec(call_instr.calleeTrace); var newcmd = new CallCmd(Token.NoToken, callee, cc.Ins, cc.Outs, cc.Attributes, cc.IsAsync); traceBlock.Cmds.Add(newcmd); addedTrans(newName, curr.Label, instrCount, c, traceBlock.Label, traceBlock.Cmds); } traceBlocks.Add(traceBlock); } Debug.Assert(traceBlocks.Count != 0); if (trace.raisesException) { var exitblk = traceBlocks.Last(); exitblk.Cmds.Add(InstrumentationConfig.getFixedRaiseExceptionProc()); addRaiseExceptionProcDecl = true; } // Add the implementation to output //var block = new Block(Token.NoToken, trace.Blocks[0].blockName, traceCmdSeq, new ReturnCmd(Token.NoToken)); //List<Block> blocks = new List<Block>(); //blocks.Add(block); //tinfo.addTrans(newName, trace.Blocks[0].blockName, trace.Blocks[0].blockName); tinfo.addProcNameTrans(trace.procName, newName); output.AddTopLevelDeclaration( new Implementation(Token.NoToken, newName, impl.TypeParameters, impl.InParams, impl.OutParams, impl.LocVars, traceBlocks, QKeyValue.FindStringAttribute(impl.Attributes, "origRTname") == null ? new QKeyValue(Token.NoToken, "origRTname", new List <object> { impl.Name }, impl.Attributes) : impl.Attributes)); return(newName); }
private static Program PrepareQuery(IEnumerable <Implementation> loopImpls, Program program) { // Sometimes loops have multiple backedges, hence multiple recursive calls: merge them loopImpls.Iter(impl => mergeRecCalls(impl)); var dup = new FixedDuplicator(true); // Make copies of loopImpl procs var loopProcsCopy = new Dictionary <string, Procedure>(); loopImpls .Iter(impl => loopProcsCopy.Add(impl.Name, dup.VisitProcedure(impl.Proc))); loopProcsCopy.Values.Iter(proc => proc.Name += "_PassiveCopy"); // Make copies of the caller implementations var loopCallerImplCopy = new Dictionary <string, Implementation>(); var loopCallerProcCopy = new Dictionary <string, Procedure>(); loopImpls .Iter(impl => loopCallerImplCopy.Add(impl.Name, dup.VisitImplementation(loopCaller[impl.Name]))); loopImpls .Iter(impl => loopCallerProcCopy.Add(impl.Name, dup.VisitProcedure(loopCaller[impl.Name].Proc))); loopCallerImplCopy .Iter(kvp => kvp.Value.Name += "_EntryCopy_" + kvp.Key); loopCallerProcCopy .Iter(kvp => kvp.Value.Name += "_EntryCopy_" + kvp.Key); loopCallerImplCopy .Iter(kvp => kvp.Value.Proc = loopCallerProcCopy[kvp.Key]); // Instrument callers foreach (var kvp in loopCallerImplCopy) { var impl = kvp.Value; var av = BoogieAstFactory.MkLocal("LoopBound_AssertVar", Microsoft.Boogie.Type.Bool); impl.LocVars.Add(av); // av := true var init = BoogieAstFactory.MkVarEqConst(av, true); var initCmds = new List <Cmd>(); initCmds.Add(init); initCmds.AddRange(impl.Blocks[0].Cmds); impl.Blocks[0].Cmds = initCmds; // av := false foreach (var blk in impl.Blocks) { var newCmds = new List <Cmd>(); for (int i = 0; i < blk.Cmds.Count; i++) { // disable assertions if (blk.Cmds[i] is AssertCmd && !BoogieUtil.isAssertTrue(blk.Cmds[i])) { newCmds.Add(new AssumeCmd(Token.NoToken, (blk.Cmds[i] as AssertCmd).Expr)); continue; } var cc = blk.Cmds[i] as CallCmd; if (cc != null && cc.callee == kvp.Key) { newCmds.Add(blk.Cmds[i]); newCmds.Add(BoogieAstFactory.MkVarEqConst(av, false)); } else if (cc != null && loopProcsCopy.ContainsKey(cc.callee)) { var ncc = new CallCmd(cc.tok, loopProcsCopy[cc.callee].Name, cc.Ins, cc.Outs, cc.Attributes, cc.IsAsync); ncc.Proc = loopProcsCopy[cc.callee]; newCmds.Add(ncc); } else { newCmds.Add(blk.Cmds[i]); } } blk.Cmds = newCmds; } // assert av impl.Blocks .Where(blk => blk.TransferCmd is ReturnCmd) .Iter(blk => blk.Cmds.Add(new AssertCmd(Token.NoToken, Expr.Ident(av)))); } // Prepare program var ret = new Program(); program.TopLevelDeclarations .Where(decl => !(decl is Implementation)) .Iter(decl => ret.AddTopLevelDeclaration(decl)); loopProcsCopy.Values .Iter(decl => ret.AddTopLevelDeclaration(decl)); loopCallerImplCopy.Values .Iter(decl => ret.AddTopLevelDeclaration(decl)); loopCallerProcCopy.Values .Iter(decl => ret.AddTopLevelDeclaration(decl)); loopImpls .Iter(impl => ret.AddTopLevelDeclaration(impl)); loopCallerImplCopy.Values .Iter(impl => impl.AddAttribute("entrypoint")); // Store mapping: entrypoint -> loop loopImpls .Select(loop => Tuple.Create(loop, loopCallerImplCopy[loop.Name])) .Iter(tup => tup.Item2.AddAttribute("LB_Mapping", tup.Item1.Name)); ret = BoogieUtil.ReResolveInMem(ret); return(ret); }