// // Analysis.GenericValueAnalysis.cs // // Authors: // Alexander Chebaturkin (chebaturkin@gmail.com) // // Copyright (C) 2012 Alexander Chebaturkin // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using System.IO; using Mono.CodeContracts.Static.AST; using Mono.CodeContracts.Static.AST.Visitors; using Mono.CodeContracts.Static.Analysis.Drivers; using Mono.CodeContracts.Static.ControlFlow; using Mono.CodeContracts.Static.DataFlowAnalysis; using Mono.CodeContracts.Static.DataStructures; using Mono.CodeContracts.Static.Lattices; using Mono.CodeContracts.Static.Providers; using Mono.CodeContracts.Static.Proving; namespace Mono.CodeContracts.Static.Analysis.Numerical { static partial class AnalysisFacade { static partial class Bind where TExpr : IEquatable where TVar : IEquatable { abstract class GenericValueAnalysis : ILVisitorBase, IAbstractAnalysis, IMethodResult where TDomain : IEnvironmentDomain, BoxedExpression> { readonly IMethodDriver method_driver; //readonly string method_name; protected ConstantEvaluator EvaluatorOfConstants; protected IFixPointInfo FixPointInfo; BoxedExpressionDecoder expression_decoder; protected GenericValueAnalysis (string methodName, IMethodDriver methodDriver) { ThresholdDB.Reset (); BoxedVariable.ResetFreshVariableCounter (); // method_name = methodName; method_driver = methodDriver; EvaluatorOfConstants = new ConstantEvaluator (ContextProvider, MetaDataProvider); } protected IExpressionContextProvider ContextProvider { get { return method_driver.ContextProvider; } } protected IMetaDataProvider MetaDataProvider { get { return method_driver.MetaDataProvider; } } protected BoxedExpressionDecoder ExpressionDecoder { get { if (expression_decoder == null) expression_decoder = new BoxedExpressionDecoder ( new ValueExpressionDecoder ( MetaDataProvider, ContextProvider)); return expression_decoder; } } public IILVisitor GetVisitor () { return this; } public TDomain Join (Pair edge, TDomain newstate, TDomain prevstate, out bool weaker, bool widen) { TDomain result; if (!widen) { result = Join (newstate, prevstate, edge); weaker = true; } else { result = Widen (newstate, prevstate, edge); weaker = !result.LessEqual (prevstate); } return result; } public TDomain ImmutableVersion (TDomain arg) { return arg; } public TDomain MutableVersion (TDomain arg) { return arg.Clone (); } public virtual TDomain EdgeConversion (APC @from, APC to, bool isJoinPoint, IImmutableMap> sourceTargetMap, TDomain state) { return state; } public bool IsBottom (APC pc, TDomain state) { return state.IsBottom; } public Predicate SaveFixPointInfo (IFixPointInfo fixPointInfo) { FixPointInfo = fixPointInfo; return a => false; } public void Dump (Pair pair) { pair.Value.WriteLine (pair.Key.ToString ()); } public abstract TDomain TopValue (); public TDomain BottomValue () { return TopValue ().Bottom; } public abstract IFactQuery FactQuery ( IFixPointInfo fixpoint); IFactQuery IMethodAnalysisFixPoint.FactQuery { get { return FactQuery (FixPointInfo); } } public FlatDomain ValidateExplicitAssertion (APC pc, TVar value) { return FlatDomain.TopValue; } public IMethodAnalysis MethodAnalysis { get; set; } public void ValidateImplicitAssertions (IFactQuery facts, List proofResults) { } protected virtual TDomain Widen (TDomain newState, TDomain prevState, Pair edge) { return newState.Widen (prevState); } protected virtual TDomain Join (TDomain newState, TDomain prevState, Pair edge) { return newState.Join (prevState); } public override TDomain Assume (APC pc, EdgeTag tag, TVar condition, TDomain data) { var boxed = ToBoxedExpression (pc, condition); if (tag != EdgeTag.False) { bool value; if (boxed.IsTrivialCondition (out value)) return !value ? data.Bottom : data; } List thresholds; if (ThresholdDB.TryGetAThreshold (boxed, expression_decoder, out thresholds)) ThresholdDB.Add (thresholds); TDomain result; switch (tag) { case EdgeTag.True: case EdgeTag.Requires: case EdgeTag.Assume: case EdgeTag.Invariant: result = data.AssumeTrue (boxed); break; case EdgeTag.False: result = data.AssumeFalse (boxed); break; default: result = data; break; } if (tag != EdgeTag.False) { var abstractType = ContextProvider.ValueContext.GetType ( ContextProvider.MethodContext.CFG.Post (pc), condition); if (abstractType.IsNormal () && MetaDataProvider.Equal (abstractType.Value, MetaDataProvider.System_Boolean)) { var guard = BoxedExpression.Binary (BinaryOperator.Ceq, boxed, BoxedExpression.Const (1, MetaDataProvider . System_Int32)); result = result.AssumeTrue (guard); } } return result; } public override TDomain Assert (APC pc, EdgeTag tag, TVar condition, TDomain data) { var boxed = ToBoxedExpression (pc, condition); bool result; if (boxed.IsTrivialCondition (out result)) return result ? data : data.Bottom; data = data.AssumeTrue (boxed); var type = ContextProvider.ValueContext.GetType ( ContextProvider.MethodContext.CFG.Post (pc), condition); if (type.IsNormal () && MetaDataProvider.Equal (type.Value, MetaDataProvider.System_Boolean)) { var guard = BoxedExpression.Binary (BinaryOperator.Ceq, boxed, BoxedExpression.Const (1, MetaDataProvider. System_Int32)); data = data.AssumeTrue (guard); } return data; } public override TDomain DefaultVisit (APC pc, TDomain data) { return data; } protected BoxedExpression ToBoxedExpression (APC pc, TVar condition) { return BoxedExpression.For ( ContextProvider.ExpressionContext.Refine (pc, condition), ExpressionDecoder.ExternalDecoder); } public IFactQuery FactQuery () { return FactQuery (FixPointInfo); } } } } }