// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
+using System;
using System.Collections.Generic;
namespace Mono.CompilerServices.SymbolWriter
List<LocalVariableEntry> _locals;
List<CodeBlockEntry> _blocks;
List<ScopeVariable> _scope_vars;
-#if NET_2_1
- System.Collections.Stack _block_stack;
-#else
Stack<CodeBlockEntry> _block_stack;
-#endif
readonly List<LineNumberEntry> method_lines;
readonly ICompileUnit _comp_unit;
}
public void MarkSequencePoint (int offset, SourceFileEntry file, int line, int column, bool is_hidden)
+ {
+ MarkSequencePoint (offset, file, line, column, -1, -1, is_hidden);
+ }
+
+ public void MarkSequencePoint (int offset, SourceFileEntry file, int line, int column, int end_line, int end_column, bool is_hidden)
{
int file_idx = file != null ? file.Index : 0;
- var lne = new LineNumberEntry (file_idx, line, column, offset, is_hidden);
+ var lne = new LineNumberEntry (file_idx, line, column, end_line, end_column, offset, is_hidden);
if (method_lines.Count > 0) {
var prev = method_lines[method_lines.Count - 1];
}
public void StartBlock (CodeBlockEntry.Type type, int start_offset)
+ {
+ StartBlock (type, start_offset, _blocks == null ? 1 : _blocks.Count + 1);
+ }
+
+ public void StartBlock (CodeBlockEntry.Type type, int start_offset, int scopeIndex)
{
if (_block_stack == null) {
-#if NET_2_1
- _block_stack = new System.Collections.Stack ();
-#else
_block_stack = new Stack<CodeBlockEntry> ();
-#endif
}
if (_blocks == null)
int parent = CurrentBlock != null ? CurrentBlock.Index : -1;
CodeBlockEntry block = new CodeBlockEntry (
- _blocks.Count + 1, parent, type, start_offset);
+ scopeIndex, parent, type, start_offset);
_block_stack.Push (block);
_blocks.Add (block);
public void DefineMethod (MonoSymbolFile file, int token)
{
- MethodEntry entry = new MethodEntry (
+ var blocks = Blocks;
+ if (blocks.Length > 0) {
+ //
+ // When index is provided by user it can be inserted in
+ // any order but mdb format does not store its value. It
+ // uses stored order as the index instead.
+ //
+ var sorted = new List<CodeBlockEntry> (blocks.Length);
+ int max_index = 0;
+ for (int i = 0; i < blocks.Length; ++i) {
+ max_index = System.Math.Max (max_index, blocks [i].Index);
+ }
+
+ for (int i = 0; i < max_index; ++i) {
+ var scope_index = i + 1;
+
+ //
+ // Common fast path
+ //
+ if (i < blocks.Length && blocks [i].Index == scope_index) {
+ sorted.Add (blocks [i]);
+ continue;
+ }
+
+ bool found = false;
+ for (int ii = 0; ii < blocks.Length; ++ii) {
+ if (blocks [ii].Index == scope_index) {
+ sorted.Add (blocks [ii]);
+ found = true;
+ break;
+ }
+ }
+
+ if (found)
+ continue;
+
+ //
+ // Ideally this should never happen but with current design we can
+ // generate scope index for unreachable code before reachable code
+ //
+ sorted.Add (new CodeBlockEntry (scope_index, -1, CodeBlockEntry.Type.CompilerGenerated, 0));
+ }
+
+ blocks = sorted.ToArray ();
+ //for (int i = 0; i < blocks.Length; ++i) {
+ // if (blocks [i].Index - 1 != i)
+ // throw new ArgumentException ("CodeBlocks cannot be converted to mdb format");
+ //}
+ }
+
+ var entry = new MethodEntry (
file, _comp_unit.Entry, token, ScopeVariables,
- Locals, method_lines.ToArray (), Blocks, null, MethodEntry.Flags.ColumnsInfoIncluded, ns_id);
+ Locals, method_lines.ToArray (), blocks, null, MethodEntry.Flags.ColumnsInfoIncluded, ns_id);
file.AddMethod (entry);
}