public override ValueTypeShapeCharacteristics ComputeValueTypeShapeCharacteristics(DefType type) { if (!type.IsValueType) { return(ValueTypeShapeCharacteristics.None); } ValueTypeShapeCharacteristics result = ComputeHomogeneousFloatAggregateCharacteristic(type); // TODO: System V AMD64 characteristics (https://github.com/dotnet/corert/issues/158) return(result); }
private void ComputeValueTypeShapeCharacteristics() { _valueTypeShapeCharacteristics = this.Context.GetLayoutAlgorithmForType(this).ComputeValueTypeShapeCharacteristics(this); _fieldLayoutFlags.AddFlags(FieldLayoutFlags.ComputedValueTypeShapeCharacteristics); }
public unsafe override ValueTypeShapeCharacteristics ComputeValueTypeShapeCharacteristics(DefType type) { // Use this constant to make the code below more laconic const ValueTypeShapeCharacteristics NotHA = ValueTypeShapeCharacteristics.None; Debug.Assert(type.IsValueType); TargetArchitecture targetArch = type.Context.Target.Architecture; if ((targetArch != TargetArchitecture.ARM) && (targetArch != TargetArchitecture.ARM64)) { return(NotHA); } if (!type.IsValueType) { return(NotHA); } // There is no reason to compute the entire field layout for the HA type/flag if // the template type is not a universal generic type (information stored in rare flags on the EEType) TypeDesc templateType = type.ComputeTemplate(false); if (templateType != null && !templateType.IsCanonicalSubtype(CanonicalFormKind.Universal)) { EEType *pEETemplate = templateType.GetRuntimeTypeHandle().ToEETypePtr(); if (!pEETemplate->IsHFA) { return(NotHA); } if (pEETemplate->RequiresAlign8) { return(ValueTypeShapeCharacteristics.Float64Aggregate); } else { return(ValueTypeShapeCharacteristics.Float32Aggregate); } } // Once this is done, the NativeLayoutFields on the type are initialized EnsureFieldLayoutLoadedForGenericType((DefType)type); Debug.Assert(type.NativeLayoutFields != null); // Empty types are not HA if (type.NativeLayoutFields.Length == 0) { return(NotHA); } // Find the common HA element type if any ValueTypeShapeCharacteristics haResultType = NotHA; for (int i = 0; i < type.NativeLayoutFields.Length; i++) { TypeDesc fieldType = type.NativeLayoutFields[i].FieldType; if (type.NativeLayoutFields[i].FieldStorage != NativeFormat.FieldStorage.Instance) { continue; } // If a field isn't a DefType, then this type cannot be a HA type if (!(fieldType is DefType fieldDefType)) { return(NotHA); } // HA types cannot contain non-HA types ValueTypeShapeCharacteristics haFieldType = fieldDefType.ValueTypeShapeCharacteristics & ValueTypeShapeCharacteristics.AggregateMask; if (haFieldType == NotHA) { return(NotHA); } if (haResultType == NotHA) { haResultType = haFieldType; } else if (haResultType != haFieldType) { return(NotHA); // If the field doesn't have the same HA type as the one we've looked at before, the type cannot be HA } } // If we didn't find any instance fields, then this can't be a HA type if (haResultType == NotHA) { return(NotHA); } int haElementSize = haResultType switch { ValueTypeShapeCharacteristics.Float32Aggregate => 4, ValueTypeShapeCharacteristics.Float64Aggregate => 8, ValueTypeShapeCharacteristics.Vector64Aggregate => 8, ValueTypeShapeCharacteristics.Vector128Aggregate => 16, _ => throw new ArgumentOutOfRangeException() }; // Note that we check the total size, but do not perform any checks on number of fields: // - Type of fields can be HA valuetype itself // - Managed C++ HFA valuetypes have just one <alignment member> of type float to signal that // the valuetype is HFA and explicitly specified size int maxSize = haElementSize * type.Context.Target.MaxHomogeneousAggregateElementCount; if (type.InstanceFieldSize.AsInt > maxSize) { return(NotHA); } return(haResultType); } }
private void ComputeValueTypeShapeCharacteristics() { _valueTypeShapeCharacteristics = this.Context.GetLayoutAlgorithmForType(this).ComputeValueTypeShapeCharacteristics(this); _fieldLayoutFlags.AddFlags(FieldLayoutFlags.ComputedValueTypeShapeCharacteristics); }