diff --git a/src/coreclr/interpreter/compiler.cpp b/src/coreclr/interpreter/compiler.cpp index f924f2f8db361c..c5b312c313d585 100644 --- a/src/coreclr/interpreter/compiler.cpp +++ b/src/coreclr/interpreter/compiler.cpp @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. #include "interpreter.h" +#include + static const StackType g_stackTypeFromInterpType[] = { StackTypeI4, // I1 @@ -1871,13 +1873,58 @@ int InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo) m_pLastIns->SetDVar(m_pStackPointer[-1].var); m_ip += 5; break; + case CEE_LDC_I8: + { + int64_t val = getI8LittleEndian(m_ip + 1); + AddIns(INTOP_LDC_I8); + PushInterpType(InterpTypeI8, NULL); + m_pLastIns->SetDVar(m_pStackPointer[-1].var); + m_pLastIns->data[0] = (int32_t)val; + m_pLastIns->data[1] = (int32_t)(val >> 32); + m_ip += 9; + break; + } + case CEE_LDC_R4: + { + int32_t val = getI4LittleEndian(m_ip + 1); + AddIns(INTOP_LDC_R4); + PushInterpType(InterpTypeR4, NULL); + m_pLastIns->SetDVar(m_pStackPointer[-1].var); + m_pLastIns->data[0] = val; + m_ip += 5; + break; + } + case CEE_LDC_R8: + { + int64_t val = getI8LittleEndian(m_ip + 1); + AddIns(INTOP_LDC_R8); + PushInterpType(InterpTypeR8, NULL); + m_pLastIns->SetDVar(m_pStackPointer[-1].var); + m_pLastIns->data[0] = (int32_t)val; + m_pLastIns->data[1] = (int32_t)(val >> 32); + m_ip += 9; + break; + } case CEE_LDNULL: AddIns(INTOP_LDNULL); PushStackType(StackTypeO, NULL); m_pLastIns->SetDVar(m_pStackPointer[-1].var); m_ip++; break; - + case CEE_LDSTR: + { + int32_t token = getI4LittleEndian(m_ip + 1); + void *str; + InfoAccessType accessType = m_compHnd->constructStringLiteral(m_compScopeHnd, token, &str); + assert(accessType == IAT_VALUE); + // str should be forever pinned, so we can include its ref inside interpreter code + AddIns(INTOP_LDPTR); + PushInterpType(InterpTypeO, m_compHnd->getBuiltinClass(CLASSID_STRING)); + m_pLastIns->SetDVar(m_pStackPointer[-1].var); + m_pLastIns->data[0] = GetDataItemIndex(str); + m_ip += 5; + break; + } case CEE_LDARG_S: EmitLoadVar(m_ip[1]); m_ip += 2; @@ -3048,6 +3095,23 @@ void InterpCompiler::PrintInsData(InterpInst *ins, int32_t insOffset, const int3 case InterpOpInt: printf(" %d", *pData); break; + case InterpOpLongInt: + { + int64_t i64 = (int64_t)pData[0] + ((int64_t)pData[1] << 32); + printf(" %" PRId64, i64); + break; + } + case InterpOpFloat: + { + printf(" %g", *(float*)pData); + break; + } + case InterpOpDouble: + { + int64_t i64 = (int64_t)pData[0] + ((int64_t)pData[1] << 32); + printf(" %g", *(double*)&i64); + break; + } case InterpOpTwoInts: printf(" %d,%d", *pData, *(pData + 1)); break; diff --git a/src/coreclr/interpreter/intops.def b/src/coreclr/interpreter/intops.def index dccbee84e60699..42ff2de08a2415 100644 --- a/src/coreclr/interpreter/intops.def +++ b/src/coreclr/interpreter/intops.def @@ -16,6 +16,10 @@ OPDEF(INTOP_MEMBAR, "membar", 1, 0, 0, InterpOpNoArgs) OPDEF(INTOP_LDC_I4, "ldc.i4", 3, 1, 0, InterpOpInt) OPDEF(INTOP_LDC_I4_0, "ldc.i4.0", 2, 1, 0, InterpOpNoArgs) OPDEF(INTOP_LDC_I8_0, "ldc.i8.0", 2, 1, 0, InterpOpNoArgs) +OPDEF(INTOP_LDC_I8, "ldc.i8", 4, 1, 0, InterpOpLongInt) + +OPDEF(INTOP_LDC_R4, "ldc.r4", 3, 1, 0, InterpOpFloat) +OPDEF(INTOP_LDC_R8, "ldc.r8", 4, 1, 0, InterpOpDouble) OPDEF(INTOP_LDPTR, "ldptr", 3, 1, 0, InterpOpInt) diff --git a/src/coreclr/interpreter/intops.h b/src/coreclr/interpreter/intops.h index 523e8665d49bb3..103893a9567ed7 100644 --- a/src/coreclr/interpreter/intops.h +++ b/src/coreclr/interpreter/intops.h @@ -13,6 +13,9 @@ typedef enum { InterpOpNoArgs, InterpOpInt, + InterpOpLongInt, + InterpOpFloat, + InterpOpDouble, InterpOpTwoInts, InterpOpThreeInts, InterpOpBranch, diff --git a/src/coreclr/vm/interpexec.cpp b/src/coreclr/vm/interpexec.cpp index b7d0dc3d02da3b..85733d8bfd3a97 100644 --- a/src/coreclr/vm/interpexec.cpp +++ b/src/coreclr/vm/interpexec.cpp @@ -80,6 +80,18 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr LOCAL_VAR(ip[1], int64_t) = 0; ip += 2; break; + case INTOP_LDC_I8: + LOCAL_VAR(ip[1], int64_t) = (int64_t)ip[2] + ((int64_t)ip[3] << 32); + ip += 4; + break; + case INTOP_LDC_R4: + LOCAL_VAR(ip[1], int32_t) = ip[2]; + ip += 3; + break; + case INTOP_LDC_R8: + LOCAL_VAR(ip[1], int64_t) = (int64_t)ip[2] + ((int64_t)ip[3] << 32); + ip += 4; + break; case INTOP_LDPTR: LOCAL_VAR(ip[1], void*) = pMethod->pDataItems[ip[2]]; ip += 3; diff --git a/src/tests/JIT/interpreter/Interpreter.cs b/src/tests/JIT/interpreter/Interpreter.cs index bd5b27581a52b0..1a634ee9fada7a 100644 --- a/src/tests/JIT/interpreter/Interpreter.cs +++ b/src/tests/JIT/interpreter/Interpreter.cs @@ -69,6 +69,8 @@ public static void RunInterpreterTests() // Environment.FailFast(null); // if (!TestSpecialFields()) // Environment.FailFast(null); + if (!TestFloat()) + Environment.FailFast(null); } public static int Mul4(int a, int b, int c, int d) @@ -186,4 +188,25 @@ public static bool TestSpecialFields() return true; } + + public static bool TestFloat() + { + float f1 = 14554.9f; + float f2 = 12543.4f; + + float sum = f1 + f2; + + if ((sum - 27098.3) > 0.001 || (sum - 27098.3) < -0.001) + return false; + + double d1 = 14554.9; + double d2 = 12543.4; + + double diff = d1 - d2; + + if ((diff - 2011.5) > 0.001 || (diff - 2011.5) < -0.001) + return false; + + return true; + } }