IL2APP ldvirtftn Runtime Error

I don’t know if it is fixed in 5.0.1p1 (677402) or not, since there are significant differences between that issue and mine. Also, since I’m mostly using my own class library (dll) instead of Assembly-CSharp in order to accelerate the compile speed, I’m not sure whether this fault belongs to me or not.

On iPhone Simulator i’ve got the exception at:
(Surely the exception is BAD_ACCESS which stands for NullReferenceException)

Colosseum`il2cpp::vm::Runtime::GetVirtualInvokeData(MethodInfo*, void*) at Runtime.cpp:517:
0x31eea10:  pushl  %ebp
0x31eea11:  movl  %esp, %ebp
0x31eea13:  pushl  %esi
0x31eea14:  pushl  %eax
0x31eea15:  movl  0xc(%ebp), %eax
0x31eea18:  movl  0x8(%ebp), %ecx
0x31eea1b:  movl  (%eax), %edx
0x31eea1d:  movzwl 0x20(%ecx), %ecx
0x31eea21:  movl  0x34(%edx), %edx
0x31eea24:  movl  (%edx,%ecx,4), %esi
0x31eea27:  movl  0x8(%esi), %ecx

which is referenced by:

inline MethodInfo* GetVirtualMethodInfo (Il2CppCodeGenObject* pThis, MethodInfo* method)
{
    VirtualInvokeData data = il2cpp::vm::Runtime::GetVirtualInvokeData (method, pThis);
    return data.methodInfo;
}

Finally here is my own code compiled by il2app.

IL_0031:
    {
        ___Phase = G_B9_0;
        Environment_t1268 * L_3 = ColosseumBehaviour_get_Environment_m7978(__this, /*hidden argument*/&ColosseumBehaviour_get_Environment_m7978_MethodInfo);
        NullCheck(L_3);
        CommandQueue_1_t1388 * L_4 = Environment_get_CommandQueue_m8077(L_3, /*hidden argument*/&Environment_get_CommandQueue_m8077_MethodInfo);
        IntPtr_t83 L_5 = { GetVirtualMethodInfo(__this, &SceneSplash_PhaseIncrementInternal_m7309_MethodInfo) };
        Action_2_t1570 * L_6 = (Action_2_t1570 *)il2cpp_codegen_object_new (InitializedTypeInfo(&Action_2_t1570_il2cpp_TypeInfo));
        Action_2__ctor_m9261(L_6, __this, L_5, /*hidden argument*/&Action_2__ctor_m9261_MethodInfo);
        GameObject_t28 * L_7 = Component_get_gameObject_m3307(__this, /*hidden argument*/&Component_get_gameObject_m3307_MethodInfo);
        String_t* L_8 = Conversions_ToString_m6568(NULL /*static, unused*/, ___Phase, /*hidden argument*/&Conversions_ToString_m6568_MethodInfo);
        NullCheck(L_4);
        CommandQueue_1_ExecuteAction_m9262(L_4, L_6, L_7, L_8, /*hidden argument*/&CommandQueue_1_ExecuteAction_m9262_MethodInfo);
        return;
    }
}
// System.Void Colosseum.Clients.SceneSplash::PhaseIncrementInternal(UnityEngine.GameObject,System.String)
void SceneSplash_PhaseIncrementInternal_m7309 (SceneSplash_t1277 * __this, GameObject_t28 * ___Source, String_t* ___Data, MethodInfo* method){
    int32_t V_0 = 0;
    bool V_1 = false;
    {
        int32_t L_0 = Int32_Parse_m4609(NULL /*static, unused*/, ___Data, /*hidden argument*/&Int32_Parse_m4609_MethodInfo);
        V_0 = L_0;
        ProgressTweener_t1266 * L_1 = (__this->___Slider_12);
        int32_t L_2 = SceneSplash_get_TotalPhases_m7302(__this, /*hidden argument*/&SceneSplash_get_TotalPhases_m7302_MethodInfo);
        NullCheck(L_1);
        ProgressTweener_SetTarget_m7281(L_1, (((float)((double)((double)(((double)V_0))/(double)(((double)L_2)))))), /*hidden argument*/&ProgressTweener_SetTarget_m7281_MethodInfo);
        int32_t L_3 = SceneSplash_get_TotalPhases_m7302(__this, /*hidden argument*/&SceneSplash_get_TotalPhases_m7302_MethodInfo);
        V_1 = ((((int32_t)V_0) == ((int32_t)L_3))? 1 : 0);
        if (!V_1)
        {
            goto IL_003d;
        }
    }
    {
        SplashTexts_t1282 * L_4 = (__this->___SplashTexts_8);
        NullCheck(L_4);
        Queue_1_t1283 * L_5 = SplashTexts_get_Texts_m7325(L_4, /*hidden argument*/&SplashTexts_get_Texts_m7325_MethodInfo);
        NullCheck(L_5);
        Queue_1_Clear_m9263(L_5, /*hidden argument*/&Queue_1_Clear_m9263_MethodInfo);
    }

I’ve used ILSpy for its IL code and got the result as such:

IL_0040: ldvirtftn instance void Colosseum.Clients.SceneSplash::PhaseIncrementInternal(class [UnityEngine]UnityEngine.GameObject, string)

Thank you for reading, and I’m eager to know whether it’s a known bug or not, since I didn’t find any post concerning GetVirtualMethodInfo or GetVirtualInvokeData.

This does not look like a know bug. Is it possible for you to submit a project with a bug report to reproduce this? We would like to have a look to see if this is a case we have missed. Thanks.

Shall I send the whole XCode project which is above 400MB? Or simply managed libraries?

I must say I’m using Visual Basic for developing Unity games (which is rare I believe) but I managed to make my game run on my iOS Device (using mono backend ;)), and I cannot see if there are actual difference between VB&C# generated IL codes. If needed I may have a try.

@John-Chen350

If you can send the Unity project, that would be best, actually. If it is too large to upload with the bug, you can submit the bug without the project, then mention that you would like to send the project via some other method. We can work out how to get the large project independently then.

The fact that you are using VB here might be the issue, as IL2CPP is likely encountering some unexpected IL code. Still, we can investigate it.

It seems that I shall try to reproduce the bug in a limited way to eliminate the needs for sending the whole project. I’m in China and have no proper way to share so large a file with you (look, many hours for uploading?)

Meanwhile I shall post the IL code here.

.method public
    instance void PhaseIncrement (
        int32 Phase
    ) cil managed
{
    // Method begins at RVA 0x22c8
    // Code size 95 (0x5f)
    .maxstack 4
    .locals init (
        [0] bool VB$CG$t_bool$S0
    )

    IL_0000: nop
    IL_0001: ldarg.1
    IL_0002: ldc.i4.0
    IL_0003: beq.s IL_0011

    IL_0005: ldarg.1
    IL_0006: ldarg.0
    IL_0007: callvirt instance int32 Colosseum.Clients.SceneSplash::get_TotalPhases()
    IL_000c: bge.s IL_0011

    IL_000e: ldc.i4.0
    IL_000f: br.s IL_0012

    IL_0011: ldc.i4.1

    IL_0012: nop
    IL_0013: stloc.0
    IL_0014: ldloc.0
    IL_0015: brfalse.s IL_0024

    IL_0017: ldarg.0
    IL_0018: callvirt instance class Colosseum.Clients.Environment Colosseum.Clients.ColosseumBehaviour::get_Environment()
    IL_001d: ldnull
    IL_001e: callvirt instance void Colosseum.Clients.Environment::set_PhaseIncrement(class [mscorlib]System.Action`1<int32>)
    IL_0023: nop

    IL_0024: ldarg.1
    IL_0025: ldc.i4.0
    IL_0026: beq.s IL_002b

    IL_0028: ldarg.1
    IL_0029: br.s IL_0031

    IL_002b: ldarg.0
    IL_002c: callvirt instance int32 Colosseum.Clients.SceneSplash::get_TotalPhases()

    IL_0031: starg.s Phase
    IL_0033: ldarg.0
    IL_0034: callvirt instance class Colosseum.Clients.Environment Colosseum.Clients.ColosseumBehaviour::get_Environment()
    IL_0039: callvirt instance class ['Colosseum Shared Library']Colosseum.Clients.CommandQueue`1<class [UnityEngine]UnityEngine.GameObject> Colosseum.Clients.Environment::get_CommandQueue()
    IL_003e: ldarg.0
    IL_003f: dup
    IL_0040: ldvirtftn instance void Colosseum.Clients.SceneSplash::PhaseIncrementInternal(class [UnityEngine]UnityEngine.GameObject, string)
    IL_0046: newobj instance void class [System.Core]System.Action`2<class [UnityEngine]UnityEngine.GameObject, string>::.ctor(object, native int)
    IL_004b: ldarg.0
    IL_004c: callvirt instance class [UnityEngine]UnityEngine.GameObject [UnityEngine]UnityEngine.Component::get_gameObject()
    IL_0051: ldarg.1
    IL_0052: call string [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.Conversions::ToString(int32)
    IL_0057: callvirt instance void class ['Colosseum Shared Library']Colosseum.Clients.CommandQueue`1<class [UnityEngine]UnityEngine.GameObject>::ExecuteAction(class [System.Core]System.Action`2<!0, string>, !0, string)
    IL_005c: nop
    IL_005d: nop
    IL_005e: ret
} // end of method SceneSplash::PhaseIncrement
.method public
    instance void PhaseIncrementInternal (
        class [UnityEngine]UnityEngine.GameObject Source,
        string Data
    ) cil managed
{
    // Method begins at RVA 0x2334
    // Code size 168 (0xa8)
    .maxstack 5
    .locals init (
        [0] int32 Phase,
        [1] bool VB$CG$t_bool$S0
    )

    IL_0000: nop
    IL_0001: ldarg.2
    IL_0002: call int32 [mscorlib]System.Int32::Parse(string)
    IL_0007: stloc.0
    IL_0008: ldarg.0
    IL_0009: ldfld class Colosseum.Clients.ProgressTweener Colosseum.Clients.SceneSplash::Slider
    IL_000e: ldloc.0
    IL_000f: conv.r8
    IL_0010: ldarg.0
    IL_0011: callvirt instance int32 Colosseum.Clients.SceneSplash::get_TotalPhases()
    IL_0016: conv.r8
    IL_0017: div
    IL_0018: conv.r4
    IL_0019: callvirt instance void Colosseum.Clients.ProgressTweener::SetTarget(float32)
    IL_001e: nop
    IL_001f: ldloc.0
    IL_0020: ldarg.0
    IL_0021: callvirt instance int32 Colosseum.Clients.SceneSplash::get_TotalPhases()
    IL_0026: ceq
    IL_0028: stloc.1
    IL_0029: ldloc.1
    IL_002a: brfalse.s IL_003d

    IL_002c: ldarg.0
    IL_002d: ldfld class Colosseum.Clients.SplashTexts Colosseum.Clients.SceneSplash::SplashTexts
    IL_0032: callvirt instance class [System]System.Collections.Generic.Queue`1<string> Colosseum.Clients.SplashTexts::get_Texts()
    IL_0037: callvirt instance void class [System]System.Collections.Generic.Queue`1<string>::Clear()
    IL_003c: nop

    IL_003d: ldarg.0
    IL_003e: ldfld class Colosseum.Clients.SplashTexts Colosseum.Clients.SceneSplash::SplashTexts
    IL_0043: callvirt instance class [System]System.Collections.Generic.Queue`1<string> Colosseum.Clients.SplashTexts::get_Texts()
    IL_0048: ldarg.0
    IL_0049: callvirt instance class Colosseum.Clients.Localization Colosseum.Clients.ColosseumBehaviour::get_Localization()
    IL_004e: ldstr "Splashes"
    IL_0053: ldstr "Initializing "
    IL_0058: ldloc.0
    IL_0059: call string [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.Conversions::ToString(int32)
    IL_005e: call string [mscorlib]System.String::Concat(string, string)
    IL_0063: callvirt instance string Colosseum.Clients.Localization::get_Item(string, string)
    IL_0068: callvirt instance void class [System]System.Collections.Generic.Queue`1<string>::Enqueue(!0)
    IL_006d: nop
    IL_006e: ldarg.0
    IL_006f: callvirt instance class Colosseum.Clients.Environment Colosseum.Clients.ColosseumBehaviour::get_Environment()
    IL_0074: ldstr "Loading Progress: "
    IL_0079: ldarg.0
    IL_007a: ldfld class Colosseum.Clients.ProgressTweener Colosseum.Clients.SceneSplash::Slider
    IL_007f: ldfld float32 Colosseum.Clients.ProgressTweener::Target
    IL_0084: ldc.r4 100
    IL_0089: mul
    IL_008a: conv.r8
    IL_008b: call float64 [mscorlib]System.Math::Round(float64)
    IL_0090: call string [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.Conversions::ToString(float64)
    IL_0095: ldstr "%"
    IL_009a: call string [mscorlib]System.String::Concat(string, string, string)
    IL_009f: ldc.i4.0
    IL_00a0: callvirt instance void Colosseum.Clients.Environment::Log(string, bool)
    IL_00a5: nop
    IL_00a6: nop
    IL_00a7: ret
} // end of method SceneSplash::PhaseIncrementInternal

.

** @JoshPeterson **
I’ve reproduced the problem though not exactly the same one. I’ve noticed that VBC are using ldvirtftn when CSC only use ldftn which is the most intriguing part. I don’t really know what’s different between them but it really happens.

I’ll submit a bugreport with a small project package to reproduce that.

What’s more, your IL2CPP compiler failed in Windows due to Microsoft.VisualBasic.dll (which has been modified by myself so as to pass the mono AOT) while in OS X it is fine.

Update: I’ve submited the bug though I don’t know how to get my ticket number.

Thanks for tracking this down. We will investigate the bug.

Thank you and please keep update to me if possible - I mean if you cannot reproduce the bug I will do something else to help you.

I’ll do that, thanks. Do you have a bug number yet? If not, can you let me know the email address (via a different, private conversation if you would like) that you used to submit this bug? That way I should be able to find it. Thanks.

I’ve found that. It’s Case 695179. Thank you again.

It looks like we can reproduce it, so we will investigate, thanks.

@JoshPeterson Two weeks passed and I am wondering if I need to provide further information to you. Thank you again.

I’ve noticed that in 5.0.2p2 there are a fix describes as “Correct the implementation of the ldvirtftn opcode for types using a constrained generic generic parameter.” Yet the issue number doesn’t match mine, so I’m curious about what’s happening and whether I shall try to download that.

@John-Chen350

No, you should not need to provide any further information about this bug. Our QA team has been able to reproduce it. You should have received confirmation from them about that, but I don’t see a record of that communication in this bug. I apologize for the lack of communication.

I doubt the correction in 5.0.2p2 will correct your issue, as that fix was specific to a case with generic types. I can’t say for sure, so it might be worth trying 5.0.2p2, but they seem like two different issues.

We will try to have a look at correcting the bug you submitted soon. Thanks.

Many thanks to you. To introduce VB language to Unity crossing platforms is really a challenging thing, especially Microsoft.VisualBasic.dll lol

Any news? I didn’t receive any further instruction as well as message from bug reporting system. It is still ‘open’ there.

Yes, actually. It looks like the bug was corrected just a few days ago. Our QA team will confirm the fix, and then should respond to you about the bug report. The fix is scheduled to make it into 5.0.3p2, which should be out this week.

I shall try it then and report to you. Thank you very much! If there are any further problems I am glad to report it again.

I cannot even get through the xcode compilation now. Although the 5.0.3p2 emerges several new problems that block IL2CPP to work, I may change my code to avoid that (all concerning generic parameters in delegates); yet when there are semantic errors in IL2CPP, I have no way to solve nor research into it.

Generally speaking, all compilation errors are like “Use of undeclared label IL_00xx”. There are usually blocks with such label BELOW, which makes compiler unavailable to recognize. Shall I upload the generated cpp to you? Or class libraries as well?