Added Mono.Tasklets test
[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                                 SourceFileEntry entry = msw.DefineDocument (url);
119                                 CompileUnitEntry comp_unit = msw.DefineCompilationUnit (entry);
120                                 doc = new SymbolDocumentWriterImpl (comp_unit);
121                                 documents [url] = doc;
122                         }
123                         return doc;
124                 }
125                         
126                 public void DefineField (
127                         SymbolToken parent,
128                         string name,
129                         FieldAttributes attributes,
130                         byte[] signature,
131                         SymAddressKind addrKind,
132                         int addr1,
133                         int addr2,
134                         int addr3)
135                 {
136                 }
137                 
138                 public void DefineGlobalVariable (
139                         string name,
140                         FieldAttributes attributes,
141                         byte[] signature,
142                         SymAddressKind addrKind,
143                         int addr1,
144                         int addr2,
145                         int addr3)
146                 {
147                 }
148                 
149                 public void DefineLocalVariable (
150                         string name,
151                         FieldAttributes attributes,
152                         byte[] signature,
153                         SymAddressKind addrKind,
154                         int addr1,
155                         int addr2,
156                         int addr3,
157                         int startOffset,
158                         int endOffset)
159                 {
160                         msw.DefineLocalVariable (nextLocalIndex++, name);
161                 }
162                 
163                 public void DefineParameter (
164                         string name,
165                         ParameterAttributes attributes,
166                         int sequence,
167                         SymAddressKind addrKind,
168                         int addr1,
169                         int addr2,
170                         int addr3)
171                 {
172                 }
173
174                 public void DefineSequencePoints (
175                         ISymbolDocumentWriter document,
176                         int[] offsets,
177                         int[] lines,
178                         int[] columns,
179                         int[] endLines,
180                         int[] endColumns)
181                 {
182                         SymbolDocumentWriterImpl doc = (SymbolDocumentWriterImpl) document;
183                         SourceFileEntry file = doc != null ? doc.Entry.SourceFile : null;
184
185                         for (int n=0; n<offsets.Length; n++) {
186                                 if (n > 0 && offsets[n] == offsets[n-1] && lines[n] == lines[n-1] && columns[n] == columns[n-1])
187                                         continue;
188                                 msw.MarkSequencePoint (offsets[n], file, lines[n], columns[n], false);
189                         }
190                 }
191                 
192                 public void Initialize (IntPtr emitter, string filename, bool fFullBuild)
193                 {
194                         msw = new MonoSymbolWriter (filename);
195                 }
196                 
197                 public void OpenMethod (SymbolToken method)
198                 {
199                         currentToken = method.GetToken ();
200                 }
201                 
202                 public void OpenNamespace (string name)
203                 {
204                         NamespaceInfo n = new NamespaceInfo ();
205                         n.NamespaceID = -1;
206                         n.Name = name;
207                         namespaceStack.Push (n);
208                 }
209
210                 public int OpenScope (int startOffset)
211                 {
212                         return msw.OpenScope (startOffset);
213                 }
214                 
215                 public void SetMethodSourceRange (
216                         ISymbolDocumentWriter startDoc,
217                         int startLine,
218                         int startColumn,
219                         ISymbolDocumentWriter endDoc,
220                         int endLine,
221                         int endColumn)
222                 {
223                         int nsId = GetCurrentNamespace (startDoc);
224                         SourceMethodImpl sm = new SourceMethodImpl (methodName, currentToken, nsId);
225                         msw.OpenMethod (((ICompileUnit)startDoc).Entry, nsId, sm);
226                         methodOpened = true;
227                 }
228                 
229                 public void SetScopeRange (int scopeID, int startOffset, int endOffset)
230                 {
231                 }
232                 
233                 public void SetSymAttribute (SymbolToken parent, string name, byte[] data)
234                 {
235                         // This is a hack! but MonoSymbolWriter needs the method name
236                         // and ISymbolWriter does not have any method for providing it
237                         if (name == "__name")
238                                 methodName = System.Text.Encoding.UTF8.GetString (data);
239                 }
240                 
241                 public void SetUnderlyingWriter (IntPtr underlyingWriter)
242                 {
243                 }
244                 
245                 public void SetUserEntryPoint (SymbolToken entryMethod)
246                 {
247                 }
248
249                 public void UsingNamespace (string fullName)
250                 {
251                         if (namespaceStack.Count == 0) {
252                                 OpenNamespace ("");
253                         }
254                         
255                         NamespaceInfo ni = (NamespaceInfo) namespaceStack.Peek ();
256                         if (ni.NamespaceID != -1) {
257                                 NamespaceInfo old = ni;
258                                 CloseNamespace ();
259                                 OpenNamespace (old.Name);
260                                 ni = (NamespaceInfo) namespaceStack.Peek ();
261                                 ni.UsingClauses = old.UsingClauses;
262                         }
263                         ni.UsingClauses.Add (fullName);
264                 }
265
266                 int GetCurrentNamespace (ISymbolDocumentWriter doc)
267                 {
268                         if (namespaceStack.Count == 0) {
269                                 OpenNamespace ("");
270                         }
271
272                         NamespaceInfo ni = (NamespaceInfo) namespaceStack.Peek ();
273                         if (ni.NamespaceID == -1)
274                         {
275                                 string[] usings = (string[]) ni.UsingClauses.ToArray (typeof(string));
276                                 
277                                 int parentId = 0;
278                                 if (namespaceStack.Count > 1) {
279                                         namespaceStack.Pop ();
280                                         parentId = ((NamespaceInfo) namespaceStack.Peek ()).NamespaceID;
281                                         namespaceStack.Push (ni);
282                                 }
283                                         
284                                 ni.NamespaceID = msw.DefineNamespace (ni.Name, ((ICompileUnit)doc).Entry, usings, parentId);
285                         }
286                         return ni.NamespaceID;
287                 }
288
289         }
290         
291         class SymbolDocumentWriterImpl: ISymbolDocumentWriter, ISourceFile, ICompileUnit
292         {
293                 CompileUnitEntry comp_unit;
294                 
295                 public SymbolDocumentWriterImpl (CompileUnitEntry comp_unit)
296                 {
297                         this.comp_unit = comp_unit;
298                 }
299                 
300                 public void SetCheckSum (Guid algorithmId, byte[] checkSum)
301                 {
302                 }
303                 
304                 public void SetSource (byte[] source)
305                 {
306                 }
307
308                 SourceFileEntry ISourceFile.Entry {
309                         get { return comp_unit.SourceFile; }
310                 }
311                 
312                 public CompileUnitEntry Entry {
313                         get { return comp_unit; }
314                 }
315         }
316         
317         class SourceMethodImpl: IMethodDef
318         {
319                 string name;
320                 int token;
321                 int namespaceID;
322                 
323                 public SourceMethodImpl (string name, int token, int namespaceID)
324                 {
325                         this.name = name;
326                         this.token = token;
327                         this.namespaceID = namespaceID;
328                 }
329                 
330                 public string Name {
331                         get { return name; }
332                 }
333
334                 public int NamespaceID {
335                         get { return namespaceID; }
336                 }
337
338                 public int Token {
339                         get { return token; }
340                 }
341         }
342         
343         class NamespaceInfo
344         {
345                 public string Name;
346                 public int NamespaceID;
347                 public ArrayList UsingClauses = new ArrayList ();
348         }
349 }