// precondition: pathProgram has a single implementation // Suppress an assertion (that failed in the pathProgram) and // return its token public AssertToken SuppressAssert(Program pathProgram) { var impl = pathProgram.TopLevelDeclarations.OfType <Implementation>() .First(); var tokenId = -1; foreach (var acmd in impl.Blocks[0].Cmds.OfType <PredicateCmd>()) { tokenId = QKeyValue.FindIntAttribute(acmd.Attributes, "avn", -1); if (tokenId == -1) { continue; } break; } Debug.Assert(tokenId != -1); var token = new AssertToken(tokenId); SuppressToken(token); BoogieUtil.DoModSetAnalysis(currProg); suppressedTokens.Add(token); return(token); }
public void Unify(string outfile) { // Gather all maps AllMaps = new HashSet <string>(); program.TopLevelDeclarations .OfType <GlobalVariable>() .Where(g => g.TypedIdent.Type.IsMap && (g.TypedIdent.Type as MapType).Result.IsInt) .Iter(g => AllMaps.Add(g.Name)); // Fix Cmds program.TopLevelDeclarations .OfType <Implementation>() .Iter(impl => impl.Blocks.Iter(block => block.Cmds .OfType <Cmd>().Iter(cmd => Visit(cmd)))); program.TopLevelDeclarations.OfType <Procedure>() .Iter(p => VisitEnsuresSeq(p.Ensures)); program.TopLevelDeclarations.OfType <Procedure>() .Iter(p => VisitRequiresSeq(p.Requires)); var impls = new HashSet <string>(); program.TopLevelDeclarations.OfType <Implementation>() .Iter(impl => impls.Add(impl.Name)); program.TopLevelDeclarations.OfType <Procedure>() .Where(p => impls.Contains(p.Name)) .Iter(p => p.Modifies = new List <IdentifierExpr>()); program.TopLevelDeclarations.OfType <Procedure>() .Iter(p => VisitIdentifierExprSeq(p.Modifies)); // Remove globals var newDecls = new List <Declaration>(); foreach (var decl in program.TopLevelDeclarations) { var glob = decl as GlobalVariable; if (glob == null || !AllMaps.Contains(glob.Name)) { newDecls.Add(decl); } } program.TopLevelDeclarations = newDecls; program.AddTopLevelDeclaration(U); // print program BoogieUtil.DoModSetAnalysis(program); BoogieUtil.PrintProgram(program, outfile); program = null; }
// Unsuppress assertions (inverse of SuppressAllButOneProcedure) public void Unsuppress() { foreach (var token in tempSuppressedTokens) { if (suppressedTokens.Contains(token)) { continue; } UnsuppressToken(token); } tempSuppressedTokens = new HashSet <AssertToken>(); BoogieUtil.DoModSetAnalysis(currProg); }
public override CBAProgram runCBAPass(CBAProgram p) { // Type information is needed in some cases. For instance, the Command // Mem[x] := untracked-expr is converted to havoc temp; Mem[x] := temp. Here // we need the type of "untracked-expr" or of "Mem[x]" if (p.Typecheck() != 0) { p.Emit(new TokenTextWriter("error.bpl")); throw new InternalError("Type errors"); } vslice.VisitProgram(p as Program); BoogieUtil.DoModSetAnalysis(p); return(p); }
public Program run(Program node) { globalsRead = new HashSet <string>(); // Typecheck -- needed for variable abstraction if (node.Typecheck() != 0) { BoogieUtil.PrintProgram(node, "error.bpl"); throw new InternalError("Type errors"); } // Go through all procedures and implementations (slice locals) var TopLevelDeclarations = node.TopLevelDeclarations.ToList(); for (int i = 0; i < TopLevelDeclarations.Count; i++) { if (TopLevelDeclarations[i] is Implementation) { TopLevelDeclarations[i] = processImplementation(TopLevelDeclarations[i] as Implementation); } else if (TopLevelDeclarations[i] is Procedure) { processProcedure(TopLevelDeclarations[i] as Procedure); } } node.TopLevelDeclarations = TopLevelDeclarations; if (onlyLocals) { return(node); } sliceGlobals = new VariableSlicing(VarSet.ToVarSet(globalsRead, node), gtinfo); node = sliceGlobals.VisitProgram(node); BoogieUtil.DoModSetAnalysis(node); return(node); }
static Program GetProgram(string filename) { var init = GetInputProgram(filename); if (Options.addInitialization) { ComputeandInitializeUninitializedLocals(init); } // Do some instrumentation for the input program if (Options.markAssumesAsSlic) { // Mark all assumes as "slic" var AddAnnotation = new Action <AssumeCmd>(ac => { ac.Attributes = new QKeyValue(Token.NoToken, "slic", new List <object>(), ac.Attributes); }); init.TopLevelDeclarations.OfType <Implementation>() .Iter(impl => impl.Blocks .Iter(blk => blk.Cmds.OfType <AssumeCmd>() .Iter(AddAnnotation))); } // Only keep assertions in assertProc procedures if (Options.assertProcs != null) { (new Instrumentations.PruneNonAssertProcs(Options.assertProcs)).Visit(init); } // Inline procedures supplied with {:inline} annotation cba.Driver.InlineProcedures(init); // Remove {:inline} impls init.RemoveTopLevelDeclarations(decl => (decl is Implementation) && (BoogieUtil.checkAttrExists("inline", decl.Attributes) || BoogieUtil.checkAttrExists("inline", (decl as Implementation).Proc.Attributes))); // Restrict entrypoints to those provided explicitly (overrides any other way to providing entryPoints) if (Options.entryPointProcs != null) { //only consider the user provided entry points in command line Options.useHarnessTag = false; Options.useProvidedEntryPoints = true; init.TopLevelDeclarations.OfType <NamedDeclaration>() .Iter(d => d.Attributes = BoogieUtil.removeAttr("entrypoint", d.Attributes)); } var matchesEntryPointExclude = new Func <string, bool>(s => { return(Options.entryPointExcludes.Any(t => new System.Text.RegularExpressions.Regex(t).IsMatch(s))); }); //when both entryPointProcs == null and entryPointExcludes == null, it should not add any entrypointProcs if (Options.entryPointProcs != null || Options.entryPointExcludes != null) { init.TopLevelDeclarations.OfType <NamedDeclaration>() .Where(d => d is Procedure || d is Implementation) .Where(d => Options.entryPointProcs == null || Options.entryPointProcs.Contains(d.Name)) .Where(d => (Options.entryPointExcludes == null || !matchesEntryPointExclude(d.Name))) .Iter(d => d.AddAttribute("entrypoint")); } // Add {:entrypoint} to procs with {:harness} if (Options.useHarnessTag) { foreach (var decl in init.TopLevelDeclarations.OfType <NamedDeclaration>() .Where(d => QKeyValue.FindBoolAttribute(d.Attributes, "harness"))) { decl.AddAttribute("entrypoint"); } } // inlining introduces havoc statements; lets just delete them (TODO: make inlining not introduce redundant havoc statements) //foreach (var impl in init.TopLevelDeclarations.OfType<Implementation>()) //{ // impl.Blocks.Iter(blk => // blk.Cmds.RemoveAll(cmd => cmd is HavocCmd)); //} ReplaceHavocsWithNonDet(init); //Instrument to create the harness harnessInstrumentation = new Instrumentations.HarnessInstrumentation(init, AvnAnnotations.CORRAL_MAIN_PROC, Options.useProvidedEntryPoints); harnessInstrumentation.DoInstrument(); //resolve+typecheck wo bothering about modSets CommandLineOptions.Clo.DoModSetAnalysis = true; init = BoogieUtil.ReResolveInMem(init); CommandLineOptions.Clo.DoModSetAnalysis = false; // Update mod sets BoogieUtil.DoModSetAnalysis(init); if (Options.AddMapSelectNonNullAssumptions) { (new Instrumentations.AssertMapSelectsNonNull()).Visit(init); } BoogieUtil.pruneProcs(init, AvnAnnotations.CORRAL_MAIN_PROC); if (Options.deadCodeDetect) { // Tag branches as reachable var tup = InstrumentBranches.Run(init, AvnAnnotations.CORRAL_MAIN_PROC, Options.UseAliasAnalysisForAngelicAssertions, false); init = tup.Item1; // TODO: inject this information into the program itself DeadCodeBranchesDependencyInfo = tup.Item2; } return(init); }
static void Main(string[] args) { con = new Context(); string inFileName = null, unrolledFileName = null, tidRewrittenFileName = null, expandedFileName = null, annotatedFileName = null, splitFileName = null, yieldedFileName = null, instantiatedFileName = null, finalFileName = null, mhpFileName = null, hmifFileName = null; dbg = false; inFileName = parseCommandLine(args); string[] parts = inFileName.Split('.'); if (parts.Count() == 1) { unrolledFileName = inFileName + "_unrolled"; hmifFileName = inFileName + "_hmif"; expandedFileName = inFileName + "_expanded"; tidRewrittenFileName = inFileName + "_tidRewritten"; annotatedFileName = inFileName + "_annotated"; splitFileName = inFileName + "_split"; yieldedFileName = inFileName + "_yielded"; finalFileName = inFileName + "_final"; mhpFileName = inFileName + "_mhp"; instantiatedFileName = inFileName + "_inst"; } else { string name = parts[0]; unrolledFileName = name + "_unrolled"; hmifFileName = name + "_hmif"; expandedFileName = name + "_expanded"; annotatedFileName = name + "_annotated"; splitFileName = name + "_split"; yieldedFileName = name + "_yielded"; finalFileName = name + "_final"; mhpFileName = name + "_mhp"; instantiatedFileName = name + "_inst"; tidRewrittenFileName = name + "_tidRewritten"; for (int i = 1; i < parts.Count(); ++i) { unrolledFileName += "." + parts[i]; hmifFileName += "." + parts[i]; expandedFileName += "." + parts[i]; annotatedFileName += "." + parts[i]; splitFileName += "." + parts[i]; yieldedFileName += "." + parts[i]; finalFileName += "." + parts[i]; tidRewrittenFileName += "." + parts[i]; mhpFileName += "." + parts[i]; instantiatedFileName += "." + parts[i]; } } var tmpFileName = "og__tmp.bpl"; ExecutionEngine.printer = new ConsolePrinter(); //CommanLineOptions will control how boogie parses the program and gives us the IR CommandLineOptions.Install(new CommandLineOptions()); CommandLineOptions.Clo.Parse(new string[] { }); CommandLineOptions.Clo.PrintInstrumented = true; CommandLineOptions.Clo.StratifiedInliningVerbose = 2; CommandLineOptions.Clo.UseArrayTheory = true; CommandLineOptions.Clo.TypeEncodingMethod = CommandLineOptions.TypeEncoding.Monomorphic; Program program; program = BoogieUtil.ReadAndOnlyResolve(inFileName); // TODO: assert that no procedure can be called in both sync and async mode! // Find entrypoint and initialize con var entry = program.TopLevelDeclarations.OfType <Procedure>() .Where(proc => QKeyValue.FindBoolAttribute(proc.Attributes, "entrypoint")) .FirstOrDefault(); if (entry == null) { Console.WriteLine("Warning: No entrypoint given"); con.entryFunc = null; } else { con.entryFunc = entry.Name; } // Remove unreachable procedures BoogieUtil.pruneProcs(program, con.entryFunc); // Extract loops if (extractLoops) { program.ExtractLoops(); } BoogieUtil.DoModSetAnalysis(program); if (pruneAsserts) { program = og.GuardAsserts(program); } if (injectYields) { program = og.InsertYields(program); } if (instantiateTemplates) { var inst = new TemplateInstantiator(program); inst.Instantiate(program); program = BoogieUtil.ReResolve(program, dbg ? instantiatedFileName : tmpFileName); } var sp = new SplitThreads(con, dbg); var hmif = new HowManyInstanceFinder(con, dbg); var split = new Converter <Program, Program>(sp.split); var findHowManyInstances = new Converter <Program, Program>(hmif.Compute); if (entry != null && splitThreads) { if (dbg) { Console.WriteLine("Splitting procedures on thread entry: {0}", splitFileName); } program = split(program); program = BoogieUtil.ReResolve(program, dbg ? hmifFileName : tmpFileName); program = findHowManyInstances(program); program = BoogieUtil.ReResolve(program, dbg ? splitFileName : tmpFileName); } // Get rid of corral_yield program = og.RemoveCorralYield(program, con.yieldProc); var yieldedProgram = new ProgTransformation.PersistentProgram(program); if (dbg) { Console.WriteLine("Instrumenting: {0}", annotatedFileName); } if (!noTid) { program = og.InstrumentTid(program); } program = og.InstrumentAtomicBlocks(program); if (instrumentPermissions) { program = og.InstrumentPermissions(program); } program = BoogieUtil.ReResolve(program, dbg ? annotatedFileName : tmpFileName); CommandLineOptions.Clo.ContractInfer = true; CommandLineOptions.Clo.AbstractHoudini = absDomain; CommandLineOptions.Clo.UseProverEvaluate = true; CommandLineOptions.Clo.ModelViewFile = "z3model"; Microsoft.Boogie.Houdini.AbstractDomainFactory.Initialize(program); // First, do sequential var answer = DoInference(program, InferenceMode.SEQUENTIAL, annotatedFileName, expandedFileName); program = BoogieUtil.ReadAndOnlyResolve(dbg ? annotatedFileName : tmpFileName); // prune "true" functions var progFuncs = new Dictionary <string, Function>(); program.TopLevelDeclarations.OfType <Function>() .Iter(f => progFuncs.Add(f.Name, f)); var truefuncs = new List <Function>(); foreach (var f in answer) { if (f.Body is LiteralExpr && (f.Body as LiteralExpr).IsTrue) { truefuncs.Add(f); var actualf = progFuncs[f.Name]; actualf.Attributes = BoogieUtil.removeAttr("existential", actualf.Attributes); actualf.Body = Expr.True; } } Console.WriteLine("Sequential check pruned away {0} functions, {1} remain", truefuncs.Count, answer.Count() - truefuncs.Count); // now do concurrent answer = DoInference(program, InferenceMode.CONCURRENT, annotatedFileName, expandedFileName); answer = answer.Concat(truefuncs); var provedAsserts = new Dictionary <string, bool>(); answer.Where(func => QKeyValue.FindBoolAttribute(func.Attributes, "assertGuard")) .Iter(func => { var le = func.Body as LiteralExpr; System.Diagnostics.Debug.Assert(le != null); provedAsserts.Add(func.Name, le.IsFalse); }); // remove injected existential functions answer = answer.Where(func => !QKeyValue.FindBoolAttribute(func.Attributes, "chignore") && !QKeyValue.FindBoolAttribute(func.Attributes, "assertGuard")); if (printAssignment) { using (var tt = new TokenTextWriter(Console.Out)) answer.ToList().Iter(func => func.Emit(tt, 0)); } if (dbg) { Console.WriteLine("Injecting invariants back into the original program: {0}", finalFileName); } program = yieldedProgram.getProgram(); // remove existential functions program.RemoveTopLevelDeclarations(decl => (decl is Function) && QKeyValue.FindBoolAttribute((decl as Function).Attributes, "existential")); program.AddTopLevelDeclarations(answer); program = og.PruneProvedAsserts(program, f => provedAsserts[f]); // Remove ensures and requires program = og.RemoveRequiresAndEnsures(program); // Remove tid func program = og.RemoveThreadIdFunc(program); using (Microsoft.Boogie.TokenTextWriter writer = new Microsoft.Boogie.TokenTextWriter(finalFileName)) program.Emit(writer); }
static Program GetProgram(string filename) { var init = GetInputProgram(filename); if (Options.addInitialization) { ComputeandInitializeUninitializedLocals(init); } // Do some instrumentation for the input program if (Options.markAssumesAsSlic) { // Mark all assumes as "slic" var AddAnnotation = new Action <AssumeCmd>(ac => { ac.Attributes = new QKeyValue(Token.NoToken, "slic", new List <object>(), ac.Attributes); }); init.TopLevelDeclarations.OfType <Implementation>() .Iter(impl => impl.Blocks .Iter(blk => blk.Cmds.OfType <AssumeCmd>() .Iter(AddAnnotation))); } // Inline procedures supplied with {:inline} annotation cba.Driver.InlineProcedures(init); // Remove {:inline} impls init.RemoveTopLevelDeclarations(decl => (decl is Implementation) && (BoogieUtil.checkAttrExists("inline", decl.Attributes) || BoogieUtil.checkAttrExists("inline", (decl as Implementation).Proc.Attributes))); // Add {:entrypoint} to procs with {:harness} if (Options.useHarnessTag) { foreach (var decl in init.TopLevelDeclarations.OfType <NamedDeclaration>() .Where(d => QKeyValue.FindBoolAttribute(d.Attributes, "harness"))) { decl.AddAttribute("entrypoint"); } } // inlining introduces havoc statements; lets just delete them (TODO: make inlining not introduce redundant havoc statements) foreach (var impl in init.TopLevelDeclarations.OfType <Implementation>()) { impl.Blocks.Iter(blk => blk.Cmds.RemoveAll(cmd => cmd is HavocCmd)); } //Instrument to create the harness harnessInstrumentation = new Instrumentations.HarnessInstrumentation(init, AvnAnnotations.CORRAL_MAIN_PROC, Options.useProvidedEntryPoints); harnessInstrumentation.DoInstrument(); //resolve+typecheck wo bothering about modSets CommandLineOptions.Clo.DoModSetAnalysis = true; init = BoogieUtil.ReResolve(init); CommandLineOptions.Clo.DoModSetAnalysis = false; // Update mod sets BoogieUtil.DoModSetAnalysis(init); if (Options.AddMapSelectNonNullAssumptions) { (new Instrumentations.AssertMapSelectsNonNull()).Visit(init); } BoogieUtil.pruneProcs(init, AvnAnnotations.CORRAL_MAIN_PROC); if (Options.deadCodeDetect) { // Tag branches as reachable var tup = InstrumentBranches.Run(init, AvnAnnotations.CORRAL_MAIN_PROC, Options.UseAliasAnalysisForAngelicAssertions, false); init = tup.Item1; // TODO: inject this information into the program itself DeadCodeBranchesDependencyInfo = tup.Item2; } return(init); }
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); }
public static bool ApplyTemplates(HashSet <int> templates) { var commonGlobals = Minimize.FindCommonGlobals(); var ret = false; // Prune away ones that don't have constants associated with them templates = new HashSet <int>( templates.Where(t => !templateMap[t].All(tup => tup.Value.SetEquals(fileToKeepConstants[tup.Key])))); // Prune away ones that don't talk about common globals templates = new HashSet <int>( templates.Where(t => { var expr = SimplifyExpr.ToExpr(templateToStr[t]); var vu = new GlobalVarsUsed(); vu.VisitExpr(expr); return(vu.globalsUsed.IsSubsetOf(commonGlobals)); })); var newFileToProg = new Dictionary <string, PersistentProgram>(); var templateToConstants = new Dictionary <int, int>(); templates.Iter(t => templateToConstants.Add(t, 0)); foreach (var tup in fileToProg) { var program = tup.Value.getProgram(); BoogieUtil.DoModSetAnalysis(program); var globals = new HashSet <string>(program.TopLevelDeclarations.OfType <GlobalVariable>().Select(g => g.Name)); var newconstants = new HashSet <Constant>(); foreach (var t in templates) { var expr = SimplifyExpr.ToExpr(templateToStr[t]); var nonold = new GatherNonOldVariables(); nonold.VisitExpr(expr); var mustmod = new HashSet <string>(nonold.variables); mustmod.IntersectWith(globals); foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>()) { var mod = new HashSet <string>(impl.Proc.Modifies.Select(ie => ie.Name)); if (!mustmod.IsSubsetOf(mod)) { continue; } // create new constant var nc = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, "PMnewConst" + (NewConstCounter++), btype.Bool), false); nc.AddAttribute("existential"); newconstants.Add(nc); if (!templateMap[t].ContainsKey(tup.Key)) { templateMap[t].Add(tup.Key, new HashSet <string>()); } templateMap[t][tup.Key].Add(nc.Name); ret = true; templateToConstants[t]++; impl.Proc.Ensures.Add(new Ensures(false, Expr.Imp(Expr.Ident(nc), expr))); } } program.AddTopLevelDeclarations(newconstants); newFileToProg.Add(tup.Key, new PersistentProgram(program)); } fileToProg = newFileToProg; foreach (var tup in templateToConstants) { Console.WriteLine("Applying template {0}: {1} ({2} constants created)", tup.Key, templateToStr[tup.Key], tup.Value); } return(ret); }