summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTanner Gooding <tagoo@outlook.com>2018-01-21 19:35:47 -0800
committerTanner Gooding <tagoo@outlook.com>2018-01-27 11:37:13 -0800
commitab4f699cef72204b96919447a3c5ca7034fcf567 (patch)
treec3187bd8fbe730f8ef1697f96068e0c5c06c2aac
parent7121570db6f356277647ebaa6d2185da489403e5 (diff)
downloadcoreclr-ab4f699cef72204b96919447a3c5ca7034fcf567.tar.gz
coreclr-ab4f699cef72204b96919447a3c5ca7034fcf567.tar.bz2
coreclr-ab4f699cef72204b96919447a3c5ca7034fcf567.zip
Updating the VM to properly pack the SIMD hardware intrinsic types.
-rw-r--r--src/vm/classnames.h9
-rw-r--r--src/vm/fieldmarshaler.cpp12
-rw-r--r--src/vm/fieldmarshaler.h2
-rw-r--r--src/vm/methodtablebuilder.cpp118
-rw-r--r--src/vm/namespace.h2
5 files changed, 117 insertions, 26 deletions
diff --git a/src/vm/classnames.h b/src/vm/classnames.h
index 6af229e546..08286f8013 100644
--- a/src/vm/classnames.h
+++ b/src/vm/classnames.h
@@ -72,6 +72,15 @@
#define g_DecimalClassName "System.Decimal"
#define g_DecimalName "Decimal"
+#define g_Vector64ClassName "System.Runtime.Intrinsics.Vector64`1"
+#define g_Vector64Name "Vector64`1"
+
+#define g_Vector128ClassName "System.Runtime.Intrinsics.Vector128`1"
+#define g_Vector128Name "Vector128`1"
+
+#define g_Vector256ClassName "System.Runtime.Intrinsics.Vector256`1"
+#define g_Vector256Name "Vector256`1"
+
#ifdef FEATURE_COMINTEROP
#define g_WindowsFoundationActivatableAttributeClassName "Windows.Foundation.Metadata.ActivatableAttribute"
diff --git a/src/vm/fieldmarshaler.cpp b/src/vm/fieldmarshaler.cpp
index 0685093483..b1a4a8b9b5 100644
--- a/src/vm/fieldmarshaler.cpp
+++ b/src/vm/fieldmarshaler.cpp
@@ -1669,7 +1669,9 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing(
if (!(alignmentRequirement == 1 ||
alignmentRequirement == 2 ||
alignmentRequirement == 4 ||
- alignmentRequirement == 8))
+ alignmentRequirement == 8 ||
+ alignmentRequirement == 16 ||
+ alignmentRequirement == 32))
{
COMPlusThrowHR(COR_E_INVALIDPROGRAM, BFA_METADATA_CORRUPT);
}
@@ -1680,7 +1682,7 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing(
// This assert means I forgot to special-case some NFT in the
// above switch.
- _ASSERTE(alignmentRequirement <= 8);
+ _ASSERTE(alignmentRequirement <= 32);
// Check if this field is overlapped with other(s)
pfwalk->m_fIsOverlapped = FALSE;
@@ -1806,7 +1808,9 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing(
if (!(alignmentRequirement == 1 ||
alignmentRequirement == 2 ||
alignmentRequirement == 4 ||
- alignmentRequirement == 8))
+ alignmentRequirement == 8 ||
+ alignmentRequirement == 16 ||
+ alignmentRequirement == 32))
{
COMPlusThrowHR(COR_E_INVALIDPROGRAM, BFA_METADATA_CORRUPT);
}
@@ -1815,7 +1819,7 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing(
LargestAlignmentRequirement = max(LargestAlignmentRequirement, alignmentRequirement);
- _ASSERTE(alignmentRequirement <= 8);
+ _ASSERTE(alignmentRequirement <= 32);
// Insert enough padding to align the current data member.
while (cbCurOffset % alignmentRequirement)
diff --git a/src/vm/fieldmarshaler.h b/src/vm/fieldmarshaler.h
index 2d11068f15..8c1f8fe1ac 100644
--- a/src/vm/fieldmarshaler.h
+++ b/src/vm/fieldmarshaler.h
@@ -88,7 +88,7 @@ enum NStructFieldType
// Currently we set this to the packing size of the largest supported
// fundamental type and let the field marshaller downsize where needed.
//=======================================================================
-#define DEFAULT_PACKING_SIZE 8
+#define DEFAULT_PACKING_SIZE 32
//=======================================================================
diff --git a/src/vm/methodtablebuilder.cpp b/src/vm/methodtablebuilder.cpp
index f48e2a7b71..f309fbc40f 100644
--- a/src/vm/methodtablebuilder.cpp
+++ b/src/vm/methodtablebuilder.cpp
@@ -9535,42 +9535,118 @@ void MethodTableBuilder::CheckForSystemTypes()
{
STANDARD_VM_CONTRACT;
+ LPCUTF8 name, nameSpace;
+
MethodTable * pMT = GetHalfBakedMethodTable();
EEClass * pClass = GetHalfBakedClass();
// We can exit early for generic types - there are just a few cases to check for.
- if (bmtGenerics->HasInstantiation() && g_pNullableClass != NULL)
+ if (bmtGenerics->HasInstantiation())
{
- _ASSERTE(g_pByReferenceClass != NULL);
- _ASSERTE(g_pByReferenceClass->IsByRefLike());
-
-#ifdef _TARGET_X86_
- if (GetCl() == g_pByReferenceClass->GetCl())
+ if (pClass->HasLayout())
{
- // x86 by default treats the type of ByReference<T> as the actual type of its IntPtr field, see calls to
- // ComputeInternalCorElementTypeForValueType in this file. This is a special case where the struct needs to be
- // treated as a value type so that its field can be considered as a by-ref pointer.
- _ASSERTE(pMT->GetFlag(MethodTable::enum_flag_Category_Mask) == MethodTable::enum_flag_Category_PrimitiveValueType);
- pMT->ClearFlag(MethodTable::enum_flag_Category_Mask);
- pMT->SetInternalCorElementType(ELEMENT_TYPE_VALUETYPE);
- return;
+ if (FAILED(GetMDImport()->GetNameOfTypeDef(GetCl(), &name, &nameSpace)))
+ {
+ BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
+ }
+
+ if (strcmp(nameSpace, g_IntrinsicsNS) == 0)
+ {
+ EEClassLayoutInfo * pLayout = pClass->GetLayoutInfo();
+
+ // The SIMD Hardware Intrinsic types correspond to fundamental data types in the underlying ABIs:
+ // * Vector64<T>: __m64
+ // * Vector128<T>: __m128
+ // * Vector256<T>: __m256
+
+ // These __m128 and __m256 types, among other requirements, are special in that they must always
+ // be aligned properly.
+
+ if (strcmp(name, g_Vector64Name) == 0)
+ {
+ // The System V ABI for i386 defaults to 8-byte alignment for __m64, except for parameter passing,
+ // where it has an alignment of 4.
+
+ pLayout->m_LargestAlignmentRequirementOfAllMembers = 8; // sizeof(__m64)
+ pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 8; // sizeof(__m64)
+ }
+ else if (strcmp(name, g_Vector128Name) == 0)
+ {
+ #ifdef _TARGET_ARM_
+ // The Procedure Call Standard for ARM defaults to 8-byte alignment for __m128
+
+ pLayout->m_LargestAlignmentRequirementOfAllMembers = 8;
+ pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 8;
+ #else
+ pLayout->m_LargestAlignmentRequirementOfAllMembers = 16; // sizeof(__m128)
+ pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16; // sizeof(__m128)
+ #endif // _TARGET_ARM_
+ }
+ else if (strcmp(name, g_Vector256Name) == 0)
+ {
+ #ifdef _TARGET_ARM_
+ // No such type exists for the Procedure Call Standard for ARM. We will default
+ // to the same alignment as __m128, which is supported by the ABI.
+
+ pLayout->m_LargestAlignmentRequirementOfAllMembers = 8;
+ pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 8;
+ #elif defined(_TARGET_ARM64_)
+ // The Procedure Call Standard for ARM 64-bit (with SVE support) defaults to
+ // 16-byte alignment for __m256.
+
+ pLayout->m_LargestAlignmentRequirementOfAllMembers = 16;
+ pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16;
+ #else
+ pLayout->m_LargestAlignmentRequirementOfAllMembers = 32; // sizeof(__m256)
+ pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 32; // sizeof(__m256)
+ #endif // _TARGET_ARM_ elif _TARGET_ARM64_
+ }
+ else
+ {
+ // These types should be handled or explicitly skipped below to ensure that we don't
+ // miss adding required ABI support for future types.
+
+ _ASSERTE_MSG((strcmp(name, "Vector64DebugView`1") == 0) ||
+ (strcmp(name, "Vector128DebugView`1") == 0) ||
+ (strcmp(name, "Vector256DebugView`1") == 0),
+ "Unhandled Hardware Intrinsic Type.");
+ }
+
+ return;
+ }
}
+
+ if (g_pNullableClass != NULL)
+ {
+ _ASSERTE(g_pByReferenceClass != NULL);
+ _ASSERTE(g_pByReferenceClass->IsByRefLike());
+
+#ifdef _TARGET_X86_
+ if (GetCl() == g_pByReferenceClass->GetCl())
+ {
+ // x86 by default treats the type of ByReference<T> as the actual type of its IntPtr field, see calls to
+ // ComputeInternalCorElementTypeForValueType in this file. This is a special case where the struct needs to be
+ // treated as a value type so that its field can be considered as a by-ref pointer.
+ _ASSERTE(pMT->GetFlag(MethodTable::enum_flag_Category_Mask) == MethodTable::enum_flag_Category_PrimitiveValueType);
+ pMT->ClearFlag(MethodTable::enum_flag_Category_Mask);
+ pMT->SetInternalCorElementType(ELEMENT_TYPE_VALUETYPE);
+ return;
+ }
#endif
- _ASSERTE(g_pNullableClass->IsNullable());
+ _ASSERTE(g_pNullableClass->IsNullable());
- // Pre-compute whether the class is a Nullable<T> so that code:Nullable::IsNullableType is efficient
- // This is useful to the performance of boxing/unboxing a Nullable
- if (GetCl() == g_pNullableClass->GetCl())
- pMT->SetIsNullable();
+ // Pre-compute whether the class is a Nullable<T> so that code:Nullable::IsNullableType is efficient
+ // This is useful to the performance of boxing/unboxing a Nullable
+ if (GetCl() == g_pNullableClass->GetCl())
+ pMT->SetIsNullable();
- return;
+ return;
+ }
}
if (IsNested() || IsEnum())
return;
-
- LPCUTF8 name, nameSpace;
if (FAILED(GetMDImport()->GetNameOfTypeDef(GetCl(), &name, &nameSpace)))
{
diff --git a/src/vm/namespace.h b/src/vm/namespace.h
index fbcdfd630a..4395071559 100644
--- a/src/vm/namespace.h
+++ b/src/vm/namespace.h
@@ -33,6 +33,8 @@
#define g_WinRTNS g_InteropNS ".WindowsRuntime"
#endif // FEATURE_COMINTEROP
+#define g_IntrinsicsNS g_RuntimeNS ".Intrinsics"
+
#define g_InternalCompilerServicesNS "Internal.Runtime.CompilerServices"
#define g_CompilerServicesNS g_RuntimeNS ".CompilerServices"