2 // System.Diagnostics.SymbolStore/MonoSymbolWriter.cs
5 // Martin Baulig (martin@gnome.org)
7 // This is the default implementation of the System.Diagnostics.SymbolStore.ISymbolWriter
10 // (C) 2002 Ximian, Inc. http://www.ximian.com
14 using System.Reflection;
15 using System.Reflection.Emit;
16 using System.Runtime.CompilerServices;
17 using System.Diagnostics.SymbolStore;
18 using System.Collections;
21 namespace Mono.CSharp.Debugger
23 internal class SourceFile : SourceFileEntry, ISymbolDocumentWriter
25 private ArrayList _methods = new ArrayList ();
27 public SourceFile (MonoSymbolFile file, string filename)
28 : base (file, filename)
31 public new SourceMethod[] Methods {
33 SourceMethod[] retval = new SourceMethod [_methods.Count];
34 _methods.CopyTo (retval);
39 public void AddMethod (SourceMethod method)
41 _methods.Add (method);
44 void ISymbolDocumentWriter.SetCheckSum (Guid algorithmId, byte[] checkSum)
46 throw new NotSupportedException ();
49 void ISymbolDocumentWriter.SetSource (byte[] source)
51 throw new NotSupportedException ();
55 internal class SourceMethod
57 LineNumberEntry [] lines;
58 private ArrayList _locals;
59 private ArrayList _blocks;
60 private Stack _block_stack;
61 private int next_block_id = 0;
63 internal readonly MethodBase _method_base;
64 internal SourceFile _source_file;
66 private int _namespace_id;
67 private LineNumberEntry _start, _end;
68 private MonoSymbolFile _file;
70 private LexicalBlockEntry _implicit_block;
72 internal SourceMethod (MonoSymbolFile file, SourceFile source_file,
73 int startLine, int startColumn, int endLine, int endColumn,
74 MethodBase method_base, int namespace_id)
77 this._method_base = method_base;
78 this._source_file = source_file;
79 this._namespace_id = namespace_id;
81 this._start = new LineNumberEntry (startLine, 0);
82 this._end = new LineNumberEntry (endLine, 0);
84 this._implicit_block = new LexicalBlockEntry (0, 0);
87 public void StartBlock (int startOffset)
89 LexicalBlockEntry block = new LexicalBlockEntry (++next_block_id, startOffset);
90 if (_block_stack == null)
91 _block_stack = new Stack ();
92 _block_stack.Push (block);
94 _blocks = new ArrayList ();
98 public void EndBlock (int endOffset)
100 LexicalBlockEntry block = (LexicalBlockEntry) _block_stack.Pop ();
102 block.Close (endOffset);
105 public LexicalBlockEntry[] Blocks {
108 return new LexicalBlockEntry [0];
110 LexicalBlockEntry[] retval = new LexicalBlockEntry [_blocks.Count];
111 _blocks.CopyTo (retval, 0);
117 public LexicalBlockEntry CurrentBlock {
119 if ((_block_stack != null) && (_block_stack.Count > 0))
120 return (LexicalBlockEntry) _block_stack.Peek ();
122 return _implicit_block;
126 public LineNumberEntry[] Lines {
132 public LocalVariableEntry[] Locals {
135 return new LocalVariableEntry [0];
137 LocalVariableEntry[] retval = new LocalVariableEntry [_locals.Count];
138 _locals.CopyTo (retval, 0);
144 public void AddLocal (string name, FieldAttributes attributes, byte[] signature)
147 _locals = new ArrayList ();
148 _locals.Add (new LocalVariableEntry (name, attributes, signature, CurrentBlock.Index));
151 public MethodBase MethodBase {
157 public string FullName {
159 return _method_base.DeclaringType.FullName + "." + _method_base.Name;
163 public Type ReturnType {
165 if (_method_base is MethodInfo)
166 return ((MethodInfo)_method_base).ReturnType;
167 else if (_method_base is ConstructorInfo)
168 return _method_base.DeclaringType;
170 throw new NotSupportedException ();
174 public ParameterInfo[] Parameters {
176 if (_method_base == null)
177 return new ParameterInfo [0];
179 ParameterInfo [] retval = _method_base.GetParameters ();
181 return new ParameterInfo [0];
187 public SourceFile SourceFile {
198 throw new NotSupportedException ();
202 public bool HasSource {
204 return _source_file != null;
208 public LineNumberEntry Start {
214 public LineNumberEntry End {
220 public int NamespaceID {
222 return _namespace_id;
227 // Passes on the lines from the MonoSymbolWriter. This method is
228 // free to mutate the lns array, and it does.
230 internal void SetLineNumbers (LineNumberEntry [] lns, int count)
234 int last_offset = -1;
236 for (int i = 0; i < count; i++) {
237 LineNumberEntry line = lns [i];
239 if (line.Offset > last_offset) {
241 lns [pos++] = new LineNumberEntry (last_row, last_offset);
244 last_offset = line.Offset;
245 } else if (line.Row > last_row) {
250 lines = new LineNumberEntry [count + ((last_row >= 0) ? 1 : 0)];
251 Array.Copy (lns, lines, pos);
253 lines [pos] = new LineNumberEntry (last_row, last_offset);
257 public class MonoSymbolWriter : IMonoSymbolWriter
259 protected ModuleBuilder module_builder;
260 protected ArrayList locals = null;
261 protected ArrayList orphant_methods = null;
262 protected ArrayList methods = null;
263 protected Hashtable sources = null;
264 private MonoSymbolFile file = null;
266 LineNumberEntry [] current_method_lines;
267 int current_method_lines_pos = 0;
269 internal SourceMethod[] Methods {
271 SourceMethod[] retval = new SourceMethod [methods.Count];
272 methods.CopyTo (retval);
277 internal SourceFile[] Sources {
279 SourceFile[] retval = new SourceFile [sources.Count];
280 sources.Values.CopyTo (retval, 0);
285 private SourceMethod current_method = null;
288 // Interface IMonoSymbolWriter
291 public MonoSymbolWriter (ModuleBuilder mb)
293 this.module_builder = mb;
294 this.methods = new ArrayList ();
295 this.sources = new Hashtable ();
296 this.orphant_methods = new ArrayList ();
297 this.locals = new ArrayList ();
298 this.file = new MonoSymbolFile ();
300 this.current_method_lines = new LineNumberEntry [50];
305 throw new InvalidOperationException ();
308 public byte[] CreateSymbolFile (AssemblyBuilder assembly_builder)
310 DoFixups (assembly_builder);
312 return CreateOutput (assembly_builder);
315 public void CloseNamespace () {
318 // Create and return a new IMonoSymbolDocumentWriter.
319 public ISymbolDocumentWriter DefineDocument (string url,
324 if (sources.ContainsKey (url))
325 return (ISymbolDocumentWriter)sources [url];
326 SourceFile source_info = new SourceFile (file, url);
327 sources.Add (url, source_info);
331 public void DefineField (
334 FieldAttributes attributes,
336 SymAddressKind addrKind,
341 throw new NotSupportedException ();
344 public void DefineGlobalVariable (
346 FieldAttributes attributes,
348 SymAddressKind addrKind,
353 throw new NotSupportedException ();
356 public void DefineLocalVariable (string name,
357 FieldAttributes attributes,
359 SymAddressKind addrKind,
366 if (current_method == null)
369 current_method.AddLocal (name, attributes, signature);
372 public void DefineParameter (string name,
373 ParameterAttributes attributes,
375 SymAddressKind addrKind,
380 throw new NotSupportedException ();
383 public void DefineSequencePoints (ISymbolDocumentWriter document,
390 throw new NotSupportedException ();
393 public void MarkSequencePoint (int offset, int line, int column)
395 if (current_method == null)
398 if (current_method_lines_pos == current_method_lines.Length) {
399 LineNumberEntry [] tmp = current_method_lines;
400 current_method_lines = new LineNumberEntry [current_method_lines.Length * 2];
401 Array.Copy (tmp, current_method_lines, current_method_lines_pos);
404 current_method_lines [current_method_lines_pos++] = new LineNumberEntry (line, offset);
407 public void Initialize (IntPtr emitter, string filename, bool fFullBuild)
409 throw new NotSupportedException ();
412 public void OpenMethod (SymbolToken symbol_token)
414 throw new NotSupportedException ();
417 public void SetMethodSourceRange (ISymbolDocumentWriter startDoc,
418 int startLine, int startColumn,
419 ISymbolDocumentWriter endDoc,
420 int endLine, int endColumn)
422 throw new NotSupportedException ();
425 public void OpenMethod (ISymbolDocumentWriter document, int startLine, int startColumn,
426 int endLine, int endColumn, MethodBase method, int namespace_id)
428 SourceFile source_info = document as SourceFile;
430 if ((source_info == null) || (method == null))
431 throw new NullReferenceException ();
433 current_method = new SourceMethod (file, source_info, startLine, startColumn,
434 endLine, endColumn, method, namespace_id);
436 methods.Add (current_method);
437 source_info.AddMethod (current_method);
440 public void CloseMethod ()
442 current_method.SetLineNumbers (current_method_lines, current_method_lines_pos);
443 current_method_lines_pos = 0;
445 current_method = null;
448 public int DefineNamespace (string name, ISymbolDocumentWriter document,
449 string[] using_clauses, int parent)
451 if ((document == null) || (using_clauses == null))
452 throw new NullReferenceException ();
453 if (!(document is SourceFile))
454 throw new ArgumentException ();
456 SourceFile source_info = (SourceFile) document;
458 return source_info.DefineNamespace (name, using_clauses, parent);
461 public void OpenNamespace (string name)
463 throw new NotSupportedException ();
466 public int OpenScope (int startOffset)
468 if (current_method == null)
471 current_method.StartBlock (startOffset);
475 public void CloseScope (int endOffset)
477 if (current_method == null)
480 current_method.EndBlock (endOffset);
483 public void SetScopeRange (int scopeID, int startOffset, int endOffset)
485 throw new NotSupportedException ();
488 public void SetSymAttribute (SymbolToken parent, string name, byte[] data)
490 throw new NotSupportedException ();
493 public void SetUnderlyingWriter (IntPtr underlyingWriter)
495 throw new NotSupportedException ();
498 public void SetUserEntryPoint (SymbolToken entryMethod)
500 throw new NotSupportedException ();
503 public void UsingNamespace (string fullName)
505 throw new NotSupportedException ();
509 // MonoSymbolWriter implementation
511 protected void DoFixups (Assembly assembly)
513 foreach (SourceMethod method in methods) {
514 if (method._method_base is MethodBuilder) {
515 MethodBuilder mb = (MethodBuilder) method._method_base;
516 method._token = mb.GetToken ().Token;
517 } else if (method._method_base is ConstructorBuilder) {
518 ConstructorBuilder cb = (ConstructorBuilder) method._method_base;
519 method._token = cb.GetToken ().Token;
521 throw new NotSupportedException ();
523 if (method.SourceFile == null)
524 orphant_methods.Add (method);
528 protected byte[] CreateOutput (Assembly assembly)
530 foreach (SourceMethod method in Methods) {
531 if (!method.HasSource) {
532 Console.WriteLine ("INGORING METHOD: {0}", method);
536 method.SourceFile.DefineMethod (
537 method.MethodBase, method.Token, method.Locals,
538 method.Lines, method.Blocks, method.Start.Row, method.End.Row,
542 return file.CreateSymbolFile ();