1 // 2 // BlockStartGatherer.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 Mono.CodeContracts.Static.AST; 30 using Mono.CodeContracts.Static.AST.Visitors; 31 using Mono.CodeContracts.Static.DataStructures; 32 using Mono.CodeContracts.Static.Providers; 33 34 namespace Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders { 35 class BlockStartGatherer<Label> : ILVisitorBase<Label, Dummy, Dummy, Dummy, bool>, 36 IAggregateVisitor<Label, Dummy, bool> { 37 private readonly SubroutineBuilder<Label> parent; 38 BlockStartGatherer(SubroutineBuilder<Label> parent)39 public BlockStartGatherer (SubroutineBuilder<Label> parent) 40 { 41 this.parent = parent; 42 } 43 44 #region IAggregateVisitor<Label,Dummy,bool> Members Branch(Label pc, Label target, bool leavesExceptionBlock, Dummy data)45 public override bool Branch (Label pc, Label target, bool leavesExceptionBlock, Dummy data) 46 { 47 AddTargetLabel (target); 48 return true; 49 } 50 BranchCond(Label pc, Label target, BranchOperator bop, Dummy value1, Dummy value2, Dummy data)51 public override bool BranchCond (Label pc, Label target, BranchOperator bop, Dummy value1, Dummy value2, Dummy data) 52 { 53 AddTargetLabel (target); 54 return true; 55 } 56 BranchFalse(Label pc, Label target, Dummy cond, Dummy data)57 public override bool BranchFalse (Label pc, Label target, Dummy cond, Dummy data) 58 { 59 AddTargetLabel (target); 60 return true; 61 } 62 BranchTrue(Label pc, Label target, Dummy cond, Dummy data)63 public override bool BranchTrue (Label pc, Label target, Dummy cond, Dummy data) 64 { 65 AddTargetLabel (target); 66 return true; 67 } 68 EndFinally(Label pc, Dummy data)69 public override bool EndFinally (Label pc, Dummy data) 70 { 71 return true; 72 } 73 Return(Label pc, Dummy source, Dummy data)74 public override bool Return (Label pc, Dummy source, Dummy data) 75 { 76 return true; 77 } 78 Rethrow(Label pc, Dummy data)79 public override bool Rethrow (Label pc, Dummy data) 80 { 81 return true; 82 } 83 Throw(Label pc, Dummy exception, Dummy data)84 public override bool Throw (Label pc, Dummy exception, Dummy data) 85 { 86 return true; 87 } 88 Call(Label pc, Method method, bool virt, TypeList extraVarargs, Dummy dest, ArgList args, Dummy data)89 public override bool Call<TypeList, ArgList> (Label pc, Method method, bool virt, TypeList extraVarargs, Dummy dest, ArgList args, Dummy data) 90 { 91 return CallHelper (pc, method, false, virt); 92 } 93 ConstrainedCallvirt(Label pc, Method method, TypeNode constraint, TypeList extraVarargs, Dummy dest, ArgList args, Dummy data)94 public override bool ConstrainedCallvirt<TypeList, ArgList> (Label pc, Method method, TypeNode constraint, TypeList extraVarargs, Dummy dest, ArgList args, Dummy data) 95 { 96 return CallHelper (pc, method, false, true); 97 } 98 NewObj(Label pc, Method ctor, Dummy dest, ArgList args, Dummy data)99 public override bool NewObj<ArgList> (Label pc, Method ctor, Dummy dest, ArgList args, Dummy data) 100 { 101 return CallHelper (pc, ctor, true, false); 102 } 103 BeginOld(Label pc, Label matchingEnd, Dummy data)104 public override bool BeginOld (Label pc, Label matchingEnd, Dummy data) 105 { 106 AddTargetLabel (pc); 107 this.parent.BeginOldHook (pc); 108 return false; 109 } 110 EndOld(Label pc, Label matchingBegin, TypeNode type, Dummy dest, Dummy source, Dummy data)111 public override bool EndOld (Label pc, Label matchingBegin, TypeNode type, Dummy dest, Dummy source, Dummy data) 112 { 113 this.parent.EndOldHook (pc); 114 return true; 115 } 116 Aggregate(Label pc, Label aggregateStart, bool canBeTargetOfBranch, Dummy data)117 public bool Aggregate (Label pc, Label aggregateStart, bool canBeTargetOfBranch, Dummy data) 118 { 119 return TraceAggregateSequentally (aggregateStart); 120 } 121 #endregion 122 DefaultVisit(Label pc, Dummy data)123 public override bool DefaultVisit (Label pc, Dummy data) 124 { 125 return false; 126 } 127 CallHelper(Label pc, Method method, bool isNewObj, bool isVirtual)128 private bool CallHelper (Label pc, Method method, bool isNewObj, bool isVirtual) 129 { 130 AddBlockStart (pc); 131 if (isNewObj) 132 this.parent.AddNewObjSite (pc, method); 133 else 134 this.parent.AddMethodCallSite (pc, new Pair<Method, bool> (method, isVirtual)); 135 136 return true; 137 } 138 TraceAggregateSequentally(Label current)139 public bool TraceAggregateSequentally (Label current) 140 { 141 bool isCurrentBranches; 142 bool isCurrentHasSuccessor; 143 do { 144 ICodeProvider<Label> codeProvider = this.parent.CodeProvider; 145 isCurrentBranches = codeProvider.Decode<BlockStartGatherer<Label>, Dummy, bool> (current, this, Dummy.Value); 146 isCurrentHasSuccessor = codeProvider.Next (current, out current); 147 if (isCurrentBranches && isCurrentHasSuccessor) 148 AddBlockStart (current); 149 } while (isCurrentHasSuccessor); 150 151 return isCurrentBranches; 152 } 153 AddBlockStart(Label target)154 private void AddBlockStart (Label target) 155 { 156 this.parent.AddBlockStart (target); 157 } 158 AddTargetLabel(Label target)159 private void AddTargetLabel (Label target) 160 { 161 this.parent.AddTargetLabel (target); 162 } 163 } 164 } 165