public void DefineMethod (MonoSymbolFile file, int token)
{
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;
- //
- // When index is provided by user it can be inserted in
- // any order but mdb format does not store its value. It
- // uses store order instead as the index.
- //
- Array.Sort (blocks, (x, y) => x.Index.CompareTo (y.Index));
+ //
+ // 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,
// Special format which encodes original variable name and
// it's scope to support lifted variables debugging. This
// is same what csc does and allows to correctly set fields
- // scope information (like ambiguity, our of scope, etc).
+ // scope information (like ambiguity, out of scope, etc).
//
var id = rc.CurrentBlock.Explicit.GetDebugSymbolScopeIndex ();
return "<" + local_info.Name + ">__" + id;
method.Block = new ToplevelBlock (method.Compiler, method.ParameterInfo, loc,
ToplevelBlock.Flags.CompilerGenerated | ToplevelBlock.Flags.NoFlowAnalysis);
+
method.Block.AddStatement (new TryFinallyBlockProxyStatement (this, block));
// Cannot it add to storey because it'd be emitted before nested
public override void Emit (EmitContext ec)
{
- if (Parent != null) {
- // TODO: It's needed only when scope has variable (normal or lifted)
- ec.BeginScope (GetDebugSymbolScopeIndex ());
+ // TODO: It's needed only when scope has variable (normal or lifted)
+ var scopeIndex = GetDebugSymbolScopeIndex ();
+ if (scopeIndex > 0) {
+ ec.BeginScope (scopeIndex);
}
EmitScopeInitialization (ec);
DoEmit (ec);
- if (Parent != null)
+ if (scopeIndex > 0)
ec.EndScope ();
if (ec.EmitAccurateDebugInfo && HasReachableClosingBrace && !(this is ParametersBlock) &&
storey.Parent.PartialContainer.AddCompilerGeneratedClass (storey);
}
- public int GetDebugSymbolScopeIndex ()
+ public void DisableDebugScopeIndex ()
+ {
+ debug_scope_index = -1;
+ }
+
+ public virtual int GetDebugSymbolScopeIndex ()
{
if (debug_scope_index == 0)
debug_scope_index = ++ParametersBlock.debug_scope_index;
return res;
}
+ public override int GetDebugSymbolScopeIndex ()
+ {
+ return 0;
+ }
+
public LabeledStatement GetLabel (string name, Block block)
{
//
ec.LoopBegin = ec.DefineLabel ();
ec.LoopEnd = ec.DefineLabel ();
- if (!(Statement is Block))
- ec.BeginCompilerScope (variable.Block.Explicit.GetDebugSymbolScopeIndex ());
+ ec.BeginCompilerScope (variable.Block.Explicit.GetDebugSymbolScopeIndex ());
+ body.Explicit.DisableDebugScopeIndex ();
variable.CreateBuilder (ec);
Statement.Emit (ec);
- if (!(Statement is Block))
- ec.EndScope ();
+ ec.EndScope ();
ec.LoopBegin = old_begin;
ec.LoopEnd = old_end;
</locals>
<scopes>
<entry index="0" start="0x1" end="0x1e" />
- <entry index="1" start="0xb" end="0x11" />
- <entry index="2" start="0xf" end="0x10" />
+ <entry index="1" start="0xf" end="0x10" />
</scopes>
</method>
<method token="0x6000019">
</locals>
<scopes>
<entry index="0" start="0x1" end="0x37" />
- <entry index="1" start="0xe" end="0x18" />
- <entry index="2" start="0x16" end="0x17" />
+ <entry index="1" start="0x16" end="0x17" />
</scopes>
</method>
<method token="0x600001a">
</locals>
<scopes>
<entry index="0" start="0x1" end="0x3c" />
- <entry index="1" start="0xf" end="0x18" />
- <entry index="2" start="0x16" end="0x17" />
+ <entry index="1" start="0x16" end="0x17" />
</scopes>
</method>
<method token="0x600001b">
</locals>
<scopes>
<entry index="0" start="0x1" end="0x4d" />
- <entry index="1" start="0x24" end="0x31" />
- <entry index="2" start="0x2f" end="0x30" />
+ <entry index="1" start="0x2f" end="0x30" />
</scopes>
</method>
</methods>
</sequencepoints>
<locals />
<scopes>
- <entry index="0" start="0x0" end="0xb" />
+ <entry index="0" start="0x0" end="0x0" />
+ <entry index="1" start="0x0" end="0xb" />
</scopes>
</method>
</methods>
</locals>
<scopes>
<entry index="0" start="0x1" end="0x1c" />
- <entry index="1" start="0xb" end="0xf" />
- <entry index="2" start="0x1c" end="0x3f" />
- <entry index="3" start="0x28" end="0x2e" />
+ <entry index="1" start="0x1c" end="0x3f" />
</scopes>
</method>
<method token="0x6000003">
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<symbols>
+ <files>
+ <file id="1" name="test-debug-31.cs" checksum="e1579371d047d82b8d90c0dc26393808" />
+ </files>
+ <methods>
+ <method token="0x6000001">
+ <sequencepoints />
+ <locals />
+ <scopes />
+ </method>
+ <method token="0x6000002">
+ <sequencepoints>
+ <entry il="0x0" row="8" col="3" file_ref="1" hidden="false" />
+ <entry il="0x1" row="9" col="4" file_ref="1" hidden="false" />
+ <entry il="0x20" row="11" col="4" file_ref="1" hidden="false" />
+ <entry il="0x21" row="11" col="25" file_ref="1" hidden="false" />
+ <entry il="0x2a" row="11" col="13" file_ref="1" hidden="false" />
+ <entry il="0x2e" row="12" col="4" file_ref="1" hidden="false" />
+ <entry il="0x2f" row="13" col="5" file_ref="1" hidden="false" />
+ <entry il="0x30" row="13" col="13" file_ref="1" hidden="false" />
+ <entry il="0x35" row="14" col="4" file_ref="1" hidden="false" />
+ <entry il="0x36" row="11" col="25" file_ref="1" hidden="false" />
+ <entry il="0x43" row="16" col="4" file_ref="1" hidden="false" />
+ <entry il="0x44" row="16" col="26" file_ref="1" hidden="false" />
+ <entry il="0x4f" row="16" col="13" file_ref="1" hidden="false" />
+ <entry il="0x56" row="16" col="33" file_ref="1" hidden="false" />
+ <entry il="0x57" row="17" col="5" file_ref="1" hidden="false" />
+ <entry il="0x59" row="17" col="13" file_ref="1" hidden="false" />
+ <entry il="0x5e" row="18" col="4" file_ref="1" hidden="false" />
+ <entry il="0x5f" row="16" col="26" file_ref="1" hidden="false" />
+ <entry il="0x70" row="20" col="4" file_ref="1" hidden="false" />
+ <entry il="0x71" row="20" col="26" file_ref="1" hidden="false" />
+ <entry il="0x7c" row="20" col="13" file_ref="1" hidden="false" />
+ <entry il="0x83" row="20" col="33" file_ref="1" hidden="false" />
+ <entry il="0x84" row="21" col="5" file_ref="1" hidden="false" />
+ <entry il="0x86" row="21" col="13" file_ref="1" hidden="false" />
+ <entry il="0x8b" row="22" col="4" file_ref="1" hidden="false" />
+ <entry il="0x8c" row="20" col="26" file_ref="1" hidden="false" />
+ <entry il="0x9d" row="23" col="3" file_ref="1" hidden="false" />
+ </sequencepoints>
+ <locals>
+ <entry name="array" il_index="0" scope_ref="0" />
+ <entry name="item" il_index="1" scope_ref="1" />
+ <entry name="item1" il_index="4" scope_ref="3" />
+ <entry name="item2" il_index="7" scope_ref="5" />
+ </locals>
+ <scopes>
+ <entry index="0" start="0x20" end="0x43" />
+ <entry index="1" start="0x2e" end="0x35" />
+ <entry index="2" start="0x43" end="0x70" />
+ <entry index="3" start="0x56" end="0x5e" />
+ <entry index="4" start="0x70" end="0x9d" />
+ <entry index="5" start="0x83" end="0x8b" />
+ </scopes>
+ </method>
+ </methods>
+</symbols>
\ No newline at end of file
--- /dev/null
+using System;
+
+namespace cp534534
+{
+ class MainClass
+ {
+ public static void Main ()
+ {
+ var array = new string[] { "a", "b", "c" };
+
+ foreach (var item in array)
+ {
+ Console.WriteLine (item);
+ }
+
+ foreach (var item1 in array) {
+ Console.WriteLine (item1);
+ }
+
+ foreach (var item2 in array) {
+ Console.WriteLine (item2);
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<symbols>
+ <files>
+ <file id="1" name="test-debug-32.cs" checksum="71a5517624c6bd01871fcb9ae65242b7" />
+ </files>
+ <methods>
+ <method token="0x6000001">
+ <sequencepoints />
+ <locals />
+ <scopes />
+ </method>
+ <method token="0x6000002">
+ <sequencepoints />
+ <locals />
+ <scopes />
+ </method>
+ <method token="0x6000003">
+ <sequencepoints>
+ <entry il="0x0" row="19" col="2" file_ref="1" hidden="false" />
+ <entry il="0x1" row="20" col="2" file_ref="1" hidden="false" />
+ </sequencepoints>
+ <locals />
+ <scopes />
+ </method>
+ <method token="0x6000004">
+ <sequencepoints />
+ <locals />
+ <scopes />
+ </method>
+ <method token="0x6000005">
+ <sequencepoints>
+ <entry il="0x27" row="6" col="2" file_ref="1" hidden="false" />
+ <entry il="0x28" row="7" col="3" file_ref="1" hidden="false" />
+ <entry il="0x43" row="9" col="3" file_ref="1" hidden="false" />
+ <entry il="0x4a" row="10" col="3" file_ref="1" hidden="false" />
+ <entry il="0x59" row="10" col="7" file_ref="1" hidden="false" />
+ <entry il="0x5a" row="11" col="4" file_ref="1" hidden="false" />
+ <entry il="0x7c" row="12" col="3" file_ref="1" hidden="false" />
+ <entry il="0x8d" row="16" col="2" file_ref="1" hidden="false" />
+ </sequencepoints>
+ <locals />
+ <scopes>
+ <entry index="0" start="0x59" end="0x7c" />
+ </scopes>
+ </method>
+ <method token="0x6000006">
+ <sequencepoints />
+ <locals />
+ <scopes />
+ </method>
+ <method token="0x6000007">
+ <sequencepoints />
+ <locals />
+ <scopes />
+ </method>
+ <method token="0x6000008">
+ <sequencepoints />
+ <locals />
+ <scopes />
+ </method>
+ <method token="0x6000009">
+ <sequencepoints />
+ <locals />
+ <scopes />
+ </method>
+ <method token="0x600000a">
+ <sequencepoints />
+ <locals />
+ <scopes />
+ </method>
+ <method token="0x600000b">
+ <sequencepoints />
+ <locals />
+ <scopes />
+ </method>
+ <method token="0x600000c">
+ <sequencepoints>
+ <entry il="0x0" row="12" col="13" file_ref="1" hidden="false" />
+ <entry il="0x1" row="13" col="4" file_ref="1" hidden="false" />
+ <entry il="0xd" row="13" col="16" file_ref="1" hidden="false" />
+ <entry il="0xe" row="14" col="4" file_ref="1" hidden="false" />
+ <entry il="0xf" row="15" col="3" file_ref="1" hidden="false" />
+ </sequencepoints>
+ <locals />
+ <scopes>
+ <entry index="0" start="0x0" end="0x0" />
+ <entry index="1" start="0x0" end="0xf" />
+ <entry index="2" start="0xd" end="0xe" />
+ </scopes>
+ </method>
+ </methods>
+</symbols>
\ No newline at end of file
--- /dev/null
+using System.Collections.Generic;
+
+class X
+{
+ internal static IEnumerable<int> EnumerateKind ()
+ {
+ yield return 1;
+
+ int h = 3;
+ try {
+ yield return h;
+ } finally {
+ if (h != 1) {
+ }
+ }
+ }
+
+ public static void Main ()
+ {
+ }
+}
\ No newline at end of file
</method>
</type>
</test>
+ <test name="test-debug-31.cs">
+ <type name="cp534534.MainClass">
+ <method name="Void Main()" attrs="150">
+ <size>158</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
+ <test name="test-debug-32.cs">
+ <type name="X">
+ <method name="System.Collections.Generic.IEnumerable`1[System.Int32] EnumerateKind()" attrs="147">
+ <size>23</size>
+ </method>
+ <method name="Void Main()" attrs="150">
+ <size>2</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ <type name="X+<EnumerateKind>c__Iterator0">
+ <method name="Boolean MoveNext()" attrs="486">
+ <size>152</size>
+ </method>
+ <method name="Int32 System.Collections.Generic.IEnumerator<int>.get_Current()" attrs="2529">
+ <size>14</size>
+ </method>
+ <method name="System.Object System.Collections.IEnumerator.get_Current()" attrs="2529">
+ <size>19</size>
+ </method>
+ <method name="Void Dispose()" attrs="486">
+ <size>57</size>
+ </method>
+ <method name="Void Reset()" attrs="486">
+ <size>6</size>
+ </method>
+ <method name="System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()" attrs="481">
+ <size>14</size>
+ </method>
+ <method name="System.Collections.Generic.IEnumerator`1[System.Int32] System.Collections.Generic.IEnumerable<int>.GetEnumerator()" attrs="481">
+ <size>26</size>
+ </method>
+ <method name="Void <>__Finally0()" attrs="129">
+ <size>17</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
<test name="test-decl-expr-01.cs">
<type name="DeclarationExpression">
<method name="Int32 Main()" attrs="150">