2007-09-25 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / Mono.CompilerServices.SymbolWriter / SymbolWriterImpl.cs
1 //
2 // SymbolWriterImpl.cs
3 //
4 // Author:
5 //   Lluis Sanchez Gual (lluis@novell.com)
6 //
7 // (C) 2005 Novell, Inc.  http://www.novell.com
8 //
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30
31 using System;
32 using System.Reflection;
33 using System.Reflection.Emit;
34 using System.Runtime.CompilerServices;
35 using System.Collections;
36 using System.IO;
37 using System.Diagnostics.SymbolStore;
38         
39 namespace Mono.CompilerServices.SymbolWriter
40 {
41         public class SymbolWriterImpl: ISymbolWriter
42         {
43                 MonoSymbolWriter msw;
44
45                 int nextLocalIndex;
46                 int currentToken;
47                 string methodName;
48                 Stack namespaceStack = new Stack ();
49                 bool methodOpened;
50
51                 Hashtable documents = new Hashtable ();
52
53 #if !CECIL
54                 ModuleBuilder mb;
55                 delegate Guid GetGuidFunc (ModuleBuilder mb);
56                 GetGuidFunc get_guid_func;
57                 
58                 public SymbolWriterImpl (ModuleBuilder mb)
59                 {
60                         this.mb = mb;
61                 }
62                 
63                 public void Close ()
64                 {
65                         MethodInfo mi = typeof (ModuleBuilder).GetMethod (
66                                 "Mono_GetGuid",
67                                 BindingFlags.Static | BindingFlags.NonPublic);
68                         if (mi == null)
69                                 return;
70
71                         get_guid_func = (GetGuidFunc) System.Delegate.CreateDelegate (
72                                 typeof (GetGuidFunc), mi);
73                         
74                         msw.WriteSymbolFile (get_guid_func (mb));
75                 }
76 #else
77                 Guid guid;
78
79                 public SymbolWriterImpl (Guid guid)
80                 {
81                         this.guid = guid;
82                 }
83
84                 public void Close ()
85                 {
86                         msw.WriteSymbolFile (guid);
87                 }
88 #endif
89                 
90                 public void CloseMethod ()
91                 {
92                         if (methodOpened) {
93                                 methodOpened = false;
94                                 nextLocalIndex = 0;
95                                 msw.CloseMethod ();
96                         }
97                 }
98                 
99                 public void CloseNamespace ()
100                 {
101                         namespaceStack.Pop ();
102                         msw.CloseNamespace ();
103                 }
104                 
105                 public void CloseScope (int endOffset)
106                 {
107                         msw.CloseScope (endOffset);
108                 }
109                 
110                 public ISymbolDocumentWriter DefineDocument (
111                         string url,
112                         Guid language,
113                         Guid languageVendor,
114                         Guid documentType)
115                 {
116                         SymbolDocumentWriterImpl doc = (SymbolDocumentWriterImpl) documents [url];
117                         if (doc == null) {
118                                 doc = new SymbolDocumentWriterImpl (msw.DefineDocument (url));
119                                 documents [url] = doc;
120                         }
121                         return doc;
122                 }
123                         
124                 public void DefineField (
125                         SymbolToken parent,
126                         string name,
127                         FieldAttributes attributes,
128                         byte[] signature,
129                         SymAddressKind addrKind,
130                         int addr1,
131                         int addr2,
132                         int addr3)
133                 {
134                 }
135                 
136                 public void DefineGlobalVariable (
137                         string name,
138                         FieldAttributes attributes,
139                         byte[] signature,
140                         SymAddressKind addrKind,
141                         int addr1,
142                         int addr2,
143                         int addr3)
144                 {
145                 }
146                 
147                 public void DefineLocalVariable (
148                         string name,
149                         FieldAttributes attributes,
150                         byte[] signature,
151                         SymAddressKind addrKind,
152                         int addr1,
153                         int addr2,
154                         int addr3,
155                         int startOffset,
156                         int endOffset)
157                 {
158                         msw.DefineLocalVariable (nextLocalIndex++, name, signature);
159                 }
160                 
161                 public void DefineParameter (
162                         string name,
163                         ParameterAttributes attributes,
164                         int sequence,
165                         SymAddressKind addrKind,
166                         int addr1,
167                         int addr2,
168                         int addr3)
169                 {
170                 }
171
172                 public void DefineSequencePoints (
173                         ISymbolDocumentWriter document,
174                         int[] offsets,
175                         int[] lines,
176                         int[] columns,
177                         int[] endLines,
178                         int[] endColumns)
179                 {
180                         for (int n=0; n<offsets.Length; n++) {
181                                 if (n > 0 && offsets[n] == offsets[n-1] && lines[n] == lines[n-1] && columns[n] == columns[n-1])
182                                         continue;
183                                 msw.MarkSequencePoint (offsets[n], lines[n], columns[n]);
184                         }
185                 }
186                 
187                 public void Initialize (IntPtr emitter, string filename, bool fFullBuild)
188                 {
189                         msw = new MonoSymbolWriter (filename);
190                 }
191                 
192                 public void OpenMethod (SymbolToken method)
193                 {
194                         currentToken = method.GetToken ();
195                 }
196                 
197                 public void OpenNamespace (string name)
198                 {
199                         NamespaceInfo n = new NamespaceInfo ();
200                         n.NamespaceID = -1;
201                         n.Name = name;
202                         namespaceStack.Push (n);
203                 }
204                 
205                 public int OpenScope (int startOffset)
206                 {
207                         return msw.OpenScope (startOffset);
208                 }
209                 
210                 public void SetMethodSourceRange (
211                         ISymbolDocumentWriter startDoc,
212                         int startLine,
213                         int startColumn,
214                         ISymbolDocumentWriter endDoc,
215                         int endLine,
216                         int endColumn)
217                 {
218                         SourceMethodImpl sm = new SourceMethodImpl (methodName, currentToken, GetCurrentNamespace (startDoc));
219                         msw.OpenMethod (startDoc as ISourceFile, sm, startLine, startColumn, endLine, endColumn);
220                         methodOpened = true;
221                 }
222                 
223                 public void SetScopeRange (int scopeID, int startOffset, int endOffset)
224                 {
225                 }
226                 
227                 public void SetSymAttribute (SymbolToken parent, string name, byte[] data)
228                 {
229                         // This is a hack! but MonoSymbolWriter needs the method name
230                         // and ISymbolWriter does not have any method for providing it
231                         if (name == "__name")
232                                 methodName = System.Text.Encoding.UTF8.GetString (data);
233                 }
234                 
235                 public void SetUnderlyingWriter (IntPtr underlyingWriter)
236                 {
237                 }
238                 
239                 public void SetUserEntryPoint (SymbolToken entryMethod)
240                 {
241                 }
242
243                 public void UsingNamespace (string fullName)
244                 {
245                         if (namespaceStack.Count == 0) {
246                                 OpenNamespace ("");
247                         }
248                         
249                         NamespaceInfo ni = (NamespaceInfo) namespaceStack.Peek ();
250                         if (ni.NamespaceID != -1) {
251                                 NamespaceInfo old = ni;
252                                 CloseNamespace ();
253                                 OpenNamespace (old.Name);
254                                 ni = (NamespaceInfo) namespaceStack.Peek ();
255                                 ni.UsingClauses = old.UsingClauses;
256                         }
257                         ni.UsingClauses.Add (fullName);
258                 }
259                 
260                 int GetCurrentNamespace (ISymbolDocumentWriter doc)
261                 {
262                         if (namespaceStack.Count == 0) {
263                                 OpenNamespace ("");
264                         }
265
266                         NamespaceInfo ni = (NamespaceInfo) namespaceStack.Peek ();
267                         if (ni.NamespaceID == -1)
268                         {
269                                 string[] usings = (string[]) ni.UsingClauses.ToArray (typeof(string));
270                                 
271                                 int parentId = 0;
272                                 if (namespaceStack.Count > 1) {
273                                         namespaceStack.Pop ();
274                                         parentId = ((NamespaceInfo) namespaceStack.Peek ()).NamespaceID;
275                                         namespaceStack.Push (ni);
276                                 }
277                                         
278                                 ni.NamespaceID = msw.DefineNamespace (ni.Name, ((ISourceFile)doc).Entry, usings, parentId);
279                         }
280                         return ni.NamespaceID;
281                 }
282         }
283         
284         class SymbolDocumentWriterImpl: ISymbolDocumentWriter, ISourceFile
285         {
286                 SourceFileEntry entry;
287                 
288                 public SymbolDocumentWriterImpl (SourceFileEntry e)
289                 {
290                         entry = e;
291                 }
292                 
293                 public void SetCheckSum (Guid algorithmId, byte[] checkSum)
294                 {
295                 }
296                 
297                 public void SetSource (byte[] source)
298                 {
299                 }
300                 
301                 public SourceFileEntry Entry {
302                         get { return entry; }
303                 }
304         }
305         
306         class SourceMethodImpl: ISourceMethod
307         {
308                 string name;
309                 int token;
310                 int namespaceID;
311                 
312                 public SourceMethodImpl (string name, int token, int namespaceID)
313                 {
314                         this.name = name;
315                         this.token = token;
316                         this.namespaceID = namespaceID;
317                 }
318                 
319                 public string Name {
320                         get { return name; }
321                 }
322
323                 public int NamespaceID {
324                         get { return namespaceID; }
325                 }
326
327                 public int Token {
328                         get { return token; }
329                 }
330         }
331         
332         class NamespaceInfo
333         {
334                 public string Name;
335                 public int NamespaceID;
336                 public ArrayList UsingClauses = new ArrayList ();
337         }
338 }