Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions src/coreclr/interpreter/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1736,6 +1736,7 @@ int32_t InterpCompiler::GetDataItemIndexForHelperFtn(CorInfoHelpFunc ftn)
size_t data = !direct
? (size_t)indirect | INTERP_INDIRECT_HELPER_TAG
: (size_t)direct;
assert(data);
return GetDataItemIndex((void*)data);
}

Expand Down Expand Up @@ -3710,6 +3711,42 @@ int InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
break;
}

case CEE_LDTOKEN:
{
AddIns(INTOP_LDTOKEN);

CORINFO_RESOLVED_TOKEN resolvedToken = { 0 };
resolvedToken.tokenScope = m_compScopeHnd;
resolvedToken.tokenContext = METHOD_BEING_COMPILED_CONTEXT();
resolvedToken.token = getU4LittleEndian(m_ip + 1);
resolvedToken.tokenType = CORINFO_TOKENKIND_Ldtoken;
m_compHnd->resolveToken(&resolvedToken);

CORINFO_CLASS_HANDLE clsHnd = m_compHnd->getTokenTypeAsHandle(&resolvedToken);
PushStackType(StackTypeVT, clsHnd);
m_pLastNewIns->SetDVar(m_pStackPointer[-1].var);

// see jit/importer.cpp CEE_LDTOKEN
CorInfoHelpFunc helper;
if (resolvedToken.hClass) {
helper = CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE;
m_pLastNewIns->data[0] = GetDataItemIndex(resolvedToken.hClass);
} else if (resolvedToken.hMethod) {
helper = CORINFO_HELP_METHODDESC_TO_STUBRUNTIMEMETHOD;
m_pLastNewIns->data[0] = GetDataItemIndex(resolvedToken.hMethod);
} else if (resolvedToken.hField) {
helper = CORINFO_HELP_FIELDDESC_TO_STUBRUNTIMEFIELD;
m_pLastNewIns->data[0] = GetDataItemIndex(resolvedToken.hField);
} else {
helper = CORINFO_HELP_FAIL_FAST;
assert(!"Token not resolved or resolved to unexpected type");
}

m_pLastNewIns->data[1] = GetDataItemIndexForHelperFtn(helper);
m_ip += 5;
break;
}

default:
assert(0);
break;
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/interpreter/interpretershared.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@

struct InterpMethod
{
InterpMethod *self;
CORINFO_METHOD_HANDLE methodHnd;
int32_t allocaSize;
void** pDataItems;
bool initLocals;

InterpMethod(CORINFO_METHOD_HANDLE methodHnd, int32_t allocaSize, void** pDataItems, bool initLocals)
{
this->self = this;
this->methodHnd = methodHnd;
this->allocaSize = allocaSize;
this->pDataItems = pDataItems;
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/interpreter/intops.def
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ OPDEF(INTOP_STELEM_I8, "stelem.i8", 4, 0, 3, InterpOpNoArgs)
OPDEF(INTOP_STELEM_R4, "stelem.r4", 4, 0, 3, InterpOpNoArgs)
OPDEF(INTOP_STELEM_R8, "stelem.r8", 4, 0, 3, InterpOpNoArgs)

OPDEF(INTOP_LDTOKEN, "ldtoken", 4, 1, 0, InterpOpTwoInts) // [token data item] [conversion helper func]

OPDEF(INTOP_MOV_I4_I1, "mov.i4.i1", 3, 1, 1, InterpOpNoArgs)
OPDEF(INTOP_MOV_I4_U1, "mov.i4.u1", 3, 1, 1, InterpOpNoArgs)
OPDEF(INTOP_MOV_I4_I2, "mov.i4.i2", 3, 1, 1, InterpOpNoArgs)
Expand Down
20 changes: 20 additions & 0 deletions src/coreclr/vm/interpexec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
int8_t *stack;

InterpMethod *pMethod = *(InterpMethod**)pFrame->startIp;
assert(pMethod->self == pMethod);

pThreadContext->pStackPointer = pFrame->pStack + pMethod->allocaSize;
ip = pFrame->startIp + sizeof(InterpMethod*) / sizeof(int32_t);
stack = pFrame->pStack;
Expand Down Expand Up @@ -1172,6 +1174,7 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr

// Set execution state for the new frame
pMethod = *(InterpMethod**)pFrame->startIp;
assert(pMethod->self == pMethod);
stack = pFrame->pStack;
ip = pFrame->startIp + sizeof(InterpMethod*) / sizeof(int32_t);
pThreadContext->pStackPointer = stack + pMethod->allocaSize;
Expand Down Expand Up @@ -1423,6 +1426,21 @@ do { \
STELEM(double, double);
break;
}
case INTOP_LDTOKEN:
Copy link

Copilot AI May 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review the ldtoken opcode implementation to ensure that the helper function resolution using the INTERP_INDIRECT_HELPER_TAG flag works correctly for all token types.

Copilot uses AI. Check for mistakes.
{
int dreg = ip[1];
void *nativeHandle = pMethod->pDataItems[ip[2]];
size_t helperDirectOrIndirect = (size_t)pMethod->pDataItems[ip[3]];
HELPER_FTN_PP helper = nullptr;
if (helperDirectOrIndirect & INTERP_INDIRECT_HELPER_TAG)
helper = *(HELPER_FTN_PP *)(helperDirectOrIndirect & ~INTERP_INDIRECT_HELPER_TAG);
else
helper = (HELPER_FTN_PP)helperDirectOrIndirect;
void *managedHandle = helper(nativeHandle);
LOCAL_VAR(dreg, void*) = managedHandle;
ip += 4;
break;
}
case INTOP_FAILFAST:
assert(0);
break;
Expand Down Expand Up @@ -1456,6 +1474,7 @@ do { \

stack = pFrame->pStack;
pMethod = *(InterpMethod**)pFrame->startIp;
assert(pMethod->self == pMethod);
pThreadContext->pStackPointer = pFrame->pStack + pMethod->allocaSize;
goto MAIN_LOOP;
}
Expand All @@ -1472,6 +1491,7 @@ do { \
ip = pFrame->ip;
stack = pFrame->pStack;
pMethod = *(InterpMethod**)pFrame->startIp;
assert(pMethod->self == pMethod);
pFrame->ip = NULL;

pThreadContext->pStackPointer = pFrame->pStack + pMethod->allocaSize;
Expand Down
34 changes: 34 additions & 0 deletions src/tests/JIT/interpreter/Interpreter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,13 @@ public static void RunInterpreterTests()
if (!TestSizeof())
Environment.FailFast(null);

if (!TestLdtoken())
Environment.FailFast(null);
/*
if (!TestMdArray())
Environment.FailFast(null);
*/

System.GC.Collect();
}

Expand Down Expand Up @@ -959,4 +966,31 @@ public static unsafe bool TestSizeof()
return false;
return true;
}

public static int LdtokenField = 7;

public static bool TestLdtoken()
{
Type t = typeof(int);
int i = 42;
if (!ReferenceEquals(t, i.GetType()))
return false;
// These generate field and method ldtoken opcodes, but the test fails because we are missing castclass and possibly also generics
/*
System.Linq.Expressions.Expression<Func<int>> f = () => LdtokenField;
System.Linq.Expressions.Expression<Action> a = () => TestLdtoken();
*/
return true;
}

public static bool TestMdArray()
{
// FIXME: This generates roughly:
// newobj int[,].ctor
// ldtoken int[,]
// call System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray
// The newobj currently fails because int[,].ctor isn't a real method, the interp needs to use getCallInfo to determine how to invoke it
int[,] a = {{1, 2}, {3, 4}};
return a[0, 1] == 2;
}
}
Loading