[msbuild] Getting build error "Error initializing task XmlPeek: Not registered task...
[mono.git] / mcs / class / Mono.CompilerServices.SymbolWriter / MonoSymbolWriter.cs
index 7a38a2e10248935a1c0b0f7c3e0fcc39471b5621..b2c2afdba619bdf08b9f47c310f3cab2f15c99a6 100644 (file)
 
 using System;
 using System.Runtime.CompilerServices;
-using System.Collections;
+using System.Collections.Generic;
 using System.IO;
        
 namespace Mono.CompilerServices.SymbolWriter
 {
-       public interface ISourceFile
-       {
-               SourceFileEntry Entry {
-                       get;
-               }
-       }
-
-       public interface ISourceMethod
-       {
-               string Name {
-                       get;
-               }
-
-               int NamespaceID {
-                       get;
-               }
-
-               int Token {
-                       get;
-               }
-       }
-
        public class MonoSymbolWriter
        {
-               protected ArrayList locals = null;
-               protected ArrayList methods = null;
-               protected ArrayList sources = null;
+               List<SourceMethodBuilder> methods;
+               List<SourceFileEntry> sources;
+               List<CompileUnitEntry> comp_units;
                protected readonly MonoSymbolFile file;
-               private string filename = null;
+               string filename;
                
-               LineNumberEntry [] current_method_lines;
-               int current_method_lines_pos = 0;
-
-               internal ISourceFile[] Sources {
-                       get {
-                               ISourceFile[] retval = new ISourceFile [sources.Count];
-                               sources.CopyTo (retval, 0);
-                               return retval;
-                       }
-               }
-
-               private SourceMethod current_method = null;
+               private SourceMethodBuilder current_method;
+               Stack<SourceMethodBuilder> current_method_stack = new Stack<SourceMethodBuilder> ();
 
                public MonoSymbolWriter (string filename)
                {
-                       this.methods = new ArrayList ();
-                       this.sources = new ArrayList ();
-                       this.locals = new ArrayList ();
+                       this.methods = new List<SourceMethodBuilder> ();
+                       this.sources = new List<SourceFileEntry> ();
+                       this.comp_units = new List<CompileUnitEntry> ();
                        this.file = new MonoSymbolFile ();
 
                        this.filename = filename + ".mdb";
-                       
-                       this.current_method_lines = new LineNumberEntry [50];
+               }
+
+               public MonoSymbolFile SymbolFile {
+                       get { return file; }
                }
 
                public void CloseNamespace ()
                { }
 
-               public void DefineLocalVariable (int index, string name, byte[] signature)
+               public void DefineLocalVariable (int index, string name)
                {
                        if (current_method == null)
                                return;
 
-                       current_method.AddLocal (index, name, signature);
+                       current_method.AddLocal (index, name);
+               }
+
+               public void DefineCapturedLocal (int scope_id, string name, string captured_name)
+               {
+                       file.DefineCapturedVariable (scope_id, name, captured_name,
+                                                    CapturedVariable.CapturedKind.Local);
+               }
+
+               public void DefineCapturedParameter (int scope_id, string name, string captured_name)
+               {
+                       file.DefineCapturedVariable (scope_id, name, captured_name,
+                                                    CapturedVariable.CapturedKind.Parameter);
+               }
+
+               public void DefineCapturedThis (int scope_id, string captured_name)
+               {
+                       file.DefineCapturedVariable (scope_id, "this", captured_name,
+                                                    CapturedVariable.CapturedKind.This);
                }
 
-               public void MarkSequencePoint (int offset, int line, int column)
+               public void DefineCapturedScope (int scope_id, int id, string captured_name)
+               {
+                       file.DefineCapturedScope (scope_id, id, captured_name);
+               }
+
+               public void DefineScopeVariable (int scope, int index)
                {
                        if (current_method == null)
                                return;
 
-                       if (current_method_lines_pos == current_method_lines.Length) {
-                               LineNumberEntry [] tmp = current_method_lines;
-                               current_method_lines = new LineNumberEntry [current_method_lines.Length * 2];
-                               Array.Copy (tmp, current_method_lines, current_method_lines_pos);
-                       }
-                       
-                       current_method_lines [current_method_lines_pos++] = new LineNumberEntry (line, offset);
+                       current_method.AddScopeVariable (scope, index);
                }
 
-               public void OpenMethod (ISourceFile file, ISourceMethod method,
-                                       int startRow, int startColumn,
-                                       int endRow, int endColumn)
+               public void MarkSequencePoint (int offset, SourceFileEntry file, int line, int column,
+                                              bool is_hidden)
                {
-                       SourceMethod source = new SourceMethod (
-                               file, method, startRow, startColumn, endRow, endColumn);
+                       if (current_method == null)
+                               return;
 
-                       current_method = source;
+                       current_method.MarkSequencePoint (offset, file, line, column, is_hidden);
+               }
+
+               public SourceMethodBuilder OpenMethod (ICompileUnit file, int ns_id, IMethodDef method)
+               {
+                       SourceMethodBuilder builder = new SourceMethodBuilder (file, ns_id, method);
+                       current_method_stack.Push (current_method);
+                       current_method = builder;
                        methods.Add (current_method);
+                       return builder;
                }
 
                public void CloseMethod ()
                {
-                       current_method.SetLineNumbers (
-                               current_method_lines, current_method_lines_pos);
-                       current_method_lines_pos = 0;
-                       
-                       current_method = null;
+                       current_method = (SourceMethodBuilder) current_method_stack.Pop ();
                }
 
                public SourceFileEntry DefineDocument (string url)
@@ -145,188 +135,103 @@ namespace Mono.CompilerServices.SymbolWriter
                        return entry;
                }
 
-               public int DefineNamespace (string name, SourceFileEntry source,
+               public SourceFileEntry DefineDocument (string url, byte[] guid, byte[] checksum)
+               {
+                       SourceFileEntry entry = new SourceFileEntry (file, url, guid, checksum);
+                       sources.Add (entry);
+                       return entry;
+               }
+
+               public CompileUnitEntry DefineCompilationUnit (SourceFileEntry source)
+               {
+                       CompileUnitEntry entry = new CompileUnitEntry (file, source);
+                       comp_units.Add (entry);
+                       return entry;
+               }
+
+               public int DefineNamespace (string name, CompileUnitEntry unit,
                                            string[] using_clauses, int parent)
                {
-                       if ((source == null) || (using_clauses == null))
+                       if ((unit == null) || (using_clauses == null))
                                throw new NullReferenceException ();
 
-                       return source.DefineNamespace (name, using_clauses, parent);
+                       return unit.DefineNamespace (name, using_clauses, parent);
                }
 
-               public int OpenScope (int startOffset)
+               public int OpenScope (int start_offset)
                {
                        if (current_method == null)
                                return 0;
 
-                       current_method.StartBlock (startOffset);
+                       current_method.StartBlock (CodeBlockEntry.Type.Lexical, start_offset);
                        return 0;
                }
 
-               public void CloseScope (int endOffset)
+               public void CloseScope (int end_offset)
                {
                        if (current_method == null)
                                return;
 
-                       current_method.EndBlock (endOffset);
+                       current_method.EndBlock (end_offset);
                }
 
-               public void WriteSymbolFile (Guid guid)
+               public void OpenCompilerGeneratedBlock (int start_offset)
                {
-                       foreach (SourceMethod method in methods) {
-                               method.SourceFile.Entry.DefineMethod (
-                                       method.Method.Name, method.Method.Token,
-                                       method.Locals, method.Lines, method.Blocks,
-                                       method.Start.Row, method.End.Row,
-                                       method.Method.NamespaceID);
-                       }
+                       if (current_method == null)
+                               return;
 
-                       using (FileStream fs = new FileStream (filename, FileMode.Create, FileAccess.Write)) {
-                               file.CreateSymbolFile (guid, fs);
-                       }
+                       current_method.StartBlock (CodeBlockEntry.Type.CompilerGenerated,
+                                                  start_offset);
                }
 
-               protected class SourceMethod
+               public void CloseCompilerGeneratedBlock (int end_offset)
                {
-                       LineNumberEntry [] lines;
-                       private ArrayList _locals;
-                       private ArrayList _blocks;
-                       private Stack _block_stack;
-                       private int next_block_id = 0;
-                       private ISourceMethod _method;
-                       private ISourceFile _file;
-                       private LineNumberEntry _start, _end;
-
-                       private LexicalBlockEntry _implicit_block;
-
-                       public SourceMethod (ISourceFile file, ISourceMethod method,
-                                            int startLine, int startColumn,
-                                            int endLine, int endColumn)
-                       {
-                               this._file = file;
-                               this._method = method;
-
-                               this._start = new LineNumberEntry (startLine, 0);
-                               this._end = new LineNumberEntry (endLine, 0);
-
-                               this._implicit_block = new LexicalBlockEntry (0, 0);
-                       }
-
-                       public void StartBlock (int startOffset)
-                       {
-                               LexicalBlockEntry block = new LexicalBlockEntry (
-                                       ++next_block_id, startOffset);
-                               if (_block_stack == null)
-                                       _block_stack = new Stack ();
-                               _block_stack.Push (block);
-                               if (_blocks == null)
-                                       _blocks = new ArrayList ();
-                               _blocks.Add (block);
-                       }
-
-                       public void EndBlock (int endOffset)
-                       {
-                               LexicalBlockEntry block =
-                                       (LexicalBlockEntry) _block_stack.Pop ();
-
-                               block.Close (endOffset);
-                       }
-
-                       public LexicalBlockEntry[] Blocks {
-                               get {
-                                       if (_blocks == null)
-                                               return new LexicalBlockEntry [0];
-                                       else {
-                                               LexicalBlockEntry[] retval =
-                                                       new LexicalBlockEntry [_blocks.Count];
-                                               _blocks.CopyTo (retval, 0);
-                                               return retval;
-                                       }
-                               }
-                       }
+                       if (current_method == null)
+                               return;
 
-                       public LexicalBlockEntry CurrentBlock {
-                               get {
-                                       if ((_block_stack != null) && (_block_stack.Count > 0))
-                                               return (LexicalBlockEntry) _block_stack.Peek ();
-                                       else
-                                               return _implicit_block;
-                               }
-                       }
+                       current_method.EndBlock (end_offset);
+               }
 
-                       public LineNumberEntry[] Lines {
-                               get {
-                                       return lines;
-                               }
-                       }
+               public void StartIteratorBody (int start_offset)
+               {
+                       current_method.StartBlock (CodeBlockEntry.Type.IteratorBody,
+                                                  start_offset);
+               }
 
-                       public LocalVariableEntry[] Locals {
-                               get {
-                                       if (_locals == null)
-                                               return new LocalVariableEntry [0];
-                                       else {
-                                               LocalVariableEntry[] retval =
-                                                       new LocalVariableEntry [_locals.Count];
-                                               _locals.CopyTo (retval, 0);
-                                               return retval;
-                                       }
-                               }
-                       }
+               public void EndIteratorBody (int end_offset)
+               {
+                       current_method.EndBlock (end_offset);
+               }
 
-                       public void AddLocal (int index, string name, byte[] signature)
-                       {
-                               if (_locals == null)
-                                       _locals = new ArrayList ();
-                               _locals.Add (new LocalVariableEntry (
-                                                    index, name, signature, CurrentBlock.Index));
-                       }
+               public void StartIteratorDispatcher (int start_offset)
+               {
+                       current_method.StartBlock (CodeBlockEntry.Type.IteratorDispatcher,
+                                                  start_offset);
+               }
 
-                       public ISourceFile SourceFile {
-                               get { return _file; }
-                       }
+               public void EndIteratorDispatcher (int end_offset)
+               {
+                       current_method.EndBlock (end_offset);
+               }
 
-                       public ISourceMethod Method {
-                               get { return _method; }
-                       }
+               public void DefineAnonymousScope (int id)
+               {
+                       file.DefineAnonymousScope (id);
+               }
 
-                       public LineNumberEntry Start {
-                               get { return _start; }
-                       }
+               public void WriteSymbolFile (Guid guid)
+               {
+                       foreach (SourceMethodBuilder method in methods)
+                               method.DefineMethod (file);
 
-                       public LineNumberEntry End {
-                               get { return _end; }
+                       try {
+                               // We mmap the file, so unlink the previous version since it may be in use
+                               File.Delete (filename);
+                       } catch {
+                               // We can safely ignore
                        }
-
-                       //
-                       // Passes on the lines from the MonoSymbolWriter. This method is
-                       // free to mutate the lns array, and it does.
-                       //
-                       internal void SetLineNumbers (LineNumberEntry [] lns, int count)
-                       {
-                               int pos = 0;
-
-                               int last_offset = -1;
-                               int last_row = -1;
-                               for (int i = 0; i < count; i++) {
-                                       LineNumberEntry line = lns [i];
-
-                                       if (line.Offset > last_offset) {
-                                               if (last_row >= 0)
-                                                       lns [pos++] = new LineNumberEntry (
-                                                               last_row, last_offset);
-
-                                               last_row = line.Row;
-                                               last_offset = line.Offset;
-                                       } else if (line.Row > last_row) {
-                                               last_row = line.Row;
-                                       }
-                               }
-                       
-                               lines = new LineNumberEntry [count + ((last_row >= 0) ? 1 : 0)];
-                               Array.Copy (lns, lines, pos);
-                               if (last_row >= 0)
-                                       lines [pos] = new LineNumberEntry (
-                                               last_row, last_offset);
+                       using (FileStream fs = new FileStream (filename, FileMode.Create, FileAccess.Write)) {
+                               file.CreateSymbolFile (guid, fs);
                        }
                }
        }