Merge pull request #301 from directhex/master
[mono.git] / mcs / class / Mono.CodeContracts / Mono.CodeContracts.Static.DataFlowAnalysis / ForwardDataFlowAnalysisBase.cs
1 // 
2 // ForwardDataFlowAnalysisBase.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.ControlFlow;
31 using Mono.CodeContracts.Static.DataStructures;
32
33 namespace Mono.CodeContracts.Static.DataFlowAnalysis {
34         abstract class ForwardDataFlowAnalysisBase<AState> : DataFlowAnalysisBase<AState> {
35                 private readonly Dictionary<APC, AState> post_state = new Dictionary<APC, AState> ();
36
37                 protected ForwardDataFlowAnalysisBase (ICFG cfg) : base (cfg)
38                 {
39                 }
40
41                 public bool GetPreState (APC pc, out AState state)
42                 {
43                         bool noInfo;
44                         state = GetPreState (pc, default(AState), out noInfo);
45                         return !noInfo;
46                 }
47
48                 public AState GetPreStateWithDefault (APC apc, AState ifMissing)
49                 {
50                         bool noInfo;
51                         AState preState = GetPreState (apc, default(AState), out noInfo);
52                         return noInfo ? ifMissing : preState;
53                 }
54
55                 private AState GetPreState (APC apc, AState ifMissing, out bool noInfo)
56                 {
57                         LispList<APC> rest = null;
58                         APC tmp = apc;
59                         APC singlePredecessor;
60                         AState state;
61                         bool weHaveState;
62                         while (!(weHaveState = this.JoinState.TryGetValue (tmp, out state)) &&
63                                !RequiresJoining (tmp) && this.CFG.HasSinglePredecessor (tmp, out singlePredecessor)) {
64                                 tmp = singlePredecessor;
65
66                                 rest = rest.Cons (tmp);
67                         }
68
69                         if (!weHaveState) {
70                                 noInfo = true;
71                                 return ifMissing;
72                         }
73
74                         bool listWasNotEmpty = rest != null;
75                         while (rest != null) {
76                                 if (IsBottom (rest.Head, state)) {
77                                         noInfo = false;
78                                         return state;
79                                 }
80                                 state = MutableVersion (state, rest.Head);
81                                 state = Transfer (rest.Head, state);
82                                 if (IsBottom (rest.Head, state)) {
83                                         noInfo = false;
84                                         return state;
85                                 }
86
87                                 rest = rest.Tail;
88                                 if (rest != null)
89                                         this.JoinState.Add (rest.Head, ImmutableVersion (state, rest.Head));
90                         }
91
92                         if (listWasNotEmpty)
93                                 this.JoinState.Add (apc, ImmutableVersion (state, apc));
94
95                         noInfo = false;
96                         return state;
97                 }
98
99                 public bool GetPostState (APC apc, out AState result)
100                 {
101                         if (this.post_state.TryGetValue (apc, out result))
102                                 return true;
103
104                         APC singleSuccessor;
105                         if (apc.Block.Count <= apc.Index)
106                                 return GetPreState (apc, out result);
107
108                         if (this.CFG.HasSingleSuccessor (apc, out singleSuccessor) && !RequiresJoining (singleSuccessor))
109                                 return GetPreState (singleSuccessor, out result);
110
111                         AState ifFound;
112                         if (!GetPreState (apc, out ifFound))
113                                 return false;
114
115                         result = MutableVersion (ifFound, apc);
116                         result = Transfer (apc, result);
117
118                         this.post_state.Add (apc, result);
119                         return true;
120                 }
121
122                 public void Run (AState startState)
123                 {
124                         Initialize (this.CFG.Entry, startState);
125                         ComputeFixPoint ();
126                 }
127
128                 protected override int WorkingListComparer (APC a, APC b)
129                 {
130                         return b.Block.ReversePostOrderIndex - a.Block.ReversePostOrderIndex;
131                 }
132
133                 protected override bool RequiresJoining (APC pc)
134                 {
135                         return this.CFG.IsJoinPoint (pc);
136                 }
137
138                 protected override bool HasSingleSuccessor (APC pc, out APC next)
139                 {
140                         return this.CFG.HasSingleSuccessor (pc, out next);
141                 }
142
143                 protected override IEnumerable<APC> Successors (APC pc)
144                 {
145                         return this.CFG.Successors (pc);
146                 }
147
148                 protected override bool IsBackEdge (APC from, APC to)
149                 {
150                         //todo: implement this
151                         //can't be false, because back edges means having cycles, so we definitely have to widen
152                         return true;
153                 }
154         }
155 }