| File: Compiler\DependencyAnalysis\ReadyToRun\TypeHandle.cs | Web Access |
| Project: src\runtime\src\coreclr\tools\aot\ILCompiler.ReadyToRun\ILCompiler.ReadyToRun.csproj (ILCompiler.ReadyToRun) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Diagnostics; using Internal.JitInterface; using Internal.TypeSystem; using Internal.CorConstants; using Internal.Runtime; using Internal.CallingConvention; namespace ILCompiler.DependencyAnalysis.ReadyToRun { /// <summary> /// Crossgen2's implementation of ITypeHandle, backed by Internal.TypeSystem.TypeDesc. /// </summary> internal struct TypeHandle : ITypeHandle { public TypeHandle(TypeDesc type) { _type = type; _isByRef = _type.IsByRef; if (_isByRef) { _type = ((ByRefType)_type).ParameterType; } } private readonly TypeDesc _type; private readonly bool _isByRef; public bool Equals(TypeHandle other) { return _isByRef == other._isByRef && _type == other._type; } public override int GetHashCode() { return (int)_type.GetHashCode(); } public bool IsNull() { return _type == null && !_isByRef; } public bool IsValueType() { if (_isByRef) return false; return _type.IsValueType; } public bool IsPointerType() { if (_isByRef) return false; return _type.IsPointer; } public bool HasIndeterminateSize() { return IsValueType() && ((DefType)_type).InstanceFieldSize.IsIndeterminate; } public int PointerSize => _type.Context.Target.PointerSize; public int GetSize() { if (IsValueType()) return ((DefType)_type).InstanceFieldSize.AsInt; else return PointerSize; } public bool RequiresAlign8() { if (_type.Context.Target.Architecture != TargetArchitecture.ARM) { return false; } if (_isByRef) { return false; } return _type.RequiresAlign8(); } public bool IsHomogeneousAggregate() { TargetArchitecture targetArch = _type.Context.Target.Architecture; if ((targetArch != TargetArchitecture.ARM) && (targetArch != TargetArchitecture.ARM64)) { return false; } if (_isByRef) { return false; } return _type is DefType defType && defType.IsHomogeneousAggregate; } public int GetHomogeneousAggregateElementSize() { Debug.Assert(IsHomogeneousAggregate()); switch (_type.Context.Target.Architecture) { case TargetArchitecture.ARM: return RequiresAlign8() ? 8 : 4; case TargetArchitecture.ARM64: return ((DefType)_type).GetHomogeneousAggregateElementSize(); } throw new InvalidOperationException(); } public CorElementType GetCorElementType() { if (_isByRef) { return CorElementType.ELEMENT_TYPE_BYREF; } Internal.TypeSystem.TypeFlags category = _type.UnderlyingType.Category; // We use the UnderlyingType to handle Enums properly return category switch { Internal.TypeSystem.TypeFlags.Boolean => CorElementType.ELEMENT_TYPE_BOOLEAN, Internal.TypeSystem.TypeFlags.Char => CorElementType.ELEMENT_TYPE_CHAR, Internal.TypeSystem.TypeFlags.SByte => CorElementType.ELEMENT_TYPE_I1, Internal.TypeSystem.TypeFlags.Byte => CorElementType.ELEMENT_TYPE_U1, Internal.TypeSystem.TypeFlags.Int16 => CorElementType.ELEMENT_TYPE_I2, Internal.TypeSystem.TypeFlags.UInt16 => CorElementType.ELEMENT_TYPE_U2, Internal.TypeSystem.TypeFlags.Int32 => CorElementType.ELEMENT_TYPE_I4, Internal.TypeSystem.TypeFlags.UInt32 => CorElementType.ELEMENT_TYPE_U4, Internal.TypeSystem.TypeFlags.Int64 => CorElementType.ELEMENT_TYPE_I8, Internal.TypeSystem.TypeFlags.UInt64 => CorElementType.ELEMENT_TYPE_U8, Internal.TypeSystem.TypeFlags.IntPtr => CorElementType.ELEMENT_TYPE_I, Internal.TypeSystem.TypeFlags.UIntPtr => CorElementType.ELEMENT_TYPE_U, Internal.TypeSystem.TypeFlags.Single => CorElementType.ELEMENT_TYPE_R4, Internal.TypeSystem.TypeFlags.Double => CorElementType.ELEMENT_TYPE_R8, Internal.TypeSystem.TypeFlags.ValueType => CorElementType.ELEMENT_TYPE_VALUETYPE, Internal.TypeSystem.TypeFlags.Nullable => CorElementType.ELEMENT_TYPE_VALUETYPE, Internal.TypeSystem.TypeFlags.Void => CorElementType.ELEMENT_TYPE_VOID, Internal.TypeSystem.TypeFlags.Pointer => CorElementType.ELEMENT_TYPE_PTR, Internal.TypeSystem.TypeFlags.FunctionPointer => CorElementType.ELEMENT_TYPE_FNPTR, _ => CorElementType.ELEMENT_TYPE_CLASS }; } public void GetSystemVAmd64PassStructInRegisterDescriptor(out SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR descriptor) { SystemVStructClassificator.GetSystemVAmd64PassStructInRegisterDescriptor(_type, out descriptor); } public FpStructInRegistersInfo GetFpStructInRegistersInfo(TargetArchitecture architecture) { return RiscVLoongArch64FpStruct.GetFpStructInRegistersInfo(_type, architecture); } public bool IsTrivialPointerSizedStruct() { Debug.Assert(IsValueType()); if (GetSize() != 4) { return false; } TypeDesc typeOfEmbeddedField = null; foreach (var field in _type.GetFields()) { if (field.IsStatic) continue; if (typeOfEmbeddedField != null) { return false; } typeOfEmbeddedField = field.FieldType; } if ((typeOfEmbeddedField != null) && ((typeOfEmbeddedField.IsValueType) || (typeOfEmbeddedField.IsPointer))) { switch (typeOfEmbeddedField.UnderlyingType.Category) { case TypeFlags.IntPtr: case TypeFlags.UIntPtr: case TypeFlags.Int32: case TypeFlags.UInt32: case TypeFlags.Pointer: return true; case TypeFlags.ValueType: return new TypeHandle(typeOfEmbeddedField).IsTrivialPointerSizedStruct(); } } return false; } public int GetFieldAlignment() { return ((DefType)_type).InstanceFieldAlignment.AsInt; } /// <summary> /// Escape hatch for crossgen2-specific code that needs the underlying TypeDesc. /// Not part of the ITypeHandle interface. /// </summary> public TypeDesc GetRuntimeTypeHandle() { return _type; } } }