Skip to content

Commit 16b28c7

Browse files
MichalPetrykaAndyAyersMSjkotas
authored
Make Type.IsEnum and Type.GetEnumUnderlyingType intrinsics (#71685)
* Make Type.GetTypeCode an intrinsic Makes Type.GetTypeCode a JIT intrinsic for primitive types, enums and strings. Makes Type.IsEnum use intrinsics instead of IsSubclassOf Makes Enum.GetUnderlyingType use Type.GetTypeCode Moves the legacy FCall to InternalGetUnderlyingTypeImpl, so that the non-intrinsic GetTypeCode can use it. Introduces JIT tests checking the generated codegen. * Change IsEnum to an intrinsic * Fallback to the FCall for nint/nuint enums * Fix compilation * Add missing Intrinsic * Add typeof support to IsKnownConstant * Use gtIsTypeHandleToRuntimeTypeHelper * Add __reftype tests * Make more places use gtIsTypeof * Update EnumTests.cs * Add impTypeGetTypeCode to the header * Update EnumGetUnderlyingTypeEnums.il * Make the IsActualEnum helper an intrinsic * Remove GetTypeCode intrinsics * Create a new JIT-EE api, add GetEnumUnderlyingType back * Optimize GetTypeCode with IsKnownConstant * Change the code to make the inliner happy * Handle all types in GetTypeCode * Check for custom types * Fix build, do suggested changes Co-authored-by: Andy Ayers <andya@microsoft.com> Co-authored-by: Jan Kotas <jkotas@microsoft.com>
1 parent 00e6482 commit 16b28c7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+903
-229
lines changed

src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3397,6 +3397,7 @@ public override unsafe bool IsEnum
33973397
// This returns true for actual enum types only.
33983398
internal unsafe bool IsActualEnum
33993399
{
3400+
[Intrinsic]
34003401
get
34013402
{
34023403
TypeHandle th = GetNativeTypeHandle();

src/coreclr/inc/corinfo.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2270,7 +2270,7 @@ class ICorStaticInfo
22702270

22712271
//------------------------------------------------------------------------------
22722272
// printObjectDescription: Prints a (possibly truncated) textual UTF8 representation of the given
2273-
// object to a preallocated buffer. It's intended to be used only for debug/diagnostic
2273+
// object to a preallocated buffer. It's intended to be used only for debug/diagnostic
22742274
// purposes such as JitDisasm. The buffer is null-terminated (even if truncated).
22752275
//
22762276
// Arguments:
@@ -2635,6 +2635,16 @@ class ICorStaticInfo
26352635
CORINFO_CLASS_HANDLE cls2
26362636
) = 0;
26372637

2638+
// Returns TypeCompareState::Must if cls is known to be an enum.
2639+
// For enums with known exact type returns the underlying
2640+
// type in underlyingType when the provided pointer is
2641+
// non-NULL.
2642+
// Returns TypeCompareState::May when a runtime check is required.
2643+
virtual TypeCompareState isEnum(
2644+
CORINFO_CLASS_HANDLE cls,
2645+
CORINFO_CLASS_HANDLE* underlyingType
2646+
) = 0;
2647+
26382648
// Given a class handle, returns the Parent type.
26392649
// For COMObjectType, it returns Class Handle of System.Object.
26402650
// Returns 0 if System.Object is passed in.
@@ -2849,7 +2859,7 @@ class ICorStaticInfo
28492859
CORINFO_CLASS_HANDLE *vcTypeRet /* OUT */
28502860
) = 0;
28512861

2852-
// Obtains a list of exact classes for a given base type. Returns 0 if the number of
2862+
// Obtains a list of exact classes for a given base type. Returns 0 if the number of
28532863
// the exact classes is greater than maxExactClasses or if more types might be loaded
28542864
// in future.
28552865
virtual int getExactClasses(

src/coreclr/inc/icorjitinfoimpl_generated.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,10 @@ bool isMoreSpecificType(
352352
CORINFO_CLASS_HANDLE cls1,
353353
CORINFO_CLASS_HANDLE cls2) override;
354354

355+
TypeCompareState isEnum(
356+
CORINFO_CLASS_HANDLE cls,
357+
CORINFO_CLASS_HANDLE* underlyingType) override;
358+
355359
CORINFO_CLASS_HANDLE getParentType(
356360
CORINFO_CLASS_HANDLE cls) override;
357361

src/coreclr/inc/jiteeversionguid.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ typedef const GUID *LPCGUID;
4343
#define GUID_DEFINED
4444
#endif // !GUID_DEFINED
4545

46-
constexpr GUID JITEEVersionIdentifier = { /* 77b6df16-d27f-4118-9dfd-d8073ff20fb6 */
47-
0x77b6df16,
48-
0xd27f,
49-
0x4118,
50-
{0x9d, 0xfd, 0xd8, 0x7, 0x3f, 0xf2, 0xf, 0xb6}
46+
constexpr GUID JITEEVersionIdentifier = { /* e452af1d-0a1a-44a8-a5b3-ef6074b8ab4a */
47+
0xe452af1d,
48+
0x0a1a,
49+
0x44a8,
50+
{0xa5, 0xb3, 0xef, 0x60, 0x74, 0xb8, 0xab, 0x4a}
5151
};
5252

5353
//////////////////////////////////////////////////////////////////////////////////////////////////////////

src/coreclr/jit/ICorJitInfo_names_generated.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ DEF_CLR_API(compareTypesForCast)
8888
DEF_CLR_API(compareTypesForEquality)
8989
DEF_CLR_API(mergeClasses)
9090
DEF_CLR_API(isMoreSpecificType)
91+
DEF_CLR_API(isEnum)
9192
DEF_CLR_API(getParentType)
9293
DEF_CLR_API(getChildType)
9394
DEF_CLR_API(satisfiesClassConstraints)

src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,16 @@ bool WrapICorJitInfo::isMoreSpecificType(
830830
return temp;
831831
}
832832

833+
TypeCompareState WrapICorJitInfo::isEnum(
834+
CORINFO_CLASS_HANDLE cls,
835+
CORINFO_CLASS_HANDLE* underlyingType)
836+
{
837+
API_ENTER(isEnum);
838+
TypeCompareState temp = wrapHnd->isEnum(cls, underlyingType);
839+
API_LEAVE(isEnum);
840+
return temp;
841+
}
842+
833843
CORINFO_CLASS_HANDLE WrapICorJitInfo::getParentType(
834844
CORINFO_CLASS_HANDLE cls)
835845
{

src/coreclr/jit/compiler.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2878,6 +2878,8 @@ class Compiler
28782878
CORINFO_CLASS_HANDLE gtGetHelperArgClassHandle(GenTree* array);
28792879
// Get the class handle for a field
28802880
CORINFO_CLASS_HANDLE gtGetFieldClassHandle(CORINFO_FIELD_HANDLE fieldHnd, bool* pIsExact, bool* pIsNonNull);
2881+
// Check if this tree is a typeof()
2882+
bool gtIsTypeof(GenTree* tree, CORINFO_CLASS_HANDLE* handle = nullptr);
28812883

28822884
GenTree* gtCallGetDefinedRetBufLclAddr(GenTreeCall* call);
28832885

src/coreclr/jit/fgbasic.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,6 +1163,8 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
11631163
break;
11641164

11651165
// These are foldable if the first argument is a constant
1166+
case NI_System_Type_get_IsEnum:
1167+
case NI_System_Type_GetEnumUnderlyingType:
11661168
case NI_System_Type_get_IsValueType:
11671169
case NI_System_Type_get_IsByRefLike:
11681170
case NI_System_Type_GetTypeFromHandle:

src/coreclr/jit/gentree.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18335,6 +18335,42 @@ CORINFO_CLASS_HANDLE Compiler::gtGetFieldClassHandle(CORINFO_FIELD_HANDLE fieldH
1833518335
return fieldClass;
1833618336
}
1833718337

18338+
//------------------------------------------------------------------------
18339+
// gtIsTypeof: Checks if the tree is a typeof()
18340+
//
18341+
// Arguments:
18342+
// tree - the tree that is checked
18343+
// handle - (optional, default nullptr) - if non-null is set to the type
18344+
//
18345+
// Return Value:
18346+
// Is the tree typeof()
18347+
//
18348+
bool Compiler::gtIsTypeof(GenTree* tree, CORINFO_CLASS_HANDLE* handle)
18349+
{
18350+
if (tree->IsCall())
18351+
{
18352+
GenTreeCall* call = tree->AsCall();
18353+
if (gtIsTypeHandleToRuntimeTypeHelper(call))
18354+
{
18355+
assert(call->gtArgs.CountArgs() == 1);
18356+
CORINFO_CLASS_HANDLE hClass = gtGetHelperArgClassHandle(call->gtArgs.GetArgByIndex(0)->GetEarlyNode());
18357+
if (hClass != NO_CLASS_HANDLE)
18358+
{
18359+
if (handle != nullptr)
18360+
{
18361+
*handle = hClass;
18362+
}
18363+
return true;
18364+
}
18365+
}
18366+
}
18367+
if (handle != nullptr)
18368+
{
18369+
*handle = NO_CLASS_HANDLE;
18370+
}
18371+
return false;
18372+
}
18373+
1833818374
//------------------------------------------------------------------------
1833918375
// gtCallGetDefinedRetBufLclAddr:
1834018376
// Get the tree corresponding to the address of the retbuf that this call defines.

src/coreclr/jit/importer.cpp

Lines changed: 17 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2932,37 +2932,24 @@ GenTree* Compiler::impTypeIsAssignable(GenTree* typeTo, GenTree* typeFrom)
29322932
//
29332933
// to true/false
29342934

2935-
if (typeTo->IsCall() && typeFrom->IsCall())
2935+
// make sure both arguments are `typeof()`
2936+
CORINFO_CLASS_HANDLE hClassTo = NO_CLASS_HANDLE;
2937+
CORINFO_CLASS_HANDLE hClassFrom = NO_CLASS_HANDLE;
2938+
if (gtIsTypeof(typeTo, &hClassTo) && gtIsTypeof(typeFrom, &hClassFrom))
29362939
{
2937-
// make sure both arguments are `typeof()`
2938-
CORINFO_METHOD_HANDLE hTypeof = eeFindHelper(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE);
2939-
if ((typeTo->AsCall()->gtCallMethHnd == hTypeof) && (typeFrom->AsCall()->gtCallMethHnd == hTypeof))
2940+
TypeCompareState castResult = info.compCompHnd->compareTypesForCast(hClassFrom, hClassTo);
2941+
if (castResult == TypeCompareState::May)
29402942
{
2941-
assert((typeTo->AsCall()->gtArgs.CountArgs() == 1) && (typeFrom->AsCall()->gtArgs.CountArgs() == 1));
2942-
CORINFO_CLASS_HANDLE hClassTo =
2943-
gtGetHelperArgClassHandle(typeTo->AsCall()->gtArgs.GetArgByIndex(0)->GetEarlyNode());
2944-
CORINFO_CLASS_HANDLE hClassFrom =
2945-
gtGetHelperArgClassHandle(typeFrom->AsCall()->gtArgs.GetArgByIndex(0)->GetEarlyNode());
2946-
2947-
if (hClassTo == NO_CLASS_HANDLE || hClassFrom == NO_CLASS_HANDLE)
2948-
{
2949-
return nullptr;
2950-
}
2951-
2952-
TypeCompareState castResult = info.compCompHnd->compareTypesForCast(hClassFrom, hClassTo);
2953-
if (castResult == TypeCompareState::May)
2954-
{
2955-
// requires runtime check
2956-
// e.g. __Canon, COMObjects, Nullable
2957-
return nullptr;
2958-
}
2943+
// requires runtime check
2944+
// e.g. __Canon, COMObjects, Nullable
2945+
return nullptr;
2946+
}
29592947

2960-
GenTreeIntCon* retNode = gtNewIconNode((castResult == TypeCompareState::Must) ? 1 : 0);
2961-
impPopStack(); // drop both CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE calls
2962-
impPopStack();
2948+
GenTreeIntCon* retNode = gtNewIconNode((castResult == TypeCompareState::Must) ? 1 : 0);
2949+
impPopStack(); // drop both CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE calls
2950+
impPopStack();
29632951

2964-
return retNode;
2965-
}
2952+
return retNode;
29662953
}
29672954

29682955
return nullptr;
@@ -13391,15 +13378,10 @@ void Compiler::impInlineRecordArgInfo(InlineInfo* pInlineInfo,
1339113378
return;
1339213379
}
1339313380
}
13394-
else
13381+
else if (gtIsTypeof(curArgVal))
1339513382
{
13396-
if (curArgVal->IsHelperCall() && gtIsTypeHandleToRuntimeTypeHelper(curArgVal->AsCall()) &&
13397-
(gtGetHelperArgClassHandle(curArgVal->AsCall()->gtArgs.GetArgByIndex(0)->GetEarlyNode()) !=
13398-
NO_CLASS_HANDLE))
13399-
{
13400-
inlCurArgInfo->argIsInvariant = true;
13401-
inlCurArgInfo->argHasSideEff = false;
13402-
}
13383+
inlCurArgInfo->argIsInvariant = true;
13384+
inlCurArgInfo->argHasSideEff = false;
1340313385
}
1340413386

1340513387
bool isExact = false;

0 commit comments

Comments
 (0)