private void UnsuppressToken(AssertToken token) { var location = tokenLocation[token]; var p = BoogieUtil.findProcedureImpl(currProg.TopLevelDeclarations, location.Item1); var block = p.Blocks.Where(blk => blk.Label == location.Item2).FirstOrDefault(); // disable assignment to assertsPassed var ncmds = new List <Cmd>(); foreach (var cmd in block.Cmds) { if (!Options.DeepAsserts && cmd is AssumeCmd && QKeyValue.FindIntAttribute((cmd as AssumeCmd).Attributes, "suppressAssert", -1) == token.id) { ncmds.Add(BoogieAstFactory.MkVarEqExpr(assertsPassed, (cmd as AssumeCmd).Expr)); } else if (Options.DeepAsserts && cmd is AssumeCmd && QKeyValue.FindIntAttribute((cmd as AssumeCmd).Attributes, "avn", -1) == token.id) { ncmds.Add(new AssertCmd(Token.NoToken, (cmd as AssertCmd).Expr, (cmd as AssertCmd).Attributes)); } else { ncmds.Add(cmd); } } block.Cmds = ncmds; }
public void ComputePreconditions() { var NameToImpl = new Func <string, Implementation>(name => BoogieUtil.findProcedureImpl(program.TopLevelDeclarations, name)); var main = id2Graph[program.mainProcName]; main.UpdatePrecondition(main.precondition.Top(NameToImpl(main.Id))); IntraGraph.TopDown = true; var worklist = new SortedSet <IntraGraph>(main); worklist.Add(main); var SetPrecondition = new Action <string, IWeight>((name, weight) => { var g = id2Graph[name]; var changed = g.UpdatePrecondition(weight); if (changed) { worklist.Add(g); } }); while (worklist.Any()) { var proc = worklist.First(); worklist.Remove(proc); proc.PropagatePrecondition(NameToImpl, SetPrecondition); } IntraGraph.TopDown = false; }
// 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); }
// Remove the dispatch to certain entrypoints public static void RemoveEntryPoints(Program program, HashSet <string> procs) { var mainImpl = BoogieUtil.findProcedureImpl(program.TopLevelDeclarations, AvnAnnotations.CORRAL_MAIN_PROC); foreach (var block in mainImpl.Blocks) { if (block.Cmds.OfType <CallCmd>().Any(cc => procs.Contains(cc.callee))) { block.Cmds.Clear(); } } BoogieUtil.pruneProcs(program, mainImpl.Name); }
// Suppress an input constraint public void RemoveInputSuppression(int id) { // find main var main = BoogieUtil.findProcedureImpl(currProg.TopLevelDeclarations, origMainName); // Requires has the right id? var Mutate = new Func <Requires, Requires>(req => { if (QKeyValue.FindIntAttribute(req.Attributes, AvnAnnotations.BlockingConstraintAttr, -1) == id) { return(new Requires(true, Expr.True)); } return(req); }); main.Proc.Requires = main.Proc.Requires.Map(r => Mutate(r)); }
public void SuppressToken(AssertToken token) { var location = tokenLocation[token]; if (Options.DeepAsserts) { location = Tuple.Create((output as PersistentProgram).mainProcName, location.Item2); } var p = BoogieUtil.findProcedureImpl(currProg.TopLevelDeclarations, location.Item1); var block = p.Blocks.Where(blk => blk.Label == location.Item2).FirstOrDefault(); // disable assignment to assertsPassed var ncmds = new List <Cmd>(); foreach (var cmd in block.Cmds) { if (!Options.DeepAsserts && (cmd is AssignCmd) && (cmd as AssignCmd).Lhss[0].DeepAssignedVariable.Name == assertsPassedName) { var acmd = BoogieAstFactory.MkAssume((cmd as AssignCmd).Rhss[0]) as AssumeCmd; acmd.Attributes = new QKeyValue(Token.NoToken, "suppressAssert", new List <object> { Expr.Literal(token.id) }, null); ncmds.Add(acmd); } else if (Options.DeepAsserts && (cmd is AssertCmd) && QKeyValue.FindIntAttribute((cmd as AssertCmd).Attributes, "avn", -1) == token.id) { var acmd = new AssumeCmd(Token.NoToken, (cmd as AssertCmd).Expr, (cmd as AssertCmd).Attributes); ncmds.Add(acmd); } else { ncmds.Add(cmd); } } block.Cmds = ncmds; }
// Suppress an input constraint public int SuppressInput(Expr input) { // find main var main = BoogieUtil.findProcedureImpl(currProg.TopLevelDeclarations, origMainName); // construct the assume var ret = SuppressionCount++; var req = new Requires(true, input); req.Attributes = new QKeyValue(Token.NoToken, AvnAnnotations.BlockingConstraintAttr, new List <object> { Expr.Literal(ret) }, req.Attributes); main.Proc.Requires.Add(req); // For mapback (is redundant now) var tinfo = new cba.InsertionTrans(); suppressInfo.Add(tinfo); return(ret); }
public override CBAProgram runCBAPass(CBAProgram p) { p.Typecheck(); p.TopLevelDeclarations.OfType <Procedure>().Iter(proc => procsWithoutBody.Add(proc.Name)); p.TopLevelDeclarations.OfType <Implementation>().Iter(impl => procsWithoutBody.Remove(impl.Name)); // remove malloc //procsWithoutBody.RemoveWhere(str => str.Contains("malloc")); // Make sure that procs without a body don't modify globals foreach (var proc in p.TopLevelDeclarations.OfType <Procedure>().Where(proc => procsWithoutBody.Contains(proc.Name))) { if (proc.Modifies.Count > 0 && !BoogieUtil.checkAttrExists("allocator", proc.Attributes)) { throw new InvalidInput("Produce Bug Witness: Procedure " + proc.Name + " modifies globals"); } } // Add the boogie_si_record_int procedure var inpVarInt = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "x", Microsoft.Boogie.Type.Int), true); var inpVarBool = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "x", Microsoft.Boogie.Type.Bool), true); var reProcInt = new Procedure(Token.NoToken, recordProcNameInt, new List <TypeVariable>(), new List <Variable> { inpVarInt }, new List <Variable>(), new List <Requires>(), new List <IdentifierExpr>(), new List <Ensures>()); var reProcBool = new Procedure(Token.NoToken, recordProcNameBool, new List <TypeVariable>(), new List <Variable> { inpVarBool }, new List <Variable>(), new List <Requires>(), new List <IdentifierExpr>(), new List <Ensures>()); // Add procedures for initialization of local variables foreach (var impl in p.TopLevelDeclarations.OfType <Implementation>()) { var ncmds = new List <Cmd>(); foreach (var loc in (impl.LocVars.Concat(impl.OutParams))) { var cc = new CallCmd(Token.NoToken, GetInitLocalsProc(loc.TypedIdent.Type).Name, new List <Expr>(), new List <IdentifierExpr>(new IdentifierExpr[] { Expr.Ident(loc) })); cc.Attributes = new QKeyValue(Token.NoToken, RestrictToTrace.ConcretizeConstantNameAttr, new List <object> { LocalVarInitValueAttr }, cc.Attributes); cc.Proc = GetInitLocalsProc(loc.TypedIdent.Type); ncmds.Add(cc); } ncmds.AddRange(impl.Blocks[0].Cmds); impl.Blocks[0].Cmds = ncmds; } typeToInitLocalsProc.Values.Iter(pr => procsWithoutBody.Add(pr.Name)); typeToInitLocalsProc.Values.Iter(pr => p.AddTopLevelDeclaration(pr)); // save the current program var fd = new FixedDuplicator(true); var modInpProg = fd.VisitProgram(p); // Instrument to record stuff p.TopLevelDeclarations.OfType <Implementation>().Iter(impl => impl.Blocks.Iter(b => instrument(b))); // Name clash if this assert fails Debug.Assert(BoogieUtil.findProcedureDecl(p.TopLevelDeclarations, recordProcNameInt) == null); Debug.Assert(BoogieUtil.findProcedureDecl(p.TopLevelDeclarations, recordProcNameBool) == null); foreach (var rp in typeToRecordProc.Values) { Debug.Assert(BoogieUtil.findProcedureDecl(p.TopLevelDeclarations, rp.Name) == null); } p.AddTopLevelDeclaration(reProcInt); p.AddTopLevelDeclaration(reProcBool); p.AddTopLevelDeclarations(typeToRecordProc.Values); var tmainimpl = BoogieUtil.findProcedureImpl(p.TopLevelDeclarations, p.mainProcName); if (!QKeyValue.FindBoolAttribute(tmainimpl.Attributes, "entrypoint")) { tmainimpl.AddAttribute("entrypoint"); } var program = new PersistentCBAProgram(p, p.mainProcName, 0); //program.writeToFile("beforeverify.bpl"); var vp = new VerificationPass(true); vp.run(program); success = vp.success; if (success) { return(null); } var trace = mapBackTraceRecord(vp.trace); RestrictToTrace.addConcretization = true; RestrictToTrace.addConcretizationAsConstants = true; var tinfo = new InsertionTrans(); var rt = new RestrictToTrace(modInpProg, tinfo); rt.addTrace(trace); RestrictToTrace.addConcretization = false; RestrictToTrace.addConcretizationAsConstants = false; var rtprog = rt.getProgram(); // Build a map of where the alloc constants are from allocConstants = rt.concretizeConstantToCall; // Add symbolic constants for angelic map havocs var newDecls = new List <Constant>(); rtprog.TopLevelDeclarations.OfType <Implementation>().Iter(impl => impl.Blocks.Iter(b => instrumentMapHavocs(b, allocConstants, newDecls))); rtprog.AddTopLevelDeclarations(newDecls); /* * foreach (var impl in rtprog.TopLevelDeclarations.OfType<Implementation>()) * { * // strip _trace from the impl name * var implName = impl.Name; * var c = implName.LastIndexOf("_trace"); * while (c != -1) * { * implName = implName.Substring(0, c); * c = implName.LastIndexOf("_trace"); * } * * var vu = new VarsUsed(); * vu.VisitImplementation(impl); * vu.varsUsed.Where(s => s.StartsWith("alloc_")) * .Iter(s => allocConstants[s] = implName); * } */ BoogieUtil.findProcedureImpl(rtprog.TopLevelDeclarations, rt.getFirstNameInstance(p.mainProcName)) .AddAttribute("entrypoint"); program = new PersistentCBAProgram(rtprog, rt.getFirstNameInstance(p.mainProcName), p.contextBound); // Lets inline it all var inlp = new InliningPass(1); program = inlp.run(program); var compress = new CompressBlocks(); var ret = program.getProgram(); compress.VisitProgram(ret); return(new CBAProgram(ret, program.mainProcName, 0)); }
public static ReturnStatus Verify(Program program, bool needErrorTraces, out List <BoogieErrorTrace> allErrors, out List <string> timedOut, bool isCBA = false) { ReturnStatus ret = ReturnStatus.OK; allErrors = new List <BoogieErrorTrace>(); timedOut = new List <string>(); Debug.Assert(program != null); // Make a copy of the input program var duper = new FixedDuplicator(true); var origProg = new Dictionary <string, Implementation>(); if (needErrorTraces) { foreach (var decl in program.TopLevelDeclarations) { if (decl is Implementation) { var origImpl = duper.VisitImplementation(decl as Implementation); origProg.Add(origImpl.Name, origImpl); } } } if (removeAsserts) { RemoveAsserts(program); } // Set options options.Set(); // save RB var rb = CommandLineOptions.Clo.RecursionBound; if (BoogieVerify.irreducibleLoopUnroll >= 0) { CommandLineOptions.Clo.RecursionBound = BoogieVerify.irreducibleLoopUnroll; } // Do loop extraction var extractionInfo = program.ExtractLoops(); // restore RB CommandLineOptions.Clo.RecursionBound = rb; // set bounds if (options.extraRecBound != null) { options.extraRecBound.Iter(tup => { var impl = BoogieUtil.findProcedureImpl(program.TopLevelDeclarations, tup.Key); if (impl != null) { impl.AddAttribute(BoogieVerify.ExtraRecBoundAttr, Expr.Literal(tup.Value)); } }); } #region Save program to disk if (shuffleProgram) { BoogieUtil.PrintProgram(program, "last_query.bpl"); program = BoogieUtil.ReadAndResolve("last_query.bpl"); } if (options.printProg) { Debug.Assert(options.progFileName != null, "Invalid options"); BoogieUtil.PrintProgram(program, options.progFileName); } #endregion var origBlocks = new Dictionary <string, Tuple <Block, Implementation> >(); // ---------- Infer invariants -------------------------------------------------------- // Abstract interpretation -> Always use (at least) intervals, if not specified otherwise (e.g. with the "/noinfer" switch) //Microsoft.Boogie.AbstractInterpretation.AbstractInterpretation.RunAbstractInterpretation(program); //// ---------- Verify ---------------------------------------------------------------- var mains = new List <Implementation>( program.TopLevelDeclarations .OfType <Implementation>() .Where(impl => QKeyValue.FindBoolAttribute(impl.Attributes, "entrypoint"))); VC.VCGen vcgen = null; try { Debug.Assert(CommandLineOptions.Clo.StratifiedInlining > 0); if (options.newStratifiedInlining) { if (options.newStratifiedInliningAlgo.ToLower() == "duality") { Microsoft.Boogie.SMTLib.Factory.UseInterpolation = true; } vcgen = new CoreLib.StratifiedInlining(program, CommandLineOptions.Clo.ProverLogFilePath, CommandLineOptions.Clo.ProverLogFileAppend, null); } else // vcgen = new VC.StratifiedVCGen(options.CallTree != null, options.CallTree, options.procsToSkip, options.extraRecBound, program, CommandLineOptions.Clo.ProverLogFilePath, CommandLineOptions.Clo.ProverLogFileAppend, new List<Checker>()); if (!useDuality || !isCBA || !needErrorTraces || options.StratifiedInlining > 1 || mains.Count > 1) { vcgen = new VC.StratifiedVCGen(options.CallTree != null, options.CallTree, program, CommandLineOptions.Clo.ProverLogFilePath, CommandLineOptions.Clo.ProverLogFileAppend, new List <Checker>()); } else { CommandLineOptions.Clo.FixedPointMode = CommandLineOptions.FixedPointInferenceMode.Corral; CommandLineOptions.Clo.FixedPointEngine = "duality"; vcgen = new Microsoft.Boogie.FixedpointVC(program, CommandLineOptions.Clo.ProverLogFilePath, CommandLineOptions.Clo.ProverLogFileAppend, new List <Checker>(), options.extraRecBound); } } catch (ProverException e) { Log.WriteLine(Log.Error, "ProverException: {0}", e.Message); return(ReturnStatus.OK); } if (!mains.Any()) { throw new InternalError("No entrypoint found"); } if (mains.Count > 1) { Console.WriteLine("Verifying {0} impls", mains.Count); } foreach (var impl in mains) { if (PrintImplsBeingVerified) { Log.WriteLine(Log.Verbose, "Verifying implementation " + impl.Name); } List <Counterexample> errors; VC.VCGen.Outcome outcome; try { var start = DateTime.Now; outcome = vcgen.VerifyImplementation(impl, out errors); var end = DateTime.Now; TimeSpan elapsed = end - start; Log.WriteLine(Log.Debug, string.Format(" [{0} s] ", elapsed.TotalSeconds)); verificationTime += elapsed; if (recordTempTime) { tempTime += elapsed; } } catch (VC.VCGenException e) { throw new InternalError("VCGenException: " + e.Message); //errors = null; //outcome = VC.VCGen.Outcome.Inconclusive; } catch (UnexpectedProverOutputException upo) { throw new InternalError("Unexpected prover output: " + upo.Message); //errors = null; //outcome = VC.VCGen.Outcome.Inconclusive; } switch (outcome) { case VC.VCGen.Outcome.Correct: break; case VC.VCGen.Outcome.Errors: break; case VC.VCGen.Outcome.ReachedBound: ret = ReturnStatus.ReachedBound; break; case VC.VCGen.Outcome.Inconclusive: throw new InternalError("z3 says inconclusive"); case VC.VCGen.Outcome.OutOfMemory: // wipe out any counterexamples timedOut.Add(impl.Name); errors = new List <Counterexample>(); break; case VC.VCGen.Outcome.OutOfResource: case VC.VCGen.Outcome.TimedOut: // wipe out any counterexamples timedOut.Add(impl.Name); errors = new List <Counterexample>(); break; default: throw new InternalError("z3 unknown response"); } Log.WriteLine(Log.Debug, outcome.ToString()); Log.WriteLine(Log.Debug, (errors == null ? 0 : errors.Count) + " counterexamples."); if (errors != null) { ret = ReturnStatus.NOK; } // Print model if (errors != null && errors.Count > 0 && errors[0].Model != null && CommandLineOptions.Clo.ModelViewFile != null) { var model = errors[0].Model; var cnt = 0; model.States.Iter(st => { if (st.Name.StartsWith("corral")) { st.ChangeName(st.Name + "_" + cnt.ToString()); cnt++; } }); using (var wr = new StreamWriter(CommandLineOptions.Clo.ModelViewFile, false)) { model.Write(wr); } } if (errors != null && needErrorTraces) { for (int i = 0; i < errors.Count; i++) { //errors[i].Print(1, Console.Out); // Map the trace across loop extraction if (vcgen is VC.VCGen) { errors[i] = (vcgen as VC.VCGen).extractLoopTrace(errors[i], impl.Name, program, extractionInfo); } if (errors[i] is AssertCounterexample) { // Special treatment for assert counterexamples for CBA: Reconstruct // trace in the input program. ReconstructImperativeTrace(errors[i], impl.Name, origProg); allErrors.Add(new BoogieAssertErrorTrace(errors[i] as AssertCounterexample, origProg[impl.Name], program)); } else { allErrors.Add(new BoogieErrorTrace(errors[i], origProg[impl.Name], program)); } } } } //PutBackAsserts(program); if (vcgen is StratifiedVCGen) { CallTreeSize = (vcgen as StratifiedVCGen).numInlined; vcSize = (vcgen as StratifiedVCGen).vcsize; if (options.CallTree != null) { options.CallTree = VC.StratifiedVCGen.callTree; VC.StratifiedVCGen.callTree = null; } } else if (vcgen is CoreLib.StratifiedInlining) { procsHitRecBound = (vcgen as CoreLib.StratifiedInlining).procsHitRecBound; CallTreeSize = (vcgen as CoreLib.StratifiedInlining).stats.numInlined; vcSize = (vcgen as CoreLib.StratifiedInlining).stats.vcSize; if (options.CallTree != null) { options.CallTree = (vcgen as CoreLib.StratifiedInlining).GetCallTree(); } } else { CallTreeSize = 0; } vcgen.Close(); CommandLineOptions.Clo.TheProverFactory.Close(); return(ret); }
public override CBAProgram runCBAPass(CBAProgram p) { if (p.mode == ConcurrencyMode.FixedContext) { InstrumentationConfig.addRaiseException = false; } // Step1: Gather program information pinfo = new ProgramInfo(p.mainProcName, p, LanguageSemantics.assertNotReachableName()); TidArithmetic.reset(); if (pinfo.threadIdType.IsBv) { TidArithmetic.useIntArithmetic = false; p.AddTopLevelDeclaration(TidArithmetic.getBvAdd()); p.AddTopLevelDeclaration(TidArithmetic.getBvGt()); } else { TidArithmetic.useIntArithmetic = true; } // Step2: Set up a variable manager vmgr = new VariableManager(pinfo); // Step3: Set up the instrumentation policy // The globals not to instrument are: // -- ones not modified by any procedure // -- ones not shared // -- ones to treat as thread-local HashSet <string> globalsToInstrument = new HashSet <string>(); foreach (var g in pinfo.declaredGlobals) { string name = g.Key; if (!pinfo.modifiedGlobals.ContainsKey(name)) { continue; } if (!LanguageSemantics.isShared(name)) { continue; } if (pinfo.threadLocalGlobals.ContainsKey(name)) { continue; } globalsToInstrument.Add(name); } var rprocs = findRecursiveProcs(p); //foreach (var be in rprocs) Console.WriteLine("{0} -> {1}", be.Item1, be.Item2); policy = new InstrumentationPolicy(p.contextBound, globalsToInstrument, pinfo.procsWithImplementation, pinfo.asyncProcs, rprocs, p.mode); //policy.print(Log.getWriter(Log.Debug)); // Step4: Split program declarations based on the instrumentation policy // skipping this step (not needed for basic CBA reduction) // Step5: Carry out the K-split instrumentation inst = new Instrumenter(policy, vmgr, pinfo, tinfo_instrument); List <Declaration> newDecls = inst.instrument(p.TopLevelDeclarations.ToList()); foreach (var trp in inst.blocksWithFixedK) { blockExecutionContextMap.Add(trp.fst + "::" + trp.snd, trp.trd); } // Step6: Instrument main with initialization and the Checker Implementation mainProcImpl = BoogieUtil.findProcedureImpl(newDecls, p.mainProcName); inst.instrumentGivenMainImpl(mainProcImpl); // Step7: Instrument Async calls bool instrumentedAsync = false; InstrumentAsyncCalls ainst = new InstrumentAsyncCalls(vmgr, pinfo, tinfo_async); foreach (var decl in newDecls) { if (decl is Implementation) { ainst.VisitImplementation(decl as Implementation); instrumentedAsync = instrumentedAsync || ainst.hasAsync; } } if (!instrumentedAsync) { Log.WriteLine(Log.Debug, "Warning: Did not find any async call"); } // Step8: Set entrypoint mainProcImpl.AddAttribute("entrypoint"); // Step9: Add new variable declarations newDecls.AddRange(vmgr.getNewDeclarations(policy.executionContextBound)); newDecls.AddRange(BoogieAstFactory.newDecls); BoogieAstFactory.newDecls.Clear(); // Thats it. Program ret = new Program(); ret.TopLevelDeclarations = newDecls; if (InstrumentationConfig.printInstrumented) { // Re-resolve ret ProgTransformation.PersistentProgram tprog = new ProgTransformation.PersistentProgram(ret); var instrumented = tprog.getProgram(); // Re-do the modsets -- make them as concise as possible. BoogieUtil.DoModSetAnalysis(instrumented); // Temporary fix for Boogie's bug while inlining calls // that have don't care expressions. RewriteCallDontCares rdc = new RewriteCallDontCares(); rdc.VisitProgram(instrumented); BoogieUtil.PrintProgram(instrumented, InstrumentationConfig.instrumentedFile); throw new NormalExit("Printed " + InstrumentationConfig.instrumentedFile); } // Resolve the program (Do not typecheck because that does inlining). //BoogieUtil.PrintProgram(ret, "instrumented.bpl"); //ret = BoogieUtil.ReadAndOnlyResolve("instrumented.bpl"); if (p.mode == ConcurrencyMode.FixedContext) { InstrumentationConfig.addRaiseException = true; } p = new CBAProgram(ret, p.mainProcName, p.contextBound); return(p); }
public override CBAProgram runCBAPass(CBAProgram program) { // Add blanks blanksInfo = AddBlanks(program); // Remove unreachable procedures BoogieUtil.pruneProcs(program, program.mainProcName); if (!Options.TraceSlicing) { // Remove source line annotations sourceInfo = cba.PrintSdvPath.DeleteSourceInfo(program); } else { sourceInfo = null; } // Remove print info //printInfo = cba.PrintSdvPath.DeletePrintCmds(program); // Compress compressBlocks.VisitProgram(program); // name Ebasic NameEnvironmentConstraints(program); // Instrument assertions int tokenId = 0; origMainName = program.mainProcName; CBAProgram ret = null; if (!Options.DeepAsserts) { // Do error-bit instrumentation var impls = BoogieUtil.nameImplMapping(program); var pwa = cba.SequentialInstrumentation.procsWithAsserts(program); foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>()) { var instrumented = new List <Block>(); foreach (var blk in impl.Blocks) { var currCmds = new List <Cmd>(); var currLabel = blk.Label; assertInstrInfo.addTrans(impl.Name, blk.Label, blk.Label); var incnt = -1; foreach (Cmd cmd in blk.Cmds) { incnt++; // instrument assert if (cmd is AssertCmd && !BoogieUtil.isAssertTrue(cmd)) { currCmds.Add(BoogieAstFactory.MkVarEqExpr(assertsPassed, (cmd as AssertCmd).Expr)); var token = new AssertToken(tokenId); originalAssertions.Add(token, cmd as AssertCmd); tokenLocation.Add(token, Tuple.Create(impl.Name, currLabel)); procToTokens.InitAndAdd(impl.Name, token); addedTrans(impl.Name, blk.Label, incnt, cmd, currLabel, currCmds); currLabel = addInstr(instrumented, currCmds, currLabel, tokenId); tokenId++; currCmds = new List <Cmd>(); continue; } // procedure call if (cmd is CallCmd && pwa.Contains((cmd as CallCmd).callee)) { currCmds.Add(cmd); addedTrans(impl.Name, blk.Label, incnt, cmd, currLabel, currCmds); currLabel = addInstr(instrumented, currCmds, currLabel, -1); currCmds = new List <Cmd>(); continue; } currCmds.Add(cmd); addedTrans(impl.Name, blk.Label, incnt, cmd, currLabel, currCmds); } instrumented.Add(new Block(Token.NoToken, currLabel, currCmds, blk.TransferCmd)); } impl.Blocks = instrumented; } program.AddTopLevelDeclaration(assertsPassed); var newMain = addMain(program); BoogieUtil.DoModSetAnalysis(program); // Set inline attribute // free requires assertsPassed == true; foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>()) { impl.Proc.Requires.Add(new Requires(true, Expr.Ident(assertsPassed))); } // convert free ensures e to: // free ensures assertsPassed == false || e foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>() .Where(impl => pwa.Contains(impl.Name))) { foreach (Ensures ens in impl.Proc.Ensures) { ens.Condition = Expr.Or(Expr.Not(Expr.Ident(assertsPassed)), ens.Condition); } } currProg = program; ret = new CBAProgram(program, newMain, 0); } else { // Use Deep-assert instrumentation da = new cba.DeepAssertRewrite(); // First, tag assertions with tokens foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>()) { foreach (var blk in impl.Blocks) { foreach (var cmd in blk.Cmds.OfType <AssertCmd>()) { if (BoogieUtil.isAssertTrue(cmd)) { continue; } var token = new AssertToken(tokenId); cmd.Attributes = new QKeyValue(Token.NoToken, "avn", new List <object> { Expr.Literal(tokenId) }, cmd.Attributes); originalAssertions.Add(token, cmd); tokenLocation.Add(token, Tuple.Create(impl.Name, blk.Label)); procToTokens.InitAndAdd(impl.Name, token); tokenId++; } } } // Second, do the rewrite var t1 = new PersistentProgram(program, program.mainProcName, program.contextBound); var t2 = da.run(t1); var daprog = t2.getCBAProgram(); // Third, revisit the assertions and remember their location // in the output program. This is a bit of a hack. The "tokenLocation" // of a token is the pair (p1,b1) where p1 is the procedure the assertion // originally came from and b1 is the block in the new main that contains // that assertion. var main = BoogieUtil.findProcedureImpl(daprog.TopLevelDeclarations, daprog.mainProcName); foreach (var block in main.Blocks) { foreach (var cmd in block.Cmds.OfType <AssertCmd>()) { var tok = QKeyValue.FindIntAttribute(cmd.Attributes, "avn", -1); if (tok < 0) { continue; } var token = new AssertToken(tok); Debug.Assert(tokenLocation.ContainsKey(token)); var oldloc = tokenLocation[token]; tokenLocation[token] = Tuple.Create(oldloc.Item1, block.Label); } } currProg = daprog; ret = daprog; } return(ret); }