Merge pull request #231 from linquize/a853199c497bb0977970974303fac7e42080809d
[mono.git] / mcs / class / Mono.CodeContracts / Mono.CodeContracts.Static.Analysis.HeapAnalysis / ValueDecoder.cs
1 // 
2 // ValueDecoder.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 using System;
29 using System.IO;
30 using Mono.CodeContracts.Static.AST.Visitors;
31 using Mono.CodeContracts.Static.ControlFlow;
32 using Mono.CodeContracts.Static.DataStructures;
33 using Mono.CodeContracts.Static.Providers;
34
35 namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis {
36         class ValueDecoder<TContext> : 
37                 IILDecoder<APC, SymbolicValue, SymbolicValue, IValueContextProvider<SymbolicValue>, IImmutableMap<SymbolicValue, LispList<SymbolicValue>>>
38                 where TContext : IStackContextProvider
39         {
40                 private readonly HeapAnalysis parent;
41                 private readonly IILDecoder<APC, int, int, TContext, Dummy> stack_decoder;
42                 private readonly Lazy<IValueContextProvider<SymbolicValue>> context;
43
44                 public ValueDecoder(HeapAnalysis parent, IILDecoder<APC, int, int, TContext, Dummy> stackDecoder)
45                 {
46                         this.context = new Lazy<IValueContextProvider<SymbolicValue>> (()=> new ValueContextProvider<TContext>(this.parent, this.stack_decoder.ContextProvider));
47                         this.parent = parent;
48                         this.stack_decoder = stackDecoder;
49                 }
50
51                 #region Implementation of IILDecoder<APC,SymbolicValue,SymbolicValue,IValueContext<SymbolicValue>,IImmutableMap<SymbolicValue,LispList<SymbolicValue>>>
52                 public IValueContextProvider<SymbolicValue> ContextProvider { get { return context.Value; } }
53
54                 public Result ForwardDecode<Data, Result, Visitor>(APC pc, Visitor visitor, Data state)
55                         where Visitor : IILVisitor<APC, SymbolicValue, SymbolicValue, Data, Result>
56                 {
57                         return this.stack_decoder.ForwardDecode<Data, Result, StackToSymbolicAdapter<Data, Result, Visitor>> 
58                                 (pc, new StackToSymbolicAdapter<Data, Result, Visitor> (this.parent, visitor), state);
59                 }
60
61                 public bool IsUnreachable(APC pc)
62                 {
63                         return this.parent.IsUnreachable (pc);
64                 }
65
66                 public IImmutableMap<SymbolicValue, LispList<SymbolicValue>> EdgeData(APC from, APC to)
67                 {
68                         if (!this.parent.RenamePoints.ContainsKey(from, to))
69                                 return null;
70                         if (this.parent.MergeInfoCache.ContainsKey(to) && this.parent.MergeInfoCache[to] == null)
71                                 return null;
72
73                         return this.parent.EdgeRenaming (new Pair<APC, APC> (from, to), this.ContextProvider.MethodContext.CFG.IsJoinPoint (to));
74                 }
75
76                 public void Dump(TextWriter tw, string prefix, IImmutableMap<SymValue, LispList<SymValue>> edgeData )
77                 {
78                         if (edgeData == null)
79                                 return;
80                         edgeData.Visit ((key, targets) => {
81                                                 tw.Write ("  {0} -> ", key);
82                                                 foreach (var target in targets.AsEnumerable ())
83                                                         tw.Write ("{0} ", target);
84                                                 tw.WriteLine ();
85                                                 return VisitStatus.ContinueVisit;
86                                         });
87                 }
88
89                 #endregion
90         }
91 }