Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions src/coreclr/inc/corinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -3461,6 +3461,10 @@ class ICorDynamicInfo : public ICorStaticInfo
virtual void updateEntryPointForTailCall(CORINFO_CONST_LOOKUP* entryPoint) = 0;

virtual CORINFO_METHOD_HANDLE getSpecialCopyHelper(CORINFO_CLASS_HANDLE type) = 0;

// Get the helper function to use when loading/storing a value of the given type via
// an indirect address (e.g. from or to a byref or pointer value), if any.
virtual CorInfoHelpFunc getSpecialIndirectLoadStoreHelper(CORINFO_CLASS_HANDLE type) = 0;
};

/**********************************************************************************/
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/inc/icorjitinfoimpl_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,9 @@ uint32_t getJitFlags(
CORINFO_METHOD_HANDLE getSpecialCopyHelper(
CORINFO_CLASS_HANDLE type) override;

CorInfoHelpFunc getSpecialIndirectLoadStoreHelper(
CORINFO_CLASS_HANDLE type) override;

/**********************************************************************************/
// clang-format on
/**********************************************************************************/
10 changes: 5 additions & 5 deletions src/coreclr/inc/jiteeversionguid.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@

#include <minipal/guid.h>

constexpr GUID JITEEVersionIdentifier = { /* d98b5b0d-dd75-4e4d-b950-0d1cafd01dea */
0xd98b5b0d,
0xdd75,
0x4e4d,
{0xb9, 0x50, 0x0d, 0x1c, 0xaf, 0xd0, 0x1d, 0xea}
constexpr GUID JITEEVersionIdentifier = { /* 853d2efc-3e07-444f-83b4-c46ffafe8cd4 */
0x853d2efc,
0x3e07,
0x444f,
{0x83, 0xb4, 0xc4, 0x6f, 0xfa, 0xfe, 0x8c, 0xd4}
};

#endif // JIT_EE_VERSIONING_GUID_H
1 change: 1 addition & 0 deletions src/coreclr/jit/ICorJitInfo_names_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,5 +181,6 @@ DEF_CLR_API(getRelocTypeHint)
DEF_CLR_API(getExpectedTargetArchitecture)
DEF_CLR_API(getJitFlags)
DEF_CLR_API(getSpecialCopyHelper)
DEF_CLR_API(getSpecialIndirectLoadStoreHelper)

#undef DEF_CLR_API
9 changes: 9 additions & 0 deletions src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1758,6 +1758,15 @@ CORINFO_METHOD_HANDLE WrapICorJitInfo::getSpecialCopyHelper(
return temp;
}

CorInfoHelpFunc WrapICorJitInfo::getSpecialIndirectLoadStoreHelper(
CORINFO_CLASS_HANDLE type)
{
API_ENTER(getSpecialIndirectLoadStoreHelper);
CorInfoHelpFunc temp = wrapHnd->getSpecialIndirectLoadStoreHelper(type);
API_LEAVE(getSpecialIndirectLoadStoreHelper);
return temp;
}

/**********************************************************************************/
// clang-format on
/**********************************************************************************/
72 changes: 72 additions & 0 deletions src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10779,6 +10779,23 @@ void Compiler::impImportBlockCode(BasicBlock* block)
op2 = impPopStack().val; // Src addr
op1 = impPopStack().val; // Dest addr

// Check if the type requires a special helper for indirect copy
CorInfoHelpFunc specialHelper =
info.compCompHnd->getSpecialIndirectLoadStoreHelper(resolvedToken.hClass);
if (specialHelper != CORINFO_HELP_UNDEF)
{
// Helper expects: TypeHandle, destination pointer, source pointer
GenTree* typeHandleOp = impTokenToHandle(&resolvedToken, nullptr, true);
if (typeHandleOp == nullptr)
{
return; // compDonotInline()
}

// op1 is destination, op2 is source
op1 = gtNewHelperCallNode(specialHelper, TYP_VOID, typeHandleOp, op1, op2);
goto SPILL_APPEND;
}

op2 = gtNewLoadValueNode(layout, op2);
op1 = gtNewStoreValueNode(layout, op1, op2);
goto SPILL_APPEND;
Expand All @@ -10804,6 +10821,27 @@ void Compiler::impImportBlockCode(BasicBlock* block)
op1 = impPopStack().val; // Ptr
assertImp(varTypeIsStruct(op2));

// Check if the type requires a special helper for indirect store
CorInfoHelpFunc specialHelper =
info.compCompHnd->getSpecialIndirectLoadStoreHelper(resolvedToken.hClass);
if (specialHelper != CORINFO_HELP_UNDEF)
{
// Helper expects: TypeHandle, destination pointer, source pointer
GenTree* typeHandleOp = impTokenToHandle(&resolvedToken, nullptr, true);
if (typeHandleOp == nullptr)
{
return; // compDonotInline()
}

// Get address of the source value
GenTreeFlags srcIndirFlags = GTF_EMPTY;
GenTree* srcAddr = impGetNodeAddr(op2, CHECK_SPILL_ALL, GTF_EMPTY, &srcIndirFlags);

// op1 is already the destination pointer
op1 = gtNewHelperCallNode(specialHelper, TYP_VOID, typeHandleOp, op1, srcAddr);
goto SPILL_APPEND;
}

GenTreeFlags indirFlags = impPrefixFlagsToIndirFlags(prefixFlags);
if (eeIsByrefLike(resolvedToken.hClass))
{
Expand Down Expand Up @@ -10872,6 +10910,40 @@ void Compiler::impImportBlockCode(BasicBlock* block)
op1 = impPopStack().val;
assertImp((genActualType(op1) == TYP_I_IMPL) || op1->TypeIs(TYP_BYREF));

// Check if the type requires a special helper for indirect load
if (varTypeIsStruct(lclTyp))
{
CorInfoHelpFunc specialHelper =
info.compCompHnd->getSpecialIndirectLoadStoreHelper(resolvedToken.hClass);
if (specialHelper != CORINFO_HELP_UNDEF)
{
// Helper expects: TypeHandle, destination pointer, source pointer
// For load, we create a temp as the destination
GenTree* typeHandleOp = impTokenToHandle(&resolvedToken, nullptr, true);
if (typeHandleOp == nullptr)
{
return; // compDonotInline()
}

// Create a temp to hold the loaded value
unsigned tmpNum = lvaGrabTemp(true DEBUGARG("special indirect load temp"));
lvaSetStruct(tmpNum, resolvedToken.hClass, false);

// Get the address of the temp (destination)
GenTree* destAddr = gtNewLclVarAddrNode(tmpNum, TYP_BYREF);

// op1 is the source pointer
GenTree* helperCall =
gtNewHelperCallNode(specialHelper, TYP_VOID, typeHandleOp, destAddr, op1);
impAppendTree(helperCall, CHECK_SPILL_ALL, impCurStmtDI);

// Push the temp value onto the stack
op1 = gtNewLclvNode(tmpNum, lclTyp);
impPushOnStack(op1, tiRetVal);
break;
}
}

op1 = gtNewLoadValueNode(lclTyp, layout, op1, impPrefixFlagsToIndirFlags(prefixFlags));
impPushOnStack(op1, tiRetVal);
break;
Expand Down
68 changes: 67 additions & 1 deletion src/coreclr/jit/lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5859,13 +5859,79 @@ void Lowering::LowerRetStruct(GenTreeUnOp* ret)
case GT_BLK:
case GT_IND:
{
CORINFO_CLASS_HANDLE retClsHnd = comp->info.compMethodInfo->args.retTypeClass;

// Check if the type requires a special helper for indirect load
CorInfoHelpFunc specialHelper = comp->info.compCompHnd->getSpecialIndirectLoadStoreHelper(retClsHnd);
if (specialHelper != CORINFO_HELP_UNDEF)
{
// Create a temp to hold the loaded value
unsigned tmpNum = comp->lvaGrabTemp(true DEBUGARG("special indirect load return temp"));
comp->lvaSetStruct(tmpNum, retClsHnd, false);

// Get source address from the indirection
GenTree* srcAddr = retVal->AsIndir()->Addr();

// Get the address of the temp (destination)
GenTree* destAddr = comp->gtNewLclVarAddrNode(tmpNum, TYP_BYREF);

// Create the type handle node
GenTree* typeHandleOp = comp->gtNewIconEmbClsHndNode(retClsHnd);

// Create placeholder nodes for fgMorphArgs
GenTree* typeHandlePlaceholder = comp->gtNewZeroConNode(TYP_I_IMPL);
GenTree* destPlaceholder = comp->gtNewZeroConNode(TYP_BYREF);
GenTree* srcPlaceholder = comp->gtNewZeroConNode(TYP_BYREF);

// Create the helper call: helper(TypeHandle, dest, src)
GenTreeCall* helperCall = comp->gtNewHelperCallNode(specialHelper, TYP_VOID, typeHandlePlaceholder,
destPlaceholder, srcPlaceholder);
comp->fgMorphArgs(helperCall);

LIR::Range helperRange = LIR::SeqTree(comp, helperCall);
GenTree* rangeStart = helperRange.FirstNode();
GenTree* rangeEnd = helperRange.LastNode();

// Insert the helper call and its arguments before the return
BlockRange().InsertBefore(ret, std::move(helperRange));
BlockRange().InsertBefore(rangeStart, typeHandleOp);
BlockRange().InsertBefore(rangeStart, destAddr);

// srcAddr is already in the LIR before ret, just need to keep it there
// We need to replace the placeholders with the real values
LIR::Use typeHandleUse;
LIR::Use destUse;
LIR::Use srcUse;
BlockRange().TryGetUse(typeHandlePlaceholder, &typeHandleUse);
BlockRange().TryGetUse(destPlaceholder, &destUse);
BlockRange().TryGetUse(srcPlaceholder, &srcUse);
typeHandleUse.ReplaceWith(typeHandleOp);
destUse.ReplaceWith(destAddr);
srcUse.ReplaceWith(srcAddr);
typeHandlePlaceholder->SetUnusedValue();
destPlaceholder->SetUnusedValue();
srcPlaceholder->SetUnusedValue();

// Remove the original indirection node
BlockRange().Remove(retVal);

LowerRange(rangeStart, rangeEnd);
MovePutArgNodesUpToCall(helperCall);

// Update the return to use the temp
LIR::Use retValUse(BlockRange(), &ret->gtOp1, ret);
ReplaceWithLclVar(retValUse, tmpNum);
LowerRetSingleRegStructLclVar(ret);
break;
}

// Spill to a local if sizes don't match so we can avoid the "load more than requested"
// problem, e.g. struct size is 5 and we emit "ldr x0, [x1]"
if (genTypeSize(nativeReturnType) > retVal->AsIndir()->Size())
{
LIR::Use retValUse(BlockRange(), &ret->gtOp1, ret);
unsigned tmpNum = comp->lvaGrabTemp(true DEBUGARG("mis-sized struct return"));
comp->lvaSetStruct(tmpNum, comp->info.compMethodInfo->args.retTypeClass, false);
comp->lvaSetStruct(tmpNum, retClsHnd, false);

ReplaceWithLclVar(retValUse, tmpNum);
LowerRetSingleRegStructLclVar(ret);
Expand Down
5 changes: 5 additions & 0 deletions src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4576,5 +4576,10 @@ private static bool TryReadRvaFieldData(FieldDesc field, byte* buffer, int buffe
{
throw new NotImplementedException("getSpecialCopyHelper");
}

private CorInfoHelpFunc getSpecialIndirectLoadStoreHelper(CORINFO_CLASS_STRUCT_* type)
{
return CorInfoHelpFunc.CORINFO_HELP_UNDEF;
}
}
}
17 changes: 17 additions & 0 deletions src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ static ICorJitInfoCallbacks()
s_callbacks.getExpectedTargetArchitecture = &_getExpectedTargetArchitecture;
s_callbacks.getJitFlags = &_getJitFlags;
s_callbacks.getSpecialCopyHelper = &_getSpecialCopyHelper;
s_callbacks.getSpecialIndirectLoadStoreHelper = &_getSpecialIndirectLoadStoreHelper;
}

public delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, byte> isIntrinsic;
Expand Down Expand Up @@ -376,6 +377,7 @@ static ICorJitInfoCallbacks()
public delegate* unmanaged<IntPtr, IntPtr*, uint> getExpectedTargetArchitecture;
public delegate* unmanaged<IntPtr, IntPtr*, CORJIT_FLAGS*, uint, uint> getJitFlags;
public delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_METHOD_STRUCT_*> getSpecialCopyHelper;
public delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CorInfoHelpFunc> getSpecialIndirectLoadStoreHelper;
}

private static IntPtr GetUnmanagedCallbacks()
Expand Down Expand Up @@ -2988,5 +2990,20 @@ private static uint _getJitFlags(IntPtr thisHandle, IntPtr* ppException, CORJIT_
}
}

[UnmanagedCallersOnly]
private static CorInfoHelpFunc _getSpecialIndirectLoadStoreHelper(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* type)
{
var _this = GetThis(thisHandle);
try
{
return _this.getSpecialIndirectLoadStoreHelper(type);
}
catch (Exception ex)
{
*ppException = _this.AllocException(ex);
return default;
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -347,3 +347,4 @@ FUNCTIONS
uint32_t getExpectedTargetArchitecture()
uint32_t getJitFlags(CORJIT_FLAGS* flags, uint32_t sizeInBytes)
CORINFO_METHOD_HANDLE getSpecialCopyHelper(CORINFO_CLASS_HANDLE type) = 0;
CorInfoHelpFunc getSpecialIndirectLoadStoreHelper(CORINFO_CLASS_HANDLE type)
10 changes: 10 additions & 0 deletions src/coreclr/tools/aot/jitinterface/jitinterface_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ struct JitInterfaceCallbacks
uint32_t (* getExpectedTargetArchitecture)(void * thisHandle, CorInfoExceptionClass** ppException);
uint32_t (* getJitFlags)(void * thisHandle, CorInfoExceptionClass** ppException, CORJIT_FLAGS* flags, uint32_t sizeInBytes);
CORINFO_METHOD_HANDLE (* getSpecialCopyHelper)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE type);
CorInfoHelpFunc (* getSpecialIndirectLoadStoreHelper)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE type);

};

Expand Down Expand Up @@ -1936,4 +1937,13 @@ class JitInterfaceWrapper : public ICorJitInfo
if (pException != nullptr) throw pException;
return temp;
}

virtual CorInfoHelpFunc getSpecialIndirectLoadStoreHelper(
CORINFO_CLASS_HANDLE type)
{
CorInfoExceptionClass* pException = nullptr;
CorInfoHelpFunc temp = _callbacks->getSpecialIndirectLoadStoreHelper(_thisHandle, &pException, type);
if (pException != nullptr) throw pException;
return temp;
}
};
1 change: 1 addition & 0 deletions src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ LWM(GetAsyncResumptionStub, DWORD, DLDL)
LWM(GetContinuationType, Agnostic_GetContinuationTypeIn, DWORDLONG)
LWM(UpdateEntryPointForTailCall, Agnostic_CORINFO_CONST_LOOKUP, Agnostic_CORINFO_CONST_LOOKUP)
LWM(GetSpecialCopyHelper, DWORDLONG, DWORDLONG)
LWM(GetSpecialIndirectLoadStoreHelper, DWORDLONG, DWORD)
LWM(GetThreadTLSIndex, DWORD, DLD)
LWM(GetTokenTypeAsHandle, GetTokenTypeAsHandleValue, DWORDLONG)
LWM(GetTypeForBox, DWORDLONG, DWORDLONG)
Expand Down
24 changes: 24 additions & 0 deletions src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7336,6 +7336,30 @@ CORINFO_METHOD_HANDLE MethodContext::repGetSpecialCopyHelper(CORINFO_CLASS_HANDL
return (CORINFO_METHOD_HANDLE)value;
}

void MethodContext::recGetSpecialIndirectLoadStoreHelper(CORINFO_CLASS_HANDLE type, CorInfoHelpFunc result)
{
if (GetSpecialIndirectLoadStoreHelper == nullptr)
GetSpecialIndirectLoadStoreHelper = new LightWeightMap<DWORDLONG, DWORD>();

DWORDLONG key = CastHandle(type);
DWORD value = (DWORD)result;
GetSpecialIndirectLoadStoreHelper->Add(key, value);
DEBUG_REC(dmpGetSpecialIndirectLoadStoreHelper(key, value));
}

void MethodContext::dmpGetSpecialIndirectLoadStoreHelper(DWORDLONG key, DWORD value)
{
printf("GetSpecialIndirectLoadStoreHelper key %016" PRIX64 ", value %u", key, value);
}

CorInfoHelpFunc MethodContext::repGetSpecialIndirectLoadStoreHelper(CORINFO_CLASS_HANDLE type)
{
DWORDLONG key = CastHandle(type);
DWORD value = LookupByKeyOrMiss(GetSpecialIndirectLoadStoreHelper, key, ": key %016" PRIX64 "", key);
DEBUG_REP(dmpGetSpecialIndirectLoadStoreHelper(key, value));
return (CorInfoHelpFunc)value;
}

void MethodContext::dmpSigInstHandleMap(DWORD key, DWORDLONG value)
{
printf("SigInstHandleMap key %u, value %016" PRIX64 "", key, value);
Expand Down
5 changes: 5 additions & 0 deletions src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -907,6 +907,10 @@ class MethodContext
void dmpGetSpecialCopyHelper(DWORDLONG key, DWORDLONG value);
CORINFO_METHOD_HANDLE repGetSpecialCopyHelper(CORINFO_CLASS_HANDLE type);

void recGetSpecialIndirectLoadStoreHelper(CORINFO_CLASS_HANDLE type, CorInfoHelpFunc result);
void dmpGetSpecialIndirectLoadStoreHelper(DWORDLONG key, DWORD value);
CorInfoHelpFunc repGetSpecialIndirectLoadStoreHelper(CORINFO_CLASS_HANDLE type);

void dmpSigInstHandleMap(DWORD key, DWORDLONG value);

struct Environment
Expand Down Expand Up @@ -1209,6 +1213,7 @@ enum mcPackets
Packet_GetCookieForInterpreterCalliSig = 232,
Packet_GetHelperFtn = 233,
Packet_GetContinuationType = 234,
Packet_GetSpecialIndirectLoadStoreHelper = 235,
};

void SetDebugDumpVariables();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2039,3 +2039,11 @@ CORINFO_METHOD_HANDLE interceptor_ICJI::getSpecialCopyHelper(CORINFO_CLASS_HANDL
mc->recGetSpecialCopyHelper(type, temp);
return temp;
}

CorInfoHelpFunc interceptor_ICJI::getSpecialIndirectLoadStoreHelper(CORINFO_CLASS_HANDLE type)
{
mc->cr->AddCall("getSpecialIndirectLoadStoreHelper");
CorInfoHelpFunc temp = original_ICorJitInfo->getSpecialIndirectLoadStoreHelper(type);
mc->recGetSpecialIndirectLoadStoreHelper(type, temp);
return temp;
}
Original file line number Diff line number Diff line change
Expand Up @@ -1454,3 +1454,10 @@ CORINFO_METHOD_HANDLE interceptor_ICJI::getSpecialCopyHelper(
return original_ICorJitInfo->getSpecialCopyHelper(type);
}

CorInfoHelpFunc interceptor_ICJI::getSpecialIndirectLoadStoreHelper(
CORINFO_CLASS_HANDLE type)
{
mcs->AddCall("getSpecialIndirectLoadStoreHelper");
return original_ICorJitInfo->getSpecialIndirectLoadStoreHelper(type);
}

Loading
Loading