From 909868c08ca531ae9cd1bda2bf95e0e9c683fddf Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Thu, 22 Jan 2026 02:34:19 +0100 Subject: [PATCH] Add interp support for field addr via helper The interpreter compiler was missing support for getting field address via helper call that is used in EnC scenarios. This change adds such support for both static and instance fields. It makes all System.Runtime.Loader.Tests libraries tests pass when running interpreted. --- src/coreclr/interpreter/compiler.cpp | 41 ++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/coreclr/interpreter/compiler.cpp b/src/coreclr/interpreter/compiler.cpp index 94020d040f325c..3f597700ec5fd0 100644 --- a/src/coreclr/interpreter/compiler.cpp +++ b/src/coreclr/interpreter/compiler.cpp @@ -6127,6 +6127,15 @@ void InterpCompiler::EmitStaticFieldAddress(CORINFO_FIELD_INFO *pFieldInfo, CORI m_pLastNewIns->SetDVar(m_pStackPointer[-1].var); break; } + case CORINFO_FIELD_STATIC_ADDR_HELPER: + { + AddIns(INTOP_CALL_HELPER_P_P); + m_pLastNewIns->data[0] = GetDataForHelperFtn(pFieldInfo->helper); + m_pLastNewIns->data[1] = GetDataItemIndex(pResolvedToken->hField); + PushInterpType(InterpTypeByRef, NULL); + m_pLastNewIns->SetDVar(m_pStackPointer[-1].var); + break; + } default: BADCODE("Unsupported static field accessor"); break; @@ -9441,6 +9450,16 @@ void InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo) m_pStackPointer--; EmitStaticFieldAddress(&fieldInfo, &resolvedToken); } + else if (fieldInfo.fieldAccessor == CORINFO_FIELD_INSTANCE_ADDR_HELPER) + { + m_pStackPointer--; + AddIns(INTOP_CALL_HELPER_P_SP); + m_pLastNewIns->data[0] = GetDataForHelperFtn(fieldInfo.helper); + m_pLastNewIns->data[1] = GetDataItemIndex(resolvedToken.hField); + m_pLastNewIns->SetSVar(m_pStackPointer[0].var); + PushInterpType(InterpTypeByRef, NULL); + m_pLastNewIns->SetDVar(m_pStackPointer[-1].var); + } else { assert(fieldInfo.fieldAccessor == CORINFO_FIELD_INSTANCE); @@ -9477,6 +9496,17 @@ void InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo) m_pStackPointer--; EmitStaticFieldAccess(interpFieldType, &fieldInfo, &resolvedToken, true); } + else if (fieldInfo.fieldAccessor == CORINFO_FIELD_INSTANCE_ADDR_HELPER) + { + m_pStackPointer--; + AddIns(INTOP_CALL_HELPER_P_SP); + m_pLastNewIns->data[0] = GetDataForHelperFtn(fieldInfo.helper); + m_pLastNewIns->data[1] = GetDataItemIndex(resolvedToken.hField); + m_pLastNewIns->SetSVar(m_pStackPointer[0].var); + PushInterpType(InterpTypeByRef, NULL); + m_pLastNewIns->SetDVar(m_pStackPointer[-1].var); + EmitLdind(interpFieldType, fieldInfo.structType, 0); + } else { assert(fieldInfo.fieldAccessor == CORINFO_FIELD_INSTANCE); @@ -9547,6 +9577,17 @@ void InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo) // Pop the unused object reference m_pStackPointer--; } + else if (fieldInfo.fieldAccessor == CORINFO_FIELD_INSTANCE_ADDR_HELPER) + { + AddIns(INTOP_CALL_HELPER_P_SP); + m_pLastNewIns->data[0] = GetDataForHelperFtn(fieldInfo.helper); + m_pLastNewIns->data[1] = GetDataItemIndex(resolvedToken.hField); + m_pLastNewIns->SetSVar(m_pStackPointer[-2].var); + PushInterpType(InterpTypeByRef, NULL); + m_pLastNewIns->SetDVar(m_pStackPointer[-1].var); + EmitStind(interpFieldType, fieldInfo.structType, 0, true, true /* enableImplicitArgConversionRules */); + m_pStackPointer--; + } else { assert(fieldInfo.fieldAccessor == CORINFO_FIELD_INSTANCE);