2 // Analysis.ConstantEvaluator.cs
5 // Alexander Chebaturkin (chebaturkin@gmail.com)
7 // Copyright (C) 2012 Alexander Chebaturkin
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using Mono.CodeContracts.Static.AST;
32 using Mono.CodeContracts.Static.ControlFlow;
33 using Mono.CodeContracts.Static.DataStructures;
34 using Mono.CodeContracts.Static.Lattices;
35 using Mono.CodeContracts.Static.Providers;
36 using Mono.CodeContracts.Static.Proving;
38 namespace Mono.CodeContracts.Static.Analysis.Numerical {
39 static partial class AnalysisFacade {
40 static partial class Bind<TVar, TExpr>
41 where TExpr : IEquatable<TExpr>
42 where TVar : IEquatable<TVar> {
43 class ConstantEvaluator {
44 readonly IExpressionContextProvider<TExpr, TVar> context_provider;
45 readonly IMetaDataProvider meta_data_provider;
47 public ConstantEvaluator (IExpressionContextProvider<TExpr, TVar> contextProvider,
48 IMetaDataProvider metaDataProvider)
50 context_provider = contextProvider;
51 meta_data_provider = metaDataProvider;
54 public bool TryEvaluateToConstant (APC pc, TVar dest, BinaryOperator op,
55 BoxedExpression left, BoxedExpression right,
59 context_provider.ValueContext.GetType (
60 context_provider.MethodContext.CFG.Post (pc), dest);
64 if (type.IsNormal () && TryEvaluateToConstant (pc, left, out l) &&
65 TryEvaluateToConstant (pc, right, out r))
66 return TryEvaluate (type.Value, op, l, r, out value);
68 return false.Without (out value);
71 bool TryEvaluate (TypeNode type, BinaryOperator op, long l, long r, out long value)
73 if (TryEvaluateIndependent (op, l, r, out value))
76 if (meta_data_provider.System_Int32.Equals (type))
77 return TryEvaluateInt32 (op, (int) l, (int) r, out value);
79 return false.Without (out value);
82 static bool TryEvaluateInt32 (BinaryOperator op, int l, int r, out long value)
85 if (EvaluateArithmeticWithOverflow.TryBinary (op.ToExpressionOperator (), l, r,
87 return true.With (result, out value);
89 return false.Without (out value);
92 bool TryEvaluateIndependent (BinaryOperator op, long l, long r, out long result)
95 case BinaryOperator.And:
96 return true.With (l & r, out result);
97 case BinaryOperator.Ceq:
98 return true.With (ToInt (l == r), out result);
99 case BinaryOperator.Cne_Un:
100 return true.With (ToInt (l != r), out result);
101 case BinaryOperator.Cge:
102 return true.With (ToInt (l >= r), out result);
103 case BinaryOperator.Cgt:
104 return true.With (ToInt (l > r), out result);
105 case BinaryOperator.Cle:
106 return true.With (ToInt (l <= r), out result);
107 case BinaryOperator.Clt:
108 return true.With (ToInt (l < r), out result);
109 case BinaryOperator.LogicalAnd:
110 return true.With (ToInt (l != 0 && r != 0), out result);
111 case BinaryOperator.LogicalOr:
112 return true.With (ToInt (l != 0 || r != 0), out result);
113 case BinaryOperator.Or:
114 return true.With (l | r, out result);
115 case BinaryOperator.Xor:
116 return true.With (l ^ r, out result);
118 return false.Without (out result);
122 static long ToInt (bool value)
124 return value ? 1 : 0;
127 static bool TryEvaluateToConstant (APC pc, BoxedExpression e, out long result)
130 if (e.IsConstantIntOrNull (out res))
131 return true.With (res, out result);
134 if (e.IsUnary && TryEvaluateToConstant (pc, e.UnaryArgument, out argValue)) {
135 switch (e.UnaryOperator) {
136 case UnaryOperator.Neg:
137 return true.With (-argValue, out result);
138 case UnaryOperator.Not:
139 return true.With (argValue != 0 ? 0L : 1L, out result);
141 throw new ArgumentOutOfRangeException ();
145 return false.Without (out result);