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 }