72c59bad8b968fb5ba5786118985b2ecacc7c178
[mono.git] / mcs / tools / linker / Mono.Linker / Annotations.cs
1 //
2 // Annotations.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@novell.com)
6 //
7 // (C) 2007 Novell, Inc.
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 System.Collections;
31 using System.Collections.Generic;
32 using System.IO;
33 using System.IO.Compression;
34
35 using Mono.Cecil;
36 using Mono.Cecil.Cil;
37
38 namespace Mono.Linker {
39
40         public class AnnotationStore {
41
42                 readonly Dictionary<AssemblyDefinition, AssemblyAction> assembly_actions = new Dictionary<AssemblyDefinition, AssemblyAction> ();
43                 readonly Dictionary<MethodDefinition, MethodAction> method_actions = new Dictionary<MethodDefinition, MethodAction> ();
44                 readonly HashSet<IMetadataTokenProvider> marked = new HashSet<IMetadataTokenProvider> ();
45                 readonly HashSet<IMetadataTokenProvider> processed = new HashSet<IMetadataTokenProvider> ();
46                 readonly Dictionary<TypeDefinition, TypePreserve> preserved_types = new Dictionary<TypeDefinition, TypePreserve> ();
47                 readonly Dictionary<IMemberDefinition, List<MethodDefinition>> preserved_methods = new Dictionary<IMemberDefinition, List<MethodDefinition>> ();
48                 readonly HashSet<IMetadataTokenProvider> public_api = new HashSet<IMetadataTokenProvider> ();
49                 readonly Dictionary<MethodDefinition, List<MethodDefinition>> override_methods = new Dictionary<MethodDefinition, List<MethodDefinition>> ();
50                 readonly Dictionary<MethodDefinition, List<MethodDefinition>> base_methods = new Dictionary<MethodDefinition, List<MethodDefinition>> ();
51                 readonly Dictionary<AssemblyDefinition, ISymbolReader> symbol_readers = new Dictionary<AssemblyDefinition, ISymbolReader> ();
52
53                 readonly Dictionary<object, Dictionary<IMetadataTokenProvider, object>> custom_annotations = new Dictionary<object, Dictionary<IMetadataTokenProvider, object>> ();
54
55                 Stack<object> dependency_stack;
56                 System.Xml.XmlWriter writer;
57                 GZipStream zipStream;
58
59                 public void PrepareDependenciesDump ()
60                 {
61                         PrepareDependenciesDump ("linker-dependencies.xml.gz");
62                 }
63
64                 public void PrepareDependenciesDump (string filename)
65                 {
66                         dependency_stack = new Stack<object> ();
67                         System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings();
68                         settings.Indent = true;
69                         settings.IndentChars = "\t";
70                         var depsFile = File.OpenWrite (filename);
71                         zipStream = new GZipStream (depsFile, CompressionMode.Compress);
72
73                         writer = System.Xml.XmlWriter.Create (zipStream, settings);
74                         writer.WriteStartDocument ();
75                         writer.WriteStartElement ("dependencies");
76                         writer.WriteStartAttribute ("version");
77                         writer.WriteString ("1.0");
78                         writer.WriteEndAttribute ();
79                 }
80
81                 public AssemblyAction GetAction (AssemblyDefinition assembly)
82                 {
83                         AssemblyAction action;
84                         if (assembly_actions.TryGetValue (assembly, out action))
85                                 return action;
86
87                         throw new NotSupportedException ();
88                 }
89
90                 public MethodAction GetAction (MethodDefinition method)
91                 {
92                         MethodAction action;
93                         if (method_actions.TryGetValue (method, out action))
94                                 return action;
95
96                         return MethodAction.Nothing;
97                 }
98
99                 public void SetAction (AssemblyDefinition assembly, AssemblyAction action)
100                 {
101                         assembly_actions [assembly] = action;
102                 }
103
104                 public bool HasAction (AssemblyDefinition assembly)
105                 {
106                         return assembly_actions.ContainsKey (assembly);
107                 }
108
109                 public void SetAction (MethodDefinition method, MethodAction action)
110                 {
111                         method_actions [method] = action;
112                 }
113
114                 public void Mark (IMetadataTokenProvider provider)
115                 {
116                         marked.Add (provider);
117                         AddDependency (provider);
118                 }
119
120                 public bool IsMarked (IMetadataTokenProvider provider)
121                 {
122                         return marked.Contains (provider);
123                 }
124
125                 public void Processed (IMetadataTokenProvider provider)
126                 {
127                         processed.Add (provider);
128                 }
129
130                 public bool IsProcessed (IMetadataTokenProvider provider)
131                 {
132                         return processed.Contains (provider);
133                 }
134
135                 public bool IsPreserved (TypeDefinition type)
136                 {
137                         return preserved_types.ContainsKey (type);
138                 }
139
140                 public void SetPreserve (TypeDefinition type, TypePreserve preserve)
141                 {
142                         preserved_types [type] = preserve;
143                 }
144
145                 public TypePreserve GetPreserve (TypeDefinition type)
146                 {
147                         TypePreserve preserve;
148                         if (preserved_types.TryGetValue (type, out preserve))
149                                 return preserve;
150
151                         throw new NotSupportedException ();
152                 }
153
154                 public void SetPublic (IMetadataTokenProvider provider)
155                 {
156                         public_api.Add (provider);
157                 }
158
159                 public bool IsPublic (IMetadataTokenProvider provider)
160                 {
161                         return public_api.Contains (provider);
162                 }
163
164                 public void AddOverride (MethodDefinition @base, MethodDefinition @override)
165                 {
166                         var methods = GetOverrides (@base);
167                         if (methods == null) {
168                                 methods = new List<MethodDefinition> ();
169                                 override_methods [@base] = methods;
170                         }
171
172                         methods.Add (@override);
173                 }
174
175                 public List<MethodDefinition> GetOverrides (MethodDefinition method)
176                 {
177                         List<MethodDefinition> overrides;
178                         if (override_methods.TryGetValue (method, out overrides))
179                                 return overrides;
180
181                         return null;
182                 }
183
184                 public void AddBaseMethod (MethodDefinition method, MethodDefinition @base)
185                 {
186                         var methods = GetBaseMethods (method);
187                         if (methods == null) {
188                                 methods = new List<MethodDefinition> ();
189                                 base_methods [method] = methods;
190                         }
191
192                         methods.Add (@base);
193                 }
194
195                 public List<MethodDefinition> GetBaseMethods (MethodDefinition method)
196                 {
197                         List<MethodDefinition> bases;
198                         if (base_methods.TryGetValue (method, out bases))
199                                 return bases;
200
201                         return null;
202                 }
203
204                 public List<MethodDefinition> GetPreservedMethods (TypeDefinition type)
205                 {
206                         return GetPreservedMethods (type as IMemberDefinition);
207                 }
208
209                 public void AddPreservedMethod (TypeDefinition type, MethodDefinition method)
210                 {
211                         AddPreservedMethod (type as IMemberDefinition, method);
212                 }
213
214                 public List<MethodDefinition> GetPreservedMethods (MethodDefinition method)
215                 {
216                         return GetPreservedMethods (method as IMemberDefinition);
217                 }
218
219                 public void AddPreservedMethod (MethodDefinition key, MethodDefinition method)
220                 {
221                         AddPreservedMethod (key as IMemberDefinition, method);
222                 }
223
224                 List<MethodDefinition> GetPreservedMethods (IMemberDefinition definition)
225                 {
226                         List<MethodDefinition> preserved;
227                         if (preserved_methods.TryGetValue (definition, out preserved))
228                                 return preserved;
229
230                         return null;
231                 }
232
233                 void AddPreservedMethod (IMemberDefinition definition, MethodDefinition method)
234                 {
235                         var methods = GetPreservedMethods (definition);
236                         if (methods == null) {
237                                 methods = new List<MethodDefinition> ();
238                                 preserved_methods [definition] = methods;
239                         }
240
241                         methods.Add (method);
242                 }
243
244                 public void AddSymbolReader (AssemblyDefinition assembly, ISymbolReader symbolReader)
245                 {
246                         symbol_readers [assembly] = symbolReader;
247                 }
248
249                 public void CloseSymbolReader (AssemblyDefinition assembly)
250                 {
251                         ISymbolReader symbolReader;
252                         if (!symbol_readers.TryGetValue (assembly, out symbolReader))
253                                 return;
254
255                         symbol_readers.Remove (assembly);
256                         symbolReader.Dispose ();
257                 }
258
259                 public Dictionary<IMetadataTokenProvider, object> GetCustomAnnotations (object key)
260                 {
261                         Dictionary<IMetadataTokenProvider, object> slots;
262                         if (custom_annotations.TryGetValue (key, out slots))
263                                 return slots;
264
265                         slots = new Dictionary<IMetadataTokenProvider, object> ();
266                         custom_annotations.Add (key, slots);
267                         return slots;
268                 }
269
270                 public void AddDependency (object o)
271                 {
272                         if (writer == null)
273                                 return;
274
275                         KeyValuePair<object, object> pair = new KeyValuePair<object, object> (dependency_stack.Count > 0 ? dependency_stack.Peek () : null, o);
276                         writer.WriteStartElement ("edge");
277                         writer.WriteAttributeString ("b", TokenString (pair.Key));
278                         writer.WriteAttributeString ("e", TokenString (pair.Value));
279                         writer.WriteEndElement ();
280                 }
281
282                 public void Push (object o)
283                 {
284                         if (writer == null)
285                                 return;
286
287                         if (dependency_stack.Count > 0)
288                                 AddDependency (o);
289                         dependency_stack.Push (o);
290                 }
291
292                 public void Pop ()
293                 {
294                         if (writer == null)
295                                 return;
296
297                         dependency_stack.Pop ();
298                 }
299
300                 string TokenString (object o)
301                 {
302                         if (o == null)
303                                 return "N:null";
304
305                         if (o is IMetadataTokenProvider)
306                                 return (o as IMetadataTokenProvider).MetadataToken.TokenType + ":" + o;
307
308                         return "Other:" + o;
309                 }
310
311                 public void SaveDependencies ()
312                 {
313                         if (writer == null)
314                                 return;
315
316                         writer.WriteEndElement ();
317                         writer.WriteEndDocument ();
318                         writer.Flush ();
319                         writer.Close ();
320                         zipStream.Close ();
321
322                         writer.Dispose ();
323                         zipStream.Dispose ();
324                         writer = null;
325                         zipStream = null;
326                         dependency_stack = null;
327                 }
328         }
329 }