| File: parent\parent\Common\TypeSystem\Canon\CanonTypes.cs | Web Access |
| Project: ILCompiler.TypeSystem.csproj (ILCompiler.TypeSystem) |
// 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.Collections.Generic; using Internal.NativeFormat; using Internal.Text; using Debug = System.Diagnostics.Debug; #if TYPE_LOADER_IMPLEMENTATION using MetadataType = Internal.TypeSystem.DefType; #endif namespace Internal.TypeSystem { /// <summary> /// Type of canonicalization applied to a type /// </summary> public enum CanonicalFormKind { /// <summary> /// Optimized for a particular set of instantiations (such as reference types) /// </summary> Specific, /// <summary> /// Canonicalization that works for any type /// </summary> Universal, /// <summary> /// Value used for lookup for Specific or Universal. Must not be used for canonicalizing. /// </summary> Any, } /// <summary> /// Base class for specialized and universal canon types /// </summary> public abstract partial class CanonBaseType { private TypeSystemContext _context; public CanonBaseType(TypeSystemContext context) { _context = context; } public sealed override TypeSystemContext Context { get { return _context; } } public override MetadataType ContainingType => null; } /// <summary> /// Type used for specific canonicalization (e.g. for reference types) /// </summary> internal sealed partial class CanonType : CanonBaseType { private int _hashcode; public override Utf8Span Namespace { get { return "System"u8; } } public override Utf8Span Name { get { return "__Canon"u8; } } public CanonType(TypeSystemContext context) : base(context) { Initialize(); } // Provides an extensibility hook for type system consumers that need to perform // consumer-specific initialization. partial void Initialize(); public override MetadataType BaseType { get { return (MetadataType)Context.GetWellKnownType(WellKnownType.Object); } } public override bool IsCanonicalSubtype(CanonicalFormKind policy) { return policy == CanonicalFormKind.Specific || policy == CanonicalFormKind.Any; } protected override TypeDesc ConvertToCanonFormImpl(CanonicalFormKind kind) { Debug.Assert(kind == CanonicalFormKind.Specific); return this; } protected override TypeFlags ComputeTypeFlags(TypeFlags mask) { TypeFlags flags = 0; if ((mask & TypeFlags.CategoryMask) != 0) { flags |= TypeFlags.Class; } if ((mask & TypeFlags.HasGenericVarianceComputed) != 0) { flags |= TypeFlags.HasGenericVarianceComputed; } flags |= TypeFlags.HasFinalizerComputed; flags |= TypeFlags.AttributeCacheComputed; return flags; } public override int GetHashCode() { if (_hashcode == 0) { _hashcode = VersionResilientHashCode.NameHashCode(Namespace, Name); } return _hashcode; } } /// <summary> /// Type that can be used for canonicalization of any type (including value types of unknown size) /// </summary> internal sealed partial class UniversalCanonType : CanonBaseType { private int _hashcode; public override Utf8Span Namespace { get { return "System"u8; } } public override Utf8Span Name { get { return "__UniversalCanon"u8; } } public UniversalCanonType(TypeSystemContext context) : base(context) { Initialize(); } // Provides an extensibility hook for type system consumers that need to perform // consumer-specific initialization. partial void Initialize(); public override MetadataType BaseType { get { // UniversalCanon is "a struct of indeterminate size and GC layout" return (MetadataType)Context.GetWellKnownType(WellKnownType.ValueType); } } public override bool IsCanonicalSubtype(CanonicalFormKind policy) { return policy == CanonicalFormKind.Universal || policy == CanonicalFormKind.Any; } protected override TypeDesc ConvertToCanonFormImpl(CanonicalFormKind kind) { return this; } protected override TypeFlags ComputeTypeFlags(TypeFlags mask) { TypeFlags flags = 0; if ((mask & TypeFlags.CategoryMask) != 0) { // Universally canonical type is reported as a variable-sized struct. // It's the closest logical thing and avoids special casing around it. flags |= TypeFlags.ValueType; } flags |= TypeFlags.HasFinalizerComputed; flags |= TypeFlags.AttributeCacheComputed; flags |= TypeFlags.HasGenericVarianceComputed; return flags; } public override int GetHashCode() { if (_hashcode == 0) { _hashcode = VersionResilientHashCode.NameHashCode(Namespace, Name); } return _hashcode; } } }