1 //
2 // ValueExpressionDecoder.cs
3 //
4 // Authors:
5 //	Alexander Chebaturkin (chebaturkin@gmail.com)
6 //
7 // Copyright (C) 2012 Alexander Chebaturkin
8 //
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:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
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.
27 //
28 
29 using System;
30 
31 using Mono.CodeContracts.Static.AST;
32 using Mono.CodeContracts.Static.AST.Visitors;
33 using Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding;
34 using Mono.CodeContracts.Static.DataStructures;
35 using Mono.CodeContracts.Static.Lattices;
36 using Mono.CodeContracts.Static.Providers;
37 
38 namespace Mono.CodeContracts.Static.Analysis.Numerical {
39         class ValueExpressionDecoder<TVar, TExpr> : FullExpressionDecoder<TVar, TExpr>, IExpressionDecoder<TVar, TExpr>
40                 where TVar : IEquatable<TVar>
41                 where TExpr : IEquatable<TExpr> {
42                 readonly VisitorForOperatorFor operator_for;
43                 readonly VisitorForTypeOf type_of;
44 
ValueExpressionDecoder(IMetaDataProvider metaDataProvider, IExpressionContextProvider<TExpr, TVar> contextProvider)45                 public ValueExpressionDecoder (IMetaDataProvider metaDataProvider, IExpressionContextProvider<TExpr, TVar> contextProvider)
46                         : base (metaDataProvider, contextProvider)
47                 {
48                         operator_for = new VisitorForOperatorFor ();
49                         type_of = new VisitorForTypeOf ();
50                 }
51 
52                 IExpressionContext<TExpr, TVar> ExpressionContext { get { return ContextProvider.ExpressionContext; } }
53 
54                 #region IExpressionDecoder<TVar,TExpr> Members
55 
OperatorFor(TExpr expr)56                 public ExpressionOperator OperatorFor (TExpr expr)
57                 {
58                         return ExpressionContext.Decode<TExpr, ExpressionOperator, VisitorForOperatorFor> (expr, operator_for, expr);
59                 }
60 
LeftExpressionFor(TExpr expr)61                 public TExpr LeftExpressionFor (TExpr expr)
62                 {
63                         UnaryOperator op;
64                         BinaryOperator bop;
65                         TExpr left;
66                         TExpr right;
67 
68                         if (IsUnaryExpression (expr, out op, out left) || IsBinaryExpression (expr, out bop, out left, out right))
69                                 return left;
70 
71                         throw new InvalidOperationException ();
72                 }
73 
RightExpressionFor(TExpr expr)74                 public TExpr RightExpressionFor (TExpr expr)
75                 {
76                         BinaryOperator bop;
77                         TExpr left;
78                         TExpr right;
79                         if (IsBinaryExpression (expr, out bop, out left, out right))
80                                 return right;
81 
82                         throw new InvalidOperationException ();
83                 }
84 
IsConstant(TExpr expr)85                 public bool IsConstant (TExpr expr)
86                 {
87                         return OperatorFor (expr) == ExpressionOperator.Constant;
88                 }
89 
IsVariable(TExpr expr)90                 public bool IsVariable (TExpr expr)
91                 {
92                         object variable;
93                         return base.IsVariable (expr, out variable);
94                 }
95 
TryValueOf(TExpr e, ExpressionType expectedType, out T result)96                 public bool TryValueOf<T> (TExpr e, ExpressionType expectedType, out T result)
97                 {
98                         object value;
99                         TypeNode actualType;
100                         if (base.IsConstant (e, out value, out actualType)) {
101                                 if (value is T)
102                                         return true.With ((T) value, out result);
103                                 if (value is int && expectedType == ExpressionType.Bool) {
104                                         result = (T) (object) ((int) value != 0);
105                                         return true;
106                                 }
107                         }
108                         return false.Without (out result);
109                 }
110 
TrySizeOf(TExpr expr, out int size)111                 public bool TrySizeOf (TExpr expr, out int size)
112                 {
113                         TypeNode type;
114                         if (VisitorForSizeOf<TVar, TExpr>.IsSizeOf (expr, out type, this)) {
115                                 size = MetaDataProvider.TypeSize (type);
116                                 return size != -1;
117                         }
118 
119                         return false.Without (out size);
120                 }
121 
TypeOf(TExpr expr)122                 public ExpressionType TypeOf (TExpr expr)
123                 {
124                         if (IsConstant (expr))
125                                 return ExpressionContext.Decode<Dummy, ExpressionType, VisitorForTypeOf> (expr, type_of, Dummy.Value);
126 
127                         var abstractType = ExpressionContext.GetType (expr);
128 
129                         if (abstractType.IsNormal ()) {
130                                 var type = abstractType.Value;
131 
132                                 if (MetaDataProvider.IsPrimitive (type)) {
133                                         if (MetaDataProvider.Equal (type, MetaDataProvider.System_Int32))
134                                                 return ExpressionType.Int32;
135                                         if (MetaDataProvider.Equal (type, MetaDataProvider.System_Single))
136                                                 return ExpressionType.Float32;
137                                         if (MetaDataProvider.Equal (type, MetaDataProvider.System_Double))
138                                                 return ExpressionType.Float64;
139                                         if (MetaDataProvider.Equal (type, MetaDataProvider.System_Boolean))
140                                                 return ExpressionType.Bool;
141                                 }
142                         }
143 
144                         return ExpressionType.Unknown;
145                 }
146 
IsConstantInt(TExpr expr, out int value)147                 public bool IsConstantInt (TExpr expr, out int value)
148                 {
149                         TypeNode type;
150                         object objValue;
151                         if (IsConstant (expr, out objValue, out type))
152                                 return true.With ((int) objValue, out value);
153 
154                         return false.Without (out value);
155                 }
156 
NameOf(TVar variable)157                 public string NameOf (TVar variable)
158                 {
159                         return variable.ToString ();
160                 }
161 
IsBinaryExpression(TExpr expr)162                 public bool IsBinaryExpression (TExpr expr)
163                 {
164                         BinaryOperator op;
165                         TExpr left;
166                         TExpr right;
167                         return IsBinaryExpression (expr, out op, out left, out right);
168                 }
169 
170                 #endregion
171 
172                 #region Nested type: VisitorForOperatorFor
173 
174                 class VisitorForOperatorFor : ISymbolicExpressionVisitor<TExpr, TExpr, TVar, TExpr, ExpressionOperator> {
175                         #region ISymbolicExpressionVisitor<TExpr,TExpr,TVar,TExpr,ExpressionOperator> Members
176 
Binary(TExpr pc, BinaryOperator bop, TVar dest, TExpr src1, TExpr src2, TExpr data)177                         public ExpressionOperator Binary (TExpr pc, BinaryOperator bop, TVar dest, TExpr src1, TExpr src2, TExpr data)
178                         {
179                                 switch (bop) {
180                                 case BinaryOperator.Add:
181                                 case BinaryOperator.Add_Ovf:
182                                 case BinaryOperator.Add_Ovf_Un:
183                                         return ExpressionOperator.Add;
184                                 case BinaryOperator.And:
185                                         return ExpressionOperator.And;
186                                 case BinaryOperator.Ceq:
187                                         return ExpressionOperator.Equal;
188                                 case BinaryOperator.Cobjeq:
189                                         return ExpressionOperator.Equal_Obj;
190                                 case BinaryOperator.Cne_Un:
191                                         return ExpressionOperator.NotEqual;
192                                 case BinaryOperator.Cge:
193                                 case BinaryOperator.Cge_Un:
194                                         return ExpressionOperator.GreaterEqualThan;
195                                 case BinaryOperator.Cgt:
196                                 case BinaryOperator.Cgt_Un:
197                                         return ExpressionOperator.GreaterThan;
198                                 case BinaryOperator.Cle:
199                                 case BinaryOperator.Cle_Un:
200                                         return ExpressionOperator.LessEqualThan;
201                                 case BinaryOperator.Clt:
202                                 case BinaryOperator.Clt_Un:
203                                         return ExpressionOperator.LessThan;
204                                 case BinaryOperator.Div:
205                                 case BinaryOperator.Div_Un:
206                                         return ExpressionOperator.Div;
207                                 case BinaryOperator.LogicalAnd:
208                                         return ExpressionOperator.LogicalAnd;
209                                 case BinaryOperator.LogicalOr:
210                                         return ExpressionOperator.LogicalOr;
211                                 case BinaryOperator.Mul:
212                                 case BinaryOperator.Mul_Ovf:
213                                 case BinaryOperator.Mul_Ovf_Un:
214                                         return ExpressionOperator.Mult;
215                                 case BinaryOperator.Or:
216                                         return ExpressionOperator.Or;
217                                 case BinaryOperator.Rem:
218                                 case BinaryOperator.Rem_Un:
219                                         return ExpressionOperator.Mod;
220                                 case BinaryOperator.Sub:
221                                 case BinaryOperator.Sub_Ovf:
222                                 case BinaryOperator.Sub_Ovf_Un:
223                                         return ExpressionOperator.Sub;
224                                 case BinaryOperator.Xor:
225                                         return ExpressionOperator.Xor;
226                                 default:
227                                         return ExpressionOperator.Unknown;
228                                 }
229                         }
230 
Unary(TExpr pc, UnaryOperator uop, bool unsigned, TVar dest, TExpr source, TExpr data)231                         public ExpressionOperator Unary (TExpr pc, UnaryOperator uop, bool unsigned, TVar dest, TExpr source, TExpr data)
232                         {
233                                 switch (uop) {
234                                 case UnaryOperator.Conv_i:
235                                 case UnaryOperator.Conv_i1:
236                                 case UnaryOperator.Conv_i2:
237                                 case UnaryOperator.Conv_i4:
238                                 case UnaryOperator.Conv_i8:
239                                         return ExpressionOperator.ConvertToInt32;
240                                 case UnaryOperator.Neg:
241                                         return ExpressionOperator.Not;
242                                 case UnaryOperator.Not:
243                                         return ExpressionOperator.Not;
244                                 default:
245                                         return ExpressionOperator.Unknown;
246                                 }
247                         }
248 
LoadNull(TExpr pc, TVar dest, TExpr polarity)249                         public ExpressionOperator LoadNull (TExpr pc, TVar dest, TExpr polarity)
250                         {
251                                 return ExpressionOperator.Constant;
252                         }
253 
LoadConst(TExpr pc, TypeNode type, object constant, TVar dest, TExpr data)254                         public ExpressionOperator LoadConst (TExpr pc, TypeNode type, object constant, TVar dest, TExpr data)
255                         {
256                                 return ExpressionOperator.Constant;
257                         }
258 
Sizeof(TExpr pc, TypeNode type, TVar dest, TExpr data)259                         public ExpressionOperator Sizeof (TExpr pc, TypeNode type, TVar dest, TExpr data)
260                         {
261                                 return ExpressionOperator.SizeOf;
262                         }
263 
Isinst(TExpr pc, TypeNode type, TVar dest, TExpr obj, TExpr data)264                         public ExpressionOperator Isinst (TExpr pc, TypeNode type, TVar dest, TExpr obj, TExpr data)
265                         {
266                                 return ExpressionOperator.Unknown;
267                         }
268 
SymbolicConstant(TExpr pc, TVar variable, TExpr data)269                         public ExpressionOperator SymbolicConstant (TExpr pc, TVar variable, TExpr data)
270                         {
271                                 return ExpressionOperator.Variable;
272                         }
273 
274                         #endregion
275                 }
276 
277                 #endregion
278 
279                 #region Nested type: VisitorForTypeOf
280 
281                 class VisitorForTypeOf : ISymbolicExpressionVisitor<TExpr, TExpr, TVar, Dummy, ExpressionType> {
282                         #region ISymbolicExpressionVisitor<TExpr,TExpr,TVar,Dummy,ExpressionType> Members
283 
Binary(TExpr pc, BinaryOperator bop, TVar dest, TExpr src1, TExpr src2, Dummy data)284                         public ExpressionType Binary (TExpr pc, BinaryOperator bop, TVar dest, TExpr src1, TExpr src2, Dummy data)
285                         {
286                                 return ExpressionType.Unknown;
287                         }
288 
Unary(TExpr pc, UnaryOperator uop, bool unsigned, TVar dest, TExpr source, Dummy data)289                         public ExpressionType Unary (TExpr pc, UnaryOperator uop, bool unsigned, TVar dest, TExpr source, Dummy data)
290                         {
291                                 return ExpressionType.Unknown;
292                         }
293 
LoadNull(TExpr pc, TVar dest, Dummy polarity)294                         public ExpressionType LoadNull (TExpr pc, TVar dest, Dummy polarity)
295                         {
296                                 return ExpressionType.Unknown;
297                         }
298 
LoadConst(TExpr pc, TypeNode type, object constant, TVar dest, Dummy data)299                         public ExpressionType LoadConst (TExpr pc, TypeNode type, object constant, TVar dest, Dummy data)
300                         {
301                                 if (constant is int)
302                                         return ExpressionType.Int32;
303                                 if (constant is float)
304                                         return ExpressionType.Float32;
305                                 if (constant is double)
306                                         return ExpressionType.Float64;
307                                 if (constant is bool)
308                                         return ExpressionType.Bool;
309 
310                                 return ExpressionType.Unknown;
311                         }
312 
Sizeof(TExpr pc, TypeNode type, TVar dest, Dummy data)313                         public ExpressionType Sizeof (TExpr pc, TypeNode type, TVar dest, Dummy data)
314                         {
315                                 return ExpressionType.Int32;
316                         }
317 
Isinst(TExpr pc, TypeNode type, TVar dest, TExpr obj, Dummy data)318                         public ExpressionType Isinst (TExpr pc, TypeNode type, TVar dest, TExpr obj, Dummy data)
319                         {
320                                 return ExpressionType.Unknown;
321                         }
322 
SymbolicConstant(TExpr pc, TVar variable, Dummy data)323                         public ExpressionType SymbolicConstant (TExpr pc, TVar variable, Dummy data)
324                         {
325                                 return ExpressionType.Unknown;
326                         }
327 
328                         #endregion
329                 }
330 
331                 #endregion
332         }
333 }