Skip to content

Commit f9afc71

Browse files
authored
[clr-interp] Implement a few minor opcodes (#114312)
* [clr-interp] Add div and rem support We assert in cases where exception should be thrown due to missing exception support at this moment * [clr-interp] Implement dup opcode * [clr-interp] Implement initobj opcode * [clr-interp] Minor tweaks to indirect loads/stores Delete LDIND_O, it is identical to LDIND_I4/LDIND_I8. Make sure stind.ref actually uses STIND_O, which reports the store to the GC. STIND_I doesn't do write barriers.
1 parent a87fd8b commit f9afc71

File tree

4 files changed

+198
-10
lines changed

4 files changed

+198
-10
lines changed

src/coreclr/interpreter/compiler.cpp

Lines changed: 74 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,15 +1518,20 @@ CORINFO_METHOD_HANDLE InterpCompiler::ResolveMethodToken(uint32_t token)
15181518
{
15191519
CORINFO_RESOLVED_TOKEN resolvedToken;
15201520

1521-
resolvedToken.tokenScope = m_compScopeHnd;
1522-
resolvedToken.tokenContext = METHOD_BEING_COMPILED_CONTEXT();
1523-
resolvedToken.token = token;
1524-
resolvedToken.tokenType = CORINFO_TOKENKIND_Method;
1525-
m_compHnd->resolveToken(&resolvedToken);
1521+
ResolveToken(token, CORINFO_TOKENKIND_Method, &resolvedToken);
15261522

15271523
return resolvedToken.hMethod;
15281524
}
15291525

1526+
CORINFO_CLASS_HANDLE InterpCompiler::ResolveClassToken(uint32_t token)
1527+
{
1528+
CORINFO_RESOLVED_TOKEN resolvedToken;
1529+
1530+
ResolveToken(token, CORINFO_TOKENKIND_Class, &resolvedToken);
1531+
1532+
return resolvedToken.hClass;
1533+
}
1534+
15301535
void InterpCompiler::EmitCall(CORINFO_CLASS_HANDLE constrainedClass, bool readonly, bool tailcall)
15311536
{
15321537
uint32_t token = getU4LittleEndian(m_ip + 1);
@@ -1622,7 +1627,7 @@ static int32_t GetStindForType(InterpType interpType)
16221627
case InterpTypeI8: return INTOP_STIND_I8;
16231628
case InterpTypeR4: return INTOP_STIND_R4;
16241629
case InterpTypeR8: return INTOP_STIND_R8;
1625-
case InterpTypeO: return INTOP_STIND_I;
1630+
case InterpTypeO: return INTOP_STIND_O;
16261631
case InterpTypeVT: return INTOP_STIND_VT;
16271632
case InterpTypeByRef: return INTOP_STIND_I;
16281633
default:
@@ -2567,6 +2572,22 @@ int InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
25672572
EmitBinaryArithmeticOp(INTOP_MUL_I4);
25682573
m_ip++;
25692574
break;
2575+
case CEE_DIV:
2576+
EmitBinaryArithmeticOp(INTOP_DIV_I4);
2577+
m_ip++;
2578+
break;
2579+
case CEE_DIV_UN:
2580+
EmitBinaryArithmeticOp(INTOP_DIV_UN_I4);
2581+
m_ip++;
2582+
break;
2583+
case CEE_REM:
2584+
EmitBinaryArithmeticOp(INTOP_REM_I4);
2585+
m_ip++;
2586+
break;
2587+
case CEE_REM_UN:
2588+
EmitBinaryArithmeticOp(INTOP_REM_UN_I4);
2589+
m_ip++;
2590+
break;
25702591
case CEE_AND:
25712592
EmitBinaryArithmeticOp(INTOP_AND_I4);
25722593
m_ip++;
@@ -2670,6 +2691,29 @@ int InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
26702691
m_pStackPointer--;
26712692
break;
26722693
}
2694+
case CEE_DUP:
2695+
{
2696+
int32_t svar = m_pStackPointer[-1].var;
2697+
InterpType interpType = m_pVars[svar].interpType;
2698+
if (interpType == InterpTypeVT)
2699+
{
2700+
int32_t size = m_pVars[svar].size;
2701+
AddIns(INTOP_MOV_VT);
2702+
m_pLastNewIns->SetSVar(svar);
2703+
PushTypeVT(m_pVars[svar].clsHnd, size);
2704+
m_pLastNewIns->SetDVar(m_pStackPointer[-1].var);
2705+
m_pLastNewIns->data[0] = size;
2706+
}
2707+
else
2708+
{
2709+
AddIns(InterpGetMovForType(interpType, false));
2710+
m_pLastNewIns->SetSVar(svar);
2711+
PushInterpType(interpType, m_pVars[svar].clsHnd);
2712+
m_pLastNewIns->SetDVar(m_pStackPointer[-1].var);
2713+
}
2714+
m_ip++;
2715+
break;
2716+
}
26732717
case CEE_POP:
26742718
CHECK_STACK(1);
26752719
AddIns(INTOP_NOP);
@@ -3041,6 +3085,30 @@ int InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
30413085
volatile_ = true;
30423086
m_ip++;
30433087
break;
3088+
case CEE_INITOBJ:
3089+
{
3090+
CHECK_STACK(1);
3091+
CORINFO_CLASS_HANDLE clsHnd = ResolveClassToken(getU4LittleEndian(m_ip + 1));
3092+
if (m_compHnd->isValueClass(clsHnd))
3093+
{
3094+
m_pStackPointer--;
3095+
AddIns(INTOP_ZEROBLK_IMM);
3096+
m_pLastNewIns->SetSVar(m_pStackPointer[0].var);
3097+
m_pLastNewIns->data[0] = m_compHnd->getClassSize(clsHnd);
3098+
}
3099+
else
3100+
{
3101+
AddIns(INTOP_LDNULL);
3102+
PushInterpType(InterpTypeO, NULL);
3103+
m_pLastNewIns->SetDVar(m_pStackPointer[-1].var);
3104+
3105+
AddIns(INTOP_STIND_O);
3106+
m_pStackPointer -= 2;
3107+
m_pLastNewIns->SetSVars2(m_pStackPointer[0].var, m_pStackPointer[1].var);
3108+
}
3109+
m_ip += 5;
3110+
break;
3111+
}
30443112
default:
30453113
assert(0);
30463114
break;

src/coreclr/interpreter/compiler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ class InterpCompiler
288288

289289
void ResolveToken(uint32_t token, CorInfoTokenKind tokenKind, CORINFO_RESOLVED_TOKEN *pResolvedToken);
290290
CORINFO_METHOD_HANDLE ResolveMethodToken(uint32_t token);
291+
CORINFO_CLASS_HANDLE ResolveClassToken(uint32_t token);
291292

292293
void* AllocMethodData(size_t numBytes);
293294
// FIXME Mempool allocation currently leaks. We need to add an allocator and then

src/coreclr/interpreter/intops.def

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,22 @@ OPDEF(INTOP_MUL_I8, "mul.i8", 4, 1, 2, InterpOpNoArgs)
160160
OPDEF(INTOP_MUL_R4, "mul.r4", 4, 1, 2, InterpOpNoArgs)
161161
OPDEF(INTOP_MUL_R8, "mul.r8", 4, 1, 2, InterpOpNoArgs)
162162

163+
OPDEF(INTOP_DIV_I4, "div.i4", 4, 1, 2, InterpOpNoArgs)
164+
OPDEF(INTOP_DIV_I8, "div.i8", 4, 1, 2, InterpOpNoArgs)
165+
OPDEF(INTOP_DIV_R4, "div.r4", 4, 1, 2, InterpOpNoArgs)
166+
OPDEF(INTOP_DIV_R8, "div.r8", 4, 1, 2, InterpOpNoArgs)
167+
168+
OPDEF(INTOP_DIV_UN_I4, "div.un.i4", 4, 1, 2, InterpOpNoArgs)
169+
OPDEF(INTOP_DIV_UN_I8, "div.un.i8", 4, 1, 2, InterpOpNoArgs)
170+
171+
OPDEF(INTOP_REM_I4, "rem.i4", 4, 1, 2, InterpOpNoArgs)
172+
OPDEF(INTOP_REM_I8, "rem.i8", 4, 1, 2, InterpOpNoArgs)
173+
OPDEF(INTOP_REM_R4, "rem.r4", 4, 1, 2, InterpOpNoArgs)
174+
OPDEF(INTOP_REM_R8, "rem.r8", 4, 1, 2, InterpOpNoArgs)
175+
176+
OPDEF(INTOP_REM_UN_I4, "rem.un.i4", 4, 1, 2, InterpOpNoArgs)
177+
OPDEF(INTOP_REM_UN_I8, "rem.un.i8", 4, 1, 2, InterpOpNoArgs)
178+
163179
OPDEF(INTOP_AND_I4, "and.i4", 4, 1, 2, InterpOpNoArgs)
164180
OPDEF(INTOP_AND_I8, "and.i8", 4, 1, 2, InterpOpNoArgs)
165181

@@ -235,6 +251,7 @@ OPDEF(INTOP_NEWOBJ_VT, "newobj.vt", 5, 1, 1, InterpOpMethodToken)
235251

236252
OPDEF(INTOP_CALL_HELPER_PP, "call.helper.pp", 5, 1, 0, InterpOpThreeInts)
237253

254+
OPDEF(INTOP_ZEROBLK_IMM, "zeroblk.imm", 3, 0, 1, InterpOpInt)
238255
OPDEF(INTOP_FAILFAST, "failfast", 1, 0, 0, InterpOpNoArgs)
239256

240257
// All instructions after this point are IROPS, instructions that are not emitted/executed

src/coreclr/vm/interpexec.cpp

Lines changed: 106 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,108 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
571571
ip += 4;
572572
break;
573573

574+
case INTOP_DIV_I4:
575+
{
576+
int32_t i1 = LOCAL_VAR(ip[2], int32_t);
577+
int32_t i2 = LOCAL_VAR(ip[3], int32_t);
578+
if (i2 == 0)
579+
assert(0); // Interpreter-TODO: DivideByZeroException
580+
if (i2 == -1 && i1 == INT32_MIN)
581+
assert(0); // Interpreter-TODO: OverflowException
582+
LOCAL_VAR(ip[1], int32_t) = i1 / i2;
583+
ip += 4;
584+
break;
585+
}
586+
case INTOP_DIV_I8:
587+
{
588+
int64_t l1 = LOCAL_VAR(ip[2], int64_t);
589+
int64_t l2 = LOCAL_VAR(ip[3], int64_t);
590+
if (l2 == 0)
591+
assert(0); // Interpreter-TODO: DivideByZeroException
592+
if (l2 == -1 && l1 == INT64_MIN)
593+
assert(0); // Interpreter-TODO: OverflowException
594+
LOCAL_VAR(ip[1], int64_t) = l1 / l2;
595+
ip += 4;
596+
break;
597+
}
598+
case INTOP_DIV_R4:
599+
LOCAL_VAR(ip[1], float) = LOCAL_VAR(ip[2], float) / LOCAL_VAR(ip[3], float);
600+
ip += 4;
601+
break;
602+
case INTOP_DIV_R8:
603+
LOCAL_VAR(ip[1], double) = LOCAL_VAR(ip[2], double) / LOCAL_VAR(ip[3], double);
604+
ip += 4;
605+
break;
606+
case INTOP_DIV_UN_I4:
607+
{
608+
uint32_t i2 = LOCAL_VAR(ip[3], uint32_t);
609+
if (i2 == 0)
610+
assert(0); // Interpreter-TODO: DivideByZeroException
611+
LOCAL_VAR(ip[1], uint32_t) = LOCAL_VAR(ip[2], uint32_t) / i2;
612+
ip += 4;
613+
break;
614+
}
615+
case INTOP_DIV_UN_I8:
616+
{
617+
uint64_t l2 = LOCAL_VAR(ip[3], uint64_t);
618+
if (l2 == 0)
619+
assert(0); // Interpreter-TODO: DivideByZeroException
620+
LOCAL_VAR(ip[1], uint64_t) = LOCAL_VAR(ip[2], uint64_t) / l2;
621+
ip += 4;
622+
break;
623+
}
624+
625+
case INTOP_REM_I4:
626+
{
627+
int32_t i1 = LOCAL_VAR(ip[2], int32_t);
628+
int32_t i2 = LOCAL_VAR(ip[3], int32_t);
629+
if (i2 == 0)
630+
assert(0); // Interpreter-TODO: DivideByZeroException
631+
if (i2 == -1 && i1 == INT32_MIN)
632+
assert(0); // Interpreter-TODO: OverflowException
633+
LOCAL_VAR(ip[1], int32_t) = i1 % i2;
634+
ip += 4;
635+
break;
636+
}
637+
case INTOP_REM_I8:
638+
{
639+
int64_t l1 = LOCAL_VAR(ip[2], int64_t);
640+
int64_t l2 = LOCAL_VAR(ip[3], int64_t);
641+
if (l2 == 0)
642+
assert(0); // Interpreter-TODO: DivideByZeroException
643+
if (l2 == -1 && l1 == INT64_MIN)
644+
assert(0); // Interpreter-TODO: OverflowException
645+
LOCAL_VAR(ip[1], int64_t) = l1 % l2;
646+
ip += 4;
647+
break;
648+
}
649+
case INTOP_REM_R4:
650+
LOCAL_VAR(ip[1], float) = fmodf(LOCAL_VAR(ip[2], float), LOCAL_VAR(ip[3], float));
651+
ip += 4;
652+
break;
653+
case INTOP_REM_R8:
654+
LOCAL_VAR(ip[1], double) = fmod(LOCAL_VAR(ip[2], double), LOCAL_VAR(ip[3], double));
655+
ip += 4;
656+
break;
657+
case INTOP_REM_UN_I4:
658+
{
659+
uint32_t i2 = LOCAL_VAR(ip[3], uint32_t);
660+
if (i2 == 0)
661+
assert(0); // Interpreter-TODO: DivideByZeroException
662+
LOCAL_VAR(ip[1], uint32_t) = LOCAL_VAR(ip[2], uint32_t) % i2;
663+
ip += 4;
664+
break;
665+
}
666+
case INTOP_REM_UN_I8:
667+
{
668+
uint64_t l2 = LOCAL_VAR(ip[3], uint64_t);
669+
if (l2 == 0)
670+
assert(0); // Interpreter-TODO: DivideByZeroException
671+
LOCAL_VAR(ip[1], uint64_t) = LOCAL_VAR(ip[2], uint64_t) % l2;
672+
ip += 4;
673+
break;
674+
}
675+
574676
case INTOP_SHL_I4:
575677
LOCAL_VAR(ip[1], int32_t) = LOCAL_VAR(ip[2], int32_t) << LOCAL_VAR(ip[3], int32_t);
576678
ip += 4;
@@ -764,10 +866,6 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
764866
case INTOP_LDIND_R8:
765867
LDIND(double, double);
766868
break;
767-
case INTOP_LDIND_O:
768-
LDIND(OBJECTREF, OBJECTREF);
769-
break;
770-
771869
case INTOP_LDIND_VT:
772870
{
773871
char *src = LOCAL_VAR(ip[2], char*);
@@ -959,6 +1057,10 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
9591057
ip += 5;
9601058
goto CALL_INTERP_SLOT;
9611059
}
1060+
case INTOP_ZEROBLK_IMM:
1061+
memset(LOCAL_VAR(ip[1], void*), 0, ip[2]);
1062+
ip += 3;
1063+
break;
9621064
case INTOP_FAILFAST:
9631065
assert(0);
9641066
break;

0 commit comments

Comments
 (0)