6 hours ago,Dexter wrote
Hmm, AFAIK "reach the dup instructions with different types" is not allowed. See 1.8.1.3 Merging Stack States in ECMA 335.
Even if this is allowed I think it's still possible to deal with. If a basic block containing dup is reached with 2 different stack states then this can be treated as if there actually were 2 distinct basic blocks in the first place.
I looked at section 1.8.1.3 and it mentions how types can be converted. This does help me completely because during my code analysis lets say I find an Int16 on the stack. Now I create a local variable of type Int16. But the at runtime something jumps to the dup instruction from another part of the code, and there happens to be an Int32 on the stack. While I can cast to an Int16, I'm going to lose precision. For now I'm going to go with the assumption that there will always be the same type on the stack when reaching a dup instruction.
Anyway, I went ahead and changed the code to create an actual local variable for each dup instruction (with the assumption that it can always only be of the type that was on the stack during the initial code analysis pass). Unfortunately I am still seeing the bug where m_length is 1 less than it should be. Below is the new generated C++ code. To me it seems that instruction IL_0029 should jump to instruction IL_002d instead of IL_003a. It is basically skipping the first increment on m_length. Can you spot the bug in my C++ code?
[EDIT: OK, I'm currently struggling with C9's code formatter in order to not have it put all of the code on one line. I'm selecting the code in VS, copying it, opening the "</>" code editor dialog in C9, pasting it, selecting the language type, pressing Insert and then Submit. What am I doing wrong? For now, I'm pasting the unformatted code in addition to the single formatted line until I can figure the formatting out]
Void T8012_VirtualString::T8012_Ctor_VirtualString(VirtualThread* pThread, T8012_VirtualString** pThis, Char* pStr)
{
// Ref type locals
T8012_VirtualString** dupRef0 = (T8012_VirtualString**)&pThread->StackPointer[1];
memset(&pThread->StackPointer[1], 0, sizeof(void*) * 1);
pThread->StackPointer += 1;
// Value type locals
Bool local0 = false;
Char* dupValue0 = 0;
IL_0000: // ldarg.0
IL_0001: // call: Void .ctor()
(*pThis)->T8003_VirtualObject::T8003_Ctor_VirtualObject(pThread, (T8003_VirtualObject**)pThis);
IL_0006: // nop
IL_0007: // nop
IL_0008: // ldarg.0
IL_0009: // ldarg.1
IL_000a: // stfld: Char* m_buffer
(*pThis)->m_buffer = pStr;
IL_000f: // ldarg.0
IL_0010: // ldc.i4.0
IL_0011: // stfld: UInt16 m_length
(*pThis)->m_length = 0;
IL_0016: // ldarg.0
IL_0017: // ldfld: Char* m_buffer
IL_001c: // ldc.i4.0
IL_001d: // conv.u
IL_001e: // ceq
IL_0020: // ldc.i4.0
IL_0021: // ceq
IL_0023: // stloc.0
local0 = (((*pThis)->m_buffer == (Int32)(UInt32)(0)) == 0);
IL_0024: // ldloc.0
IL_0025: // brtrue.s: 2
if (local0 != 0)
goto IL_0029;
IL_0027: // br.s: 36
goto IL_004d;
IL_0029: // br.s: 15
goto IL_003a;
IL_002b: // ldarg.0
IL_002c: // dup
(*dupRef0) = *(pThis);
IL_002d: // ldfld: UInt16 m_length
IL_0032: // ldc.i4.1
IL_0033: // add
IL_0034: // conv.u2
IL_0035: // stfld: UInt16 m_length
(*pThis)->m_length = (Int32)(UInt16)(((Int32)(*dupRef0)->m_length + 1));
IL_003a: // ldarg.1
IL_003b: // dup
dupValue0 = pStr;
IL_003c: // ldc.i4.2
IL_003d: // conv.i
IL_003e: // add
IL_003f: // starg.s: Char* pStr
pStr = (Char*)(((Int32)dupValue0 + (Int32)2));
IL_0041: // ldind.u2
IL_0042: // ldc.i4.0
IL_0043: // ceq
IL_0045: // ldc.i4.0
IL_0046: // ceq
IL_0048: // stloc.0
local0 = ((((UInt16)*(UInt16*)pStr) == 0) == 0);
IL_0049: // ldloc.0
IL_004a: // brtrue.s: -33
if (local0 != 0)
goto IL_002b;
IL_004c: // nop
IL_004d: // ret
goto Exit;
Exit:
pThread->StackPointer -= 1;
}
[Does the following block of code display properly for anyone? It is all on one line for me. I filed a C9 bug report about this and referred back to this post. I'll leave this extra block of code here until the bug in the forum has been fixed.]
void T8012_VirtualString::T8012_Ctor_VirtualString(VirtualThread* pThread, T8012_VirtualString** pThis, Char* pStr){ // Ref type locals T8012_VirtualString** dupRef0 = (T8012_VirtualString**)&pThread->StackPointer[1]; memset(&pThread->StackPointer[1], 0, sizeof(void*) * 1); pThread->StackPointer += 1; // Value type locals Bool local0 = false; Char* dupValue0 = 0;IL_0000: // ldarg.0IL_0001: // call: Void .ctor() (*pThis)->T8003_VirtualObject::T8003_Ctor_VirtualObject(pThread, (T8003_VirtualObject**)pThis);IL_0006: // nopIL_0007: // nopIL_0008: // ldarg.0IL_0009: // ldarg.1IL_000a: // stfld: Char* m_buffer (*pThis)->m_buffer = pStr;IL_000f: // ldarg.0IL_0010: // ldc.i4.0IL_0011: // stfld: UInt16 m_length (*pThis)->m_length = 0;IL_0016: // ldarg.0IL_0017: // ldfld: Char* m_bufferIL_001c: // ldc.i4.0IL_001d: // conv.uIL_001e: // ceqIL_0020: // ldc.i4.0IL_0021: // ceqIL_0023: // stloc.0 local0 = (((*pThis)->m_buffer == (Int32)(UInt32)(0)) == 0);IL_0024: // ldloc.0IL_0025: // brtrue.s: 2 if (local0 != 0) goto IL_0029;IL_0027: // br.s: 36 goto IL_004d;IL_0029: // br.s: 15 goto IL_003a;IL_002b: // ldarg.0IL_002c: // dup (*dupRef0) = *(pThis);IL_002d: // ldfld: UInt16 m_lengthIL_0032: // ldc.i4.1IL_0033: // addIL_0034: // conv.u2IL_0035: // stfld: UInt16 m_length (*pThis)->m_length = (Int32)(UInt16)(((Int32)(*dupRef0)->m_length + 1));IL_003a: // ldarg.1IL_003b: // dup dupValue0 = pStr;IL_003c: // ldc.i4.2IL_003d: // conv.iIL_003e: // addIL_003f: // starg.s: Char* pStr pStr = (Char*)(((Int32)dupValue0 + (Int32)2));IL_0041: // ldind.u2IL_0042: // ldc.i4.0IL_0043: // ceqIL_0045: // ldc.i4.0IL_0046: // ceqIL_0048: // stloc.0 local0 = ((((UInt16)*(UInt16*)pStr) == 0) == 0);IL_0049: // ldloc.0IL_004a: // brtrue.s: -33 if (local0 != 0) goto IL_002b;IL_004c: // nopIL_004d: // ret goto Exit;Exit: pThread->StackPointer -= 1;}
Thread Closed
This thread is kinda stale and has been closed but if you'd like to continue the conversation, please create a new thread in our Forums,
or Contact Us and let us know.