Skip to content

Commit 778427c

Browse files
authored
[clrinterp] Add support for ldc.r4, ldc.r8, ldc.i8 and ldstr (#114201)
* Add support for ldc.r4, ldc.r8 and ldc.i8 * Add support for ldstr * Add test for basic float operations
1 parent 76093e0 commit 778427c

File tree

5 files changed

+107
-1
lines changed

5 files changed

+107
-1
lines changed

src/coreclr/interpreter/compiler.cpp

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
#include "interpreter.h"
44

5+
#include <inttypes.h>
6+
57
static const StackType g_stackTypeFromInterpType[] =
68
{
79
StackTypeI4, // I1
@@ -1962,13 +1964,58 @@ int InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
19621964
m_pLastNewIns->SetDVar(m_pStackPointer[-1].var);
19631965
m_ip += 5;
19641966
break;
1967+
case CEE_LDC_I8:
1968+
{
1969+
int64_t val = getI8LittleEndian(m_ip + 1);
1970+
AddIns(INTOP_LDC_I8);
1971+
PushInterpType(InterpTypeI8, NULL);
1972+
m_pLastIns->SetDVar(m_pStackPointer[-1].var);
1973+
m_pLastIns->data[0] = (int32_t)val;
1974+
m_pLastIns->data[1] = (int32_t)(val >> 32);
1975+
m_ip += 9;
1976+
break;
1977+
}
1978+
case CEE_LDC_R4:
1979+
{
1980+
int32_t val = getI4LittleEndian(m_ip + 1);
1981+
AddIns(INTOP_LDC_R4);
1982+
PushInterpType(InterpTypeR4, NULL);
1983+
m_pLastIns->SetDVar(m_pStackPointer[-1].var);
1984+
m_pLastIns->data[0] = val;
1985+
m_ip += 5;
1986+
break;
1987+
}
1988+
case CEE_LDC_R8:
1989+
{
1990+
int64_t val = getI8LittleEndian(m_ip + 1);
1991+
AddIns(INTOP_LDC_R8);
1992+
PushInterpType(InterpTypeR8, NULL);
1993+
m_pLastIns->SetDVar(m_pStackPointer[-1].var);
1994+
m_pLastIns->data[0] = (int32_t)val;
1995+
m_pLastIns->data[1] = (int32_t)(val >> 32);
1996+
m_ip += 9;
1997+
break;
1998+
}
19651999
case CEE_LDNULL:
19662000
AddIns(INTOP_LDNULL);
19672001
PushStackType(StackTypeO, NULL);
19682002
m_pLastNewIns->SetDVar(m_pStackPointer[-1].var);
19692003
m_ip++;
19702004
break;
1971-
2005+
case CEE_LDSTR:
2006+
{
2007+
int32_t token = getI4LittleEndian(m_ip + 1);
2008+
void *str;
2009+
InfoAccessType accessType = m_compHnd->constructStringLiteral(m_compScopeHnd, token, &str);
2010+
assert(accessType == IAT_VALUE);
2011+
// str should be forever pinned, so we can include its ref inside interpreter code
2012+
AddIns(INTOP_LDPTR);
2013+
PushInterpType(InterpTypeO, m_compHnd->getBuiltinClass(CLASSID_STRING));
2014+
m_pLastIns->SetDVar(m_pStackPointer[-1].var);
2015+
m_pLastIns->data[0] = GetDataItemIndex(str);
2016+
m_ip += 5;
2017+
break;
2018+
}
19722019
case CEE_LDARG_S:
19732020
EmitLoadVar(m_ip[1]);
19742021
m_ip += 2;
@@ -3141,6 +3188,23 @@ void InterpCompiler::PrintInsData(InterpInst *ins, int32_t insOffset, const int3
31413188
case InterpOpInt:
31423189
printf(" %d", *pData);
31433190
break;
3191+
case InterpOpLongInt:
3192+
{
3193+
int64_t i64 = (int64_t)pData[0] + ((int64_t)pData[1] << 32);
3194+
printf(" %" PRId64, i64);
3195+
break;
3196+
}
3197+
case InterpOpFloat:
3198+
{
3199+
printf(" %g", *(float*)pData);
3200+
break;
3201+
}
3202+
case InterpOpDouble:
3203+
{
3204+
int64_t i64 = (int64_t)pData[0] + ((int64_t)pData[1] << 32);
3205+
printf(" %g", *(double*)&i64);
3206+
break;
3207+
}
31443208
case InterpOpTwoInts:
31453209
printf(" %d,%d", *pData, *(pData + 1));
31463210
break;

src/coreclr/interpreter/intops.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ OPDEF(INTOP_MEMBAR, "membar", 1, 0, 0, InterpOpNoArgs)
1616
OPDEF(INTOP_LDC_I4, "ldc.i4", 3, 1, 0, InterpOpInt)
1717
OPDEF(INTOP_LDC_I4_0, "ldc.i4.0", 2, 1, 0, InterpOpNoArgs)
1818
OPDEF(INTOP_LDC_I8_0, "ldc.i8.0", 2, 1, 0, InterpOpNoArgs)
19+
OPDEF(INTOP_LDC_I8, "ldc.i8", 4, 1, 0, InterpOpLongInt)
20+
21+
OPDEF(INTOP_LDC_R4, "ldc.r4", 3, 1, 0, InterpOpFloat)
22+
OPDEF(INTOP_LDC_R8, "ldc.r8", 4, 1, 0, InterpOpDouble)
1923

2024
OPDEF(INTOP_LDPTR, "ldptr", 3, 1, 0, InterpOpInt)
2125

src/coreclr/interpreter/intops.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ typedef enum
1313
{
1414
InterpOpNoArgs,
1515
InterpOpInt,
16+
InterpOpLongInt,
17+
InterpOpFloat,
18+
InterpOpDouble,
1619
InterpOpTwoInts,
1720
InterpOpThreeInts,
1821
InterpOpBranch,

src/coreclr/vm/interpexec.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,18 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
8080
LOCAL_VAR(ip[1], int64_t) = 0;
8181
ip += 2;
8282
break;
83+
case INTOP_LDC_I8:
84+
LOCAL_VAR(ip[1], int64_t) = (int64_t)ip[2] + ((int64_t)ip[3] << 32);
85+
ip += 4;
86+
break;
87+
case INTOP_LDC_R4:
88+
LOCAL_VAR(ip[1], int32_t) = ip[2];
89+
ip += 3;
90+
break;
91+
case INTOP_LDC_R8:
92+
LOCAL_VAR(ip[1], int64_t) = (int64_t)ip[2] + ((int64_t)ip[3] << 32);
93+
ip += 4;
94+
break;
8395
case INTOP_LDPTR:
8496
LOCAL_VAR(ip[1], void*) = pMethod->pDataItems[ip[2]];
8597
ip += 3;

src/tests/JIT/interpreter/Interpreter.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ public static void RunInterpreterTests()
6969
// Environment.FailFast(null);
7070
// if (!TestSpecialFields())
7171
// Environment.FailFast(null);
72+
if (!TestFloat())
73+
Environment.FailFast(null);
7274
}
7375

7476
public static int Mul4(int a, int b, int c, int d)
@@ -186,4 +188,25 @@ public static bool TestSpecialFields()
186188

187189
return true;
188190
}
191+
192+
public static bool TestFloat()
193+
{
194+
float f1 = 14554.9f;
195+
float f2 = 12543.4f;
196+
197+
float sum = f1 + f2;
198+
199+
if ((sum - 27098.3) > 0.001 || (sum - 27098.3) < -0.001)
200+
return false;
201+
202+
double d1 = 14554.9;
203+
double d2 = 12543.4;
204+
205+
double diff = d1 - d2;
206+
207+
if ((diff - 2011.5) > 0.001 || (diff - 2011.5) < -0.001)
208+
return false;
209+
210+
return true;
211+
}
189212
}

0 commit comments

Comments
 (0)