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