Merge pull request #439 from mono-soc-2012/garyb/iconfix
[mono.git] / mcs / class / Mono.CodeContracts / Mono.CodeContracts.Static.Analysis.ExpressionAnalysis / ExpressionDecoder.cs
1 // 
2 // ExpressionDecoder.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;
30 using Mono.CodeContracts.Static.AST;
31 using Mono.CodeContracts.Static.AST.Visitors;
32 using Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Expressions;
33 using Mono.CodeContracts.Static.Analysis.HeapAnalysis;
34 using Mono.CodeContracts.Static.ControlFlow;
35 using Mono.CodeContracts.Static.DataStructures;
36 using Mono.CodeContracts.Static.Lattices;
37 using Mono.CodeContracts.Static.Providers;
38
39 namespace Mono.CodeContracts.Static.Analysis.ExpressionAnalysis {
40         class ExpressionDecoder<TSymbolicValue, TContext, TEdgeData> :
41                 IILDecoder<APC, LabeledSymbol<APC, TSymbolicValue>, TSymbolicValue, IExpressionContextProvider<LabeledSymbol<APC, TSymbolicValue>, TSymbolicValue>, TEdgeData>,
42                 IExpressionContextProvider<LabeledSymbol<APC, TSymbolicValue>, TSymbolicValue>,
43                 IExpressionContext<LabeledSymbol<APC, TSymbolicValue>, TSymbolicValue>
44                 where TSymbolicValue : IEquatable<TSymbolicValue>
45                 where TContext : IValueContextProvider<TSymbolicValue>
46                 where TEdgeData : IImmutableMap<TSymbolicValue, Sequence<TSymbolicValue>> {
47                 private readonly IILDecoder<APC, TSymbolicValue, TSymbolicValue, IValueContextProvider<TSymbolicValue>, TEdgeData> value_decoder;
48                 private readonly ExpressionAnalysisFacade<TSymbolicValue, TContext, TEdgeData> parent;
49                 private readonly IValueContextProvider<TSymbolicValue> underlying;
50
51                 public ExpressionDecoder (IILDecoder<APC, TSymbolicValue, TSymbolicValue, IValueContextProvider<TSymbolicValue>, TEdgeData> valueDecoder,
52                                           ExpressionAnalysisFacade<TSymbolicValue, TContext, TEdgeData> parent)
53                 {
54                         this.value_decoder = valueDecoder;
55                         this.parent = parent;
56                         this.underlying = valueDecoder.ContextProvider;
57                 }
58
59                 #region IExpressionContext<LabeledSymbol<APC,SymbolicValue>,SymbolicValue> Members
60                 public LabeledSymbol<APC, TSymbolicValue> Refine (APC pc, TSymbolicValue variable)
61                 {
62                         return new LabeledSymbol<APC, TSymbolicValue> (pc, variable);
63                 }
64
65                 public TSymbolicValue Unrefine (LabeledSymbol<APC, TSymbolicValue> expression)
66                 {
67                         return expression.Symbol;
68                 }
69
70                 public Result Decode<Data, Result, Visitor> (LabeledSymbol<APC, TSymbolicValue> expr, Visitor visitor, Data data)
71                         where Visitor : ISymbolicExpressionVisitor<LabeledSymbol<APC, TSymbolicValue>, LabeledSymbol<APC, TSymbolicValue>, TSymbolicValue, Data, Result>
72                 {
73                         ExprDomain<TSymbolicValue> ifFound;
74                         if (!this.parent.PreStateLookup (expr.ReadAt, out ifFound) || ifFound.IsBottom)
75                                 return visitor.SymbolicConstant (expr, expr.Symbol, data);
76
77                         FlatDomain<Expr<TSymbolicValue>> aExpr = ifFound [expr.Symbol];
78                         if (aExpr.IsNormal()) {
79                                 return aExpr.Value.Decode<Data, Result, ExpressionDecoderAdapter<TSymbolicValue, Data, Result, Visitor>>
80                                         (expr.ReadAt, expr.Symbol, new ExpressionDecoderAdapter<TSymbolicValue, Data, Result, Visitor> (visitor), data);
81                         }
82
83                         TypeNode type;
84                         object constant;
85                         if (this.parent.ValueLayer.ILDecoder.ContextProvider.ValueContext.IsConstant (expr.ReadAt, expr.Symbol, out type, out constant))
86                                 return visitor.LoadConst (expr, type, constant, expr.Symbol, data);
87
88                         return visitor.SymbolicConstant (expr, expr.Symbol, data);
89                 }
90
91                 public FlatDomain<TypeNode> GetType (LabeledSymbol<APC, TSymbolicValue> expr)
92                 {
93                         return this.underlying.ValueContext.GetType (expr.ReadAt, expr.Symbol);
94                 }
95
96                 public APC GetPC (LabeledSymbol<APC, TSymbolicValue> pc)
97                 {
98                         return pc.ReadAt;
99                 }
100
101                 public LabeledSymbol<APC, TSymbolicValue> For (TSymbolicValue variable)
102                 {
103                         return new LabeledSymbol<APC, TSymbolicValue> (MethodContext.CFG.Entry, variable);
104                 }
105
106                 public bool IsZero (LabeledSymbol<APC, TSymbolicValue> expression)
107                 {
108                         return ValueContext.IsZero (expression.ReadAt, expression.Symbol);
109                 }
110                 #endregion
111
112                 #region IILDecoder<APC,LabeledSymbol<APC,SymbolicValue>,SymbolicValue,IExpressionContextProvider<LabeledSymbol<APC,SymbolicValue>,SymbolicValue>,EdgeData> Members
113                 public IExpressionContextProvider<LabeledSymbol<APC, TSymbolicValue>, TSymbolicValue> ContextProvider
114                 {
115                         get { return this; }
116                 }
117
118                 public Result ForwardDecode<Data, Result, Visitor> (APC pc, Visitor visitor, Data state)
119                         where Visitor : IILVisitor<APC, LabeledSymbol<APC, TSymbolicValue>, TSymbolicValue, Data, Result>
120                 {
121                         return this.value_decoder.ForwardDecode<Data, Result, ILDecoderAdapter<TSymbolicValue, Data, Result, Visitor>>
122                                 (pc, new ILDecoderAdapter<TSymbolicValue, Data, Result, Visitor> (visitor), state);
123                 }
124
125                 public bool IsUnreachable (APC pc)
126                 {
127                         return this.parent.IsUnreachable (pc);
128                 }
129
130                 public TEdgeData EdgeData (APC from, APC to)
131                 {
132                         return this.parent.ValueLayer.ILDecoder.EdgeData (from, to);
133                 }
134                 #endregion
135
136                 #region Implementation of IMethodContextProvider<Field,Method>
137                 public IMethodContext MethodContext
138                 {
139                         get { return this.underlying.MethodContext; }
140                 }
141                 #endregion
142
143                 #region Implementation of IStackContextProvider<Field,Method>
144                 public IStackContext StackContext
145                 {
146                         get { return this.underlying.StackContext; }
147                 }
148                 #endregion
149
150                 #region Implementation of IValueContextProvider<Local,Parameter,Method,Field,Type,SymbolicValue>
151                 public IValueContext<TSymbolicValue> ValueContext
152                 {
153                         get { return this.underlying.ValueContext; }
154                 }
155                 #endregion
156
157                 #region Implementation of IExpressionContextProvider<Local,Parameter,Method,Field,Type,ExternalExpression<APC,SymbolicValue>,SymbolicValue>
158                 public IExpressionContext<LabeledSymbol<APC, TSymbolicValue>, TSymbolicValue> ExpressionContext
159                 {
160                         get { return this; }
161                 }
162                 #endregion
163         }
164 }