The base architecture for code-contracts analysis
[mono.git] / mcs / class / Mono.CodeContracts / Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders / BlockStartGatherer.cs
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
39                 public BlockStartGatherer (SubroutineBuilder<Label> parent)
40                 {
41                         this.parent = parent;
42                 }
43
44                 #region IAggregateVisitor<Label,Dummy,bool> Members
45                 public override bool Branch (Label pc, Label target, bool leavesExceptionBlock, Dummy data)
46                 {
47                         AddTargetLabel (target);
48                         return true;
49                 }
50
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
57                 public override bool BranchFalse (Label pc, Label target, Dummy cond, Dummy data)
58                 {
59                         AddTargetLabel (target);
60                         return true;
61                 }
62
63                 public override bool BranchTrue (Label pc, Label target, Dummy cond, Dummy data)
64                 {
65                         AddTargetLabel (target);
66                         return true;
67                 }
68
69                 public override bool EndFinally (Label pc, Dummy data)
70                 {
71                         return true;
72                 }
73
74                 public override bool Return (Label pc, Dummy source, Dummy data)
75                 {
76                         return true;
77                 }
78
79                 public override bool Rethrow (Label pc, Dummy data)
80                 {
81                         return true;
82                 }
83
84                 public override bool Throw (Label pc, Dummy exception, Dummy data)
85                 {
86                         return true;
87                 }
88
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
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
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
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
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
117                 public bool Aggregate (Label pc, Label aggregateStart, bool canBeTargetOfBranch, Dummy data)
118                 {
119                         return TraceAggregateSequentally (aggregateStart);
120                 }
121                 #endregion
122
123                 public override bool DefaultVisit (Label pc, Dummy data)
124                 {
125                         return false;
126                 }
127
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
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
154                 private void AddBlockStart (Label target)
155                 {
156                         this.parent.AddBlockStart (target);
157                 }
158
159                 private void AddTargetLabel (Label target)
160                 {
161                         this.parent.AddTargetLabel (target);
162                 }
163         }
164 }