1 //
2 // FunctionsTable.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.Collections.Generic;
29 using Mono.CodeContracts.Static.AST;
30 using Mono.CodeContracts.Static.Providers;
31 
32 namespace Mono.CodeContracts.Static.Analysis.HeapAnalysis {
33 	class FunctionsTable
34 	{
35 		public readonly SymFunction BoxOperator;
36 		public readonly SymFunction ElementAddress;
37 		public readonly SymFunction Length;
38 		public readonly SymFunction NeZero;
39 		public readonly SymFunction NullValue;
40 		public readonly SymFunction ObjectVersion;
41 		public readonly SymFunction OldValueOf;
42 		public readonly SymFunction ResultOfCall;
43 		public readonly SymFunction ResultOfLoadElement;
44 		public readonly SymFunction StructId;
45 		public readonly SymFunction UnaryNot;
46 		public readonly SymFunction ValueOf;
47 		public readonly SymFunction VoidAddr;
48 		public readonly SymFunction ZeroValue;
49 		private readonly Dictionary<BinaryOperator, Wrapper<BinaryOperator>> binary_operators;
50 		private readonly Dictionary<Field, Wrapper<Field>> fields;
51 		private readonly Dictionary<Local, Wrapper<Local>> locals;
52 		private readonly IMetaDataProvider meta_data_provider;
53 		private readonly Dictionary<Method, Wrapper<Method>> method_pointers;
54 		private readonly Dictionary<Parameter, Wrapper<Parameter>> parameters;
55 		private readonly Dictionary<object, Wrapper<object>> program_constants;
56 		private readonly Dictionary<Method, Wrapper<Method>> pseudo_fields;
57 		private readonly Dictionary<string, Wrapper<string>> strings;
58 		private readonly Dictionary<int, Wrapper<int>> temp;
59 		private readonly Dictionary<UnaryOperator, Wrapper<UnaryOperator>> unary_operators;
60 
61 		private int id_gen;
62 
FunctionsTable(IMetaDataProvider metaDataProvider)63 		public FunctionsTable(IMetaDataProvider metaDataProvider)
64 		{
65 			this.meta_data_provider = metaDataProvider;
66 			this.locals = new Dictionary<Local, Wrapper<Local>> ();
67 			this.parameters = new Dictionary<Parameter, Wrapper<Parameter>> ();
68 			this.fields = new Dictionary<Field, Wrapper<Field>> ();
69 			this.pseudo_fields = new Dictionary<Method, Wrapper<Method>> ();
70 			this.temp = new Dictionary<int, Wrapper<int>> ();
71 			this.strings = new Dictionary<string, Wrapper<string>> ();
72 			this.program_constants = new Dictionary<object, Wrapper<object>> ();
73 			this.method_pointers = new Dictionary<Method, Wrapper<Method>> ();
74 			this.binary_operators = new Dictionary<BinaryOperator, Wrapper<BinaryOperator>> ();
75 			this.unary_operators = new Dictionary<UnaryOperator, Wrapper<UnaryOperator>> ();
76 
77 			this.ValueOf = For ("$Value");
78 			this.OldValueOf = For ("$OldValue");
79 			this.StructId = For ("$StructId");
80 			this.ObjectVersion = For ("$ObjectVersion");
81 			this.NullValue = For ("$Null");
82 			this.ElementAddress = For ("$ElementAddress");
83 			this.Length = For ("$Length");
84 			this.VoidAddr = For ("$VoidAddr");
85 			this.UnaryNot = For ("$UnaryNot");
86 			this.NeZero = For ("$NeZero");
87 			this.BoxOperator = For ("$Box");
88 			this.ResultOfCall = For ("$ResultOfCall");
89 			this.ResultOfLoadElement = For ("$ResultOfLoadElement");
90 			this.ZeroValue = ForConstant (0, this.meta_data_provider.System_Int32);
91 		}
92 
For(T key, Dictionary<T, Wrapper<T>> cache)93 		private Wrapper<T> For<T>(T key, Dictionary<T, Wrapper<T>> cache)
94 		{
95 			Wrapper<T> wrapper;
96 			if (!cache.TryGetValue (key, out wrapper)) {
97 				wrapper = SymFunction.For (key, ref this.id_gen, this.meta_data_provider);
98 				cache.Add (key, wrapper);
99 			}
100 			return wrapper;
101 		}
102 
For(Local v)103 		public SymFunction For(Local v)
104 		{
105 			return For (v, this.locals);
106 		}
107 
For(Parameter v)108 		public SymFunction For(Parameter v)
109 		{
110 			return For (v, this.parameters);
111 		}
112 
For(Field v)113 		public SymFunction For(Field v)
114 		{
115 			v = this.meta_data_provider.Unspecialized (v);
116 			return For (v, this.fields);
117 		}
118 
For(Method v)119 		public SymFunction For(Method v)
120 		{
121 			return For (v, this.pseudo_fields);
122 		}
123 
For(string v)124 		public SymFunction For(string v)
125 		{
126 			return For (v, this.strings);
127 		}
128 
For(int v)129 		public SymFunction For(int v)
130 		{
131 			return For (v, this.temp);
132 		}
133 
For(BinaryOperator v)134 		public SymFunction For(BinaryOperator v)
135 		{
136 			return For (v, this.binary_operators);
137 		}
138 
For(UnaryOperator v)139 		public SymFunction For(UnaryOperator v)
140 		{
141 			return For (v, this.unary_operators);
142 		}
143 
ForConstant(object constant, TypeNode type)144 		public SymFunction ForConstant(object constant, TypeNode type)
145 		{
146 			Wrapper<object> wrapper = For (constant, this.program_constants);
147 			wrapper.Type = type;
148 			return wrapper;
149 		}
150 
ForMethod(Method method, TypeNode type)151 		public SymFunction ForMethod(Method method, TypeNode type)
152 		{
153 			Wrapper<Method> wrapper = For (method, this.method_pointers);
154 			wrapper.Type = type;
155 			return wrapper;
156 		}
157 
IsConstantOrMethod(SymFunction constant)158 		public bool IsConstantOrMethod(SymFunction constant)
159 		{
160 			var wrapper = constant as Wrapper<object>;
161 			if (wrapper != null && this.program_constants.ContainsKey (wrapper.Item))
162 				return true;
163 
164 			var wrapper1 = constant as Wrapper<Method>;
165 			if (wrapper1 != null && this.method_pointers.ContainsKey (wrapper1.Item))
166 				return true;
167 
168 			return false;
169 		}
170 
IsConstant(SymFunction c, out TypeNode type, out object value)171 		public bool IsConstant(SymFunction c, out TypeNode type, out object value)
172 		{
173 			var wrapper = c as Wrapper<object>;
174 			if (wrapper != null && this.program_constants.ContainsKey (wrapper.Item)) {
175 				type = wrapper.Type;
176 				value = wrapper.Item;
177 				return true;
178 			}
179 
180 			type = null;
181 			value = null;
182 			return false;
183 		}
184 	}
185 }