1 // 2 // RemoveBranchDelegator.cs 3 // 4 // Authors: 5 // Alexander Chebaturkin (chebaturkin@gmail.com) 6 // 7 // Copyright (C) 2011 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.Collections.Generic; 30 using Mono.CodeContracts.Static.AST; 31 using Mono.CodeContracts.Static.AST.Visitors; 32 using Mono.CodeContracts.Static.DataStructures; 33 using Mono.CodeContracts.Static.Providers; 34 35 namespace Mono.CodeContracts.Static.ControlFlow { 36 /// <summary> 37 /// This class wraps underlying visitor. 38 /// Replaces: branches to nop; branchCond to binary. 39 /// 40 /// EdgeTag.Requires: (inside method) => assume, (outside method) => assert 41 /// EdgeTag.Ensures: (inside method) => assert, (outside method) => assume 42 /// </summary> 43 struct RemoveBranchDelegator<Data, Result, Visitor> : IILVisitor<APC, Dummy, Dummy, Data, Result> 44 where Visitor : IILVisitor<APC, Dummy, Dummy, Data, Result> { 45 private readonly IMetaDataProvider meta_data_provider; 46 private readonly Visitor visitor; 47 RemoveBranchDelegatorMono.CodeContracts.Static.ControlFlow.RemoveBranchDelegator48 public RemoveBranchDelegator (Visitor visitor, 49 IMetaDataProvider metaDataProvider) 50 { 51 this.visitor = visitor; 52 this.meta_data_provider = metaDataProvider; 53 } 54 55 #region IILVisitor<APC,Dummy,Dummy,Data,Result> Members BinaryMono.CodeContracts.Static.ControlFlow.RemoveBranchDelegator56 public Result Binary (APC pc, BinaryOperator op, Dummy dest, Dummy operand1, Dummy operand2, Data data) 57 { 58 return this.visitor.Binary (pc, op, dest, operand1, operand2, data); 59 } 60 IsinstMono.CodeContracts.Static.ControlFlow.RemoveBranchDelegator61 public Result Isinst (APC pc, TypeNode type, Dummy dest, Dummy obj, Data data) 62 { 63 return this.visitor.Isinst (pc, type, dest, obj, data); 64 } 65 LoadNullMono.CodeContracts.Static.ControlFlow.RemoveBranchDelegator66 public Result LoadNull (APC pc, Dummy dest, Data polarity) 67 { 68 return this.visitor.LoadNull (pc, dest, polarity); 69 } 70 LoadConstMono.CodeContracts.Static.ControlFlow.RemoveBranchDelegator71 public Result LoadConst (APC pc, TypeNode type, object constant, Dummy dest, Data data) 72 { 73 return this.visitor.LoadConst (pc, type, constant, dest, data); 74 } 75 SizeofMono.CodeContracts.Static.ControlFlow.RemoveBranchDelegator76 public Result Sizeof (APC pc, TypeNode type, Dummy dest, Data data) 77 { 78 return this.visitor.Sizeof (pc, type, dest, data); 79 } 80 UnaryMono.CodeContracts.Static.ControlFlow.RemoveBranchDelegator81 public Result Unary (APC pc, UnaryOperator op, bool unsigned, Dummy dest, Dummy source, Data data) 82 { 83 return this.visitor.Unary (pc, op, unsigned, dest, source, data); 84 } 85 EntryMono.CodeContracts.Static.ControlFlow.RemoveBranchDelegator86 public Result Entry (APC pc, Method method, Data data) 87 { 88 return this.visitor.Entry (pc, method, data); 89 } 90 AssumeMono.CodeContracts.Static.ControlFlow.RemoveBranchDelegator91 public Result Assume (APC pc, EdgeTag tag, Dummy condition, Data data) 92 { 93 if (tag == EdgeTag.Requires && pc.InsideRequiresAtCall || tag == EdgeTag.Invariant && pc.InsideInvariantOnExit) 94 return this.visitor.Assert (pc, tag, condition, data); 95 96 return this.visitor.Assume (pc, tag, condition, data); 97 } 98 AssertMono.CodeContracts.Static.ControlFlow.RemoveBranchDelegator99 public Result Assert (APC pc, EdgeTag tag, Dummy condition, Data data) 100 { 101 if (pc.InsideEnsuresAtCall) 102 return this.visitor.Assume (pc, tag, condition, data); 103 104 return this.visitor.Assert (pc, tag, condition, data); 105 } 106 BeginOldMono.CodeContracts.Static.ControlFlow.RemoveBranchDelegator107 public Result BeginOld (APC pc, APC matchingEnd, Data data) 108 { 109 return this.visitor.BeginOld (pc, matchingEnd, data); 110 } 111 EndOldMono.CodeContracts.Static.ControlFlow.RemoveBranchDelegator112 public Result EndOld (APC pc, APC matchingBegin, TypeNode type, Dummy dest, Dummy source, Data data) 113 { 114 return this.visitor.EndOld (pc, matchingBegin, type, dest, source, data); 115 } 116 LoadStackMono.CodeContracts.Static.ControlFlow.RemoveBranchDelegator117 public Result LoadStack (APC pc, int offset, Dummy dest, Dummy source, bool isOld, Data data) 118 { 119 return this.visitor.LoadStack (pc, offset, dest, source, isOld, data); 120 } 121 LoadStackAddressMono.CodeContracts.Static.ControlFlow.RemoveBranchDelegator122 public Result LoadStackAddress (APC pc, int offset, Dummy dest, Dummy source, TypeNode type, bool isOld, Data data) 123 { 124 return this.visitor.LoadStackAddress (pc, offset, dest, source, type, isOld, data); 125 } 126 LoadResultMono.CodeContracts.Static.ControlFlow.RemoveBranchDelegator127 public Result LoadResult (APC pc, TypeNode type, Dummy dest, Dummy source, Data data) 128 { 129 return this.visitor.LoadResult (pc, type, dest, source, data); 130 } 131 ArglistMono.CodeContracts.Static.ControlFlow.RemoveBranchDelegator132 public Result Arglist (APC pc, Dummy dest, Data data) 133 { 134 return this.visitor.Arglist (pc, dest, data); 135 } 136 BranchMono.CodeContracts.Static.ControlFlow.RemoveBranchDelegator137 public Result Branch (APC pc, APC target, bool leavesExceptionBlock, Data data) 138 { 139 return this.visitor.Nop (pc, data); 140 } 141 BranchCondMono.CodeContracts.Static.ControlFlow.RemoveBranchDelegator142 public Result BranchCond (APC pc, APC target, BranchOperator bop, Dummy value1, Dummy value2, Data data) 143 { 144 Dummy dest = Dummy.Value; 145 switch (bop) { 146 case BranchOperator.Beq: 147 return this.visitor.Binary (pc, BinaryOperator.Ceq, dest, value1, value2, data); 148 case BranchOperator.Bge: 149 return this.visitor.Binary (pc, BinaryOperator.Cge, dest, value1, value2, data); 150 case BranchOperator.Bge_Un: 151 return this.visitor.Binary (pc, BinaryOperator.Cge_Un, dest, value1, value2, data); 152 case BranchOperator.Bgt: 153 return this.visitor.Binary (pc, BinaryOperator.Cgt, dest, value1, value2, data); 154 case BranchOperator.Bgt_Un: 155 return this.visitor.Binary (pc, BinaryOperator.Cgt_Un, dest, value1, value2, data); 156 case BranchOperator.Ble: 157 return this.visitor.Binary (pc, BinaryOperator.Cle, dest, value1, value2, data); 158 case BranchOperator.Ble_Un: 159 return this.visitor.Binary (pc, BinaryOperator.Cle_Un, dest, value1, value2, data); 160 case BranchOperator.Blt: 161 return this.visitor.Binary (pc, BinaryOperator.Clt, dest, value1, value2, data); 162 case BranchOperator.Blt_Un: 163 return this.visitor.Binary (pc, BinaryOperator.Clt_Un, dest, value1, value2, data); 164 case BranchOperator.Bne_un: 165 return this.visitor.Binary (pc, BinaryOperator.Cne_Un, dest, value1, value2, data); 166 default: 167 return this.visitor.Nop (pc, data); 168 } 169 } 170 BranchTrueMono.CodeContracts.Static.ControlFlow.RemoveBranchDelegator171 public Result BranchTrue (APC pc, APC target, Dummy cond, Data data) 172 { 173 return this.visitor.Nop (pc, data); 174 } 175 BranchFalseMono.CodeContracts.Static.ControlFlow.RemoveBranchDelegator176 public Result BranchFalse (APC pc, APC target, Dummy cond, Data data) 177 { 178 return this.visitor.Nop (pc, data); 179 } 180 BreakMono.CodeContracts.Static.ControlFlow.RemoveBranchDelegator181 public Result Break (APC pc, Data data) 182 { 183 return this.visitor.Break (pc, data); 184 } 185 186 public Result Call<TypeList, ArgList> (APC pc, Method method, bool virt, TypeList extraVarargs, Dummy dest, ArgList args, Data data) 187 where TypeList : IIndexable<TypeNode> 188 where ArgList : IIndexable<Dummy> 189 { 190 TypeNode declaringType = this.meta_data_provider.DeclaringType (method); 191 if (MethodIsReferenceEquals (method, args, declaringType)) 192 return this.visitor.Binary (pc, BinaryOperator.Ceq, dest, args [0], args [1], data); 193 194 return this.visitor.Call (pc, method, virt, extraVarargs, dest, args, data); 195 } 196 197 public Result Calli<TypeList, ArgList> (APC pc, TypeNode returnType, TypeList argTypes, bool instance, Dummy dest, Dummy functionPointer, ArgList args, Data data) 198 where TypeList : IIndexable<TypeNode> 199 where ArgList : IIndexable<Dummy> 200 { 201 return this.visitor.Calli (pc, returnType, argTypes, instance, dest, functionPointer, args, data); 202 } 203 CheckFinite(APC pc, Dummy dest, Dummy source, Data data)204 public Result CheckFinite (APC pc, Dummy dest, Dummy source, Data data) 205 { 206 return this.visitor.CheckFinite (pc, dest, source, data); 207 } 208 CopyBlock(APC pc, Dummy destAddress, Dummy srcAddress, Dummy len, Data data)209 public Result CopyBlock (APC pc, Dummy destAddress, Dummy srcAddress, Dummy len, Data data) 210 { 211 return this.visitor.CopyBlock (pc, destAddress, srcAddress, len, data); 212 } 213 EndFilter(APC pc, Dummy decision, Data data)214 public Result EndFilter (APC pc, Dummy decision, Data data) 215 { 216 return this.visitor.EndFilter (pc, decision, data); 217 } 218 EndFinally(APC pc, Data data)219 public Result EndFinally (APC pc, Data data) 220 { 221 return this.visitor.EndFinally (pc, data); 222 } 223 Jmp(APC pc, Method method, Data data)224 public Result Jmp (APC pc, Method method, Data data) 225 { 226 return this.visitor.Jmp (pc, method, data); 227 } 228 LoadArg(APC pc, Parameter argument, bool isOld, Dummy dest, Data data)229 public Result LoadArg (APC pc, Parameter argument, bool isOld, Dummy dest, Data data) 230 { 231 return this.visitor.LoadArg (pc, argument, isOld, dest, data); 232 } 233 LoadArgAddress(APC pc, Parameter argument, bool isOld, Dummy dest, Data data)234 public Result LoadArgAddress (APC pc, Parameter argument, bool isOld, Dummy dest, Data data) 235 { 236 return this.visitor.LoadArgAddress (pc, argument, isOld, dest, data); 237 } 238 LoadLocal(APC pc, Local local, Dummy dest, Data data)239 public Result LoadLocal (APC pc, Local local, Dummy dest, Data data) 240 { 241 return this.visitor.LoadLocal (pc, local, dest, data); 242 } 243 LoadLocalAddress(APC pc, Local local, Dummy dest, Data data)244 public Result LoadLocalAddress (APC pc, Local local, Dummy dest, Data data) 245 { 246 return this.visitor.LoadLocalAddress (pc, local, dest, data); 247 } 248 LoadElement(APC pc, TypeNode type, Dummy dest, Dummy array, Dummy index, Data data)249 public Result LoadElement (APC pc, TypeNode type, Dummy dest, Dummy array, Dummy index, Data data) 250 { 251 return this.visitor.LoadElement (pc, type, dest, array, index, data); 252 } 253 LoadField(APC pc, Field field, Dummy dest, Dummy obj, Data data)254 public Result LoadField (APC pc, Field field, Dummy dest, Dummy obj, Data data) 255 { 256 return this.visitor.LoadField (pc, field, dest, obj, data); 257 } 258 LoadFieldAddress(APC pc, Field field, Dummy dest, Dummy obj, Data data)259 public Result LoadFieldAddress (APC pc, Field field, Dummy dest, Dummy obj, Data data) 260 { 261 return this.visitor.LoadFieldAddress (pc, field, dest, obj, data); 262 } 263 LoadLength(APC pc, Dummy dest, Dummy array, Data data)264 public Result LoadLength (APC pc, Dummy dest, Dummy array, Data data) 265 { 266 return this.visitor.LoadLength (pc, dest, array, data); 267 } 268 LoadStaticField(APC pc, Field field, Dummy dest, Data data)269 public Result LoadStaticField (APC pc, Field field, Dummy dest, Data data) 270 { 271 return this.visitor.LoadStaticField (pc, field, dest, data); 272 } 273 LoadStaticFieldAddress(APC pc, Field field, Dummy dest, Data data)274 public Result LoadStaticFieldAddress (APC pc, Field field, Dummy dest, Data data) 275 { 276 return this.visitor.LoadStaticFieldAddress (pc, field, dest, data); 277 } 278 LoadTypeToken(APC pc, TypeNode type, Dummy dest, Data data)279 public Result LoadTypeToken (APC pc, TypeNode type, Dummy dest, Data data) 280 { 281 return this.visitor.LoadTypeToken (pc, type, dest, data); 282 } 283 LoadFieldToken(APC pc, Field type, Dummy dest, Data data)284 public Result LoadFieldToken (APC pc, Field type, Dummy dest, Data data) 285 { 286 return this.visitor.LoadFieldToken (pc, type, dest, data); 287 } 288 LoadMethodToken(APC pc, Method type, Dummy dest, Data data)289 public Result LoadMethodToken (APC pc, Method type, Dummy dest, Data data) 290 { 291 return this.visitor.LoadMethodToken (pc, type, dest, data); 292 } 293 Nop(APC pc, Data data)294 public Result Nop (APC pc, Data data) 295 { 296 return this.visitor.Nop (pc, data); 297 } 298 Pop(APC pc, Dummy source, Data data)299 public Result Pop (APC pc, Dummy source, Data data) 300 { 301 return this.visitor.Pop (pc, source, data); 302 } 303 Return(APC pc, Dummy source, Data data)304 public Result Return (APC pc, Dummy source, Data data) 305 { 306 return this.visitor.Return (pc, source, data); 307 } 308 StoreArg(APC pc, Parameter argument, Dummy source, Data data)309 public Result StoreArg (APC pc, Parameter argument, Dummy source, Data data) 310 { 311 return this.visitor.StoreArg (pc, argument, source, data); 312 } 313 StoreLocal(APC pc, Local local, Dummy source, Data data)314 public Result StoreLocal (APC pc, Local local, Dummy source, Data data) 315 { 316 return this.visitor.StoreLocal (pc, local, source, data); 317 } 318 StoreElement(APC pc, TypeNode type, Dummy array, Dummy index, Dummy value, Data data)319 public Result StoreElement (APC pc, TypeNode type, Dummy array, Dummy index, Dummy value, Data data) 320 { 321 return this.visitor.StoreElement (pc, type, array, index, value, data); 322 } 323 StoreField(APC pc, Field field, Dummy obj, Dummy value, Data data)324 public Result StoreField (APC pc, Field field, Dummy obj, Dummy value, Data data) 325 { 326 return this.visitor.StoreField (pc, field, obj, value, data); 327 } 328 StoreStaticField(APC pc, Field field, Dummy value, Data data)329 public Result StoreStaticField (APC pc, Field field, Dummy value, Data data) 330 { 331 return this.visitor.StoreStaticField (pc, field, value, data); 332 } 333 Switch(APC pc, TypeNode type, IEnumerable<Pair<object, APC>> cases, Dummy value, Data data)334 public Result Switch (APC pc, TypeNode type, IEnumerable<Pair<object, APC>> cases, Dummy value, Data data) 335 { 336 return this.visitor.Nop (pc, data); 337 } 338 Box(APC pc, TypeNode type, Dummy dest, Dummy source, Data data)339 public Result Box (APC pc, TypeNode type, Dummy dest, Dummy source, Data data) 340 { 341 return this.visitor.Box (pc, type, dest, source, data); 342 } 343 344 public Result ConstrainedCallvirt<TypeList, ArgList> (APC pc, Method method, TypeNode constraint, TypeList extraVarargs, Dummy dest, ArgList args, Data data) 345 where TypeList : IIndexable<TypeNode> 346 where ArgList : IIndexable<Dummy> 347 { 348 return this.visitor.ConstrainedCallvirt (pc, method, constraint, extraVarargs, dest, args, data); 349 } 350 CastClass(APC pc, TypeNode type, Dummy dest, Dummy obj, Data data)351 public Result CastClass (APC pc, TypeNode type, Dummy dest, Dummy obj, Data data) 352 { 353 return this.visitor.CastClass (pc, type, dest, obj, data); 354 } 355 CopyObj(APC pc, TypeNode type, Dummy destPtr, Dummy sourcePtr, Data data)356 public Result CopyObj (APC pc, TypeNode type, Dummy destPtr, Dummy sourcePtr, Data data) 357 { 358 return this.visitor.CopyObj (pc, type, destPtr, sourcePtr, data); 359 } 360 Initobj(APC pc, TypeNode type, Dummy ptr, Data data)361 public Result Initobj (APC pc, TypeNode type, Dummy ptr, Data data) 362 { 363 return this.visitor.Initobj (pc, type, ptr, data); 364 } 365 366 public Result NewArray<ArgList> (APC pc, TypeNode type, Dummy dest, ArgList lengths, Data data) where ArgList : IIndexable<Dummy> 367 { 368 return this.visitor.NewArray (pc, type, dest, lengths, data); 369 } 370 371 public Result NewObj<ArgList> (APC pc, Method ctor, Dummy dest, ArgList args, Data data) where ArgList : IIndexable<Dummy> 372 { 373 return this.visitor.NewObj (pc, ctor, dest, args, data); 374 } 375 MkRefAny(APC pc, TypeNode type, Dummy dest, Dummy obj, Data data)376 public Result MkRefAny (APC pc, TypeNode type, Dummy dest, Dummy obj, Data data) 377 { 378 return this.visitor.MkRefAny (pc, type, dest, obj, data); 379 } 380 RefAnyType(APC pc, Dummy dest, Dummy source, Data data)381 public Result RefAnyType (APC pc, Dummy dest, Dummy source, Data data) 382 { 383 return this.visitor.RefAnyType (pc, dest, source, data); 384 } 385 RefAnyVal(APC pc, TypeNode type, Dummy dest, Dummy source, Data data)386 public Result RefAnyVal (APC pc, TypeNode type, Dummy dest, Dummy source, Data data) 387 { 388 return this.visitor.RefAnyVal (pc, type, dest, source, data); 389 } 390 Rethrow(APC pc, Data data)391 public Result Rethrow (APC pc, Data data) 392 { 393 return this.visitor.Rethrow (pc, data); 394 } 395 Throw(APC pc, Dummy exception, Data data)396 public Result Throw (APC pc, Dummy exception, Data data) 397 { 398 return this.visitor.Throw (pc, exception, data); 399 } 400 Unbox(APC pc, TypeNode type, Dummy dest, Dummy obj, Data data)401 public Result Unbox (APC pc, TypeNode type, Dummy dest, Dummy obj, Data data) 402 { 403 return this.visitor.Unbox (pc, type, dest, obj, data); 404 } 405 UnboxAny(APC pc, TypeNode type, Dummy dest, Dummy obj, Data data)406 public Result UnboxAny (APC pc, TypeNode type, Dummy dest, Dummy obj, Data data) 407 { 408 return this.visitor.UnboxAny (pc, type, dest, obj, data); 409 } 410 #endregion 411 412 private bool MethodIsReferenceEquals<ArgList> (Method method, ArgList args, TypeNode declaringType) 413 where ArgList : IIndexable<Dummy> 414 { 415 return args.Count == 2 && this.meta_data_provider.IsStatic (method) 416 && this.meta_data_provider.Equal (declaringType, this.meta_data_provider.System_Object) 417 && this.meta_data_provider.Name (method) == "ReferenceEquals"; 418 } 419 } 420 } 421