Skip to content

Intrinsify typeof(T).GetGenericTypeDefinition #97159

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
15 changes: 15 additions & 0 deletions src/coreclr/inc/corinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -2134,6 +2134,21 @@ class ICorStaticInfo
CORINFO_METHOD_HANDLE meth1Hnd,
CORINFO_METHOD_HANDLE meth2Hnd) = 0;

//------------------------------------------------------------------------------
// getTypeDefinition: Get the (unconstructed) type definition from a given type handle.
//
// Arguments:
// type - The input type handle
//
// Return Value:
// The type handle for the (unconstructed) type definition from type.
//
// Remarks:
// This is equivalent of Type.GetGenericTypeDefinition(). Given a generic type handle, it will
// return the original type definition (eg. for Foo<int> it will return Foo<>). This method
// should only be called when the input type is in fact a generic type.
virtual CORINFO_CLASS_HANDLE getTypeDefinition(CORINFO_CLASS_HANDLE type) = 0;

// Decides if you have any limitations for inlining. If everything's OK, it will return
// INLINE_PASS.
//
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 @@ -48,6 +48,9 @@ bool haveSameMethodDefinition(
CORINFO_METHOD_HANDLE meth1Hnd,
CORINFO_METHOD_HANDLE meth2Hnd) override;

CORINFO_CLASS_HANDLE getTypeDefinition(
CORINFO_CLASS_HANDLE type) override;

CorInfoInline canInline(
CORINFO_METHOD_HANDLE callerHnd,
CORINFO_METHOD_HANDLE calleeHnd) override;
Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/inc/jiteeversionguid.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID;
#define GUID_DEFINED
#endif // !GUID_DEFINED

constexpr GUID JITEEVersionIdentifier = { /* 86eab154-5d93-4fad-bc07-e94fd9268b70 */
0x86eab154,
0x5d93,
0x4fad,
{0xbc, 0x07, 0xe9, 0x4f, 0xd9, 0x26, 0x8b, 0x70}
constexpr GUID JITEEVersionIdentifier = { /* dbcd6414-2c05-4414-9086-6417cffb94d1 */
0xdbcd6414,
0x2c05,
0x4414,
{0x90, 0x86, 0x64, 0x17, 0xcf, 0xfb, 0x94, 0xd1}
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
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 @@ -11,6 +11,7 @@ DEF_CLR_API(setMethodAttribs)
DEF_CLR_API(getMethodSig)
DEF_CLR_API(getMethodInfo)
DEF_CLR_API(haveSameMethodDefinition)
DEF_CLR_API(getTypeDefinition)
DEF_CLR_API(canInline)
DEF_CLR_API(beginInlining)
DEF_CLR_API(reportInliningDecision)
Expand Down
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 @@ -79,6 +79,15 @@ bool WrapICorJitInfo::haveSameMethodDefinition(
return temp;
}

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

CorInfoInline WrapICorJitInfo::canInline(
CORINFO_METHOD_HANDLE callerHnd,
CORINFO_METHOD_HANDLE calleeHnd)
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -4429,6 +4429,7 @@ class Compiler
void impImportLeave(BasicBlock* block);
void impResetLeaveBlock(BasicBlock* block, unsigned jmpAddr);
GenTree* impTypeIsAssignable(GenTree* typeTo, GenTree* typeFrom);
GenTree* impGetGenericTypeDefinition(GenTree* type);

// Mirrors StringComparison.cs
enum StringComparison
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/fgbasic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1345,6 +1345,7 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
case NI_System_Type_get_IsPrimitive:
case NI_System_Type_get_IsByRefLike:
case NI_System_Type_GetTypeFromHandle:
case NI_System_Type_GetGenericTypeDefinition:
case NI_System_String_get_Length:
case NI_System_Buffers_Binary_BinaryPrimitives_ReverseEndianness:
#if defined(FEATURE_HW_INTRINSICS)
Expand Down
27 changes: 27 additions & 0 deletions src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2486,6 +2486,33 @@ GenTree* Compiler::impTypeIsAssignable(GenTree* typeTo, GenTree* typeFrom)
return nullptr;
}


GenTree* Compiler::impGetGenericTypeDefinition(GenTree* type)
{
// This intrinsic requires the first arg to be some `typeof()` expression,
// ie. it applies to cases such as `typeof(...).GetGenericTypeDefinition()`.
CORINFO_CLASS_HANDLE hClassType = NO_CLASS_HANDLE;
if (gtIsTypeof(type, &hClassType))
{
// Check that the 'typeof()' expression is being used on a type that is in fact generic.
// If that is not the case, we don't expand the intrinsic. This will end up using
// the usual Type.GetGenericTypeDefinition() at runtime, which will throw in this case.
if (info.compCompHnd->getTypeInstantiationArgument(hClassType, 0) != NO_CLASS_HANDLE)
{
CORINFO_CLASS_HANDLE hClassResult = info.compCompHnd->getTypeDefinition(hClassType);

GenTree* retNode = gtNewIconEmbClsHndNode(hClassResult);

// Drop the typeof(T) node
impPopStack();

return retNode;
}
}

return nullptr;
}

/*****************************************************************************
* 'logMsg' is true if a log message needs to be logged. false if the caller has
* already logged it (presumably in a more detailed fashion than done here)
Expand Down
15 changes: 15 additions & 0 deletions src/coreclr/jit/importercalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2874,6 +2874,9 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
case NI_System_Type_op_Equality:
case NI_System_Type_op_Inequality:

// This allows folding "typeof(...).GetGenericTypeDefinition() == typeof(...)"
case NI_System_Type_GetGenericTypeDefinition:

// These may lead to early dead code elimination
case NI_System_Type_get_IsValueType:
case NI_System_Type_get_IsPrimitive:
Expand Down Expand Up @@ -3391,6 +3394,14 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
break;
}

case NI_System_Type_GetGenericTypeDefinition:
{
GenTree* type = impStackTop(0).val;

retNode = impGetGenericTypeDefinition(type);
break;
}

case NI_System_Type_op_Equality:
case NI_System_Type_op_Inequality:
{
Expand Down Expand Up @@ -9250,6 +9261,10 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method)
{
result = NI_System_Type_GetTypeFromHandle;
}
else if (strcmp(methodName, "GetGenericTypeDefinition") == 0)
{
result = NI_System_Type_GetGenericTypeDefinition;
}
else if (strcmp(methodName, "IsAssignableFrom") == 0)
{
result = NI_System_Type_IsAssignableFrom;
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/namedintrinsiclist.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ enum NamedIntrinsic : unsigned short
NI_System_Type_op_Equality,
NI_System_Type_op_Inequality,
NI_System_Type_GetTypeFromHandle,
NI_System_Type_GetGenericTypeDefinition,
NI_System_Array_Clone,
NI_System_Array_GetLength,
NI_System_Array_GetLowerBound,
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 @@ -1253,6 +1253,11 @@ private bool haveSameMethodDefinition(CORINFO_METHOD_STRUCT_* methHnd1, CORINFO_
return meth1.GetTypicalMethodDefinition() == meth2.GetTypicalMethodDefinition();
}

private CORINFO_CLASS_STRUCT_* getTypeDefinition(CORINFO_CLASS_STRUCT_* type)
{
return ObjectToHandle(HandleToObject(type).GetTypeDefinition());
}

private CorInfoInline canInline(CORINFO_METHOD_STRUCT_* callerHnd, CORINFO_METHOD_STRUCT_* calleeHnd)
{
MethodDesc callerMethod = HandleToObject(callerHnd);
Expand Down
Loading