2004-10-20 Martin Baulig <martin@ximian.com>
[mono.git] / mcs / class / Mono.CSharp.Debugger / MonoSymbolWriter.cs
index bbd9ed35e355cdfcee2a8a2f164084cb0fbbccc2..10fc8ce88af4dc540bc18f96b2e457de9dbe26b5 100755 (executable)
@@ -1,8 +1,8 @@
 //
-// System.Diagnostics.SymbolStore/MonoSymbolWriter.cs
+// Mono.CSharp.Debugger/MonoSymbolWriter.cs
 //
 // Author:
-//   Martin Baulig (martin@gnome.org)
+//   Martin Baulig (martin@ximian.com)
 //
 // This is the default implementation of the System.Diagnostics.SymbolStore.ISymbolWriter
 // interface.
 // (C) 2002 Ximian, Inc.  http://www.ximian.com
 //
 
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
 using System;
-using System.Reflection;
-using System.Reflection.Emit;
 using System.Runtime.CompilerServices;
-using System.Diagnostics.SymbolStore;
 using System.Collections;
 using System.IO;
        
-namespace Mono.CSharp.Debugger
+namespace Mono.CompilerServices.SymbolWriter
 {
-       public class SourceFile : ISourceFile
+       public interface ISourceFile
        {
-               private ArrayList _methods = new ArrayList ();
-               private string _file_name;
-
-               public SourceFile (string filename)
-               {
-                       this._file_name = filename;
-               }
-
-               public override string ToString ()
-               {
-                       return _file_name;
-               }
-
-               // interface ISourceFile
-
-               public string FileName {
-                       get {
-                               return _file_name;
-                       }
-               }
-
-               public ISourceMethod[] Methods {
-                       get {
-                               ISourceMethod[] retval = new ISourceMethod [_methods.Count];
-                               _methods.CopyTo (retval);
-                               return retval;
-                       }
-               }
-
-               public void AddMethod (ISourceMethod method)
-               {
-                       _methods.Add (method);
+               SourceFileEntry Entry {
+                       get;
                }
        }
 
-       public class SourceBlock : ISourceBlock
+       public interface ISourceMethod
        {
-               static private int next_index;
-               private readonly int _index;
-
-               public SourceBlock (ISourceMethod method, ISourceLine start, ISourceLine end)
-               {
-                       this._method = method;
-                       this._start = start;
-                       this._end = end;
-                       this._index = ++next_index;
-               }
-
-               internal SourceBlock (ISourceMethod method, int startOffset)
-               {
-                       this._method = method;
-                       this._start = new SourceLine (startOffset);
-                       this._index = ++next_index;
-               }
-
-               public override string ToString ()
-               {
-                       return "SourceBlock #" + ID + " (" + Start + " - " + End + ")";
-               }
-
-               private readonly ISourceMethod _method;
-               private ArrayList _blocks = new ArrayList ();
-               internal ISourceLine _start;
-               internal ISourceLine _end;
-
-               private ArrayList _locals = new ArrayList ();
-
-               public ISourceMethod SourceMethod {
-                       get {
-                               return _method;
-                       }
-               }
-
-               public ISourceBlock[] Blocks {
-                       get {
-                               ISourceBlock[] retval = new ISourceBlock [_blocks.Count];
-                               _blocks.CopyTo (retval);
-                               return retval;
-                       }
-               }
-
-               public void AddBlock (ISourceBlock block)
-               {
-                       _blocks.Add (block);
-               }
-
-               public ISourceLine Start {
-                       get {
-                               return _start;
-                       }
-               }
-
-               public ISourceLine End {
-                       get {
-                               return _end;
-                       }
-               }
-
-               public int ID {
-                       get {
-                               return _index;
-                       }
-               }
-
-               public ILocalVariable[] Locals {
-                       get {
-                               ILocalVariable[] retval = new ILocalVariable [_locals.Count];
-                               _locals.CopyTo (retval);
-                               return retval;
-                       }
-               }
-
-               public void AddLocal (ILocalVariable local)
-               {
-                       _locals.Add (local);
-               }
-       }
-
-       public class SourceLine : ISourceLine
-       {
-               public SourceLine (int row, int column)
-                       : this (0, row, column)
-               {
-                       this._type = SourceOffsetType.OFFSET_NONE;
-               }
-
-               public SourceLine (int offset, int row, int column)
-               {
-                       this._offset = offset;
-                       this._row = row;
-                       this._column = column;
-                       this._type = SourceOffsetType.OFFSET_IL;
-               }
-
-               internal SourceLine (int offset)
-                       : this (offset, 0, 0)
-               { }
-
-               public override string ToString ()
-               {
-                       return "SourceLine (" + _offset + "@" + _row + ":" + _column + ")";
-               }
-
-               internal SourceOffsetType _type;
-               internal int _offset;
-               internal int _row;
-               internal int _column;
-
-               // interface ISourceLine
-
-               public SourceOffsetType OffsetType {
-                       get {
-                               return _type;
-                       }
-               }
-
-               public int Offset {
-                       get {
-                               return _offset;
-                       }
-               }
-
-               public int Row {
-                       get {
-                               return _row;
-                       }
-               }
-
-               public int Column {
-                       get {
-                               return _column;
-                       }
-               }
-       }
-
-       public class Variable : IVariable
-       {
-               public Variable (string name, ITypeHandle handle, ISourceMethod method, int index)
-                       : this (name, handle, method, index, null)
-               { }
-
-               public Variable (string name, ITypeHandle handle, ISourceMethod method,
-                                int index, ISourceLine line)
-               {
-                       this._name = name;
-                       this._handle = handle;
-                       this._method = method;
-                       this._line = line;
-                       this._index = index;
-               }
-
-               private readonly string _name;
-               private readonly ITypeHandle _handle;
-               private readonly ISourceMethod _method;
-               private readonly ISourceLine _line;
-               private readonly int _index;
-
-               // interface IVariable
-
-               public string Name {
-                       get {
-                               return _name;
-                       }
-               }
-
-               public ISourceMethod Method {
-                       get {
-                               return _method;
-                       }
-               }
-
-               public int Index {
-                       get {
-                               return _index;
-                       }
-               }
-
-               public ITypeHandle TypeHandle {
-                       get {
-                               return _handle;
-                       }
-               }
-
-               public ISourceLine Line {
-                       get {
-                               return _line;
-                       }
-               }
-       }
-
-       public class LocalVariable : Variable, ILocalVariable
-       {
-               public LocalVariable (string name, ITypeHandle handle, ISourceMethod method,
-                                     int index, ISourceLine line)
-                       : base (name, handle, method, index, line)
-               { }
-
-               public override string ToString ()
-               {
-                       return "LocalVariable (" + Index + "," + Name + ")";
-               }
-       }
-
-       public class MethodParameter : Variable, IMethodParameter
-       {
-               private static int get_index (ISourceMethod method, ParameterInfo param)
-               {
-                       return method.MethodBase.IsStatic ? param.Position - 1 :
-                               param.Position;
-               }
-
-               public MethodParameter (DwarfFileWriter writer, ISourceMethod method,
-                                       ParameterInfo param)
-                       : base (param.Name, writer.RegisterType (param.ParameterType),
-                               method, get_index (method, param))
-               {
-                       this._method = method;
-                       this._param = param;
-               }
-
-               private readonly ISourceMethod _method;
-               private readonly ParameterInfo _param;
-       }
-
-       public class SourceMethod : ISourceMethod
-       {
-               private ArrayList _lines = new ArrayList ();
-               private ArrayList _blocks = new ArrayList ();
-               private Hashtable _block_hash = new Hashtable ();
-               private Stack _block_stack = new Stack ();
-
-               internal readonly MethodBase _method_base;
-               internal ISourceFile _source_file;
-               internal int _token;
-
-               private SourceBlock _implicit_block;
-
-               public SourceMethod (MethodBase method_base, ISourceFile source_file)
-                       : this (method_base)
-               {
-                       this._source_file = source_file;
-               }
-
-               internal SourceMethod (MethodBase method_base)
-               {
-                       this._method_base = method_base;
-
-                       this._implicit_block = new SourceBlock (this, 0);
-               }
-
-               public void SetSourceRange (ISourceFile sourceFile,
-                                           int startLine, int startColumn,
-                                           int endLine, int endColumn)
-               {
-                       _source_file = sourceFile;
-                       _implicit_block._start = new SourceLine (startLine, startColumn);
-                       _implicit_block._end = new SourceLine (endLine, endColumn);
-               }
-
-
-               public void StartBlock (ISourceBlock block)
-               {
-                       _block_stack.Push (block);
-               }
-
-               public void EndBlock (int endOffset) {
-                       SourceBlock block = (SourceBlock) _block_stack.Pop ();
-
-                       block._end = new SourceLine (endOffset);
-
-                       if (_block_stack.Count > 0) {
-                               ISourceBlock parent = (ISourceBlock) _block_stack.Peek ();
-
-                               parent.AddBlock (block);
-                       } else
-                               _blocks.Add (block);
-
-                       _block_hash.Add (block.ID, block);
+               string Name {
+                       get;
                }
 
-               public void SetBlockRange (int BlockID, int startOffset, int endOffset)
-               {
-                       SourceBlock block = (SourceBlock) _block_hash [BlockID];
-                       ((SourceLine) block.Start)._offset = startOffset;
-                       ((SourceLine) block.End)._offset = endOffset;
+               int NamespaceID {
+                       get;
                }
 
-               public ISourceBlock CurrentBlock {
-                       get {
-                               if (_block_stack.Count > 0)
-                                       return (ISourceBlock) _block_stack.Peek ();
-                               else
-                                       return _implicit_block;
-                       }
-               }
-
-               // interface ISourceMethod
-
-               public ISourceLine[] Lines {
-                       get {
-                               ISourceLine[] retval = new ISourceLine [_lines.Count];
-                               _lines.CopyTo (retval);
-                               return retval;
-                       }
-               }
-
-               public void AddLine (ISourceLine line)
-               {
-                       _lines.Add (line);
-               }
-
-               public ISourceBlock[] Blocks {
-                       get {
-                               ISourceBlock[] retval = new ISourceBlock [_blocks.Count];
-                               _blocks.CopyTo (retval);
-                               return retval;
-                       }
-               }
-
-               public ILocalVariable[] Locals {
-                       get {
-                               return _implicit_block.Locals;
-                       }
-               }
-
-               public void AddLocal (ILocalVariable local)
-               {
-                       _implicit_block.AddLocal (local);
-               }
-
-               public MethodBase MethodBase {
-                       get {
-                               return _method_base;
-                       }
-               }
-
-               public string FullName {
-                       get {
-                               return _method_base.DeclaringType.FullName + "." + _method_base.Name;
-                       }
-               }
-
-               public Type ReturnType {
-                       get {
-                               if (_method_base is MethodInfo)
-                                       return ((MethodInfo)_method_base).ReturnType;
-                               else if (_method_base is ConstructorInfo)
-                                       return _method_base.DeclaringType;
-                               else
-                                       throw new NotSupportedException ();
-                       }
-               }
-
-               public ParameterInfo[] Parameters {
-                       get {
-                               if (_method_base == null)
-                                       return new ParameterInfo [0];
-
-                               ParameterInfo [] retval = _method_base.GetParameters ();
-                               if (retval == null)
-                                       return new ParameterInfo [0];
-                               else
-                                       return retval;
-                       }
-               }
-
-               public ISourceFile SourceFile {
-                       get {
-                               return _source_file;
-                       }
-               }
-
-               public int Token {
-                       get {
-                               if (_token != 0)
-                                       return _token;
-                               else
-                                       throw new NotSupportedException ();
-                       }
-               }
-
-               public ISourceLine Start {
-                       get {
-                               return _implicit_block.Start;
-                       }
-               }
-
-               public ISourceLine End {
-                       get {
-                               return _implicit_block.End;
-                       }
+               int Token {
+                       get;
                }
        }
 
-       public class MonoSymbolWriter : IMonoSymbolWriter
+       public class MonoSymbolWriter
        {
-               protected Assembly assembly;
-               protected ModuleBuilder module_builder;
-               protected string output_filename = null;
                protected ArrayList locals = null;
-               protected ArrayList orphant_methods = null;
                protected ArrayList methods = null;
-               protected Hashtable sources = null;
-               protected DwarfFileWriter writer = null;
-
-               public ISourceMethod[] Methods {
-                       get {
-                               ISourceMethod[] retval = new ISourceMethod [methods.Count];
-                               methods.CopyTo (retval);
-                               return retval;
-                       }
-               }
+               protected ArrayList sources = null;
+               protected readonly MonoSymbolFile file;
+               private string filename = null;
+               
+               LineNumberEntry [] current_method_lines;
+               int current_method_lines_pos = 0;
 
-               public ISourceFile[] Sources {
+               internal ISourceFile[] Sources {
                        get {
                                ISourceFile[] retval = new ISourceFile [sources.Count];
-                               sources.Values.CopyTo (retval, 0);
+                               sources.CopyTo (retval, 0);
                                return retval;
                        }
                }
 
-               public DwarfFileWriter DwarfFileWriter {
-                       get {
-                               return writer;
-                       }
-               }
-
-               protected SourceMethod current_method = null;
-               private readonly string assembly_filename = null;
+               private SourceMethod current_method = null;
 
                //
                // Interface IMonoSymbolWriter
                //
 
-               public MonoSymbolWriter (ModuleBuilder mb, string filename)
+               public MonoSymbolWriter (string filename)
                {
-                       this.assembly_filename = filename;
-                       this.module_builder = mb;
                        this.methods = new ArrayList ();
-                       this.sources = new Hashtable ();
-                       this.orphant_methods = new ArrayList ();
+                       this.sources = new ArrayList ();
                        this.locals = new ArrayList ();
-               }
-
-               public void Close () {
-                       if (assembly == null)
-                               assembly = Assembly.LoadFrom (assembly_filename);
+                       this.file = new MonoSymbolFile ();
 
-                       DoFixups (assembly);
-
-                       CreateDwarfFile (assembly);
-               }
-
-               public void CloseNamespace () {
-               }
-
-               // Create and return a new IMonoSymbolDocumentWriter.
-               public ISymbolDocumentWriter DefineDocument (string url,
-                                                            Guid language,
-                                                            Guid languageVendor,
-                                                            Guid documentType)
-               {
-                       return new MonoSymbolDocumentWriter (url);
+                       this.filename = filename + ".mdb";
+                       
+                       this.current_method_lines = new LineNumberEntry [50];
                }
 
-               public void DefineField (
-                       SymbolToken parent,
-                       string name,
-                       FieldAttributes attributes,
-                       byte[] signature,
-                       SymAddressKind addrKind,
-                       int addr1,
-                       int addr2,
-                       int addr3)
-               {
-               }
+               public void CloseNamespace ()
+               { }
 
-               public void DefineGlobalVariable (
-                       string name,
-                       FieldAttributes attributes,
-                       byte[] signature,
-                       SymAddressKind addrKind,
-                       int addr1,
-                       int addr2,
-                       int addr3)
+               public void DefineLocalVariable (string name, byte[] signature)
                {
-               }
+                       if (current_method == null)
+                               return;
 
-               public void DefineLocalVariable (string name,
-                                                FieldAttributes attributes,
-                                                byte[] signature,
-                                                SymAddressKind addrKind,
-                                                int addr1,
-                                                int addr2,
-                                                int addr3,
-                                                int startOffset,
-                                                int endOffset)
-               {
-                       throw new NotSupportedException ();
+                       current_method.AddLocal (name, signature);
                }
 
-               public void DefineLocalVariable (string name,
-                                                LocalBuilder local,
-                                                FieldAttributes attributes,
-                                                int position,
-                                                int startOffset,
-                                                int endOffset)
+               public void MarkSequencePoint (int offset, int line, int column)
                {
                        if (current_method == null)
                                return;
 
-                       ITypeHandle type = writer.RegisterType (local.LocalType);
-
-                       LocalVariable local_info = new LocalVariable (name, type, current_method,
-                                                                     position, null);
-
-                       current_method.CurrentBlock.AddLocal (local_info);
-                       locals.Add (local_info);
-               }
-
-
-               public void DefineParameter (string name,
-                                            ParameterAttributes attributes,
-                                            int sequence,
-                                            SymAddressKind addrKind,
-                                            int addr1,
-                                            int addr2,
-                                            int addr3)
-               {
-                       throw new NotSupportedException ();
+                       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);
                }
 
-               public void DefineSequencePoints (ISymbolDocumentWriter document,
-                                                 int[] offsets,
-                                                 int[] lines,
-                                                 int[] columns,
-                                                 int[] endLines,
-                                                 int[] endColumns)
+               public void OpenMethod (ISourceFile file, ISourceMethod method,
+                                       int startRow, int startColumn,
+                                       int endRow, int endColumn)
                {
-                       SourceLine source_line = new SourceLine (offsets [0], lines [0], columns [0]);
+                       SourceMethod source = new SourceMethod (
+                               file, method, startRow, startColumn, endRow, endColumn);
 
-                       if (current_method != null)
-                               current_method.AddLine (source_line);
+                       current_method = source;
+                       methods.Add (current_method);
                }
 
-               public void Initialize (IntPtr emitter, string filename, bool fFullBuild)
+               public void CloseMethod ()
                {
-                       this.output_filename = filename;
-
-                       this.writer = new DwarfFileWriter (filename);
+                       current_method.SetLineNumbers (
+                               current_method_lines, current_method_lines_pos);
+                       current_method_lines_pos = 0;
+                       
+                       current_method = null;
                }
 
-               public void OpenMethod (SymbolToken symbol_token)
+               public SourceFileEntry DefineDocument (string url)
                {
-                       int token = symbol_token.GetToken ();
-
-                       MethodBuilder mb = get_method_builder (module_builder, token);
-
-                       current_method = new SourceMethod (mb);
-
-                       methods.Add (current_method);
+                       SourceFileEntry entry = new SourceFileEntry (file, url);
+                       sources.Add (entry);
+                       return entry;
                }
 
-               public void SetMethodSourceRange (ISymbolDocumentWriter startDoc,
-                                                 int startLine, int startColumn,
-                                                 ISymbolDocumentWriter endDoc,
-                                                 int endLine, int endColumn)
+               public int DefineNamespace (string name, SourceFileEntry source,
+                                           string[] using_clauses, int parent)
                {
-                       if (current_method == null)
-                               return;
-
-                       if ((startDoc == null) || (endDoc == null))
+                       if ((source == null) || (using_clauses == null))
                                throw new NullReferenceException ();
 
-                       if (!(startDoc is MonoSymbolDocumentWriter) || !(endDoc is MonoSymbolDocumentWriter))
-                               throw new NotSupportedException ("both startDoc and endDoc must be of type "
-                                                                + "MonoSymbolDocumentWriter");
-
-                       if (!startDoc.Equals (endDoc))
-                               throw new NotSupportedException ("startDoc and endDoc must be the same");
-
-                       string source_file = ((MonoSymbolDocumentWriter) startDoc).FileName;
-                       SourceFile source_info;
-
-                       if (sources.ContainsKey (source_file))
-                               source_info = (SourceFile) sources [source_file];
-                       else {
-                               source_info = new SourceFile (source_file);
-                               sources.Add (source_file, source_info);
-                       }
-
-                       current_method.SetSourceRange (source_info, startLine, startColumn,
-                                                      endLine, endColumn);
-
-                       source_info.AddMethod (current_method);
-               }
-
-               public void CloseMethod () {
-                       current_method = null;
-               }
-
-               public void OpenNamespace (string name)
-               {
+                       return source.DefineNamespace (name, using_clauses, parent);
                }
 
                public int OpenScope (int startOffset)
@@ -672,127 +163,182 @@ namespace Mono.CSharp.Debugger
                        if (current_method == null)
                                return 0;
 
-                       ISourceBlock block = new SourceBlock (current_method, startOffset);
-                       current_method.StartBlock (block);
-
-                       return block.ID;
+                       current_method.StartBlock (startOffset);
+                       return 0;
                }
 
-               public void CloseScope (int endOffset) {
+               public void CloseScope (int endOffset)
+               {
                        if (current_method == null)
                                return;
 
                        current_method.EndBlock (endOffset);
                }
 
-               public void SetScopeRange (int scopeID, int startOffset, int endOffset)
+               protected byte[] CreateOutput (Guid guid)
                {
-                       if (current_method == null)
-                               return;
-
-                       current_method.SetBlockRange (scopeID, startOffset, endOffset);
-               }
+                       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);
+                       }
 
-               public void SetSymAttribute (SymbolToken parent, string name, byte[] data)
-               {
+                       return file.CreateSymbolFile (guid);
                }
 
-               public void SetUnderlyingWriter (IntPtr underlyingWriter)
+               public void WriteSymbolFile (Guid guid)
                {
-                       throw new NotSupportedException ();
+                       using (FileStream stream = new FileStream (
+                                      filename, FileMode.Create, FileAccess.Write)) {
+                               byte[] data = CreateOutput (guid);
+                               stream.Write (data, 0, data.Length);
+                       }
                }
 
-               public void SetUserEntryPoint (SymbolToken entryMethod)
+               protected class SourceMethod
                {
-               }
+                       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;
 
-               public void UsingNamespace (string fullName)
-               {
-               }
+                       private LexicalBlockEntry _implicit_block;
 
-               //
-               // MonoSymbolWriter implementation
-               //
-               protected void WriteLocal (DwarfFileWriter.Die parent_die, ILocalVariable local)
-               {
-                       DwarfFileWriter.DieMethodVariable die;
+                       public SourceMethod (ISourceFile file, ISourceMethod method,
+                                            int startLine, int startColumn,
+                                            int endLine, int endColumn)
+                       {
+                               this._file = file;
+                               this._method = method;
 
-                       die = new DwarfFileWriter.DieMethodVariable (parent_die, local);
-               }
+                               this._start = new LineNumberEntry (startLine, 0);
+                               this._end = new LineNumberEntry (endLine, 0);
 
-               protected void WriteBlock (DwarfFileWriter.Die parent_die, ISourceBlock block)
-               {
-                       DwarfFileWriter.DieLexicalBlock die;
+                               this._implicit_block = new LexicalBlockEntry (0, 0);
+                       }
 
-                       die = new DwarfFileWriter.DieLexicalBlock (parent_die, block);
+                       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);
+                       }
 
-                       foreach (ILocalVariable local in block.Locals)
-                               WriteLocal (die, local);
+                       public void EndBlock (int endOffset)
+                       {
+                               LexicalBlockEntry block =
+                                       (LexicalBlockEntry) _block_stack.Pop ();
 
-                       foreach (ISourceBlock subblock in block.Blocks)
-                               WriteBlock (die, subblock);
-               }
+                               block.Close (endOffset);
+                       }
 
-               protected void WriteMethod (ISourceMethod method)
-               {
-                       DwarfFileWriter.DieCompileUnit parent_die = writer.DieGlobalCompileUnit;
-                       DwarfFileWriter.DieSubProgram die;
+                       public LexicalBlockEntry[] Blocks {
+                               get {
+                                       if (_blocks == null)
+                                               return new LexicalBlockEntry [0];
+                                       else {
+                                               LexicalBlockEntry[] retval =
+                                                       new LexicalBlockEntry [_blocks.Count];
+                                               _blocks.CopyTo (retval, 0);
+                                               return retval;
+                                       }
+                               }
+                       }
 
-                       die = new DwarfFileWriter.DieSubProgram (parent_die, method);
+                       public LexicalBlockEntry CurrentBlock {
+                               get {
+                                       if ((_block_stack != null) && (_block_stack.Count > 0))
+                                               return (LexicalBlockEntry) _block_stack.Peek ();
+                                       else
+                                               return _implicit_block;
+                               }
+                       }
 
-                       foreach (ILocalVariable local in method.Locals)
-                               WriteLocal (die, local);
+                       public LineNumberEntry[] Lines {
+                               get {
+                                       return lines;
+                               }
+                       }
 
-                       foreach (ISourceBlock block in method.Blocks)
-                               WriteBlock (die, block);
-               }
+                       public LocalVariableEntry[] Locals {
+                               get {
+                                       if (_locals == null)
+                                               return new LocalVariableEntry [0];
+                                       else {
+                                               LocalVariableEntry[] retval =
+                                                       new LocalVariableEntry [_locals.Count];
+                                               _locals.CopyTo (retval, 0);
+                                               return retval;
+                                       }
+                               }
+                       }
 
-               protected void WriteSource (DwarfFileWriter writer, ISourceFile source)
-               {
-                       foreach (ISourceMethod method in source.Methods)
-                               WriteMethod (method);
-               }
+                       public void AddLocal (string name, byte[] signature)
+                       {
+                               if (_locals == null)
+                                       _locals = new ArrayList ();
+                               _locals.Add (new LocalVariableEntry (
+                                                    name, signature, CurrentBlock.Index));
+                       }
 
-               [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               internal extern static MethodBuilder get_method_builder (ModuleBuilder mb, int token);
+                       public ISourceFile SourceFile {
+                               get { return _file; }
+                       }
 
-               protected void DoFixups (Assembly assembly)
-               {
-                       foreach (SourceMethod method in methods) {
-                               if (method._method_base is MethodBuilder) {
-                                       MethodBuilder mb = (MethodBuilder) method._method_base;
-                                       method._token = mb.GetToken ().Token;
-                               } else if (method._method_base is ConstructorBuilder) {
-                                       ConstructorBuilder cb = (ConstructorBuilder) method._method_base;
-                                       method._token = cb.GetToken ().Token;
-                               } else
-                                       throw new NotSupportedException ();
-
-                               if (method.SourceFile == null)
-                                       orphant_methods.Add (method);
+                       public ISourceMethod Method {
+                               get { return _method; }
                        }
-               }
 
-               protected void CreateDwarfFile (Assembly assembly)
-               {
-                       foreach (ISourceFile source in sources.Values)
-                               WriteSource (writer, source);
+                       public LineNumberEntry Start {
+                               get { return _start; }
+                       }
 
-                       if (orphant_methods.Count > 0) {
-                               SourceFile source = new SourceFile ("<unknown>");
+                       public LineNumberEntry End {
+                               get { return _end; }
+                       }
 
-                               foreach (SourceMethod orphant in orphant_methods) {
-                                       orphant._source_file = source;
-                                       source.AddMethod (orphant);
-                               }
+                       //
+                       // 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;
 
-                               WriteSource (writer, source);
-                       }
+                               int last_offset = -1;
+                               int last_row = -1;
+                               for (int i = 0; i < count; i++) {
+                                       LineNumberEntry line = lns [i];
 
-                       writer.WriteSymbolTable (this);
+                                       if (line.Offset > last_offset) {
+                                               if (last_row >= 0)
+                                                       lns [pos++] = new LineNumberEntry (
+                                                               last_row, last_offset);
 
-                       writer.Close ();
+                                               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);
+                       }
                }
        }
 }
-