Exemplo n.º 1
0
        /// <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;
        }
Exemplo n.º 2
0
        /// <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;
        }