[mcs] More work on debug scopes declared out of order. Fixes #45774
authorMarek Safar <marek.safar@gmail.com>
Fri, 4 Nov 2016 15:03:52 +0000 (16:03 +0100)
committerMarek Safar <marek.safar@gmail.com>
Fri, 4 Nov 2016 15:05:07 +0000 (16:05 +0100)
mcs/class/Mono.CompilerServices.SymbolWriter/SourceMethodBuilder.cs
mcs/mcs/iterators.cs
mcs/mcs/statement.cs
mcs/tests/test-debug-11-ref.xml
mcs/tests/test-debug-21-ref.xml
mcs/tests/test-debug-28-ref.xml
mcs/tests/test-debug-31-ref.xml [new file with mode: 0644]
mcs/tests/test-debug-31.cs [new file with mode: 0644]
mcs/tests/test-debug-32-ref.xml [new file with mode: 0644]
mcs/tests/test-debug-32.cs [new file with mode: 0644]
mcs/tests/ver-il-net_4_x.xml

index 89763f52ec9185327ba7f17d63a6ffc14e349b6e..306570627a5847f96cc42b2b87b4114c2cd433c1 100644 (file)
@@ -187,13 +187,54 @@ namespace Mono.CompilerServices.SymbolWriter
                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,
index 47919ec8ce2b5fda133bddbb93509096ba9ef671..0b6fc1abf7722452569bed9c6c1ae75ac2815296 100644 (file)
@@ -254,7 +254,7 @@ namespace Mono.CSharp
                        // 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;
@@ -1067,6 +1067,7 @@ namespace Mono.CSharp
 
                        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
index eab87d16a17871ef5789fd98503ec70a99708f86..fbb060f52960da9af8218171c9cf6991e8b102cc 100644 (file)
@@ -3245,9 +3245,10 @@ namespace Mono.CSharp {
 
                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);
@@ -3258,7 +3259,7 @@ namespace Mono.CSharp {
 
                        DoEmit (ec);
 
-                       if (Parent != null)
+                       if (scopeIndex > 0)
                                ec.EndScope ();
 
                        if (ec.EmitAccurateDebugInfo && HasReachableClosingBrace && !(this is ParametersBlock) &&
@@ -3451,7 +3452,12 @@ namespace Mono.CSharp {
                        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;
@@ -3859,6 +3865,11 @@ namespace Mono.CSharp {
                        return res;
                }
 
+               public override int GetDebugSymbolScopeIndex ()
+               {
+                       return 0;
+               }
+
                public LabeledStatement GetLabel (string name, Block block)
                {
                        //
@@ -8338,15 +8349,14 @@ namespace Mono.CSharp {
                        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;
index db740c2456f8f89c415ad5d6ed13f835ade27ad1..d14a377f00fc9f23f40ad4633e7bc5617f6201d7 100644 (file)
       </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>
index 3958eb589f82a1a044189259b56b365b575b8d74..41445be8cee95dca28411f414d9893332c8fae87 100644 (file)
@@ -83,7 +83,8 @@
       </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>
index 1038be00dde8b9d78e423fe0197ab430a7661d3e..c823a34e298adbe4cf07c325c957aa767c639503 100644 (file)
@@ -28,9 +28,7 @@
       </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">
diff --git a/mcs/tests/test-debug-31-ref.xml b/mcs/tests/test-debug-31-ref.xml
new file mode 100644 (file)
index 0000000..1a77894
--- /dev/null
@@ -0,0 +1,58 @@
+<?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
diff --git a/mcs/tests/test-debug-31.cs b/mcs/tests/test-debug-31.cs
new file mode 100644 (file)
index 0000000..5a3d55d
--- /dev/null
@@ -0,0 +1,25 @@
+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
diff --git a/mcs/tests/test-debug-32-ref.xml b/mcs/tests/test-debug-32-ref.xml
new file mode 100644 (file)
index 0000000..acabcfb
--- /dev/null
@@ -0,0 +1,92 @@
+<?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
diff --git a/mcs/tests/test-debug-32.cs b/mcs/tests/test-debug-32.cs
new file mode 100644 (file)
index 0000000..ba52a10
--- /dev/null
@@ -0,0 +1,21 @@
+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
index 56e35f7709f857723d5c158e14535337098d1e93..3bf44ceb436bac0046a32ca1ab1d47f82d28b211 100644 (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+&lt;EnumerateKind&gt;c__Iterator0">
+      <method name="Boolean MoveNext()" attrs="486">
+        <size>152</size>
+      </method>
+      <method name="Int32 System.Collections.Generic.IEnumerator&lt;int&gt;.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&lt;int&gt;.GetEnumerator()" attrs="481">
+        <size>26</size>
+      </method>
+      <method name="Void &lt;&gt;__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">