Bug 320779 (MONO78031) - [GMCS] gmcs generates invalid IL for iterators
Summary: [GMCS] gmcs generates invalid IL for iterators
Status: RESOLVED FIXED
Alias: MONO78031
Product: Mono: Compilers
Classification: Mono
Component: C# (show other bugs)
Version: 1.1
Hardware: Other Other
: P3 - Medium : Normal
Target Milestone: ---
Assignee: Miguel de Icaza
QA Contact: Mono Bugs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-04-06 07:08 UTC by Sanghyeon Seo
Modified: 2007-09-15 21:24 UTC (History)
0 users

See Also:
Found By: ---
Services Priority:
Business Priority:
Blocker: ---
Marketing QA Status: ---
IT Deployment: ---


Attachments
gdb transcript (4.11 KB, text/plain)
2006-04-06 07:10 UTC, Thomas Wiest
Details
Switch inversion for iterators in MoveNext. (14.07 KB, patch)
2006-04-20 04:33 UTC, Thomas Wiest
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas Wiest 2007-09-15 19:54:17 UTC


---- Reported by sanxiyn@gmail.com 2006-04-06 00:08:38 MST ----

SVN revision 59107. Always reproducible.

1. Get IronPython 1.0 Beta 5

2. Create test.py

class C(type):
    pass

3. Run mono IronPythonConsole.exe test.py with provided binary. This causes
no problem.

4. Rebuild IronPython.

5. Run mono IronPythonConsole.exe test.py again. This terminates with SIGTRAP.

6. Run 5 inside gdb. Continuing after receiving SIGTRAP receives SIGSEGV.



---- Additional Comments From sanxiyn@gmail.com 2006-04-06 00:10:48 MST ----

Created an attachment (id=169542)
gdb transcript




---- Additional Comments From sanxiyn@gmail.com 2006-04-06 00:48:19 MST ----

I copied the binary compiled by Mono to Windows and ran with MS.NET.
Interestingly enough, MS.NET refuses to run the binary.

F:\Documents and
Settings\sanxiyn\Desktop\IronPython-1.0-Beta5>IronPythonConsole
.exe -X:ExceptionDetail test.py
Operation could destabilize the runtime.
   at IronPython.Runtime.CustomFieldIdDict.<GetEnumerator>__17.MoveNext()
   at
IronPython.Runtime.UserType.CreateNamespaceDictionary(IDictionary`2 dict)
   at IronPython.Runtime.UserType..ctor(String moduleName, String
name, Tuple ba
ses, IDictionary`2 dict)
   at IronPython.Runtime.Ops.MakeClass(String mod, String name, Tuple
bases, IDi
ctionary`2 vars)
   at __main__.Initialize() in F:\Documents and
Settings\sanxiyn\Desktop\IronPyt
hon-1.0-Beta5\test.py:line 1
   at IronPython.Runtime.PythonModule.Initialize()
   at IronPython.Hosting.PythonEngine.RunFileInNewModule(String
fileName, String
 moduleName, Boolean skipLine, Boolean& exitRaised)
   at IronPython.Hosting.PythonEngine.RunFileInNewModule(String
fileName, ArrayL
ist commandLineArgs, Boolean introspection, Boolean skipLine)
   at IronPythonConsole.PythonCommandLine.RunFile(PythonEngine engine,
ArrayList
 args)
SystemError: Operation could destabilize the runtime.

F:\Documents and Settings\sanxiyn\Desktop\IronPython-1.0-Beta5>



---- Additional Comments From vargaz@gmail.com 2006-04-07 13:32:46 MST ----

This is because mcs generates invalid IL for the following test case:

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
using System;
using System.Collections.Generic;

public class Tests {

	Dictionary<object, object> objData;

        public IEnumerator<KeyValuePair<object, object>> GetEnumerator() {
            if (objData != null) {
                foreach(KeyValuePair<object, object> o in objData){
                    yield return o;
                }
            }
	}

        public static int Main ()
        {
			Tests t = new Tests ();
			foreach (KeyValuePair<object, object> o in t)
				Console.WriteLine (o);

			return 0;
        }
}
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Running this with PEVerify prints:
... Tests+<GetEnumeration>__0:MoveNext ()[offset 0x...] Stack depth
differs depending on path.




---- Additional Comments From vargaz@gmail.com 2006-04-07 13:35:33 MST ----

This blocks a gmcs compiled IronPython from working under mono.




---- Additional Comments From miguel@ximian.com 2006-04-07 20:32:17 MST ----

I do get the trap if I run this with Mono and IronPython, but not with
the sample test case.

I was looking at the disassembled IL, and although it produces the
incorrect IL I can not find the two "codepaths" that would lead to the
problem.  Also, the sample program works fine with Mono (even if I
populate the objData Dictionary).



---- Additional Comments From miguel@ximian.com 2006-04-07 21:32:37 MST ----

The Illegal IL report from PEverify seems to be wrong, I reduced the
generated routine to this:

    .method public hidebysig newslot virtual final
            instance bool  MoveNext() cil managed
    {
      // Code size       193 (0xc1)
      .maxstack  12
      .locals init (int32 V_0,
               valuetype
[mscorlib]System.Collections.Generic.KeyValuePair`2<object,object> V_1)

        IL_0071:
        IL_0077:  ldarg.0
        IL_0078:  ldflda     valuetype
[mscorlib]System.Collections.Generic.Dictionary`2/Enumerator<object,object>
Tests/'<GetEnumerator>__0'::'<1:$s_1>'
        IL_007d:  call       instance void valuetype
[mscorlib]System.Collections.Generic.Dictionary`2/Enumerator<object,object>::Dispose()
        IL_008e:  ldarg.0
        IL_008f:  ldfld      int32 Tests/'<GetEnumerator>__0'::$PC
        IL_0094:  switch     (
                              IL_0071)
      IL_00bf:  ldc.0
      IL_00c0:  ret     } // end of method '<GetEnumerator>__0'::MoveNext

And PEVerify continued to complain about it, somehow it gets confused
by the back switch.   



---- Additional Comments From miguel@ximian.com 2006-04-07 21:39:17 MST ----

My bat-feeling is that the IL verifier in MS does not like the jump at
the start to the switch, and then the switch jumping back.  That
sounds lame to me.

Am not sure if we can change the compiler easily to change the order
in which switch is generated, I will look into that.

Sadly, the IronPython problem is probably somewhere else.



---- Additional Comments From miguel@ximian.com 2006-04-18 22:38:14 MST ----

I rewrote the code to produce the switch statement on top, and am
still having problems with the resulting executable on PEVerify, am
investigating. 



---- Additional Comments From miguel@ximian.com 2006-04-19 21:33:46 MST ----

Created an attachment (id=169543)
Switch inversion for iterators in MoveNext.




---- Additional Comments From miguel@ximian.com 2006-04-19 22:43:28 MST ----

Martin tracked this down, I likely did a clerical error and got confused.

The problem was that we were emitting the instance for Dispose twice:

          IL_0071:  ldarg.0
          IL_0072:  ldfld  valuetype
[mscorlib]System.Collections.Generic.Dictionary`2/Enumerator<object,object>
Tests/'<GetEnumerator>__0'::'<1:$s_1>'
          IL_0077:  ldarg.0
          IL_0078:  ldflda  valuetype
[mscorlib]System.Collections.Generic.Dictionary`2/Enumerator<object,object>
Tests/'<GetEnumerator>__0'::'<1:$s_1>'

The problem was in Foreach's EmitFinally code, there was a duplicated
call to enumerator.Emit.




Imported an attachment (id=169542)
Imported an attachment (id=169543)

Unknown operating system unknown. Setting to default OS "Other".