diff options
author | Simon Nattress <simonn@microsoft.com> | 2015-11-23 22:42:12 +0300 |
---|---|---|
committer | Simon Nattress <simonn@microsoft.com> | 2015-12-04 10:43:16 +0300 |
commit | d4f77bc3fa5601d8c8956d5681eb080f0993fe8a (patch) | |
tree | 1cf144aaf1dbb16ccf13fa61857a43c1e387a618 /src | |
parent | de72db556da5ff4f205ec7aa6b76dbd1a72d8550 (diff) |
Fill out EEType fields
Fill out the fixed portion of the EEType data structure as expected by the runtime along with most of the variable pieces that follow.
Correct the code-gen's calculation of where VTable entries start in the EEType.
Add type-system support for asking if a type has a finalizer.
Move EEType Flags and Kinds enums to the Common folder and consume them from the compiler and runtime.
Transpose the new Type System's Category to a CorElementType for primitives / enum underlying types.
Remove HasFinalizer assert in RhNewObject
The following pieces are incomplete:
Optional fields side data structure
Interface dispatch map pointers
Type variance
Sealed virtual slots blob
Generic Type Def EETypes
Diffstat (limited to 'src')
11 files changed, 476 insertions, 131 deletions
diff --git a/src/Common/src/Internal/Runtime/EETypeFlags.cs b/src/Common/src/Internal/Runtime/EETypeFlags.cs new file mode 100644 index 000000000..ac0aca03b --- /dev/null +++ b/src/Common/src/Internal/Runtime/EETypeFlags.cs @@ -0,0 +1,104 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; + +namespace Internal.Runtime +{ + /// <summary> + /// Represents the flags stored in the <c>_usFlags</c> field of a <c>System.Runtime.EEType</c>. + /// </summary> + [Flags] + internal enum EETypeFlags : ushort + { + /// <summary> + /// There are four kinds of EETypes, defined in <c>Kinds</c>. + /// </summary> + EETypeKindMask = 0x0003, + + /// <summary> + /// This flag is set when m_RelatedType is in a different module. In that case, _pRelatedType + /// actually points to an IAT slot in this module, which then points to the desired EEType in the + /// other module. In other words, there is an extra indirection through m_RelatedType to get to + /// the related type in the other module. When this flag is set, it is expected that you use the + /// "_ppXxxxViaIAT" member of the RelatedTypeUnion for the particular related type you're + /// accessing. + /// </summary> + RelatedTypeViaIATFlag = 0x0004, + + /// <summary> + /// This EEType represents a value type. + /// </summary> + ValueTypeFlag = 0x0008, + + /// <summary> + /// This EEType represents a type which requires finalization. + /// </summary> + HasFinalizerFlag = 0x0010, + + /// <summary> + /// This type contain GC pointers. + /// </summary> + HasPointersFlag = 0x0020, + + /// <summary> + /// This type instance was allocated at runtime (rather than being embedded in a module image). + /// </summary> + RuntimeAllocatedFlag = 0x0040, + + /// <summary> + /// This type is generic and one or more of its type parameters is co- or contra-variant. This + /// only applies to interface and delegate types. + /// </summary> + GenericVarianceFlag = 0x0080, + + /// <summary> + /// This type has optional fields present. + /// </summary> + OptionalFieldsFlag = 0x0100, + + /// <summary> + /// This EEType represents an interface. + /// </summary> + IsInterfaceFlag = 0x0200, + + /// <summary> + /// This type is generic. + /// </summary> + IsGenericFlag = 0x0400, + + /// <summary> + /// We are storing a CorElementType in the upper bits for unboxing enums. + /// </summary> + CorElementTypeMask = 0xf800, + CorElementTypeShift = 11, + + /// <summary> + /// Single mark to check TypeKind and two flags. When non-zero, casting is more complicated. + /// </summary> + ComplexCastingMask = EETypeKindMask | RelatedTypeViaIATFlag | GenericVarianceFlag + }; + + internal enum EETypeKind : ushort + { + /// <summary> + /// Represents a standard ECMA type + /// </summary> + CanonicalEEType = 0x0000, + + /// <summary> + /// Represents a type cloned from another EEType + /// </summary> + ClonedEEType = 0x0001, + + /// <summary> + /// Represents a paramaterized type. For example a single dimensional array or pointer type + /// </summary> + ParameterizedEEType = 0x0002, + + /// <summary> + /// Represents an uninstantiated generic type definition + /// </summary> + GenericTypeDefEEType = 0x0003, + } +} diff --git a/src/Common/src/TypeSystem/Common/InstantiatedType.cs b/src/Common/src/TypeSystem/Common/InstantiatedType.cs index 3c47c63d4..9e69a4ff0 100644 --- a/src/Common/src/TypeSystem/Common/InstantiatedType.cs +++ b/src/Common/src/TypeSystem/Common/InstantiatedType.cs @@ -137,6 +137,14 @@ namespace Internal.TypeSystem return _typeDef.Context.GetMethodForInstantiatedType(typicalCctor, this); } + public override MethodDesc GetFinalizer() + { + MethodDesc typicalFinalizer = _typeDef.GetFinalizer(); + if (typicalFinalizer == null) + return null; + return _typeDef.Context.GetMethodForInstantiatedType(typicalFinalizer, this); + } + public override IEnumerable<FieldDesc> GetFields() { foreach (var fieldDef in _typeDef.GetFields()) diff --git a/src/Common/src/TypeSystem/Common/MetadataType.cs b/src/Common/src/TypeSystem/Common/MetadataType.cs index 232fcd048..336a9dcb4 100644 --- a/src/Common/src/TypeSystem/Common/MetadataType.cs +++ b/src/Common/src/TypeSystem/Common/MetadataType.cs @@ -16,6 +16,14 @@ namespace Internal.TypeSystem } } + public override bool HasFinalizer + { + get + { + return GetFinalizer() != null; + } + } + /// <summary> /// Gets metadata that controls instance layout of this type. /// </summary> diff --git a/src/Common/src/TypeSystem/Common/TypeDesc.cs b/src/Common/src/TypeSystem/Common/TypeDesc.cs index bf7fa3286..0ff784fd2 100644 --- a/src/Common/src/TypeSystem/Common/TypeDesc.cs +++ b/src/Common/src/TypeSystem/Common/TypeDesc.cs @@ -443,5 +443,18 @@ namespace Internal.TypeSystem { return GetTypeDefinition() == otherType.GetTypeDefinition(); } + + public virtual bool HasFinalizer + { + get + { + return false; + } + } + + public virtual MethodDesc GetFinalizer() + { + return null; + } } } diff --git a/src/Common/src/TypeSystem/Ecma/EcmaType.cs b/src/Common/src/TypeSystem/Ecma/EcmaType.cs index 902a5595b..33db0150f 100644 --- a/src/Common/src/TypeSystem/Ecma/EcmaType.cs +++ b/src/Common/src/TypeSystem/Ecma/EcmaType.cs @@ -259,6 +259,32 @@ namespace Internal.TypeSystem.Ecma return null; } + public override MethodDesc GetFinalizer() + { + // System.Object defines Finalize but doesn't use it, so we can determine that a type has a Finalizer + // by checking for a virtual method override that lands anywhere other than Object in the inheritance + // chain. + if (!HasBaseType) + return null; + + TypeDesc objectType = Context.GetWellKnownType(WellKnownType.Object); + MethodDesc decl = objectType.GetMethod("Finalize", null); + + if (decl != null) + { + MethodDesc impl = VirtualFunctionResolution.FindVirtualFunctionTargetMethodOnObjectType(decl, this); + if (impl.OwningType != objectType) + { + return impl; + } + + return null; + } + + // TODO: Better exception type. Should be: "CoreLib doesn't have a required thing in it". + throw new NotImplementedException(); + } + public override IEnumerable<FieldDesc> GetFields() { foreach (var handle in _typeDefinition.GetFields()) diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs index beaac9bc9..782f03a03 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs @@ -1,20 +1,53 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System; -using System.Collections.Generic; using ILCompiler.DependencyAnalysisFramework; +using Internal.Runtime; using Internal.TypeSystem; - +using System; +using System.Collections.Generic; using Debug = System.Diagnostics.Debug; namespace ILCompiler.DependencyAnalysis { + /// <summary> + /// Given a type, EETypeNode writes an EEType data structure in the format expected by the runtime. + /// + /// Format of an EEType: + /// + /// Field Size | Contents + /// ----------------+----------------------------------- + /// UInt16 | Component Size. For arrays this is the element type size, for strings it is 2 (.NET uses + /// | UTF16 character encoding), and 0 for all other types. + /// | + /// UInt16 | EETypeKind (Normal, Array, Pointer type). Flags for: IsValueType, IsCrossModule, HasPointers, + /// | HasOptionalFields, IsInterface, IsGeneric. Top 5 bits are used for enum CorElementType to + /// | record whether it's back by an Int32, Int16 etc + /// | + /// [Pointer Size] | Related type. Base type for regular types. Element type for arrays / pointer types. + /// | + /// UInt16 | Number of VTable slots (X) + /// | + /// UInt16 | Number of interfaces implemented by type (Y) + /// | + /// UInt32 | Hash code + /// | + /// X * [Ptr Size] | VTable entries (optional) + /// | + /// Y * [Ptr Size] | Pointers to interface map data structures (optional) + /// | + /// [Pointer Size] | Pointer to finalizer method (optional) + /// | + /// [Pointer Size] | Pointer to optional fields (optional) + /// | + /// [Pointer Size] | Pointer to the generic type argument of a Nullable<T> (optional) + /// + /// </summary> internal class EETypeNode : ObjectNode, ISymbolNode { private TypeDesc _type; private bool _constructed; - + public EETypeNode(TypeDesc type, bool constructed) { _type = type; @@ -94,25 +127,210 @@ namespace ILCompiler.DependencyAnalysis ObjectDataBuilder objData = new ObjectDataBuilder(factory); objData.Alignment = 16; objData.DefinedSymbols.Add(this); + + OutputComponentSize(ref objData); + OutputFlags(factory, ref objData); + OutputBaseSize(ref objData); + OutputRelatedType(factory, ref objData); + OutputVirtualSlotAndInterfaceCount(factory, ref objData); + + objData.EmitInt(_type.GetHashCode()); + + if (_constructed) + { + OutputVirtualSlots(factory, ref objData, _type, _type); + OutputFinalizerMethod(factory, ref objData); + OutputNullableTypeParameter(factory, ref objData); + } + + return objData.ToObjectData(); + } + + public override bool HasConditionalStaticDependencies + { + get + { + // non constructed types don't have vtables + if (!_constructed) + return false; + + // Since the vtable is dependency driven, generate conditional static dependencies for + // all possible vtable entries + foreach (MethodDesc method in _type.GetMethods()) + { + if (method.IsVirtual) + return true; + } + + return false; + } + } + + public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory) + { + if (_type is MetadataType) + { + foreach (MethodDesc decl in VirtualFunctionResolution.EnumAllVirtualSlots((MetadataType)_type)) + { + MethodDesc impl = VirtualFunctionResolution.FindVirtualFunctionTargetMethodOnObjectType(decl, (MetadataType)_type); + if (impl.OwningType == _type && !impl.IsAbstract) + { + yield return new DependencyNodeCore<NodeFactory>.CombinedDependencyListEntry(factory.MethodEntrypoint(impl), factory.VirtualMethodUse(decl), "Virtual method"); + } + } + } + } + + /// <summary> + /// Returns the offset within an EEType of the beginning of VTable entries + /// </summary> + /// <param name="pointerSize">The size of a pointer in bytes in the target architecture</param> + public static int GetVTableOffset(int pointerSize) + { + return 16 + pointerSize; + } + + private void OutputComponentSize(ref ObjectDataBuilder objData) + { if (_type.IsArray) { - objData.EmitShort((short)((ArrayType)_type).ElementType.GetElementSize()); // m_ComponentSize - objData.EmitShort(0x4); // m_flags: IsArray(0x4) + objData.EmitShort((short)((ArrayType)_type).ElementType.GetElementSize()); } else if (_type.IsString) { - objData.EmitShort(2); // m_ComponentSize - objData.EmitShort(0); // m_flags: 0 + objData.EmitShort(2); } else { - objData.EmitShort(0); // m_ComponentSize - objData.EmitShort(0); // m_flags: 0 + objData.EmitShort(0); + } + } + + private void OutputFlags(NodeFactory factory, ref ObjectDataBuilder objData) + { + // Todo: RelatedTypeViaIATFlag when we support cross-module EETypes + // Todo: GenericVarianceFlag when we support variance + // Todo: OptionalFieldsFlag + // Todo: Generic Type Definition EETypes + + UInt16 flags = (UInt16)EETypeKind.CanonicalEEType; + + if (_type.IsArray || _type.IsPointer) + { + flags = (UInt16)EETypeKind.ParameterizedEEType; + } + + if (_type.IsValueType) + { + flags |= (UInt16)EETypeFlags.ValueTypeFlag; + } + + if (_type.HasFinalizer) + { + flags |= (UInt16)EETypeFlags.HasFinalizerFlag; + } + + if (_type is MetadataType && ((MetadataType)_type).ContainsPointers) + { + flags |= (UInt16)EETypeFlags.HasPointersFlag; + } + else if (_type.IsArray) + { + ArrayType arrayType = _type as ArrayType; + if ((arrayType.ElementType.IsValueType && ((DefType)arrayType.ElementType).ContainsPointers) || + !arrayType.ElementType.IsValueType) + { + flags |= (UInt16)EETypeFlags.HasPointersFlag; + } + } + + if (_type.IsInterface) + { + flags |= (UInt16)EETypeFlags.IsInterfaceFlag; + } + + if (_type.HasInstantiation) + { + flags |= (UInt16)EETypeFlags.IsGenericFlag; + } + + int corElementType = 0; + + // The top 5 bits of flags are used to convey enum underlying type, primitive type, or mark the type as being System.Array + if (_type.IsEnum) + { + TypeDesc underlyingType = _type.UnderlyingType; + Debug.Assert(TypeFlags.SByte <= underlyingType.Category && underlyingType.Category <= TypeFlags.UInt64); + corElementType = ComputeRhCorElementType(underlyingType); + } + else if (_type.IsPrimitive) + { + corElementType = ComputeRhCorElementType(_type); + } + else if (_type.IsArray) + { + corElementType = 0x14; // ELEMENT_TYPE_ARRAY + } + + if (corElementType > 0) + { + flags |= (UInt16)(corElementType << (UInt16)EETypeFlags.CorElementTypeShift); } + objData.EmitShort((short)flags); + } + + private int ComputeRhCorElementType(TypeDesc type) + { + Debug.Assert(type.IsPrimitive); + Debug.Assert(type.Category != TypeFlags.Unknown); + + switch (type.Category) + { + case TypeFlags.Void: + return 0x00; + case TypeFlags.Boolean: + return 0x02; + case TypeFlags.Char: + return 0x03; + case TypeFlags.SByte: + return 0x04; + case TypeFlags.Byte: + return 0x05; + case TypeFlags.Int16: + return 0x06; + case TypeFlags.UInt16: + return 0x07; + case TypeFlags.Int32: + return 0x08; + case TypeFlags.UInt32: + return 0x09; + case TypeFlags.Int64: + return 0x0A; + case TypeFlags.UInt64: + return 0x0B; + case TypeFlags.IntPtr: + return 0x18; + case TypeFlags.UIntPtr: + return 0x19; + case TypeFlags.Single: + return 0x0C; + case TypeFlags.Double: + return 0x0D; + default: + break; + } + + Debug.Assert(false, "Primitive type value expected."); + return 0; + } + + private void OutputBaseSize(ref ObjectDataBuilder objData) + { int pointerSize = _type.Context.Target.PointerSize; int minimumObjectSize = pointerSize * 3; int objectSize; + if (_type is MetadataType) { objectSize = pointerSize + @@ -126,12 +344,18 @@ namespace ILCompiler.DependencyAnalysis objectSize += 2 * _type.Context.GetWellKnownType(WellKnownType.Int32).GetElementSize() * rank; } + else if (_type is PointerType) + { + // Object size 0 is a sentinel value in the runtime for parameterized types that means "Pointer Type" + objData.EmitInt(0); + return; + } else throw new NotImplementedException(); - + objectSize = AlignmentHelper.AlignUp(objectSize, pointerSize); objectSize = Math.Max(minimumObjectSize, objectSize); - + if (_type.IsString) { // If this is a string, throw away objectSize we computed so far. Strings are special. @@ -142,89 +366,96 @@ namespace ILCompiler.DependencyAnalysis } objData.EmitInt(objectSize); + } - if (Type.BaseType != null) + private void OutputRelatedType(NodeFactory factory, ref ObjectDataBuilder objData) + { + TypeDesc relatedType = _type.BaseType; + if (_type.IsArray || _type.IsPointer) + { + relatedType = ((ParameterizedType)_type).ParameterType; + } + + if (relatedType != null) { if (_constructed) { - objData.EmitPointerReloc(factory.ConstructedTypeSymbol(Type.BaseType)); + objData.EmitPointerReloc(factory.ConstructedTypeSymbol(relatedType)); } else { - objData.EmitPointerReloc(factory.NecessaryTypeSymbol(Type.BaseType)); + objData.EmitPointerReloc(factory.NecessaryTypeSymbol(relatedType)); } } else { objData.EmitZeroPointer(); } - - if (_constructed) - { - OutputVirtualSlots(ref objData, _type, _type, factory); - } - - return objData.ToObjectData(); } - public override bool HasConditionalStaticDependencies + private void OutputVirtualSlotAndInterfaceCount(NodeFactory factory, ref ObjectDataBuilder objData) { - get - { - // non constructed types don't have vtables - if (!_constructed) - return false; + int virtualSlotCount = 0; + TypeDesc currentTypeSlice = _type; - // Since the vtable is dependency driven, generate conditional static dependencies for - // all possible vtable entries - foreach (MethodDesc method in _type.GetMethods()) + while (currentTypeSlice != null) + { + List<MethodDesc> virtualSlots; + factory.VirtualSlots.TryGetValue(currentTypeSlice, out virtualSlots); + if (virtualSlots != null) { - if (method.IsVirtual) - return true; + virtualSlotCount += virtualSlots.Count; } - return false; + currentTypeSlice = currentTypeSlice.BaseType; } - } + + objData.EmitShort(checked((short)virtualSlotCount)); - public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory) - { - if (_type is MetadataType) - { - foreach (MethodDesc decl in VirtualFunctionResolution.EnumAllVirtualSlots((MetadataType)_type)) - { - MethodDesc impl = VirtualFunctionResolution.FindVirtualFunctionTargetMethodOnObjectType(decl, (MetadataType)_type); - if (impl.OwningType == _type && !impl.IsAbstract) - { - yield return new DependencyNodeCore<NodeFactory>.CombinedDependencyListEntry(factory.MethodEntrypoint(impl), factory.VirtualMethodUse(decl), "Virtual method"); - } - } - } + // Todo: Number of slots of EEInterfaceInfo when we add interface support + objData.EmitShort(0); } - private void OutputVirtualSlots(ref ObjectDataBuilder objData, TypeDesc implType, TypeDesc declType, NodeFactory context) + private void OutputVirtualSlots(NodeFactory factory, ref ObjectDataBuilder objData, TypeDesc implType, TypeDesc declType) { var baseType = declType.BaseType; if (baseType != null) - OutputVirtualSlots(ref objData, implType, baseType, context); + OutputVirtualSlots(factory, ref objData, implType, baseType); List<MethodDesc> virtualSlots; - context.VirtualSlots.TryGetValue(declType, out virtualSlots); + factory.VirtualSlots.TryGetValue(declType, out virtualSlots); if (virtualSlots != null) { for (int i = 0; i < virtualSlots.Count; i++) { MethodDesc declMethod = virtualSlots[i]; - MethodDesc implMethod = VirtualFunctionResolution.FindVirtualFunctionTargetMethodOnObjectType(declMethod, implType.GetClosestMetadataType()); if (!implMethod.IsAbstract) - objData.EmitPointerReloc(context.MethodEntrypoint(implMethod)); + objData.EmitPointerReloc(factory.MethodEntrypoint(implMethod)); else objData.EmitZeroPointer(); } } } + + private void OutputFinalizerMethod(NodeFactory factory, ref ObjectDataBuilder objData) + { + MethodDesc finalizerMethod = _type.GetFinalizer(); + + if (finalizerMethod != null) + { + objData.EmitPointerReloc(factory.MethodEntrypoint(finalizerMethod)); + } + } + + private void OutputNullableTypeParameter(NodeFactory factory, ref ObjectDataBuilder objData) + { + if (_type.IsNullable) + { + objData.EmitPointerReloc(factory.NecessaryTypeSymbol(_type.Instantiation[0])); + } + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs index 73a1e9e56..c50307fd2 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs @@ -58,9 +58,9 @@ namespace ILCompiler.DependencyAnalysis break; } } - + Debug.Assert(methodSlot != -1); - AddrMode jmpAddrMode = new AddrMode(encoder.TargetRegister.Result, null, 16 + (baseSlots + methodSlot) * factory.Target.PointerSize, 0, AddrModeSize.Int64); + AddrMode jmpAddrMode = new AddrMode(encoder.TargetRegister.Result, null, EETypeNode.GetVTableOffset(factory.Target.PointerSize) + (baseSlots + methodSlot) * factory.Target.PointerSize, 0, AddrModeSize.Int64); encoder.EmitJmpToAddrMode(ref jmpAddrMode); } break; diff --git a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj index 8d28d0664..e8f4c1ef4 100644 --- a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj +++ b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj @@ -83,6 +83,9 @@ <Compile Include="..\..\Common\src\System\Collections\Generic\ArrayBuilder.cs"> <Link>Common\ArrayBuilder.cs</Link> </Compile> + <Compile Include="..\..\Common\src\Internal\Runtime\EETypeFlags.cs" > + <Link>Common\EETypeFlags.cs</Link> + </Compile> </ItemGroup> <ItemGroup> <Compile Include="..\..\Common\src\TypeSystem\IL\EcmaMethodIL.cs"> diff --git a/src/Native/Runtime/portable.cpp b/src/Native/Runtime/portable.cpp index 0d28b5263..86135e0c6 100644 --- a/src/Native/Runtime/portable.cpp +++ b/src/Native/Runtime/portable.cpp @@ -74,7 +74,7 @@ COOP_PINVOKE_HELPER(void, RhpReversePInvokeReturn, (ReversePInvokeFrame* pFrame) // runtimeexports.cs -- @TODO: use C# implementation COOP_PINVOKE_HELPER(Object *, RhNewObject, (EEType* pEEType)) { - ASSERT_MSG(!pEEType->RequiresAlign8() && !pEEType->HasFinalizer(), "NYI"); + ASSERT_MSG(!pEEType->RequiresAlign8(), "NYI"); Thread * pCurThread = ThreadStore::GetCurrentThread(); alloc_context * acontext = pCurThread->GetAllocContext(); diff --git a/src/Runtime.Base/src/Runtime.Base.csproj b/src/Runtime.Base/src/Runtime.Base.csproj index 1588de2ae..768550921 100644 --- a/src/Runtime.Base/src/Runtime.Base.csproj +++ b/src/Runtime.Base/src/Runtime.Base.csproj @@ -137,6 +137,11 @@ <Compile Include="RhBaseName.cs" /> </ItemGroup> <ItemGroup> + <Compile Include="..\..\Common\src\Internal\Runtime\EETypeFlags.cs" > + <Link>Common\EETypeFlags.cs</Link> + </Compile> + </ItemGroup> + <ItemGroup> <Compile Include="$(BaseIntermediateOutputPath)\Native\$(BinDirOSGroup).$(BinDirPlatform).$(BinDirConfiguration)\Runtime\Full\AsmOffsets.cs" /> </ItemGroup> diff --git a/src/Runtime.Base/src/System/Runtime/EEType.cs b/src/Runtime.Base/src/System/Runtime/EEType.cs index 066c83ce8..61e60cb65 100644 --- a/src/Runtime.Base/src/System/Runtime/EEType.cs +++ b/src/Runtime.Base/src/System/Runtime/EEType.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using Internal.Runtime; using System.Diagnostics; using System.Runtime.InteropServices; @@ -45,52 +46,6 @@ namespace System.Runtime #pragma warning restore - private enum Flags : ushort - { - // There are three kinds of EETypes, the fourth state is currently unused and disallowed. - EETypeKindMask = 0x0003, - - // This flag is set when m_RelatedType is in a different module. In that case, _pRelatedType - // actually points to an IAT slot in this module, which then points to the desired EEType in the - // other module. In other words, there is an extra indirection through m_RelatedType to get to - // the related type in the other module. When this flag is set, it is expected that you use the - // "_ppXxxxViaIAT" member of the RelatedTypeUnion for the particular related type you're - // accessing. - RelatedTypeViaIATFlag = 0x0004, - - // This EEType represents a value type - ValueTypeFlag = 0x0008, - - // This EEType represents a type which requires finalization - HasFinalizerFlag = 0x0010, - - // This type contain gc pointers - HasPointersFlag = 0x0020, - - // This type instance was allocated at runtime (rather than being embedded in a module image) - RuntimeAllocatedFlag = 0x0040, - - // This type is generic and one or more of it's type parameters is co- or contra-variant. This - // only applies to interface and delegate types. - GenericVarianceFlag = 0x0080, - - // This type has optional fields present. - OptionalFieldsFlag = 0x0100, - - // This EEType represents an interface. - IsInterfaceFlag = 0x0200, - - // This type is generic. - IsGenericFlag = 0x0400, - - // We are storing a CorElementType in the upper bits for unboxing enums - CorElementTypeMask = 0xf800, - CorElementTypeShift = 11, - - // Single mark to check TypeKind and two flags. When non-zero, casting is more complicated - ComplexCastingMask = EETypeKindMask | RelatedTypeViaIATFlag | GenericVarianceFlag - }; - // These are flag values that are rarely set for types. If any of them are set then an optional field will // be associated with the EEType to represent them. private enum RareFlags @@ -125,20 +80,12 @@ namespace System.Runtime // This EEType represents a structure that is an HFA IsHFAFlag = 0x00000100, } - - private enum Kinds : ushort - { - CanonicalEEType = 0x0000, - ClonedEEType = 0x0001, - ParameterizedEEType = 0x0002, // parameter eetype, currently either pointer or single dimensional array type - GenericTypeDefEEType = 0x0003, // Generic type definition EEType - } - - private Kinds Kind + + private EETypeKind Kind { get { - return (Kinds)(_usFlags & (ushort)Flags.EETypeKindMask); + return (EETypeKind)(_usFlags & (ushort)EETypeFlags.EETypeKindMask); } } @@ -178,7 +125,7 @@ namespace System.Runtime { get { - return ((_usFlags & (ushort)Flags.HasFinalizerFlag) != 0); + return ((_usFlags & (ushort)EETypeFlags.HasFinalizerFlag) != 0); } } @@ -186,7 +133,7 @@ namespace System.Runtime { get { - return ((_usFlags & (ushort)Flags.IsInterfaceFlag) != 0); + return ((_usFlags & (ushort)EETypeFlags.IsInterfaceFlag) != 0); } } @@ -194,7 +141,7 @@ namespace System.Runtime { get { - return Kind == Kinds.CanonicalEEType; + return Kind == EETypeKind.CanonicalEEType; } } @@ -202,7 +149,7 @@ namespace System.Runtime { get { - return Kind == Kinds.ClonedEEType; + return Kind == EETypeKind.ClonedEEType; } } @@ -210,7 +157,7 @@ namespace System.Runtime { get { - return ((_usFlags & (UInt16)Flags.HasPointersFlag) != 0); + return ((_usFlags & (UInt16)EETypeFlags.HasPointersFlag) != 0); } } @@ -218,7 +165,7 @@ namespace System.Runtime { get { - return ((_usFlags & (UInt16)Flags.OptionalFieldsFlag) != 0); + return ((_usFlags & (UInt16)EETypeFlags.OptionalFieldsFlag) != 0); } } @@ -236,7 +183,7 @@ namespace System.Runtime { get { - return Kind == Kinds.ParameterizedEEType; + return Kind == EETypeKind.ParameterizedEEType; } } @@ -257,7 +204,7 @@ namespace System.Runtime { get { - return ((_usFlags & (UInt16)Flags.RelatedTypeViaIATFlag) != 0); + return ((_usFlags & (UInt16)EETypeFlags.RelatedTypeViaIATFlag) != 0); } } @@ -265,7 +212,7 @@ namespace System.Runtime { get { - return ((_usFlags & (UInt16)Flags.ValueTypeFlag) != 0); + return ((_usFlags & (UInt16)EETypeFlags.ValueTypeFlag) != 0); } } @@ -281,7 +228,7 @@ namespace System.Runtime { get { - return ((_usFlags & (UInt16)Flags.RuntimeAllocatedFlag) != 0); + return ((_usFlags & (UInt16)EETypeFlags.RuntimeAllocatedFlag) != 0); } } @@ -289,7 +236,7 @@ namespace System.Runtime { get { - return (_usFlags & (UInt16)Flags.IsGenericFlag) != 0; + return (_usFlags & (UInt16)EETypeFlags.IsGenericFlag) != 0; } } @@ -299,7 +246,7 @@ namespace System.Runtime { get { - return ((_usFlags & (UInt16)Flags.GenericVarianceFlag) != 0); + return ((_usFlags & (UInt16)EETypeFlags.GenericVarianceFlag) != 0); } } @@ -461,7 +408,7 @@ namespace System.Runtime Debug.Assert(!IsParameterizedType, "array type not supported in NonArrayBaseType"); Debug.Assert(!IsCloned, "cloned type not supported in NonClonedNonArrayBaseType"); Debug.Assert(IsCanonical, "we expect canonical types here"); - _usFlags &= (ushort)~Flags.RelatedTypeViaIATFlag; + _usFlags &= (ushort)~EETypeFlags.RelatedTypeViaIATFlag; _relatedType._pBaseType = value; } } @@ -533,7 +480,7 @@ namespace System.Runtime { get { - return (TypeCast.CorElementType)((_usFlags & (ushort)Flags.CorElementTypeMask) >> (ushort)Flags.CorElementTypeShift); + return (TypeCast.CorElementType)((_usFlags & (ushort)EETypeFlags.CorElementTypeMask) >> (ushort)EETypeFlags.CorElementTypeShift); } } @@ -596,7 +543,7 @@ namespace System.Runtime { get { - return Kind == Kinds.GenericTypeDefEEType; + return Kind == EETypeKind.GenericTypeDefEEType; } } @@ -604,7 +551,7 @@ namespace System.Runtime { get { - if (Kind != Kinds.ParameterizedEEType) + if (Kind != EETypeKind.ParameterizedEEType) return false; return ParameterizedTypeShape == 0; // See comment above ParameterizedTypeShape for details. } @@ -632,7 +579,7 @@ namespace System.Runtime /// </summary> internal bool SimpleCasting() { - return (_usFlags & (ushort)Flags.ComplexCastingMask) == (ushort)Kinds.CanonicalEEType; + return (_usFlags & (ushort)EETypeFlags.ComplexCastingMask) == (ushort)EETypeKind.CanonicalEEType; } /// <summary> @@ -652,7 +599,7 @@ namespace System.Runtime /// </summary> static internal bool BothSimpleCasting(EEType* pThis, EEType* pOther) { - return ((pThis->_usFlags | pOther->_usFlags) & (ushort)Flags.ComplexCastingMask) == (ushort)Kinds.CanonicalEEType; + return ((pThis->_usFlags | pOther->_usFlags) & (ushort)EETypeFlags.ComplexCastingMask) == (ushort)EETypeKind.CanonicalEEType; } } |