diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h b/src/coreclr/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h index 03c722caed896..1e7d51988eddb 100644 --- a/src/coreclr/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h +++ b/src/coreclr/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h @@ -614,7 +614,7 @@ CORINFO_CLASS_HANDLE getArgClass(CORINFO_SIG_INFO* sig, /* IN */ ); // Returns type of HFA for valuetype -CorInfoType getHFAType(CORINFO_CLASS_HANDLE hClass); +CorInfoHFAElemType getHFAType(CORINFO_CLASS_HANDLE hClass); /***************************************************************************** * ICorErrorInfo contains methods to deal with SEH exceptions being thrown diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp index 77603de0a850c..ccd8a12caf859 100644 --- a/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp @@ -2680,7 +2680,7 @@ CORINFO_CLASS_HANDLE MethodContext::repGetArgClass(CORINFO_SIG_INFO* sig, return (CORINFO_CLASS_HANDLE)value.result; } -void MethodContext::recGetHFAType(CORINFO_CLASS_HANDLE clsHnd, CorInfoType result) +void MethodContext::recGetHFAType(CORINFO_CLASS_HANDLE clsHnd, CorInfoHFAElemType result) { if (GetHFAType == nullptr) GetHFAType = new LightWeightMap(); @@ -2696,7 +2696,7 @@ void MethodContext::dmpGetHFAType(DWORDLONG key, DWORD value) return; } -CorInfoType MethodContext::repGetHFAType(CORINFO_CLASS_HANDLE clsHnd) +CorInfoHFAElemType MethodContext::repGetHFAType(CORINFO_CLASS_HANDLE clsHnd) { DWORD value; @@ -2706,7 +2706,7 @@ CorInfoType MethodContext::repGetHFAType(CORINFO_CLASS_HANDLE clsHnd) value = GetHFAType->Get((DWORDLONG)clsHnd); DEBUG_REP(dmpGetHFAType((DWORDLONG)clsHnd, value)); - return (CorInfoType)value; + return (CorInfoHFAElemType)value; } void MethodContext::recGetMethodInfo(CORINFO_METHOD_HANDLE ftn, diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.h index 1f34c4569e335..2e2b4b9dc0013 100644 --- a/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.h @@ -867,9 +867,9 @@ class MethodContext void dmpGetArgClass(const GetArgClassValue& key, const Agnostic_GetArgClass_Value& value); CORINFO_CLASS_HANDLE repGetArgClass(CORINFO_SIG_INFO* sig, CORINFO_ARG_LIST_HANDLE args, DWORD* exceptionCode); - void recGetHFAType(CORINFO_CLASS_HANDLE clsHnd, CorInfoType result); + void recGetHFAType(CORINFO_CLASS_HANDLE clsHnd, CorInfoHFAElemType result); void dmpGetHFAType(DWORDLONG key, DWORD value); - CorInfoType repGetHFAType(CORINFO_CLASS_HANDLE clsHnd); + CorInfoHFAElemType repGetHFAType(CORINFO_CLASS_HANDLE clsHnd); void recGetMethodInfo(CORINFO_METHOD_HANDLE ftn, CORINFO_METHOD_INFO* info, bool result, DWORD exceptionCode); void dmpGetMethodInfo(DWORDLONG key, const Agnostic_GetMethodInfo& value); diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp index 2da8785f96bc2..ec7bfde1fd16b 100644 --- a/src/coreclr/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -1314,10 +1314,10 @@ CORINFO_CLASS_HANDLE interceptor_ICJI::getArgClass(CORINFO_SIG_INFO* sig, } // Returns type of HFA for valuetype -CorInfoType interceptor_ICJI::getHFAType(CORINFO_CLASS_HANDLE hClass) +CorInfoHFAElemType interceptor_ICJI::getHFAType(CORINFO_CLASS_HANDLE hClass) { mc->cr->AddCall("getHFAType"); - CorInfoType temp = original_ICorJitInfo->getHFAType(hClass); + CorInfoHFAElemType temp = original_ICorJitInfo->getHFAType(hClass); this->mc->recGetHFAType(hClass, temp); return temp; } diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp b/src/coreclr/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp index febd952a655fa..2b89a4a81df9d 100644 --- a/src/coreclr/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp +++ b/src/coreclr/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp @@ -1009,7 +1009,7 @@ CORINFO_CLASS_HANDLE interceptor_ICJI::getArgClass(CORINFO_SIG_INFO* sig, } // Returns type of HFA for valuetype -CorInfoType interceptor_ICJI::getHFAType(CORINFO_CLASS_HANDLE hClass) +CorInfoHFAElemType interceptor_ICJI::getHFAType(CORINFO_CLASS_HANDLE hClass) { mcs->AddCall("getHFAType"); return original_ICorJitInfo->getHFAType(hClass); diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp b/src/coreclr/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp index 26141d06068f4..4fc6c03ec439c 100644 --- a/src/coreclr/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp +++ b/src/coreclr/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp @@ -902,7 +902,7 @@ CORINFO_CLASS_HANDLE interceptor_ICJI::getArgClass(CORINFO_SIG_INFO* sig, } // Returns type of HFA for valuetype -CorInfoType interceptor_ICJI::getHFAType(CORINFO_CLASS_HANDLE hClass) +CorInfoHFAElemType interceptor_ICJI::getHFAType(CORINFO_CLASS_HANDLE hClass) { return original_ICorJitInfo->getHFAType(hClass); } diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp index 24bc4415e586e..53df692f43de6 100644 --- a/src/coreclr/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp @@ -1088,10 +1088,10 @@ CORINFO_CLASS_HANDLE MyICJI::getArgClass(CORINFO_SIG_INFO* sig, /* IN */ } // Returns type of HFA for valuetype -CorInfoType MyICJI::getHFAType(CORINFO_CLASS_HANDLE hClass) +CorInfoHFAElemType MyICJI::getHFAType(CORINFO_CLASS_HANDLE hClass) { jitInstance->mc->cr->AddCall("getHFAType"); - CorInfoType value = jitInstance->mc->repGetHFAType(hClass); + CorInfoHFAElemType value = jitInstance->mc->repGetHFAType(hClass); return value; } diff --git a/src/coreclr/src/inc/corhdr.h b/src/coreclr/src/inc/corhdr.h index abef978313a9e..ce6b0ce1f3f1f 100644 --- a/src/coreclr/src/inc/corhdr.h +++ b/src/coreclr/src/inc/corhdr.h @@ -1908,6 +1908,17 @@ typedef enum NativeTypeArrayFlags ntaReserved = 0xfffe // All the reserved bits. } NativeTypeArrayFlags; +// +// Enum used for HFA type recognition. +// Supported across architectures, so that it can be used in altjits and cross-compilation. +typedef enum CorInfoHFAElemType : unsigned { + CORINFO_HFA_ELEM_NONE, + CORINFO_HFA_ELEM_FLOAT, + CORINFO_HFA_ELEM_DOUBLE, + CORINFO_HFA_ELEM_VECTOR64, + CORINFO_HFA_ELEM_VECTOR128, +} CorInfoHFAElemType; + // // Opaque types for security properties and values. // diff --git a/src/coreclr/src/inc/corinfo.h b/src/coreclr/src/inc/corinfo.h index 159b8ad92a640..d9d4f777eeca0 100644 --- a/src/coreclr/src/inc/corinfo.h +++ b/src/coreclr/src/inc/corinfo.h @@ -217,12 +217,12 @@ TODO: Talk about initializing strutures before use #endif #endif -SELECTANY const GUID JITEEVersionIdentifier = { /* 8b2226a2-ac30-4f5c-ae5c-926c792ecdb9 */ - 0x8b2226a2, - 0xac30, - 0x4f5c, - { 0xae, 0x5c, 0x92, 0x6c, 0x79, 0x2e, 0xcd, 0xb9 } -}; +SELECTANY const GUID JITEEVersionIdentifier = { /* 2ca8d539-5db9-4831-8f1b-ade425f036bd */ + 0x2ca8d539, + 0x5db9, + 0x4831, + {0x8f, 0x1b, 0xad, 0xe4, 0x25, 0xf0, 0x36, 0xbd} + }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// // @@ -2743,7 +2743,7 @@ class ICorStaticInfo ) = 0; // Returns type of HFA for valuetype - virtual CorInfoType getHFAType ( + virtual CorInfoHFAElemType getHFAType ( CORINFO_CLASS_HANDLE hClass ) = 0; diff --git a/src/coreclr/src/jit/codegencommon.cpp b/src/coreclr/src/jit/codegencommon.cpp index 0449e3291b09c..dde9e43d00163 100644 --- a/src/coreclr/src/jit/codegencommon.cpp +++ b/src/coreclr/src/jit/codegencommon.cpp @@ -10108,30 +10108,19 @@ unsigned Compiler::GetHfaCount(GenTree* tree) var_types Compiler::GetHfaType(CORINFO_CLASS_HANDLE hClass) { - var_types result = TYP_UNDEF; +#ifdef FEATURE_HFA if (hClass != NO_CLASS_HANDLE) { -#ifdef FEATURE_HFA - CorInfoType corType = info.compCompHnd->getHFAType(hClass); -#if defined(TARGET_ARM64) && defined(FEATURE_SIMD) - if (corType == CORINFO_TYPE_VALUECLASS) + CorInfoHFAElemType elemKind = info.compCompHnd->getHFAType(hClass); + if (elemKind != CORINFO_HFA_ELEM_NONE) { - // This is a vector type. - // HVAs are only supported on ARM64, and only for homogeneous aggregates of 8 or 16 byte vectors. - // For 8-byte vectors corType will be returned as CORINFO_TYPE_DOUBLE. - result = TYP_SIMD16; // This type may not appear elsewhere, but it will occupy a floating point register. compFloatingPointUsed = true; } - else -#endif // TARGET_ARM64 && FEATURE_SIMD - if (corType != CORINFO_TYPE_UNDEF) - { - result = JITtype2varType(corType); - } -#endif // FEATURE_HFA + return HfaTypeFromElemKind(elemKind); } - return result; +#endif // FEATURE_HFA + return TYP_UNDEF; } //------------------------------------------------------------------------ diff --git a/src/coreclr/src/jit/compiler.h b/src/coreclr/src/jit/compiler.h index 852b57f8359b8..c47a0b6ad928d 100644 --- a/src/coreclr/src/jit/compiler.h +++ b/src/coreclr/src/jit/compiler.h @@ -139,53 +139,50 @@ const int BAD_STK_OFFS = 0xBAADF00D; // for LclVarDsc::lvStkOffs // HFA info shared by LclVarDsc and fgArgTabEntry //------------------------------------------------------------------------ #ifdef FEATURE_HFA -enum HfaElemKind : unsigned int +inline bool IsHfa(CorInfoHFAElemType kind) { - HFA_ELEM_NONE, - HFA_ELEM_FLOAT, - HFA_ELEM_DOUBLE, - HFA_ELEM_SIMD16 -}; -inline bool IsHfa(HfaElemKind kind) -{ - return kind != HFA_ELEM_NONE; + return kind != CORINFO_HFA_ELEM_NONE; } -inline var_types HfaTypeFromElemKind(HfaElemKind kind) +inline var_types HfaTypeFromElemKind(CorInfoHFAElemType kind) { switch (kind) { - case HFA_ELEM_FLOAT: + case CORINFO_HFA_ELEM_FLOAT: return TYP_FLOAT; - case HFA_ELEM_DOUBLE: + case CORINFO_HFA_ELEM_DOUBLE: return TYP_DOUBLE; #ifdef FEATURE_SIMD - case HFA_ELEM_SIMD16: + case CORINFO_HFA_ELEM_VECTOR64: + return TYP_SIMD8; + case CORINFO_HFA_ELEM_VECTOR128: return TYP_SIMD16; #endif - case HFA_ELEM_NONE: + case CORINFO_HFA_ELEM_NONE: return TYP_UNDEF; default: assert(!"Invalid HfaElemKind"); return TYP_UNDEF; } } -inline HfaElemKind HfaElemKindFromType(var_types type) +inline CorInfoHFAElemType HfaElemKindFromType(var_types type) { switch (type) { case TYP_FLOAT: - return HFA_ELEM_FLOAT; + return CORINFO_HFA_ELEM_FLOAT; case TYP_DOUBLE: - return HFA_ELEM_DOUBLE; + return CORINFO_HFA_ELEM_DOUBLE; #ifdef FEATURE_SIMD + case TYP_SIMD8: + return CORINFO_HFA_ELEM_VECTOR64; case TYP_SIMD16: - return HFA_ELEM_SIMD16; + return CORINFO_HFA_ELEM_VECTOR128; #endif case TYP_UNDEF: - return HFA_ELEM_NONE; + return CORINFO_HFA_ELEM_NONE; default: assert(!"Invalid HFA Type"); - return HFA_ELEM_NONE; + return CORINFO_HFA_ELEM_NONE; } } #endif // FEATURE_HFA @@ -484,8 +481,8 @@ class LclVarDsc unsigned char lvIsMultiRegRet : 1; // true if this is a multireg LclVar struct assigned from a multireg call #ifdef FEATURE_HFA - HfaElemKind _lvHfaElemKind : 2; // What kind of an HFA this is (HFA_ELEM_NONE if it is not an HFA). -#endif // FEATURE_HFA + CorInfoHFAElemType _lvHfaElemKind : 3; // What kind of an HFA this is (CORINFO_HFA_ELEM_NONE if it is not an HFA). +#endif // FEATURE_HFA #ifdef DEBUG // TODO-Cleanup: See the note on lvSize() - this flag is only in use by asserts that are checking for struct @@ -591,18 +588,19 @@ class LclVarDsc #elif defined(TARGET_ARM64) switch (_lvHfaElemKind) { - case HFA_ELEM_NONE: + case CORINFO_HFA_ELEM_NONE: assert(!"lvHfaSlots called for non-HFA"); break; - case HFA_ELEM_FLOAT: + case CORINFO_HFA_ELEM_FLOAT: assert((lvExactSize % 4) == 0); slots = lvExactSize >> 2; break; - case HFA_ELEM_DOUBLE: + case CORINFO_HFA_ELEM_DOUBLE: + case CORINFO_HFA_ELEM_VECTOR64: assert((lvExactSize % 8) == 0); slots = lvExactSize >> 3; break; - case HFA_ELEM_SIMD16: + case CORINFO_HFA_ELEM_VECTOR128: assert((lvExactSize % 16) == 0); slots = lvExactSize >> 4; break; @@ -919,7 +917,10 @@ class LclVarDsc void SetHfaType(var_types type) { #ifdef FEATURE_HFA - _lvHfaElemKind = HfaElemKindFromType(type); + CorInfoHFAElemType elemKind = HfaElemKindFromType(type); + _lvHfaElemKind = elemKind; + // Ensure we've allocated enough bits. + assert(_lvHfaElemKind == elemKind); #endif // FEATURE_HFA } @@ -1447,7 +1448,7 @@ struct fgArgTabEntry bool _isSplit : 1; // True when this argument is split between the registers and OutArg area #endif // FEATURE_ARG_SPLIT #ifdef FEATURE_HFA - HfaElemKind _hfaElemKind : 2; // What kind of an HFA this is (HFA_ELEM_NONE if it is not an HFA). + CorInfoHFAElemType _hfaElemKind : 3; // What kind of an HFA this is (CORINFO_HFA_ELEM_NONE if it is not an HFA). #endif bool isLateArg() @@ -1610,7 +1611,10 @@ struct fgArgTabEntry if (!IsHfaArg()) { // We haven't previously set this; do so now. - _hfaElemKind = HfaElemKindFromType(type); + CorInfoHFAElemType elemKind = HfaElemKindFromType(type); + _hfaElemKind = elemKind; + // Ensure we've allocated enough bits. + assert(_hfaElemKind == elemKind); if (isPassedInRegisters()) { numRegs = numHfaRegs; @@ -2126,10 +2130,11 @@ class Compiler #endif // ARM_SOFTFP //------------------------------------------------------------------------- - // Functions to handle homogeneous floating-point aggregates (HFAs) in ARM. + // Functions to handle homogeneous floating-point aggregates (HFAs) in ARM/ARM64. // HFAs are one to four element structs where each element is the same - // type, either all float or all double. They are treated specially - // in the ARM Procedure Call Standard, specifically, they are passed in + // type, either all float or all double. We handle HVAs (one to four elements of + // vector types) uniformly with HFAs. HFAs are treated specially + // in the ARM/ARM64 Procedure Call Standards, specifically, they are passed in // floating-point registers instead of the general purpose registers. // diff --git a/src/coreclr/src/jit/morph.cpp b/src/coreclr/src/jit/morph.cpp index 44b79e600335f..e8ce24c9ce889 100644 --- a/src/coreclr/src/jit/morph.cpp +++ b/src/coreclr/src/jit/morph.cpp @@ -773,6 +773,7 @@ void fgArgTabEntry::Dump() printf("fgArgTabEntry[arg %u", argNum); printf(" %d.%s", GetNode()->gtTreeID, GenTree::OpName(GetNode()->OperGet())); printf(" %s", varTypeName(argType)); + printf(" (%s)", passedByRef ? "By ref" : "By value"); if (GetRegNum() != REG_STK) { printf(", %u reg%s:", numRegs, numRegs == 1 ? "" : "s"); @@ -1005,7 +1006,7 @@ fgArgTabEntry* fgArgInfo::AddRegArg(unsigned argNum, curArgTabEntry->needPlace = false; curArgTabEntry->processed = false; #ifdef FEATURE_HFA - curArgTabEntry->_hfaElemKind = HFA_ELEM_NONE; + curArgTabEntry->_hfaElemKind = CORINFO_HFA_ELEM_NONE; #endif curArgTabEntry->isBackFilled = false; curArgTabEntry->isNonStandard = false; @@ -1087,7 +1088,7 @@ fgArgTabEntry* fgArgInfo::AddStkArg(unsigned argNum, curArgTabEntry->needPlace = false; curArgTabEntry->processed = false; #ifdef FEATURE_HFA - curArgTabEntry->_hfaElemKind = HFA_ELEM_NONE; + curArgTabEntry->_hfaElemKind = CORINFO_HFA_ELEM_NONE; #endif curArgTabEntry->isBackFilled = false; curArgTabEntry->isNonStandard = false; @@ -4422,12 +4423,7 @@ GenTree* Compiler::fgMorphMultiregStructArg(GenTree* arg, fgArgTabEntry* fgEntry ) { // We have a HFA struct. - // Note that GetHfaType may not be the same as elemType, since TYP_SIMD8 is handled the same as TYP_DOUBLE. - var_types useElemType = elemType; -#if defined(TARGET_ARM64) & defined(FEATURE_SIMD) - useElemType = (elemType == TYP_SIMD8) ? TYP_DOUBLE : useElemType; -#endif // TARGET_ARM64 && FEATURE_SIMD - noway_assert(useElemType == varDsc->GetHfaType()); + noway_assert(elemType == varDsc->GetHfaType()); noway_assert(elemSize == genTypeSize(elemType)); noway_assert(elemCount == (varDsc->lvExactSize / elemSize)); noway_assert(elemSize * elemCount == varDsc->lvExactSize); diff --git a/src/coreclr/src/tools/Common/JitInterface/CorInfoBase.cs b/src/coreclr/src/tools/Common/JitInterface/CorInfoBase.cs index 6b2869f23967e..54595b1d26368 100644 --- a/src/coreclr/src/tools/Common/JitInterface/CorInfoBase.cs +++ b/src/coreclr/src/tools/Common/JitInterface/CorInfoBase.cs @@ -214,7 +214,7 @@ unsafe partial class CorInfoImpl [UnmanagedFunctionPointerAttribute(default(CallingConvention))] delegate CORINFO_CLASS_STRUCT_* __getArgClass(IntPtr _this, IntPtr* ppException, CORINFO_SIG_INFO* sig, CORINFO_ARG_LIST_STRUCT_* args); [UnmanagedFunctionPointerAttribute(default(CallingConvention))] - delegate CorInfoType __getHFAType(IntPtr _this, IntPtr* ppException, CORINFO_CLASS_STRUCT_* hClass); + delegate CorInfoHFAElemType __getHFAType(IntPtr _this, IntPtr* ppException, CORINFO_CLASS_STRUCT_* hClass); [UnmanagedFunctionPointerAttribute(default(CallingConvention))] delegate HRESULT __GetErrorHRESULT(IntPtr _this, IntPtr* ppException, _EXCEPTION_POINTERS* pExceptionPointers); [UnmanagedFunctionPointerAttribute(default(CallingConvention))] @@ -1743,7 +1743,7 @@ static CorInfoTypeWithMod _getArgType(IntPtr thisHandle, IntPtr* ppException, CO } } - static CorInfoType _getHFAType(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* hClass) + static CorInfoHFAElemType _getHFAType(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* hClass) { var _this = GetThis(thisHandle); try @@ -1753,7 +1753,7 @@ static CorInfoType _getHFAType(IntPtr thisHandle, IntPtr* ppException, CORINFO_C catch (Exception ex) { *ppException = _this.AllocException(ex); - return default(CorInfoType); + return default(CorInfoHFAElemType); } } diff --git a/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs index 508b2b7864c82..d9a2433c434a3 100644 --- a/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs @@ -2203,20 +2203,18 @@ private CorInfoTypeWithMod getArgType(CORINFO_SIG_INFO* sig, CORINFO_ARG_LIST_ST } } - private CorInfoType getHFAType(CORINFO_CLASS_STRUCT_* hClass) + private CorInfoHFAElemType getHFAType(CORINFO_CLASS_STRUCT_* hClass) { var type = (DefType)HandleToObject(hClass); - // For 8-byte vectors return CORINFO_TYPE_DOUBLE, which is mapped by JIT to SIMD8. - // For 16-byte vectors return CORINFO_TYPE_VALUECLASS, which is mapped by JIT to SIMD16. // See MethodTable::GetHFAType and Compiler::GetHfaType. return (type.ValueTypeShapeCharacteristics & ValueTypeShapeCharacteristics.AggregateMask) switch { - ValueTypeShapeCharacteristics.Float32Aggregate => CorInfoType.CORINFO_TYPE_FLOAT, - ValueTypeShapeCharacteristics.Float64Aggregate => CorInfoType.CORINFO_TYPE_DOUBLE, - ValueTypeShapeCharacteristics.Vector64Aggregate => CorInfoType.CORINFO_TYPE_DOUBLE, - ValueTypeShapeCharacteristics.Vector128Aggregate => CorInfoType.CORINFO_TYPE_VALUECLASS, - _ => CorInfoType.CORINFO_TYPE_UNDEF + ValueTypeShapeCharacteristics.Float32Aggregate => CorInfoHFAElemType.CORINFO_HFA_ELEM_FLOAT, + ValueTypeShapeCharacteristics.Float64Aggregate => CorInfoHFAElemType.CORINFO_HFA_ELEM_DOUBLE, + ValueTypeShapeCharacteristics.Vector64Aggregate => CorInfoHFAElemType.CORINFO_HFA_ELEM_VECTOR64, + ValueTypeShapeCharacteristics.Vector128Aggregate => CorInfoHFAElemType.CORINFO_HFA_ELEM_VECTOR128, + _ => CorInfoHFAElemType.CORINFO_HFA_ELEM_NONE }; } diff --git a/src/coreclr/src/tools/Common/JitInterface/CorInfoTypes.cs b/src/coreclr/src/tools/Common/JitInterface/CorInfoTypes.cs index 2313d5e58b7a0..ea1d607aac6cf 100644 --- a/src/coreclr/src/tools/Common/JitInterface/CorInfoTypes.cs +++ b/src/coreclr/src/tools/Common/JitInterface/CorInfoTypes.cs @@ -748,6 +748,17 @@ public enum CorInfoGenericHandleType CORINFO_HANDLETYPE_FIELD } + // Enum used for HFA type recognition. + // Supported across architectures, so that it can be used in altjits and cross-compilation. + public enum CorInfoHFAElemType + { + CORINFO_HFA_ELEM_NONE, + CORINFO_HFA_ELEM_FLOAT, + CORINFO_HFA_ELEM_DOUBLE, + CORINFO_HFA_ELEM_VECTOR64, + CORINFO_HFA_ELEM_VECTOR128, + } + /* data to optimize delegate construction */ public unsafe struct DelegateCtorArgs { diff --git a/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index fd5b9f464452c..0e17908daabbe 100644 --- a/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -121,6 +121,7 @@ CorInfoIsAccessAllowedResult,,int CorInfoMethodRuntimeFlags,,int CorInfoTailCall,,int CorInfoType,,int +CorInfoHFAElemType,,int CorInfoTypeWithMod,,int CorInfoUnmanagedCallConv,,int InfoAccessType,,int @@ -263,7 +264,7 @@ FUNCTIONS CORINFO_ARG_LIST_HANDLE getArgNext(CORINFO_ARG_LIST_HANDLE args); CorInfoTypeWithMod getArgType(CORINFO_SIG_INFO* sig, CORINFO_ARG_LIST_HANDLE args, CORINFO_CLASS_HANDLE* vcTypeRet); CORINFO_CLASS_HANDLE getArgClass(CORINFO_SIG_INFO* sig, CORINFO_ARG_LIST_HANDLE args); - CorInfoType getHFAType(CORINFO_CLASS_HANDLE hClass); + CorInfoHFAElemType getHFAType(CORINFO_CLASS_HANDLE hClass); HRESULT GetErrorHRESULT(struct _EXCEPTION_POINTERS *pExceptionPointers); ULONG GetErrorMessage(LPWSTR buffer, ULONG bufferLength); [ManualNativeWrapper] int FilterException(struct _EXCEPTION_POINTERS* pExceptionPointers); diff --git a/src/coreclr/src/tools/crossgen2/jitinterface/jitwrapper.cpp b/src/coreclr/src/tools/crossgen2/jitinterface/jitwrapper.cpp index 63fa69eda34f4..e9918b307b204 100644 --- a/src/coreclr/src/tools/crossgen2/jitinterface/jitwrapper.cpp +++ b/src/coreclr/src/tools/crossgen2/jitinterface/jitwrapper.cpp @@ -27,11 +27,11 @@ class CORJIT_FLAGS uint64_t corJitFlags; }; -static const GUID JITEEVersionIdentifier = { /* 8b2226a2-ac30-4f5c-ae5c-926c792ecdb9 */ - 0x8b2226a2, - 0xac30, - 0x4f5c, - { 0xae, 0x5c, 0x92, 0x6c, 0x79, 0x2e, 0xcd, 0xb9 } +static const GUID JITEEVersionIdentifier = { /* 2ca8d539-5db9-4831-8f1b-ade425f036bd */ + 0x2ca8d539, + 0x5db9, + 0x4831, + { 0x8f, 0x1b, 0xad, 0xe4, 0x25, 0xf0, 0x36, 0xbd } }; class Jit diff --git a/src/coreclr/src/vm/callingconvention.h b/src/coreclr/src/vm/callingconvention.h index 6cd90b4376d15..f57232ccb97db 100644 --- a/src/coreclr/src/vm/callingconvention.h +++ b/src/coreclr/src/vm/callingconvention.h @@ -50,21 +50,21 @@ struct ArgLocDesc #endif // UNIX_AMD64_ABI #ifdef FEATURE_HFA - static unsigned getHFAFieldSize(CorElementType hfaType) + static unsigned getHFAFieldSize(CorInfoHFAElemType hfaType) { switch (hfaType) { - case ELEMENT_TYPE_R4: return 4; - case ELEMENT_TYPE_R8: return 8; - // We overload VALUETYPE for 16-byte vectors. - case ELEMENT_TYPE_VALUETYPE: return 16; + case CORINFO_HFA_ELEM_FLOAT: return 4; + case CORINFO_HFA_ELEM_DOUBLE: return 8; + case CORINFO_HFA_ELEM_VECTOR64: return 8; + case CORINFO_HFA_ELEM_VECTOR128: return 16; default: _ASSERTE(!"Invalid HFA Type"); return 0; } } #endif #if defined(TARGET_ARM64) unsigned m_hfaFieldSize; // Size of HFA field in bytes. - void setHFAFieldSize(CorElementType hfaType) + void setHFAFieldSize(CorInfoHFAElemType hfaType) { m_hfaFieldSize = getHFAFieldSize(hfaType); } @@ -624,7 +624,7 @@ class ArgIteratorTemplate : public ARGITERATOR_BASE if (!m_argTypeHandle.IsNull() && m_argTypeHandle.IsHFA()) { - CorElementType type = m_argTypeHandle.GetHFAType(); + CorInfoHFAElemType type = m_argTypeHandle.GetHFAType(); pLoc->setHFAFieldSize(type); pLoc->m_cFloatReg = GetArgSize()/pLoc->m_hfaFieldSize; @@ -1350,7 +1350,7 @@ int ArgIteratorTemplate::GetNextOffset() // that are passed in FP argument registers if possible. if (thValueType.IsHFA()) { - CorElementType type = thValueType.GetHFAType(); + CorInfoHFAElemType type = thValueType.GetHFAType(); m_argLocDescForStructInRegs.Init(); m_argLocDescForStructInRegs.m_idxFloatReg = m_idxFPReg; @@ -1528,7 +1528,7 @@ void ArgIteratorTemplate::ComputeReturnFlags() #ifdef FEATURE_HFA if (thValueType.IsHFA() && !this->IsVarArg()) { - CorElementType hfaType = thValueType.GetHFAType(); + CorInfoHFAElemType hfaType = thValueType.GetHFAType(); int hfaFieldSize = ArgLocDesc::getHFAFieldSize(hfaType); flags |= ((4 * hfaFieldSize) << RETURN_FP_SIZE_SHIFT); diff --git a/src/coreclr/src/vm/class.cpp b/src/coreclr/src/vm/class.cpp index 0bb0d30d92816..a00b8c8958035 100644 --- a/src/coreclr/src/vm/class.cpp +++ b/src/coreclr/src/vm/class.cpp @@ -1412,7 +1412,7 @@ int MethodTable::GetVectorSize() } //******************************************************************************* -CorElementType MethodTable::GetHFAType() +CorInfoHFAElemType MethodTable::GetHFAType() { CONTRACTL { @@ -1422,7 +1422,7 @@ CorElementType MethodTable::GetHFAType() CONTRACTL_END; if (!IsHFA()) - return ELEMENT_TYPE_END; + return CORINFO_HFA_ELEM_NONE; MethodTable * pMT = this; for (;;) @@ -1433,7 +1433,7 @@ CorElementType MethodTable::GetHFAType() int vectorSize = pMT->GetVectorSize(); if (vectorSize != 0) { - return (vectorSize == 8) ? ELEMENT_TYPE_R8 : ELEMENT_TYPE_VALUETYPE; + return (vectorSize == 8) ? CORINFO_HFA_ELEM_VECTOR64 : CORINFO_HFA_ELEM_VECTOR128; } PTR_FieldDesc pFirstField = pMT->GetApproxFieldDescListRaw(); @@ -1448,14 +1448,15 @@ CorElementType MethodTable::GetHFAType() break; case ELEMENT_TYPE_R4: + return CORINFO_HFA_ELEM_FLOAT; case ELEMENT_TYPE_R8: - return fieldType; + return CORINFO_HFA_ELEM_DOUBLE; default: // This should never happen. MethodTable::IsHFA() should be set only on types // that have a valid HFA type when the flag is used to track HFA status. _ASSERTE(false); - return ELEMENT_TYPE_END; + return CORINFO_HFA_ELEM_NONE; } } } @@ -1471,7 +1472,7 @@ bool MethodTable::IsNativeHFA() return GetNativeLayoutInfo()->IsNativeHFA(); } -CorElementType MethodTable::GetNativeHFAType() +CorInfoHFAElemType MethodTable::GetNativeHFAType() { LIMITED_METHOD_CONTRACT; if (!HasLayout() || IsBlittable()) @@ -1499,7 +1500,6 @@ EEClass::CheckForHFA() // This method should be called for valuetypes only _ASSERTE(GetMethodTable()->IsValueType()); - // The opaque Vector types appear to have multiple fields, but need to be treated // as an opaque type of a single vector. if (GetMethodTable()->GetVectorSize() != 0) @@ -1510,8 +1510,7 @@ EEClass::CheckForHFA() return true; } - int elemSize = 0; - CorElementType hfaType = ELEMENT_TYPE_END; + CorInfoHFAElemType hfaType = CORINFO_HFA_ELEM_NONE; FieldDesc *pFieldDescList = GetFieldDescList(); @@ -1523,17 +1522,13 @@ EEClass::CheckForHFA() hasZeroOffsetField |= (pFD->GetOffset() == 0); CorElementType fieldType = pFD->GetFieldType(); + CorInfoHFAElemType fieldHFAType = CORINFO_HFA_ELEM_NONE; switch (fieldType) { case ELEMENT_TYPE_VALUETYPE: { #ifdef TARGET_ARM64 - // hfa/hva types are unique by size, except for Vector64 which we can conveniently - // treat as if it were a double for ABI purposes. However, it only qualifies as - // an HVA if all fields are the same type. This will ensure that we only - // consider it an HVA if all the fields are ELEMENT_TYPE_VALUETYPE (which have been - // determined above to be vectors) of the same size. MethodTable* pMT; #if defined(FEATURE_HFA) pMT = pByValueClassCache[i]; @@ -1543,22 +1538,15 @@ EEClass::CheckForHFA() int thisElemSize = pMT->GetVectorSize(); if (thisElemSize != 0) { - if (elemSize == 0) - { - elemSize = thisElemSize; - } - else if ((thisElemSize != elemSize) || (hfaType != ELEMENT_TYPE_VALUETYPE)) - { - return false; - } + fieldHFAType = (thisElemSize == 8) ? CORINFO_HFA_ELEM_VECTOR64 : CORINFO_HFA_ELEM_VECTOR128; } else #endif // TARGET_ARM64 { #if defined(FEATURE_HFA) - fieldType = pByValueClassCache[i]->GetHFAType(); + fieldHFAType = pByValueClassCache[i]->GetHFAType(); #else - fieldType = pFD->LookupApproxFieldTypeHandle().AsMethodTable()->GetHFAType(); + fieldHFAType = pFD->LookupApproxFieldTypeHandle().AsMethodTable()->GetHFAType(); #endif } } @@ -1571,6 +1559,7 @@ EEClass::CheckForHFA() { return false; } + fieldHFAType = CORINFO_HFA_ELEM_FLOAT; } break; case ELEMENT_TYPE_R8: @@ -1580,6 +1569,7 @@ EEClass::CheckForHFA() { return false; } + fieldHFAType = CORINFO_HFA_ELEM_DOUBLE; } break; default: @@ -1588,38 +1578,36 @@ EEClass::CheckForHFA() } // Field type should be a valid HFA type. - if (fieldType == ELEMENT_TYPE_END) + if (fieldHFAType == CORINFO_HFA_ELEM_NONE) { return false; } // Initialize with a valid HFA type. - if (hfaType == ELEMENT_TYPE_END) + if (hfaType == CORINFO_HFA_ELEM_NONE) { - hfaType = fieldType; + hfaType = fieldHFAType; } // All field types should be equal. - else if (fieldType != hfaType) + else if (fieldHFAType != hfaType) { return false; } } + int elemSize = 0; switch (hfaType) { - case ELEMENT_TYPE_R4: + case CORINFO_HFA_ELEM_FLOAT: elemSize = 4; break; - case ELEMENT_TYPE_R8: + case CORINFO_HFA_ELEM_DOUBLE: + case CORINFO_HFA_ELEM_VECTOR64: elemSize = 8; break; #ifdef TARGET_ARM64 - case ELEMENT_TYPE_VALUETYPE: - // Should already have set elemSize, but be conservative - if (elemSize == 0) - { - return false; - } + case CORINFO_HFA_ELEM_VECTOR128: + elemSize = 16; break; #endif default: diff --git a/src/coreclr/src/vm/classlayoutinfo.cpp b/src/coreclr/src/vm/classlayoutinfo.cpp index 35b74bec52b99..4c145f26bfa6e 100644 --- a/src/coreclr/src/vm/classlayoutinfo.cpp +++ b/src/coreclr/src/vm/classlayoutinfo.cpp @@ -526,8 +526,8 @@ namespace if (pMT->GetClass()->HasExplicitFieldOffsetLayout()) return; - CorElementType hfaType = pNativeLayoutInfo->GetNativeHFATypeRaw(); - if (hfaType == ELEMENT_TYPE_END) + CorInfoHFAElemType hfaType = pNativeLayoutInfo->GetNativeHFATypeRaw(); + if (hfaType == CORINFO_HFA_ELEM_NONE) { return; } @@ -997,20 +997,20 @@ EEClassNativeLayoutInfo* EEClassNativeLayoutInfo::CollectNativeLayoutFieldMetada #endif // DACCESS_COMPILE -CorElementType EEClassNativeLayoutInfo::GetNativeHFATypeRaw() const +CorInfoHFAElemType EEClassNativeLayoutInfo::GetNativeHFATypeRaw() const { LIMITED_METHOD_CONTRACT; uint32_t numReferenceFields = GetNumFields(); - CorElementType hfaType = ELEMENT_TYPE_END; + CorInfoHFAElemType hfaType = CORINFO_HFA_ELEM_NONE; #ifndef DACCESS_COMPILE const NativeFieldDescriptor* pNativeFieldDescriptorsBegin = GetNativeFieldDescriptors(); const NativeFieldDescriptor* pNativeFieldDescriptorsEnd = pNativeFieldDescriptorsBegin + numReferenceFields; for (const NativeFieldDescriptor* pCurrNFD = pNativeFieldDescriptorsBegin; pCurrNFD < pNativeFieldDescriptorsEnd; ++pCurrNFD) { - CorElementType fieldType = ELEMENT_TYPE_END; + CorInfoHFAElemType fieldType = CORINFO_HFA_ELEM_NONE; NativeFieldCategory category = pCurrNFD->GetCategory(); @@ -1018,22 +1018,22 @@ CorElementType EEClassNativeLayoutInfo::GetNativeHFATypeRaw() const { if (pCurrNFD->NativeSize() == 4) { - fieldType = ELEMENT_TYPE_R4; + fieldType = CORINFO_HFA_ELEM_FLOAT; } else if (pCurrNFD->NativeSize() == 8) { - fieldType = ELEMENT_TYPE_R8; + fieldType = CORINFO_HFA_ELEM_DOUBLE; } else { UNREACHABLE_MSG("Invalid NativeFieldCategory."); - fieldType = ELEMENT_TYPE_END; + fieldType = CORINFO_HFA_ELEM_NONE; } // An HFA can only have aligned float and double fields. if (pCurrNFD->GetExternalOffset() % pCurrNFD->AlignmentRequirement() != 0) { - fieldType = ELEMENT_TYPE_END; + fieldType = CORINFO_HFA_ELEM_NONE; } } else if (category == NativeFieldCategory::NESTED) @@ -1042,37 +1042,38 @@ CorElementType EEClassNativeLayoutInfo::GetNativeHFATypeRaw() const } else { - return ELEMENT_TYPE_END; + return CORINFO_HFA_ELEM_NONE; } // Field type should be a valid HFA type. - if (fieldType == ELEMENT_TYPE_END) + if (fieldType == CORINFO_HFA_ELEM_NONE) { - return ELEMENT_TYPE_END; + return CORINFO_HFA_ELEM_NONE; } // Initialize with a valid HFA type. - if (hfaType == ELEMENT_TYPE_END) + if (hfaType == CORINFO_HFA_ELEM_NONE) { hfaType = fieldType; } // All field types should be equal. else if (fieldType != hfaType) { - return ELEMENT_TYPE_END; + return CORINFO_HFA_ELEM_NONE; } } - if (hfaType == ELEMENT_TYPE_END) - return ELEMENT_TYPE_END; + if (hfaType == CORINFO_HFA_ELEM_NONE) + return CORINFO_HFA_ELEM_NONE; int elemSize = 1; switch (hfaType) { - case ELEMENT_TYPE_R4: elemSize = sizeof(float); break; - case ELEMENT_TYPE_R8: elemSize = sizeof(double); break; + case CORINFO_HFA_ELEM_FLOAT: elemSize = sizeof(float); break; + case CORINFO_HFA_ELEM_DOUBLE: elemSize = sizeof(double); break; #ifdef TARGET_ARM64 - case ELEMENT_TYPE_VALUETYPE: elemSize = 16; break; + case CORINFO_HFA_ELEM_VECTOR64: elemSize = 8; break; + case CORINFO_HFA_ELEM_VECTOR128: elemSize = 16; break; #endif default: _ASSERTE(!"Invalid HFA Type"); } @@ -1085,11 +1086,11 @@ CorElementType EEClassNativeLayoutInfo::GetNativeHFATypeRaw() const DWORD totalSize = GetSize(); if (totalSize % elemSize != 0) - return ELEMENT_TYPE_END; + return CORINFO_HFA_ELEM_NONE; // On ARM, HFAs can have a maximum of four fields regardless of whether those are float or double. if (totalSize / elemSize > 4) - return ELEMENT_TYPE_END; + return CORINFO_HFA_ELEM_NONE; #endif // !DACCESS_COMPILE diff --git a/src/coreclr/src/vm/fieldmarshaler.h b/src/coreclr/src/vm/fieldmarshaler.h index 075f9798bfe29..9366a8a0746e6 100644 --- a/src/coreclr/src/vm/fieldmarshaler.h +++ b/src/coreclr/src/vm/fieldmarshaler.h @@ -208,14 +208,7 @@ class EEClassNativeLayoutInfo bool m_passInRegisters; #endif #ifdef FEATURE_HFA - enum class HFAType : uint8_t - { - Unset = ELEMENT_TYPE_END, - R4 = ELEMENT_TYPE_R4, - R8 = ELEMENT_TYPE_R8, - R16 = ELEMENT_TYPE_VALUETYPE - }; - HFAType m_hfaType; + CorInfoHFAElemType m_hfaType; #endif bool m_isMarshalable; uint32_t m_size; @@ -260,34 +253,34 @@ class EEClassNativeLayoutInfo return &m_nativeFieldDescriptors[0]; } - CorElementType GetNativeHFATypeRaw() const; + CorInfoHFAElemType GetNativeHFATypeRaw() const; #ifdef FEATURE_HFA bool IsNativeHFA() const { LIMITED_METHOD_CONTRACT; - return m_hfaType != HFAType::Unset; + return m_hfaType != CORINFO_HFA_ELEM_NONE; } - CorElementType GetNativeHFAType() const + CorInfoHFAElemType GetNativeHFAType() const { LIMITED_METHOD_CONTRACT; - return (CorElementType)m_hfaType; + return m_hfaType; } - void SetHFAType(CorElementType hfaType) + void SetHFAType(CorInfoHFAElemType hfaType) { LIMITED_METHOD_CONTRACT; // We should call this at most once. - _ASSERTE(m_hfaType == HFAType::Unset); - m_hfaType = (HFAType)hfaType; + _ASSERTE(m_hfaType == CORINFO_HFA_ELEM_NONE); + m_hfaType = hfaType; } #else bool IsNativeHFA() const { - return GetNativeHFATypeRaw() != ELEMENT_TYPE_END; + return GetNativeHFATypeRaw() != CORINFO_HFA_ELEM_NONE; } - CorElementType GetNativeHFAType() const + CorInfoHFAElemType GetNativeHFAType() const { return GetNativeHFATypeRaw(); } diff --git a/src/coreclr/src/vm/interpreter.cpp b/src/coreclr/src/vm/interpreter.cpp index 7604b0b6bfa5f..a25c334a3732d 100644 --- a/src/coreclr/src/vm/interpreter.cpp +++ b/src/coreclr/src/vm/interpreter.cpp @@ -86,7 +86,7 @@ InterpreterMethodInfo::InterpreterMethodInfo(CEEInfo* comp, CORINFO_METHOD_INFO* bool hasRetBuff = (methInfo->args.retType == CORINFO_TYPE_VALUECLASS || methInfo->args.retType == CORINFO_TYPE_REFANY); #if defined(FEATURE_HFA) // ... unless its an HFA type (and not varargs)... - if (hasRetBuff && CorInfoTypeIsFloatingPoint(comp->getHFAType(methInfo->args.retTypeClass)) && methInfo->args.getCallConv() != CORINFO_CALLCONV_VARARG) + if (hasRetBuff && (comp->getHFAType(methInfo->args.retTypeClass) != CORINFO_HFA_ELEM_NONE) && methInfo->args.getCallConv() != CORINFO_CALLCONV_VARARG) { hasRetBuff = false; } @@ -291,7 +291,7 @@ void InterpreterMethodInfo::InitArgInfo(CEEInfo* comp, CORINFO_METHOD_INFO* meth // So figure out if we have an HFA return type. bool hasHFARetType = methInfo->args.retType == CORINFO_TYPE_VALUECLASS - && CorInfoTypeIsFloatingPoint(comp->getHFAType(methInfo->args.retTypeClass)) + && (comp->getHFAType(methInfo->args.retTypeClass) != CORINFO_HFA_ELEM_NONE) && methInfo->args.getCallConv() != CORINFO_CALLCONV_VARARG; #endif // defined(HOST_ARM) @@ -953,7 +953,7 @@ CorJitResult Interpreter::GenerateInterpreterStub(CEEInfo* comp, unsigned cHFAVars = 0; #endif if (info->args.retType == CORINFO_TYPE_VALUECLASS - && CorInfoTypeIsFloatingPoint(comp->getHFAType(info->args.retTypeClass)) + && (comp->getHFAType(info->args.retTypeClass) != CORINFO_HFA_ELEM_NONE) && info->args.getCallConv() != CORINFO_CALLCONV_VARARG) { HFARetTypeSize = getClassSize(info->args.retTypeClass); @@ -968,7 +968,7 @@ CorJitResult Interpreter::GenerateInterpreterStub(CEEInfo* comp, // for instance a VT with two float fields will have the same size as a VT with 1 double field. (ARM64TODO: Verify it) // It works on ARM because the overlapping layout of the floating point registers // but it won't work on ARM64. - cHFAVars = (comp->getHFAType(info->args.retTypeClass) == CORINFO_TYPE_FLOAT) ? HFARetTypeSize/sizeof(float) : HFARetTypeSize/sizeof(double); + cHFAVars = (comp->getHFAType(info->args.retTypeClass) == CORINFO_HFA_ELEM_FLOAT) ? HFARetTypeSize/sizeof(float) : HFARetTypeSize/sizeof(double); #endif } @@ -1112,12 +1112,12 @@ CorJitResult Interpreter::GenerateInterpreterStub(CEEInfo* comp, #elif defined(HOST_AMD64) argState.AddArg(k, static_cast(szSlots)); #elif defined(HOST_ARM) || defined(HOST_ARM64) - CorInfoType hfaType = comp->getHFAType(vcTypeRet); + CorInfoHFAElemType hfaType = comp->getHFAType(vcTypeRet); if (CorInfoTypeIsFloatingPoint(hfaType)) { argState.AddFPArg(k, szSlots, #if defined(HOST_ARM) - /*twoSlotAlign*/ (hfaType == CORINFO_TYPE_DOUBLE) + /*twoSlotAlign*/ (hfaType == CORINFO_HFA_ELEM_DOUBLE) #elif defined(HOST_ARM64) /*twoSlotAlign*/ false // unlike ARM32 FP args always consume 1 slot on ARM64 #endif @@ -2203,7 +2203,7 @@ void Interpreter::ExecuteMethod(ARG_SLOT* retVal, __out bool* pDoJmpCall, __out size_t sz = retValIt.Size(&m_interpCeeInfo); #if defined(FEATURE_HFA) - CorInfoType cit = CORINFO_TYPE_UNDEF; + CorInfoHFAElemType cit = CORINFO_HFA_ELEM_NONE; { GCX_PREEMP(); if(m_methInfo->m_returnType == CORINFO_TYPE_VALUECLASS) @@ -2237,7 +2237,7 @@ void Interpreter::ExecuteMethod(ARG_SLOT* retVal, __out bool* pDoJmpCall, __out #if defined(FEATURE_HFA) // Is it an HFA? else if (m_methInfo->m_returnType == CORINFO_TYPE_VALUECLASS - && CorInfoTypeIsFloatingPoint(cit) + && (cit != CORINFO_HFA_ELEM_NONE)) && (MetaSig(reinterpret_cast(m_methInfo->m_method)).GetCallingConventionInfo() & CORINFO_CALLCONV_VARARG) == 0) { if (retValIt.IsLargeStruct(&m_interpCeeInfo)) @@ -9223,7 +9223,7 @@ void Interpreter::DoCallWork(bool virtualCall, void* thisArg, CORINFO_RESOLVED_T GCX_PREEMP(); if (sigInfo.retType == CORINFO_TYPE_VALUECLASS - && CorInfoTypeIsFloatingPoint(m_interpCeeInfo.getHFAType(sigInfo.retTypeClass)) + && (m_interpCeeInfo.getHFAType(sigInfo.retTypeClass) != CORINFO_HFA_ELEM_NONE) && (sigInfo.getCallConv() & CORINFO_CALLCONV_VARARG) == 0) { HFAReturnArgSlots = getClassSize(sigInfo.retTypeClass); diff --git a/src/coreclr/src/vm/jitinterface.cpp b/src/coreclr/src/vm/jitinterface.cpp index 4574daca8e295..9a4f1191ac7d1 100644 --- a/src/coreclr/src/vm/jitinterface.cpp +++ b/src/coreclr/src/vm/jitinterface.cpp @@ -9724,7 +9724,7 @@ CORINFO_CLASS_HANDLE CEEInfo::getArgClass ( /*********************************************************************/ -CorInfoType CEEInfo::getHFAType(CORINFO_CLASS_HANDLE hClass) +CorInfoHFAElemType CEEInfo::getHFAType(CORINFO_CLASS_HANDLE hClass) { CONTRACTL { THROWS; @@ -9732,13 +9732,13 @@ CorInfoType CEEInfo::getHFAType(CORINFO_CLASS_HANDLE hClass) MODE_PREEMPTIVE; } CONTRACTL_END; - CorInfoType result = CORINFO_TYPE_UNDEF; + CorInfoHFAElemType result = CORINFO_HFA_ELEM_NONE; JIT_TO_EE_TRANSITION(); TypeHandle VMClsHnd(hClass); - result = asCorInfoType(VMClsHnd.GetHFAType()); + result = VMClsHnd.GetHFAType(); EE_TO_JIT_TRANSITION(); diff --git a/src/coreclr/src/vm/jitinterface.h b/src/coreclr/src/vm/jitinterface.h index 0e52a1eccc572..471554d39d89a 100644 --- a/src/coreclr/src/vm/jitinterface.h +++ b/src/coreclr/src/vm/jitinterface.h @@ -848,7 +848,7 @@ class CEEInfo : public ICorJitInfo CORINFO_ARG_LIST_HANDLE args ); - CorInfoType getHFAType ( + CorInfoHFAElemType getHFAType ( CORINFO_CLASS_HANDLE hClass ); diff --git a/src/coreclr/src/vm/methodtable.h b/src/coreclr/src/vm/methodtable.h index 76d390ed5282d..141e9e58fb4b6 100644 --- a/src/coreclr/src/vm/methodtable.h +++ b/src/coreclr/src/vm/methodtable.h @@ -1859,10 +1859,10 @@ class MethodTable // Get the HFA type. This is supported both with FEATURE_HFA, in which case it // depends on the cached bit on the class, or without, in which case it is recomputed // for each invocation. - CorElementType GetHFAType(); + CorInfoHFAElemType GetHFAType(); // The managed and unmanaged HFA type can differ for types with layout. The following two methods return the unmanaged HFA type. bool IsNativeHFA(); - CorElementType GetNativeHFAType(); + CorInfoHFAElemType GetNativeHFAType(); #ifdef UNIX_AMD64_ABI inline bool IsRegPassedStruct() diff --git a/src/coreclr/src/vm/typehandle.cpp b/src/coreclr/src/vm/typehandle.cpp index b1b00c199d56f..a7a8508e294fe 100644 --- a/src/coreclr/src/vm/typehandle.cpp +++ b/src/coreclr/src/vm/typehandle.cpp @@ -421,7 +421,7 @@ bool TypeHandle::IsHFA() const return false; } -CorElementType TypeHandle::GetHFAType() const +CorInfoHFAElemType TypeHandle::GetHFAType() const { WRAPPER_NO_CONTRACT; @@ -431,7 +431,7 @@ CorElementType TypeHandle::GetHFAType() const if (AsTypeDesc()->IsNativeValueType()) return AsNativeValueType()->GetNativeHFAType(); - return ELEMENT_TYPE_END; + return CORINFO_HFA_ELEM_NONE; } diff --git a/src/coreclr/src/vm/typehandle.h b/src/coreclr/src/vm/typehandle.h index c7dd727bb8c66..ba3455241a4ce 100644 --- a/src/coreclr/src/vm/typehandle.h +++ b/src/coreclr/src/vm/typehandle.h @@ -372,7 +372,7 @@ class TypeHandle #endif bool IsHFA() const; - CorElementType GetHFAType() const; + CorInfoHFAElemType GetHFAType() const; #ifdef FEATURE_64BIT_ALIGNMENT bool RequiresAlign8() const; diff --git a/src/coreclr/src/zap/zapinfo.cpp b/src/coreclr/src/zap/zapinfo.cpp index 1f4f83c0e48e8..e413b9a37e153 100644 --- a/src/coreclr/src/zap/zapinfo.cpp +++ b/src/coreclr/src/zap/zapinfo.cpp @@ -2966,7 +2966,7 @@ CORINFO_CLASS_HANDLE ZapInfo::getArgClass(CORINFO_SIG_INFO* sig, return m_pEEJitInfo->getArgClass(sig, args); } -CorInfoType ZapInfo::getHFAType(CORINFO_CLASS_HANDLE hClass) +CorInfoHFAElemType ZapInfo::getHFAType(CORINFO_CLASS_HANDLE hClass) { return m_pEEJitInfo->getHFAType(hClass); } diff --git a/src/coreclr/src/zap/zapinfo.h b/src/coreclr/src/zap/zapinfo.h index 6079f3291c6ea..50e8b66f35bcd 100644 --- a/src/coreclr/src/zap/zapinfo.h +++ b/src/coreclr/src/zap/zapinfo.h @@ -467,7 +467,7 @@ class ZapInfo CORINFO_CLASS_HANDLE *vcTypeRet); CORINFO_CLASS_HANDLE getArgClass(CORINFO_SIG_INFO* sig, CORINFO_ARG_LIST_HANDLE args); - CorInfoType getHFAType(CORINFO_CLASS_HANDLE hClass); + CorInfoHFAElemType getHFAType(CORINFO_CLASS_HANDLE hClass); // ICorDebugInfo diff --git a/src/coreclr/tests/src/JIT/Regression/JitBlue/Runtime_35144/Runtime_35144.cs b/src/coreclr/tests/src/JIT/Regression/JitBlue/Runtime_35144/Runtime_35144.cs new file mode 100644 index 0000000000000..937f1ea4e41d9 --- /dev/null +++ b/src/coreclr/tests/src/JIT/Regression/JitBlue/Runtime_35144/Runtime_35144.cs @@ -0,0 +1,66 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// This test was the repro case for issue #35144. +// Until interop is supported for vectors, it is difficult to validate +// that the ABI is correctly implemented, but this test is here to enable +// these cases to be manually verified (and diffed). +// +using System; +using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics; + +#pragma warning disable 0169 // warning CS0169: The field '{0}' is never used +struct WrappedVector64 { Vector64 _; } +struct WrappedVector128 { Vector128 _; } +struct WrappedVector256 { Vector256 _; } + +// Was incorrectly treated as non-HVA: passed in x0, x1. +// Should be recognized as HVA(SIMD8) and passed in d0, d1. +struct S1 { WrappedVector64 x; Vector64 y; } + +// Was incorrectly treated as HFA(double): passed in d0, d1. +// Should be passed as non-HFA in x0, x1. +struct S2 { WrappedVector64 x; double y; } + +// Incorrectly treated as HVA(simd16): passed in q0, q1, q2. +// Should be passed by reference as non-HFA. +struct S3 { Vector128 x; WrappedVector256 y; } + +static class Runtime_35144 +{ + [MethodImpl(MethodImplOptions.NoInlining)] + static void Foo(T x, object o) + { + if (o.GetType() != typeof(string)) throw new Exception(); + if (((string)o) != "SomeString") throw new Exception(); + } + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + static void FooOpt(T x, object o) + { + if (o.GetType() != typeof(string)) throw new Exception(); + if (((string)o) != "SomeString") throw new Exception(); + } + + static int Main() + { + int returnVal = 100; + try + { + Foo(new S1(), "SomeString"); + Foo(new S2(), "SomeString"); + Foo(new S3(), "SomeString"); + FooOpt(new S1(), "SomeString"); + FooOpt(new S2(), "SomeString"); + FooOpt(new S3(), "SomeString"); + } + catch (Exception e) + { + Console.WriteLine("Unexpected exception " + e.Message); + returnVal = -1; + } + return returnVal; + } +} diff --git a/src/coreclr/tests/src/JIT/Regression/JitBlue/Runtime_35144/Runtime_35144.csproj b/src/coreclr/tests/src/JIT/Regression/JitBlue/Runtime_35144/Runtime_35144.csproj new file mode 100644 index 0000000000000..986494e092b5a --- /dev/null +++ b/src/coreclr/tests/src/JIT/Regression/JitBlue/Runtime_35144/Runtime_35144.csproj @@ -0,0 +1,12 @@ + + + Exe + + + + True + + + + + diff --git a/src/coreclr/tests/src/JIT/Regression/JitBlue/Runtime_35976/Runtime_35976.cs b/src/coreclr/tests/src/JIT/Regression/JitBlue/Runtime_35976/Runtime_35976.cs new file mode 100644 index 0000000000000..417d03782eb91 --- /dev/null +++ b/src/coreclr/tests/src/JIT/Regression/JitBlue/Runtime_35976/Runtime_35976.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// This test was the repro case for issue #35144. +// Until interop is supported for vectors, it is difficult to validate +// that the ABI is correctly implemented, but this test is here to enable +// these cases to be manually verified (and diffed). +// +using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Arm; + +static class Runtime_35976 +{ + [MethodImpl(MethodImplOptions.NoInlining)] + public static uint fo1(uint value) + { + if (AdvSimd.IsSupported) + { + var input = Vector64.CreateScalar(value); + return AdvSimd.Extract(input, 0); + } + return 0; + } + + static int Main() + { + fo1(1); + return 100; + } +} diff --git a/src/coreclr/tests/src/JIT/Regression/JitBlue/Runtime_35976/Runtime_35976.csproj b/src/coreclr/tests/src/JIT/Regression/JitBlue/Runtime_35976/Runtime_35976.csproj new file mode 100644 index 0000000000000..986494e092b5a --- /dev/null +++ b/src/coreclr/tests/src/JIT/Regression/JitBlue/Runtime_35976/Runtime_35976.csproj @@ -0,0 +1,12 @@ + + + Exe + + + + True + + + + +