2 // Mono.CSharp.Debugger/MonoSymbolWriter.cs
5 // Martin Baulig (martin@ximian.com)
7 // This is the default implementation of the System.Diagnostics.SymbolStore.ISymbolWriter
10 // (C) 2002 Ximian, Inc. http://www.ximian.com
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 using System.Runtime.CompilerServices;
36 using System.Collections.Generic;
39 namespace Mono.CompilerServices.SymbolWriter
41 public class MonoSymbolWriter
43 List<SourceMethodBuilder> methods;
44 List<SourceFileEntry> sources;
45 List<CompileUnitEntry> comp_units;
46 protected readonly MonoSymbolFile file;
49 private SourceMethodBuilder current_method;
51 System.Collections.Stack current_method_stack = new System.Collections.Stack ();
53 Stack<SourceMethodBuilder> current_method_stack = new Stack<SourceMethodBuilder> ();
56 public MonoSymbolWriter (string filename)
58 this.methods = new List<SourceMethodBuilder> ();
59 this.sources = new List<SourceFileEntry> ();
60 this.comp_units = new List<CompileUnitEntry> ();
61 this.file = new MonoSymbolFile ();
63 this.filename = filename + ".mdb";
66 public MonoSymbolFile SymbolFile {
70 public void CloseNamespace ()
73 public void DefineLocalVariable (int index, string name)
75 if (current_method == null)
78 current_method.AddLocal (index, name);
81 public void DefineCapturedLocal (int scope_id, string name, string captured_name)
83 file.DefineCapturedVariable (scope_id, name, captured_name,
84 CapturedVariable.CapturedKind.Local);
87 public void DefineCapturedParameter (int scope_id, string name, string captured_name)
89 file.DefineCapturedVariable (scope_id, name, captured_name,
90 CapturedVariable.CapturedKind.Parameter);
93 public void DefineCapturedThis (int scope_id, string captured_name)
95 file.DefineCapturedVariable (scope_id, "this", captured_name,
96 CapturedVariable.CapturedKind.This);
99 public void DefineCapturedScope (int scope_id, int id, string captured_name)
101 file.DefineCapturedScope (scope_id, id, captured_name);
104 public void DefineScopeVariable (int scope, int index)
106 if (current_method == null)
109 current_method.AddScopeVariable (scope, index);
112 public void MarkSequencePoint (int offset, SourceFileEntry file, int line, int column,
115 if (current_method == null)
118 current_method.MarkSequencePoint (offset, file, line, column, is_hidden);
121 public SourceMethodBuilder OpenMethod (ICompileUnit file, int ns_id, IMethodDef method)
123 SourceMethodBuilder builder = new SourceMethodBuilder (file, ns_id, method);
124 current_method_stack.Push (current_method);
125 current_method = builder;
126 methods.Add (current_method);
130 public void CloseMethod ()
132 current_method = (SourceMethodBuilder) current_method_stack.Pop ();
135 public SourceFileEntry DefineDocument (string url)
137 SourceFileEntry entry = new SourceFileEntry (file, url);
142 public SourceFileEntry DefineDocument (string url, byte[] guid, byte[] checksum)
144 SourceFileEntry entry = new SourceFileEntry (file, url, guid, checksum);
149 public CompileUnitEntry DefineCompilationUnit (SourceFileEntry source)
151 CompileUnitEntry entry = new CompileUnitEntry (file, source);
152 comp_units.Add (entry);
156 public int DefineNamespace (string name, CompileUnitEntry unit,
157 string[] using_clauses, int parent)
159 if ((unit == null) || (using_clauses == null))
160 throw new NullReferenceException ();
162 return unit.DefineNamespace (name, using_clauses, parent);
165 public int OpenScope (int start_offset)
167 if (current_method == null)
170 current_method.StartBlock (CodeBlockEntry.Type.Lexical, start_offset);
174 public void CloseScope (int end_offset)
176 if (current_method == null)
179 current_method.EndBlock (end_offset);
182 public void OpenCompilerGeneratedBlock (int start_offset)
184 if (current_method == null)
187 current_method.StartBlock (CodeBlockEntry.Type.CompilerGenerated,
191 public void CloseCompilerGeneratedBlock (int end_offset)
193 if (current_method == null)
196 current_method.EndBlock (end_offset);
199 public void StartIteratorBody (int start_offset)
201 current_method.StartBlock (CodeBlockEntry.Type.IteratorBody,
205 public void EndIteratorBody (int end_offset)
207 current_method.EndBlock (end_offset);
210 public void StartIteratorDispatcher (int start_offset)
212 current_method.StartBlock (CodeBlockEntry.Type.IteratorDispatcher,
216 public void EndIteratorDispatcher (int end_offset)
218 current_method.EndBlock (end_offset);
221 public void DefineAnonymousScope (int id)
223 file.DefineAnonymousScope (id);
226 public void WriteSymbolFile (Guid guid)
228 foreach (SourceMethodBuilder method in methods)
229 method.DefineMethod (file);
232 // We mmap the file, so unlink the previous version since it may be in use
233 File.Delete (filename);
235 // We can safely ignore
237 using (FileStream fs = new FileStream (filename, FileMode.Create, FileAccess.Write)) {
238 file.CreateSymbolFile (guid, fs);
243 public class SourceMethodBuilder
245 List<LocalVariableEntry> _locals;
246 List<CodeBlockEntry> _blocks;
247 List<ScopeVariable> _scope_vars;
249 System.Collections.Stack _block_stack;
251 Stack<CodeBlockEntry> _block_stack;
255 ICompileUnit _comp_unit;
256 // MethodEntry.Flags _method_flags;
259 public SourceMethodBuilder (ICompileUnit comp_unit, int ns_id, IMethodDef method)
261 this._comp_unit = comp_unit;
262 this._method = method;
265 method_lines = new LineNumberEntry [32];
268 private LineNumberEntry [] method_lines;
269 private int method_lines_pos = 0;
271 public void MarkSequencePoint (int offset, SourceFileEntry file, int line, int column,
274 if (method_lines_pos == method_lines.Length) {
275 LineNumberEntry [] tmp = method_lines;
276 method_lines = new LineNumberEntry [method_lines.Length * 2];
277 Array.Copy (tmp, method_lines, method_lines_pos);
280 int file_idx = file != null ? file.Index : 0;
281 method_lines [method_lines_pos++] = new LineNumberEntry (
282 file_idx, line, offset, is_hidden);
285 public void StartBlock (CodeBlockEntry.Type type, int start_offset)
287 if (_block_stack == null) {
289 _block_stack = new System.Collections.Stack ();
291 _block_stack = new Stack<CodeBlockEntry> ();
296 _blocks = new List<CodeBlockEntry> ();
298 int parent = CurrentBlock != null ? CurrentBlock.Index : -1;
300 CodeBlockEntry block = new CodeBlockEntry (
301 _blocks.Count + 1, parent, type, start_offset);
303 _block_stack.Push (block);
307 public void EndBlock (int end_offset)
309 CodeBlockEntry block = (CodeBlockEntry) _block_stack.Pop ();
310 block.Close (end_offset);
313 public CodeBlockEntry[] Blocks {
316 return new CodeBlockEntry [0];
318 CodeBlockEntry[] retval = new CodeBlockEntry [_blocks.Count];
319 _blocks.CopyTo (retval, 0);
324 public CodeBlockEntry CurrentBlock {
326 if ((_block_stack != null) && (_block_stack.Count > 0))
327 return (CodeBlockEntry) _block_stack.Peek ();
333 public LocalVariableEntry[] Locals {
336 return new LocalVariableEntry [0];
338 LocalVariableEntry[] retval =
339 new LocalVariableEntry [_locals.Count];
340 _locals.CopyTo (retval, 0);
346 public void AddLocal (int index, string name)
349 _locals = new List<LocalVariableEntry> ();
350 int block_idx = CurrentBlock != null ? CurrentBlock.Index : 0;
351 _locals.Add (new LocalVariableEntry (index, name, block_idx));
354 public ScopeVariable[] ScopeVariables {
356 if (_scope_vars == null)
357 return new ScopeVariable [0];
359 ScopeVariable[] retval = new ScopeVariable [_scope_vars.Count];
360 _scope_vars.CopyTo (retval);
365 public void AddScopeVariable (int scope, int index)
367 if (_scope_vars == null)
368 _scope_vars = new List<ScopeVariable> ();
370 new ScopeVariable (scope, index));
373 public string RealMethodName {
374 get { return _real_name; }
377 public void SetRealMethodName (string name)
382 public ICompileUnit SourceFile {
383 get { return _comp_unit; }
386 public IMethodDef Method {
387 get { return _method; }
390 public void DefineMethod (MonoSymbolFile file)
392 LineNumberEntry[] lines = new LineNumberEntry [method_lines_pos];
393 Array.Copy (method_lines, lines, method_lines_pos);
395 MethodEntry entry = new MethodEntry (
396 file, _comp_unit.Entry, _method.Token, ScopeVariables,
397 Locals, lines, Blocks, RealMethodName, 0, //_method_flags,
400 file.AddMethod (entry);