2 // BlockStartGatherer.cs
5 // Alexander Chebaturkin (chebaturkin@gmail.com)
7 // Copyright (C) 2011 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.
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;
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;
39 public BlockStartGatherer (SubroutineBuilder<Label> parent)
44 #region IAggregateVisitor<Label,Dummy,bool> Members
45 public override bool Branch (Label pc, Label target, bool leavesExceptionBlock, Dummy data)
47 AddTargetLabel (target);
51 public override bool BranchCond (Label pc, Label target, BranchOperator bop, Dummy value1, Dummy value2, Dummy data)
53 AddTargetLabel (target);
57 public override bool BranchFalse (Label pc, Label target, Dummy cond, Dummy data)
59 AddTargetLabel (target);
63 public override bool BranchTrue (Label pc, Label target, Dummy cond, Dummy data)
65 AddTargetLabel (target);
69 public override bool EndFinally (Label pc, Dummy data)
74 public override bool Return (Label pc, Dummy source, Dummy data)
79 public override bool Rethrow (Label pc, Dummy data)
84 public override bool Throw (Label pc, Dummy exception, Dummy data)
89 public override bool Call<TypeList, ArgList> (Label pc, Method method, bool virt, TypeList extraVarargs, Dummy dest, ArgList args, Dummy data)
91 return CallHelper (pc, method, false, virt);
94 public override bool ConstrainedCallvirt<TypeList, ArgList> (Label pc, Method method, TypeNode constraint, TypeList extraVarargs, Dummy dest, ArgList args, Dummy data)
96 return CallHelper (pc, method, false, true);
99 public override bool NewObj<ArgList> (Label pc, Method ctor, Dummy dest, ArgList args, Dummy data)
101 return CallHelper (pc, ctor, true, false);
104 public override bool BeginOld (Label pc, Label matchingEnd, Dummy data)
107 this.parent.BeginOldHook (pc);
111 public override bool EndOld (Label pc, Label matchingBegin, TypeNode type, Dummy dest, Dummy source, Dummy data)
113 this.parent.EndOldHook (pc);
117 public bool Aggregate (Label pc, Label aggregateStart, bool canBeTargetOfBranch, Dummy data)
119 return TraceAggregateSequentally (aggregateStart);
123 public override bool DefaultVisit (Label pc, Dummy data)
128 private bool CallHelper (Label pc, Method method, bool isNewObj, bool isVirtual)
132 this.parent.AddNewObjSite (pc, method);
134 this.parent.AddMethodCallSite (pc, new Pair<Method, bool> (method, isVirtual));
139 public bool TraceAggregateSequentally (Label current)
141 bool isCurrentBranches;
142 bool isCurrentHasSuccessor;
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);
151 return isCurrentBranches;
154 private void AddBlockStart (Label target)
156 this.parent.AddBlockStart (target);
159 private void AddTargetLabel (Label target)
161 this.parent.AddTargetLabel (target);