string PrintBoogie(BoogieProgram program) { var result = new StringWriter(); var writer = new TokenTextWriter(result); program.Emit(writer); return(result.ToString()); }
public static void PrintProgram(Program program, string path = null) { var ttw = path == null ? new TokenTextWriter(Console.Out, true) : new TokenTextWriter(path, true); program.Emit(ttw); ttw.Close(); // re-read to see there are no parse errors Program writtenProgram; if (path != null && !ParseProgram(path, out writtenProgram)) ErrorAndDie($"Created program {path} with parse errors."); }
/// <summary> /// Writes the program to a temp file. /// </summary> /// <param name="filePath">The file path.</param> /// <param name="program">The program.</param> /// <returns>The temp file path.</returns> public static string WriteFile(string filePath, Microsoft.Boogie.Program program) { string tempFile = filePath.Replace(".cbpl", ".temp.cbpl"); if (File.Exists(tempFile)) { File.Delete(tempFile); } using (TokenTextWriter writer = new TokenTextWriter(tempFile, true)) program.Emit(writer); return(tempFile); }
/// <summary> /// Deep clone the program. /// </summary> private static Program DeepCloneProgram(Program program) { var oldPrintInstrumented = DafnyOptions.O.PrintInstrumented; var oldPrintFile = DafnyOptions.O.PrintFile; DafnyOptions.O.PrintInstrumented = true; DafnyOptions.O.PrintFile = "-"; var textRepresentation = Utils.CaptureConsoleOutput( () => program.Emit(new TokenTextWriter(Console.Out))); Microsoft.Boogie.Parser.Parse(textRepresentation, "", out var copy); DafnyOptions.O.PrintInstrumented = oldPrintInstrumented; DafnyOptions.O.PrintFile = oldPrintFile; return(copy); }
public static void PrintBplFile(string filename, Program program, bool allowPrintDesugaring, bool setTokens = true, bool pretty = false) { Contract.Requires(program != null); Contract.Requires(filename != null); bool oldPrintDesugaring = CommandLineOptions.Clo.PrintDesugarings; if (!allowPrintDesugaring) { CommandLineOptions.Clo.PrintDesugarings = false; } using (TokenTextWriter writer = filename == "-" ? new TokenTextWriter("<console>", Console.Out, setTokens, pretty) : new TokenTextWriter(filename, setTokens, pretty)) { if (CommandLineOptions.Clo.ShowEnv != CommandLineOptions.ShowEnvironment.Never) { writer.WriteLine("// " + CommandLineOptions.Clo.Version); writer.WriteLine("// " + CommandLineOptions.Clo.Environment); } writer.WriteLine(); program.Emit(writer); } CommandLineOptions.Clo.PrintDesugarings = oldPrintDesugaring; }
/// <summary> /// Given a resolved and type checked Boogie program, infers invariants for the program /// and then attempts to verify it. Returns: /// - Done if command line specified no verification /// - FatalError if a fatal error occurred, in which case an error has been printed to console /// - VerificationCompleted if inference and verification completed, in which the out /// parameters contain meaningful values /// </summary> public static PipelineOutcome InferAndVerify(Program program, PipelineStatistics stats, string programId = null, ErrorReporterDelegate er = null, string requestId = null) { Contract.Requires(program != null); Contract.Requires(stats != null); Contract.Ensures(0 <= Contract.ValueAtReturn(out stats.InconclusiveCount) && 0 <= Contract.ValueAtReturn(out stats.TimeoutCount)); if (requestId == null) { requestId = FreshRequestId(); } var start = DateTime.UtcNow; #region Do some pre-abstract-interpretation preprocessing on the program // Doing lambda expansion before abstract interpretation means that the abstract interpreter // never needs to see any lambda expressions. (On the other hand, if it were useful for it // to see lambdas, then it would be better to more lambda expansion until after infererence.) if (CommandLineOptions.Clo.ExpandLambdas) { LambdaHelper.ExpandLambdas(program); //PrintBplFile ("-", program, true); } #endregion #region Infer invariants using Abstract Interpretation // Always use (at least) intervals, if not specified otherwise (e.g. with the "/noinfer" switch) if (CommandLineOptions.Clo.UseAbstractInterpretation) { if (!CommandLineOptions.Clo.Ai.J_Intervals && !CommandLineOptions.Clo.Ai.J_Trivial) { // use /infer:j as the default CommandLineOptions.Clo.Ai.J_Intervals = true; } } Microsoft.Boogie.AbstractInterpretation.NativeAbstractInterpretation.RunAbstractInterpretation(program); #endregion #region Do some post-abstract-interpretation preprocessing on the program (e.g., loop unrolling) if (CommandLineOptions.Clo.LoopUnrollCount != -1) { program.UnrollLoops(CommandLineOptions.Clo.LoopUnrollCount, CommandLineOptions.Clo.SoundLoopUnrolling); } Dictionary<string, Dictionary<string, Block>> extractLoopMappingInfo = null; if (CommandLineOptions.Clo.ExtractLoops) { extractLoopMappingInfo = program.ExtractLoops(); } if (CommandLineOptions.Clo.PrintInstrumented) { program.Emit(new TokenTextWriter(Console.Out, CommandLineOptions.Clo.PrettyPrint)); } #endregion if (!CommandLineOptions.Clo.Verify) { return PipelineOutcome.Done; } #region Run Houdini and verify if (CommandLineOptions.Clo.ContractInfer) { return RunHoudini(program, stats, er); } #endregion #region Select and prioritize implementations that should be verified var impls = program.Implementations.Where( impl => impl != null && CommandLineOptions.Clo.UserWantsToCheckRoutine(cce.NonNull(impl.Name)) && !impl.SkipVerification); // operate on a stable copy, in case it gets updated while we're running Implementation[] stablePrioritizedImpls = null; if (0 < CommandLineOptions.Clo.VerifySnapshots) { OtherDefinitionAxiomsCollector.Collect(program.Axioms); DependencyCollector.Collect(program); stablePrioritizedImpls = impls.OrderByDescending( impl => impl.Priority != 1 ? impl.Priority : Cache.VerificationPriority(impl)).ToArray(); } else { stablePrioritizedImpls = impls.OrderByDescending(impl => impl.Priority).ToArray(); } #endregion if (1 < CommandLineOptions.Clo.VerifySnapshots) { CachedVerificationResultInjector.Inject(program, stablePrioritizedImpls, requestId, programId, out stats.CachingActionCounts); } #region Verify each implementation var outputCollector = new OutputCollector(stablePrioritizedImpls); var outcome = PipelineOutcome.VerificationCompleted; try { var cts = new CancellationTokenSource(); RequestIdToCancellationTokenSource.AddOrUpdate(requestId, cts, (k, ov) => cts); var tasks = new Task[stablePrioritizedImpls.Length]; // We use this semaphore to limit the number of tasks that are currently executing. var semaphore = new SemaphoreSlim(CommandLineOptions.Clo.VcsCores); // Create a task per implementation. for (int i = 0; i < stablePrioritizedImpls.Length; i++) { var taskIndex = i; var id = stablePrioritizedImpls[taskIndex].Id; CancellationTokenSource old; if (ImplIdToCancellationTokenSource.TryGetValue(id, out old)) { old.Cancel(); } ImplIdToCancellationTokenSource.AddOrUpdate(id, cts, (k, ov) => cts); var t = new Task((dummy) => { try { if (outcome == PipelineOutcome.FatalError) { return; } if (cts.Token.IsCancellationRequested) { cts.Token.ThrowIfCancellationRequested(); } VerifyImplementation(program, stats, er, requestId, extractLoopMappingInfo, stablePrioritizedImpls, taskIndex, outputCollector, Checkers, programId); ImplIdToCancellationTokenSource.TryRemove(id, out old); } finally { semaphore.Release(); } }, cts.Token, TaskCreationOptions.None); tasks[taskIndex] = t; } // Execute the tasks. int j = 0; for (; j < stablePrioritizedImpls.Length && outcome != PipelineOutcome.FatalError; j++) { try { semaphore.Wait(cts.Token); } catch (OperationCanceledException) { break; } tasks[j].Start(TaskScheduler.Default); } // Don't wait for tasks that haven't been started yet. tasks = tasks.Take(j).ToArray(); Task.WaitAll(tasks); } catch (AggregateException ae) { ae.Handle(e => { var pe = e as ProverException; if (pe != null) { printer.ErrorWriteLine(Console.Out, "Fatal Error: ProverException: {0}", e); outcome = PipelineOutcome.FatalError; return true; } var oce = e as OperationCanceledException; if (oce != null) { return true; } return false; }); } finally { CleanupCheckers(requestId); } cce.NonNull(CommandLineOptions.Clo.TheProverFactory).Close(); outputCollector.WriteMoreOutput(); if (1 < CommandLineOptions.Clo.VerifySnapshots && programId != null) { program.FreezeTopLevelDeclarations(); programCache.Set(programId, program, policy); } if (0 <= CommandLineOptions.Clo.VerifySnapshots && CommandLineOptions.Clo.TraceCachingForBenchmarking) { var end = DateTime.UtcNow; if (TimePerRequest.Count == 0) { FirstRequestStart = start; } TimePerRequest[requestId] = end.Subtract(start); StatisticsPerRequest[requestId] = stats; var printTimes = true; Console.Out.WriteLine(CachedVerificationResultInjector.Statistics.Output(printTimes)); Console.Out.WriteLine("Statistics per request as CSV:"); var actions = string.Join(", ", Enum.GetNames(typeof(VC.ConditionGeneration.CachingAction))); Console.Out.WriteLine("Request ID{0}, Error, E (C), Inconclusive, I (C), Out of Memory, OoM (C), Timeout, T (C), Verified, V (C), {1}", printTimes ? ", Time (ms)" : "", actions); foreach (var kv in TimePerRequest.OrderBy(kv => ExecutionEngine.AutoRequestId(kv.Key))) { var s = StatisticsPerRequest[kv.Key]; var cacs = s.CachingActionCounts; var c = cacs != null ? ", " + cacs.Select(ac => string.Format("{0,3}", ac)).Concat(", ") : ""; var t = printTimes ? string.Format(", {0,8:F0}", kv.Value.TotalMilliseconds) : ""; Console.Out.WriteLine("{0,-19}{1}, {2,2}, {3,2}, {4,2}, {5,2}, {6,2}, {7,2}, {8,2}, {9,2}, {10,2}, {11,2}{12}", kv.Key, t, s.ErrorCount, s.CachedErrorCount, s.InconclusiveCount, s.CachedInconclusiveCount, s.OutOfMemoryCount, s.CachedOutOfMemoryCount, s.TimeoutCount, s.CachedTimeoutCount, s.VerifiedCount, s.CachedVerifiedCount, c); } if (printTimes) { Console.Out.WriteLine(); Console.Out.WriteLine("Total time (ms) since first request: {0:F0}", end.Subtract(FirstRequestStart).TotalMilliseconds); } } #endregion if (SecureVCGen.outfile != null) SecureVCGen.outfile.Close(); return outcome; }
/// <summary> /// The entry point of the program. /// </summary> /// <param name="args">The command line arguments.</param> public static void Main(string[] args) { int?statusCode = null; try { // standard command line options for Boogie CommandLineOptions.Install(new GRCommandLineOptions()); if (!CommandLineOptions.Clo.Parse(args)) { return; } CommandLineOptions.Clo.PrintUnstructured = 2; CommandLineOptions.Clo.DoModSetAnalysis = true; CommandLineOptions.Clo.PruneInfeasibleEdges = true; if (!CommandLineOptions.Clo.Files.Any()) { throw new Exception("An input file must be provided!"); } else if (CommandLineOptions.Clo.Files.Count > 1) { throw new Exception("GPURepair can work on only one file at a time!"); } Logger.FileName = CommandLineOptions.Clo.Files.First(); Logger.DetailedLogging = ((GRCommandLineOptions)CommandLineOptions.Clo).DetailedLogging; ClauseLogger.FileName = CommandLineOptions.Clo.Files.First(); ClauseLogger.LogCLauses = ((GRCommandLineOptions)CommandLineOptions.Clo).LogClauses; Barrier.LoopDepthWeight = ((GRCommandLineOptions)CommandLineOptions.Clo).LoopDepthWeight; Barrier.GridBarrierWeight = ((GRCommandLineOptions)CommandLineOptions.Clo).GridBarrierWeight; Dictionary <string, bool> assignments; // repair the program Solver.SolverType solverType = ((GRCommandLineOptions)CommandLineOptions.Clo).SolverType; bool disableInspection = ((GRCommandLineOptions)CommandLineOptions.Clo).DisableInspection; bool useAxioms = ((GRCommandLineOptions)CommandLineOptions.Clo).UseAxioms; Repairer repairer = new Repairer(Logger.FileName, disableInspection, useAxioms); Microsoft.Boogie.Program program = repairer.Repair(solverType, out assignments); SummaryGenerator generator = new SummaryGenerator(); IEnumerable <string> changes = generator.GenerateSummary(assignments, Logger.FileName.Replace(".cbpl", ".summary")); Logger.Log($"Changes;{changes.Count()}"); Console.WriteLine("Number of changes required: {0}.", changes.Count()); if (changes.Any()) { using (TokenTextWriter writer = new TokenTextWriter(Logger.FileName.Replace(".cbpl", ".fixed.cbpl"), true)) program.Emit(writer); } } catch (Exception ex) { Logger.Log($"ExceptionMessage;{ex.Message}"); Console.Error.WriteLine(ex.Message); if (ex is AssertionException) { statusCode = 201; } else if (ex is RepairException) { statusCode = 202; } else if (ex is NonBarrierException) { statusCode = 203; } else if (ex is SummaryGeneratorException) { statusCode = 204; } } if (statusCode != null) { Environment.Exit(statusCode.Value); } }
/// <summary> /// Given a resolved and type checked Boogie program, infers invariants for the program /// and then attempts to verify it. Returns: /// - Done if command line specified no verification /// - FatalError if a fatal error occurred, in which case an error has been printed to console /// - VerificationCompleted if inference and verification completed, in which the out /// parameters contain meaningful values /// </summary> public static PipelineOutcome InferAndVerify(Program program, PipelineStatistics stats, string filename, ErrorReporterDelegate er = null, string requestId = "unknown") { Contract.Requires(program != null); Contract.Requires(stats != null); Contract.Ensures(0 <= Contract.ValueAtReturn(out stats.InconclusiveCount) && 0 <= Contract.ValueAtReturn(out stats.TimeoutCount)); if (requestId == null) { requestId = "unknown"; } RequestIdToCancellationTokenSources[requestId] = new List<CancellationTokenSource>(); #region Infer invariants using Abstract Interpretation // Always use (at least) intervals, if not specified otherwise (e.g. with the "/noinfer" switch) if (CommandLineOptions.Clo.UseAbstractInterpretation) { if (!CommandLineOptions.Clo.Ai.J_Intervals && !CommandLineOptions.Clo.Ai.J_Trivial) { // use /infer:j as the default CommandLineOptions.Clo.Ai.J_Intervals = true; } } Microsoft.Boogie.AbstractInterpretation.NativeAbstractInterpretation.RunAbstractInterpretation(program); #endregion #region Do some preprocessing on the program (e.g., loop unrolling, lambda expansion) if (CommandLineOptions.Clo.LoopUnrollCount != -1) { program.UnrollLoops(CommandLineOptions.Clo.LoopUnrollCount, CommandLineOptions.Clo.SoundLoopUnrolling); } Dictionary<string, Dictionary<string, Block>> extractLoopMappingInfo = null; if (CommandLineOptions.Clo.ExtractLoops) { extractLoopMappingInfo = program.ExtractLoops(); } if (CommandLineOptions.Clo.PrintInstrumented) { program.Emit(new TokenTextWriter(Console.Out)); } if (CommandLineOptions.Clo.ExpandLambdas) { LambdaHelper.ExpandLambdas(program); //PrintBplFile ("-", program, true); } #endregion if (!CommandLineOptions.Clo.Verify) { return PipelineOutcome.Done; } #region Run Houdini and verify if (CommandLineOptions.Clo.ContractInfer) { return RunHoudini(program, stats, er, filename); } #endregion #region Select and prioritize implementations that should be verified var impls = program.TopLevelDeclarations.OfType<Implementation>().Where( impl => impl != null && CommandLineOptions.Clo.UserWantsToCheckRoutine(cce.NonNull(impl.Name)) && !impl.SkipVerification); // operate on a stable copy, in case it gets updated while we're running Implementation[] stablePrioritizedImpls = null; if (CommandLineOptions.Clo.VerifySnapshots) { impls.Iter(impl => { impl.DependenciesChecksum = DependencyCollector.DependenciesChecksum(impl); }); stablePrioritizedImpls = impls.OrderByDescending( impl => impl.Priority != 1 ? impl.Priority : Cache.VerificationPriority(impl)).ToArray(); } else { stablePrioritizedImpls = impls.OrderByDescending(impl => impl.Priority).ToArray(); } #endregion #region Verify each implementation var outputCollector = new OutputCollector(stablePrioritizedImpls); var outcome = PipelineOutcome.VerificationCompleted; var tasks = new Task[stablePrioritizedImpls.Length]; for (int i = 0; i < stablePrioritizedImpls.Length && outcome != PipelineOutcome.FatalError; i++) { var taskIndex = i; var id = stablePrioritizedImpls[i].Id; CancellationTokenSource src; if (ImplIdToCancellationTokenSource.TryGetValue(id, out src)) { src.Cancel(); } src = new CancellationTokenSource(); RequestIdToCancellationTokenSources[requestId].Add(src); ImplIdToCancellationTokenSource[id] = src; var t = Task.Factory.StartNew((dummy) => { VerifyImplementation(program, stats, er, requestId, extractLoopMappingInfo, stablePrioritizedImpls, taskIndex, outputCollector, Checkers, src.Token); ImplIdToCancellationTokenSource.Remove(id); }, src.Token, TaskCreationOptions.LongRunning); tasks[taskIndex] = t; } try { Task.WaitAll(tasks); } catch (AggregateException ae) { ae.Handle(e => { var pe = e as ProverException; if (pe != null) { printer.ErrorWriteLine(Console.Out, "Fatal Error: ProverException: {0}", e); outcome = PipelineOutcome.FatalError; return true; } var oce = e as OperationCanceledException; if (oce != null) { return true; } return false; }); } finally { CleanupCheckers(requestId); } cce.NonNull(CommandLineOptions.Clo.TheProverFactory).Close(); outputCollector.WriteMoreOutput(); #endregion return outcome; }