|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
namespace Microsoft.Diagnostics.DataContractReader.RuntimeTypeSystemHelpers;
internal struct MethodTableFlags_1
{
// Low order bit of EEClassOrCanonMT.
// See MethodTable::LowBits UNION_EECLASS / UNION_METHODABLE
[Flags]
internal enum EEClassOrCanonMTBits
{
EEClass = 0,
CanonMT = 1,
Mask = 1,
}
// The lower 16-bits of the MTFlags field are used for these flags,
// if WFLAGS_HIGH.HasComponentSize is unset
[Flags]
internal enum WFLAGS_LOW : uint
{
GenericsMask = 0x00000030,
GenericsMask_NonGeneric = 0x00000000, // no instantiation
GenericsMask_TypicalInstantiation = 0x00000030, // the type instantiated at its formal parameters, e.g. List<T>
StringArrayValues =
GenericsMask_NonGeneric |
0,
}
// Upper bits of MTFlags
[Flags]
internal enum WFLAGS_HIGH : uint
{
Category_Mask = 0x000F0000,
Category_Array = 0x00080000,
Category_IfArrayThenSzArray = 0x00020000,
Category_Array_Mask = 0x000C0000,
Category_ValueType_Mask = 0x000C0000,
Category_ElementType_Mask = 0x000E0000,
Category_ValueType = 0x00040000,
Category_Nullable = 0x00050000,
Category_PrimitiveValueType = 0x00060000,
Category_TruePrimitive = 0x00070000,
Category_Interface = 0x000C0000,
Collectible = 0x00200000, // GC depends on this bit.
RequiresAlign8 = 0x00800000,
ContainsGCPointers = 0x01000000,
IsTrackedReferenceWithFinalizer = 0x04000000, // [cDAC] [RuntimeTypeSystem]: Contract depends on this value
ContainsGenericVariables = 0x20000000,
HasComponentSize = 0x80000000, // This is set if lower 16 bits is used for the component size,
// otherwise the lower bits are used for WFLAGS_LOW
}
[Flags]
internal enum WFLAGS2_ENUM : uint
{
DynamicStatics = 0x0002,
}
public uint MTFlags { get; init; }
public uint MTFlags2 { get; init; }
public uint BaseSize { get; init; }
private const int MTFlags2TypeDefRidShift = 8;
private WFLAGS_HIGH FlagsHigh => (WFLAGS_HIGH)MTFlags;
private WFLAGS_LOW FlagsLow => (WFLAGS_LOW)MTFlags;
public int GetTypeDefRid() => (int)(MTFlags2 >> MTFlags2TypeDefRidShift);
public WFLAGS_LOW GetFlag(WFLAGS_LOW mask) => throw new NotImplementedException("TODO");
public WFLAGS_HIGH GetFlag(WFLAGS_HIGH mask) => FlagsHigh & mask;
public WFLAGS2_ENUM GetFlag(WFLAGS2_ENUM mask) => (WFLAGS2_ENUM)MTFlags2 & mask;
private ushort ComponentSizeBits => (ushort)(MTFlags & 0x0000ffff); // note: caller should check HasComponentSize
private bool TestFlagWithMask(WFLAGS_LOW mask, WFLAGS_LOW flag)
{
if (IsStringOrArray)
{
return (WFLAGS_LOW.StringArrayValues & mask) == flag;
}
else
{
return (FlagsLow & mask) == flag;
}
}
private bool TestFlagWithMask(WFLAGS2_ENUM mask, WFLAGS2_ENUM flag)
{
return ((WFLAGS2_ENUM)MTFlags2 & mask) == flag;
}
public bool HasComponentSize => GetFlag(WFLAGS_HIGH.HasComponentSize) != 0;
public bool IsInterface => GetFlag(WFLAGS_HIGH.Category_Mask) == WFLAGS_HIGH.Category_Interface;
public bool IsValueType => GetFlag(WFLAGS_HIGH.Category_ValueType_Mask) == WFLAGS_HIGH.Category_ValueType;
public bool IsString => HasComponentSize && !IsArray && ComponentSizeBits == 2;
public bool IsArray => GetFlag(WFLAGS_HIGH.Category_Array_Mask) == WFLAGS_HIGH.Category_Array;
public bool IsStringOrArray => HasComponentSize;
public ushort ComponentSize => HasComponentSize ? ComponentSizeBits : (ushort)0;
public bool HasInstantiation => !TestFlagWithMask(WFLAGS_LOW.GenericsMask, WFLAGS_LOW.GenericsMask_NonGeneric);
public bool ContainsGCPointers => GetFlag(WFLAGS_HIGH.ContainsGCPointers) != 0;
public bool RequiresAlign8 => GetFlag(WFLAGS_HIGH.RequiresAlign8) != 0;
public bool IsCollectible => GetFlag(WFLAGS_HIGH.Collectible) != 0;
public bool IsTrackedReferenceWithFinalizer => GetFlag(WFLAGS_HIGH.IsTrackedReferenceWithFinalizer) != 0;
public bool IsDynamicStatics => GetFlag(WFLAGS2_ENUM.DynamicStatics) != 0;
public bool IsGenericTypeDefinition => TestFlagWithMask(WFLAGS_LOW.GenericsMask, WFLAGS_LOW.GenericsMask_TypicalInstantiation);
public bool ContainsGenericVariables => GetFlag(WFLAGS_HIGH.ContainsGenericVariables) != 0;
internal static EEClassOrCanonMTBits GetEEClassOrCanonMTBits(TargetPointer eeClassOrCanonMTPtr)
{
return (EEClassOrCanonMTBits)(eeClassOrCanonMTPtr & (ulong)EEClassOrCanonMTBits.Mask);
}
internal static TargetPointer UntagEEClassOrCanonMT(TargetPointer eeClassOrCanonMTPtr)
{
return eeClassOrCanonMTPtr & ~(ulong)EEClassOrCanonMTBits.Mask;
}
internal static TargetPointer TagEEClassOrCanonMT(TargetPointer eeClassOrCanonMTPtr, EEClassOrCanonMTBits tag)
{
return (eeClassOrCanonMTPtr & ~(ulong)EEClassOrCanonMTBits.Mask) | (ulong)tag;
}
}
|