Set more state on TaskCompletionSource inner Task<T>
[mono.git] / mcs / class / Mono.CompilerServices.SymbolWriter / MonoSymbolWriter.cs
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
34 using System;
35 using System.Runtime.CompilerServices;
36 using System.Collections.Generic;
37 using System.IO;
38         
39 namespace 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 }