2002-03-20 Martin Baulig <martin@gnome.org>
[mono.git] / mcs / class / Mono.CSharp.Debugger / MonoSymbolWriter.cs
1 //
2 // System.Diagnostics.SymbolStore/MonoSymbolWriter.cs
3 //
4 // Author:
5 //   Martin Baulig (martin@gnome.org)
6 //
7 // This is the default implementation of the System.Diagnostics.SymbolStore.ISymbolWriter
8 // interface.
9 //
10 // (C) 2002 Ximian, Inc.  http://www.ximian.com
11 //
12
13 using System;
14 using System.Reflection;
15 using System.Reflection.Emit;
16 using System.Diagnostics.SymbolStore;
17 using System.Collections;
18 using System.IO;
19         
20 namespace Mono.CSharp.Debugger
21 {
22
23         public class MonoSymbolWriter : IMonoSymbolWriter
24         {
25                 protected string output_filename = null;
26                 protected Hashtable methods = null;
27                 protected Hashtable sources = null;
28
29                 protected class SourceFile : ISourceFile
30                 {
31                         private ArrayList _methods = new ArrayList ();
32                         private string _file_name;
33
34                         public SourceFile (string filename)
35                         {
36                                 this._file_name = filename;
37                         }
38
39                         // interface ISourceFile
40
41                         public string FileName {
42                                 get {
43                                         return _file_name;
44                                 }
45                         }
46
47                         public ISourceMethod[] Methods {
48                                 get {
49                                         ISourceMethod[] retval = new ISourceMethod [_methods.Count];
50                                         _methods.CopyTo (retval);
51                                         return retval;
52                                 }
53                         }
54
55                         public void AddMethod (ISourceMethod method)
56                         {
57                                 _methods.Add (method);
58                         }
59                 }
60
61                 protected class SourceLine : ISourceLine
62                 {
63                         public SourceLine (int offset, int line)
64                         {
65                                 this._offset = offset;
66                                 this._line = line;
67                         }
68
69                         private readonly int _offset;
70                         private readonly int _line;
71
72                         // interface ISourceLine
73
74                         public int Offset {
75                                 get {
76                                         return _offset;
77                                 }
78                         }
79
80                         public int Line {
81                                 get {
82                                         return _line;
83                                 }
84                         }
85                 }
86
87                 protected class LocalVariable : ILocalVariable
88                 {
89                         public LocalVariable (string name, int index)
90                         {
91                                 this._name = name;
92                                 this._index = index;
93                         }
94
95                         private readonly string _name;
96                         private readonly int _index;
97
98                         // interface ILocalVariable
99
100                         public string Name {
101                                 get {
102                                         return _name;
103                                 }
104                         }
105
106                         public int Index {
107                                 get {
108                                         return _index;
109                                 }
110                         }
111                 }
112
113                 protected class SourceMethod : ISourceMethod
114                 {
115                         private ArrayList _lines = new ArrayList ();
116                         private ArrayList _locals = new ArrayList ();
117
118                         private readonly MethodInfo _method_info;
119                         private readonly SourceFile _source_file;
120                         private readonly int _token;
121
122                         public SourceMethod (int token, MethodInfo method_info, SourceFile source_file) {
123                                 this._method_info = method_info;
124                                 this._source_file = source_file;
125                                 this._token = token;
126                         }
127
128                         public void SetSourceRange (int startLine, int startColumn,
129                                                     int endLine, int endColumn)
130                         {
131                                 AddLine (new SourceLine (0, startLine));
132                         }
133
134                         // interface ISourceMethod
135
136                         public ISourceLine[] Lines {
137                                 get {
138                                         ISourceLine[] retval = new ISourceLine [_lines.Count];
139                                         _lines.CopyTo (retval);
140                                         return retval;
141                                 }
142                         }
143
144                         public ILocalVariable[] Locals {
145                                 get {
146                                         ILocalVariable[] retval = new ILocalVariable [_locals.Count];
147                                         _locals.CopyTo (retval);
148                                         return retval;
149                                 }
150                         }
151
152                         public void AddLine (ISourceLine line)
153                         {
154                                 _lines.Add (line);
155                         }
156
157                         public void AddLocal (ILocalVariable local)
158                         {
159                                 _locals.Add (local);
160                         }
161
162                         public MethodInfo MethodInfo {
163                                 get {
164                                         return _method_info;
165                                 }
166                         }
167
168                         public ISourceFile SourceFile {
169                                 get {
170                                         return _source_file;
171                                 }
172                         }
173
174                         public int FirstLine {
175                                 get {
176                                         if (_lines.Count > 0)
177                                                 return ((ISourceLine) _lines [0]).Line;
178                                         else
179                                                 return 0;
180                                 }
181                         }
182
183                         public int LastLine {
184                                 get {
185                                         if (_lines.Count > 0)
186                                                 return ((ISourceLine) _lines [_lines.Count - 1]).Line;
187                                         else
188                                                 return 0;
189                                 }
190                         }
191
192                         public int CodeSize {
193                                 get {
194                                         return -1;
195                                 }
196                         }
197
198                         public int Token {
199                                 get {
200                                         return _token;
201                                 }
202                         }
203                 }
204
205                 protected SourceMethod current_method = null;
206
207                 //
208                 // Interface IMonoSymbolWriter
209                 //
210
211                 public MonoSymbolWriter ()
212                 {
213                         methods = new Hashtable ();
214                         sources = new Hashtable ();
215                 }
216
217                 public void Close () {
218                         CreateDwarfFile (output_filename);
219                 }
220
221                 public void CloseNamespace () {
222                 }
223
224                 public void CloseScope (int endOffset) {
225                 }
226
227                 // Create and return a new IMonoSymbolDocumentWriter.
228                 public ISymbolDocumentWriter DefineDocument (string url,
229                                                              Guid language,
230                                                              Guid languageVendor,
231                                                              Guid documentType)
232                 {
233                         return new MonoSymbolDocumentWriter (url);
234                 }
235
236                 public void DefineField (
237                         SymbolToken parent,
238                         string name,
239                         FieldAttributes attributes,
240                         byte[] signature,
241                         SymAddressKind addrKind,
242                         int addr1,
243                         int addr2,
244                         int addr3)
245                 {
246                 }
247
248                 public void DefineGlobalVariable (
249                         string name,
250                         FieldAttributes attributes,
251                         byte[] signature,
252                         SymAddressKind addrKind,
253                         int addr1,
254                         int addr2,
255                         int addr3)
256                 {
257                 }
258
259                 public void DefineLocalVariable (string name,
260                                                  FieldAttributes attributes,
261                                                  byte[] signature,
262                                                  SymAddressKind addrKind,
263                                                  int addr1,
264                                                  int addr2,
265                                                  int addr3,
266                                                  int startOffset,
267                                                  int endOffset)
268                 {
269                         LocalVariable local_info = new LocalVariable (name, addr1);
270
271                         if (current_method != null)
272                                 current_method.AddLocal (local_info);
273                 }
274
275                 public void DefineParameter (
276                         string name,
277                         ParameterAttributes attributes,
278                         int sequence,
279                         SymAddressKind addrKind,
280                         int addr1,
281                         int addr2,
282                         int addr3)
283                 {
284                 }
285
286                 public void DefineSequencePoints (ISymbolDocumentWriter document,
287                                                   int[] offsets,
288                                                   int[] lines,
289                                                   int[] columns,
290                                                   int[] endLines,
291                                                   int[] endColumns)
292                 {
293                         SourceLine source_line = new SourceLine (offsets [0], lines [0]);
294
295                         if (current_method != null)
296                                 current_method.AddLine (source_line);
297                 }
298
299                 public void Initialize (IntPtr emitter, string filename, bool fFullBuild)
300                 {
301                         throw new NotSupportedException ("Please use the 'Initialize (string filename)' "
302                                                          + "constructor and read the documentation in "
303                                                          + "Mono.CSharp.Debugger/IMonoSymbolWriter.cs");
304                 }
305
306                 // This is documented in IMonoSymbolWriter.cs
307                 public void Initialize (string filename)
308                 {
309                         this.output_filename = filename;
310                 }
311
312                 public void OpenMethod (SymbolToken method)
313                 {
314                         // do nothing
315                 }
316
317                 // This is documented in IMonoSymbolWriter.cs
318                 public void OpenMethod (SymbolToken symbol_token, MethodInfo method_info,
319                                         string source_file)
320                 {
321                         int token = symbol_token.GetToken ();
322                         SourceFile source_info;
323
324                         if (methods.ContainsKey (token))
325                                 methods.Remove (token);
326
327                         if (sources.ContainsKey (source_file))
328                                 source_info = (SourceFile) sources [source_file];
329                         else {
330                                 source_info = new SourceFile (source_file);
331                                 sources.Add (source_file, source_info);
332                         }
333
334                         current_method = new SourceMethod (token, method_info, source_info);
335
336                         source_info.AddMethod (current_method);
337
338                         methods.Add (token, current_method);
339
340                         OpenMethod (symbol_token);
341                 }
342
343                 public void SetMethodSourceRange (ISymbolDocumentWriter startDoc,
344                                                   int startLine, int startColumn,
345                                                   ISymbolDocumentWriter endDoc,
346                                                   int endLine, int endColumn)
347                 {
348                         if ((startDoc == null) || (endDoc == null))
349                                 throw new NullReferenceException ();
350
351                         if (!(startDoc is MonoSymbolDocumentWriter) || !(endDoc is MonoSymbolDocumentWriter))
352                                 throw new NotSupportedException ("both startDoc and endDoc must be of type "
353                                                                  + "MonoSymbolDocumentWriter");
354
355                         if (!startDoc.Equals (endDoc))
356                                 throw new NotSupportedException ("startDoc and endDoc must be the same");
357
358                         if (current_method != null)
359                                 current_method.SetSourceRange (startLine, startColumn,
360                                                                endLine, endColumn);
361
362                         Console.WriteLine ("SOURCE RANGE");
363                 }
364
365                 public void CloseMethod () {
366                         current_method = null;
367                 }
368
369                 public void OpenNamespace (string name)
370                 {
371                 }
372
373                 public int OpenScope (int startOffset)
374                 {
375                         throw new NotImplementedException ();
376                 }
377
378                 public void SetScopeRange (int scopeID, int startOffset, int endOffset)
379                 {
380                 }
381
382                 public void SetSymAttribute (SymbolToken parent, string name, byte[] data)
383                 {
384                 }
385
386                 public void SetUnderlyingWriter (IntPtr underlyingWriter)
387                 {
388                 }
389
390                 public void SetUserEntryPoint (SymbolToken entryMethod)
391                 {
392                 }
393
394                 public void UsingNamespace (string fullName)
395                 {
396                 }
397
398                 //
399                 // MonoSymbolWriter implementation
400                 //
401                 protected void WriteMethod (DwarfFileWriter.DieCompileUnit parent_die, ISourceMethod method)
402                 {
403                         Console.WriteLine ("WRITING METHOD: " + method.MethodInfo.Name);
404
405                         DwarfFileWriter.DieSubProgram die;
406
407                         die = new DwarfFileWriter.DieSubProgram (parent_die, method);
408                 }
409
410                 protected void WriteSource (DwarfFileWriter writer, ISourceFile source)
411                 {
412                         Console.WriteLine ("WRITING SOURCE: " + writer + " " + source.FileName);
413
414                         DwarfFileWriter.CompileUnit compile_unit = new DwarfFileWriter.CompileUnit (
415                                 writer, source.FileName);
416
417                         DwarfFileWriter.DieCompileUnit die = new DwarfFileWriter.DieCompileUnit (compile_unit);
418
419                         foreach (ISourceMethod method in source.Methods)
420                                 WriteMethod (die, method);
421                 }
422
423                 protected void CreateDwarfFile (string filename)
424                 {
425                         Console.WriteLine ("WRITING DWARF FILE: " + filename);
426
427                         DwarfFileWriter writer = new DwarfFileWriter (filename);
428
429                         foreach (ISourceFile source in sources.Values)
430                                 WriteSource (writer, source);
431
432                         writer.Close ();
433
434                         Console.WriteLine ("DONE WRITING DWARF FILE");
435
436                 }
437         }
438 }