Free cookie consent management tool by TermsFeed Policy Generator

source: stable/HeuristicLab.ExtLibs/HeuristicLab.Cecil/0.9.5/Mono.Cecil-0.9.5/Symbols/Mono.Cecil.Mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolWriter.cs @ 12931

Last change on this file since 12931 was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

File size: 10.3 KB
Line 
1//
2// Mono.CSharp.Debugger/MonoSymbolWriter.cs
3//
4// Author:
5//   Martin Baulig (martin@ximian.com)
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//
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:
21//
22// The above copyright notice and this permission notice shall be
23// included in all copies or substantial portions of the Software.
24//
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.
32//
33
34using System;
35using System.Runtime.CompilerServices;
36using System.Collections.Generic;
37using System.IO;
38
39namespace Mono.CompilerServices.SymbolWriter
40{
41  public class MonoSymbolWriter
42  {
43    List<SourceMethodBuilder> methods;
44    List<SourceFileEntry> sources;
45    List<CompileUnitEntry> comp_units;
46    protected readonly MonoSymbolFile file;
47    string filename;
48
49    private SourceMethodBuilder current_method;
50#if NET_2_1
51    System.Collections.Stack current_method_stack = new System.Collections.Stack ();
52#else
53    Stack<SourceMethodBuilder> current_method_stack = new Stack<SourceMethodBuilder> ();
54#endif
55
56    public MonoSymbolWriter (string filename)
57    {
58      this.methods = new List<SourceMethodBuilder> ();
59      this.sources = new List<SourceFileEntry> ();
60      this.comp_units = new List<CompileUnitEntry> ();
61      this.file = new MonoSymbolFile ();
62
63      this.filename = filename + ".mdb";
64    }
65
66    public MonoSymbolFile SymbolFile {
67      get { return file; }
68    }
69
70    public void CloseNamespace ()
71    { }
72
73    public void DefineLocalVariable (int index, string name)
74    {
75      if (current_method == null)
76        return;
77
78      current_method.AddLocal (index, name);
79    }
80
81    public void DefineCapturedLocal (int scope_id, string name, string captured_name)
82    {
83      file.DefineCapturedVariable (scope_id, name, captured_name,
84                 CapturedVariable.CapturedKind.Local);
85    }
86
87    public void DefineCapturedParameter (int scope_id, string name, string captured_name)
88    {
89      file.DefineCapturedVariable (scope_id, name, captured_name,
90                 CapturedVariable.CapturedKind.Parameter);
91    }
92
93    public void DefineCapturedThis (int scope_id, string captured_name)
94    {
95      file.DefineCapturedVariable (scope_id, "this", captured_name,
96                 CapturedVariable.CapturedKind.This);
97    }
98
99    public void DefineCapturedScope (int scope_id, int id, string captured_name)
100    {
101      file.DefineCapturedScope (scope_id, id, captured_name);
102    }
103
104    public void DefineScopeVariable (int scope, int index)
105    {
106      if (current_method == null)
107        return;
108
109      current_method.AddScopeVariable (scope, index);
110    }
111
112    public void MarkSequencePoint (int offset, SourceFileEntry file, int line, int column,
113                 bool is_hidden)
114    {
115      if (current_method == null)
116        return;
117
118      current_method.MarkSequencePoint (offset, file, line, column, is_hidden);
119    }
120
121    public SourceMethodBuilder OpenMethod (ICompileUnit file, int ns_id, IMethodDef method)
122    {
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);
127      return builder;
128    }
129
130    public void CloseMethod ()
131    {
132      current_method = (SourceMethodBuilder) current_method_stack.Pop ();
133    }
134
135    public SourceFileEntry DefineDocument (string url)
136    {
137      SourceFileEntry entry = new SourceFileEntry (file, url);
138      sources.Add (entry);
139      return entry;
140    }
141
142    public SourceFileEntry DefineDocument (string url, byte[] guid, byte[] checksum)
143    {
144      SourceFileEntry entry = new SourceFileEntry (file, url, guid, checksum);
145      sources.Add (entry);
146      return entry;
147    }
148
149    public CompileUnitEntry DefineCompilationUnit (SourceFileEntry source)
150    {
151      CompileUnitEntry entry = new CompileUnitEntry (file, source);
152      comp_units.Add (entry);
153      return entry;
154    }
155
156    public int DefineNamespace (string name, CompileUnitEntry unit,
157              string[] using_clauses, int parent)
158    {
159      if ((unit == null) || (using_clauses == null))
160        throw new NullReferenceException ();
161
162      return unit.DefineNamespace (name, using_clauses, parent);
163    }
164
165    public int OpenScope (int start_offset)
166    {
167      if (current_method == null)
168        return 0;
169
170      current_method.StartBlock (CodeBlockEntry.Type.Lexical, start_offset);
171      return 0;
172    }
173
174    public void CloseScope (int end_offset)
175    {
176      if (current_method == null)
177        return;
178
179      current_method.EndBlock (end_offset);
180    }
181
182    public void OpenCompilerGeneratedBlock (int start_offset)
183    {
184      if (current_method == null)
185        return;
186
187      current_method.StartBlock (CodeBlockEntry.Type.CompilerGenerated,
188               start_offset);
189    }
190
191    public void CloseCompilerGeneratedBlock (int end_offset)
192    {
193      if (current_method == null)
194        return;
195
196      current_method.EndBlock (end_offset);
197    }
198
199    public void StartIteratorBody (int start_offset)
200    {
201      current_method.StartBlock (CodeBlockEntry.Type.IteratorBody,
202               start_offset);
203    }
204
205    public void EndIteratorBody (int end_offset)
206    {
207      current_method.EndBlock (end_offset);
208    }
209
210    public void StartIteratorDispatcher (int start_offset)
211    {
212      current_method.StartBlock (CodeBlockEntry.Type.IteratorDispatcher,
213               start_offset);
214    }
215
216    public void EndIteratorDispatcher (int end_offset)
217    {
218      current_method.EndBlock (end_offset);
219    }
220
221    public void DefineAnonymousScope (int id)
222    {
223      file.DefineAnonymousScope (id);
224    }
225
226    public void WriteSymbolFile (Guid guid)
227    {
228      foreach (SourceMethodBuilder method in methods)
229        method.DefineMethod (file);
230
231      try {
232        // We mmap the file, so unlink the previous version since it may be in use
233        File.Delete (filename);
234      } catch {
235        // We can safely ignore
236      }
237      using (FileStream fs = new FileStream (filename, FileMode.Create, FileAccess.Write)) {
238        file.CreateSymbolFile (guid, fs);
239      }
240    }
241  }
242
243  public class SourceMethodBuilder
244  {
245    List<LocalVariableEntry> _locals;
246    List<CodeBlockEntry> _blocks;
247    List<ScopeVariable> _scope_vars;
248#if NET_2_1
249    System.Collections.Stack _block_stack;
250#else
251    Stack<CodeBlockEntry> _block_stack;
252#endif
253    string _real_name;
254    IMethodDef _method;
255    ICompileUnit _comp_unit;
256//    MethodEntry.Flags _method_flags;
257    int _ns_id;
258
259    public SourceMethodBuilder (ICompileUnit comp_unit, int ns_id, IMethodDef method)
260    {
261      this._comp_unit = comp_unit;
262      this._method = method;
263      this._ns_id = ns_id;
264
265      method_lines = new LineNumberEntry [32];
266    }
267
268    private LineNumberEntry [] method_lines;
269    private int method_lines_pos = 0;
270
271    public void MarkSequencePoint (int offset, SourceFileEntry file, int line, int column,
272                 bool is_hidden)
273    {
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);
278      }
279
280      int file_idx = file != null ? file.Index : 0;
281      method_lines [method_lines_pos++] = new LineNumberEntry (
282        file_idx, line, offset, is_hidden);
283    }
284
285    public void StartBlock (CodeBlockEntry.Type type, int start_offset)
286    {
287      if (_block_stack == null) {
288#if NET_2_1
289        _block_stack = new System.Collections.Stack ();
290#else
291        _block_stack = new Stack<CodeBlockEntry> ();
292#endif
293      }
294
295      if (_blocks == null)
296        _blocks = new List<CodeBlockEntry> ();
297
298      int parent = CurrentBlock != null ? CurrentBlock.Index : -1;
299
300      CodeBlockEntry block = new CodeBlockEntry (
301        _blocks.Count + 1, parent, type, start_offset);
302
303      _block_stack.Push (block);
304      _blocks.Add (block);
305    }
306
307    public void EndBlock (int end_offset)
308    {
309      CodeBlockEntry block = (CodeBlockEntry) _block_stack.Pop ();
310      block.Close (end_offset);
311    }
312
313    public CodeBlockEntry[] Blocks {
314      get {
315        if (_blocks == null)
316          return new CodeBlockEntry [0];
317
318        CodeBlockEntry[] retval = new CodeBlockEntry [_blocks.Count];
319        _blocks.CopyTo (retval, 0);
320        return retval;
321      }
322    }
323
324    public CodeBlockEntry CurrentBlock {
325      get {
326        if ((_block_stack != null) && (_block_stack.Count > 0))
327          return (CodeBlockEntry) _block_stack.Peek ();
328        else
329          return null;
330      }
331    }
332
333    public LocalVariableEntry[] Locals {
334      get {
335        if (_locals == null)
336          return new LocalVariableEntry [0];
337        else {
338          LocalVariableEntry[] retval =
339            new LocalVariableEntry [_locals.Count];
340          _locals.CopyTo (retval, 0);
341          return retval;
342        }
343      }
344    }
345
346    public void AddLocal (int index, string name)
347    {
348      if (_locals == null)
349        _locals = new List<LocalVariableEntry> ();
350      int block_idx = CurrentBlock != null ? CurrentBlock.Index : 0;
351      _locals.Add (new LocalVariableEntry (index, name, block_idx));
352    }
353
354    public ScopeVariable[] ScopeVariables {
355      get {
356        if (_scope_vars == null)
357          return new ScopeVariable [0];
358
359        ScopeVariable[] retval = new ScopeVariable [_scope_vars.Count];
360        _scope_vars.CopyTo (retval);
361        return retval;
362      }
363    }
364
365    public void AddScopeVariable (int scope, int index)
366    {
367      if (_scope_vars == null)
368        _scope_vars = new List<ScopeVariable> ();
369      _scope_vars.Add (
370        new ScopeVariable (scope, index));
371    }
372
373    public string RealMethodName {
374      get { return _real_name; }
375    }
376
377    public void SetRealMethodName (string name)
378    {
379      _real_name = name;
380    }
381
382    public ICompileUnit SourceFile {
383      get { return _comp_unit; }
384    }
385
386    public IMethodDef Method {
387      get { return _method; }
388    }
389
390    public void DefineMethod (MonoSymbolFile file)
391    {
392      LineNumberEntry[] lines = new LineNumberEntry [method_lines_pos];
393      Array.Copy (method_lines, lines, method_lines_pos);
394
395      MethodEntry entry = new MethodEntry (
396        file, _comp_unit.Entry, _method.Token, ScopeVariables,
397        Locals, lines, Blocks, RealMethodName, 0, //_method_flags,
398        _ns_id);
399
400      file.AddMethod (entry);
401    }
402  }
403}
Note: See TracBrowser for help on using the repository browser.