diff options
author | Jan Kotas <jkotas@microsoft.com> | 2015-12-01 10:12:23 +0300 |
---|---|---|
committer | Jan Kotas <jkotas@microsoft.com> | 2015-12-22 02:57:17 +0300 |
commit | 0fd800466452d74c011f602c79bca1c8b318ed18 (patch) | |
tree | aae76724c51da726baa946621a0ca8e3988842fd /src/Common | |
parent | d4023eecf7fcc7306802f3d0363ea96837579217 (diff) |
Remove CoreRT TODOs in Buffer.CopyBlock and Array.Copy
- Respect explicit layout and emit proper EEType flags in CppCodeGen - required for "Hello world" with TODOs removed
- Reduce dependencies of autogenerated files for CppCodeGen
Diffstat (limited to 'src/Common')
-rw-r--r-- | src/Common/src/Internal/Runtime/EEType.cs | 56 | ||||
-rw-r--r-- | src/Common/src/Internal/Runtime/EETypeBuilderHelpers.cs | 172 |
2 files changed, 172 insertions, 56 deletions
diff --git a/src/Common/src/Internal/Runtime/EEType.cs b/src/Common/src/Internal/Runtime/EEType.cs deleted file mode 100644 index f7c7bc4ee..000000000 --- a/src/Common/src/Internal/Runtime/EEType.cs +++ /dev/null @@ -1,56 +0,0 @@ -// 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.Diagnostics; - -namespace Internal.Runtime -{ - internal partial class EEType - { - // These masks and paddings have been chosen so that the ValueTypePadding field can always fit in a byte of data - // if the alignment is 8 bytes or less. If the alignment is higher then there may be a need for more bits to hold - // the rest of the padding data. - // If paddings of greater than 7 bytes are necessary, then the high bits of the field represent that padding - private const UInt32 ValueTypePaddingLowMask = 0x7; - private const UInt32 ValueTypePaddingHighMask = 0xFFFFFF00; - private const UInt32 ValueTypePaddingMax = 0x07FFFFFF; - private const int ValueTypePaddingHighShift = 8; - private const UInt32 ValueTypePaddingAlignmentMask = 0xF8; - private const int ValueTypePaddingAlignmentShift = 3; - - /// <summary> - /// Compute the encoded value type padding and alignment that are stored as optional fields on an - /// <c>EEType</c>. This padding as added to naturally align value types when laid out as fields - /// of objects on the GCHeap. The amount of padding is recorded to allow unboxing to locals / - /// arrays of value types which don't need it. - /// </summary> - internal static UInt32 ComputeValueTypeFieldPaddingFieldValue(UInt32 padding, UInt32 alignment) - { - // For the default case, return 0 - if ((padding == 0) && (alignment == IntPtr.Size)) - return 0; - - UInt32 alignmentLog2 = 0; - Debug.Assert(alignment != 0); - - while ((alignment & 1) == 0) - { - alignmentLog2++; - alignment = alignment >> 1; - } - Debug.Assert(alignment == 1); - - Debug.Assert(ValueTypePaddingMax >= padding); - - // Our alignment values here are adjusted by one to allow for a default of 0 (which represents pointer alignment) - alignmentLog2++; - - UInt32 paddingLowBits = padding & ValueTypePaddingLowMask; - UInt32 paddingHighBits = ((padding & ~ValueTypePaddingLowMask) >> ValueTypePaddingAlignmentShift) << ValueTypePaddingHighShift; - UInt32 alignmentLog2Bits = alignmentLog2 << ValueTypePaddingAlignmentShift; - Debug.Assert((alignmentLog2Bits & ~ValueTypePaddingAlignmentMask) == 0); - return paddingLowBits | paddingHighBits | alignmentLog2Bits; - } - } -}
\ No newline at end of file diff --git a/src/Common/src/Internal/Runtime/EETypeBuilderHelpers.cs b/src/Common/src/Internal/Runtime/EETypeBuilderHelpers.cs new file mode 100644 index 000000000..178f90fa0 --- /dev/null +++ b/src/Common/src/Internal/Runtime/EETypeBuilderHelpers.cs @@ -0,0 +1,172 @@ +// 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.Diagnostics; + +using Internal.TypeSystem; + +namespace Internal.Runtime +{ + internal static class EETypeBuilderHelpers + { + private static 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; + } + + public static UInt16 ComputeFlags(TypeDesc type) + { + 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); + } + + return flags; + } + + // These masks and paddings have been chosen so that the ValueTypePadding field can always fit in a byte of data + // if the alignment is 8 bytes or less. If the alignment is higher then there may be a need for more bits to hold + // the rest of the padding data. + // If paddings of greater than 7 bytes are necessary, then the high bits of the field represent that padding + private const UInt32 ValueTypePaddingLowMask = 0x7; + private const UInt32 ValueTypePaddingHighMask = 0xFFFFFF00; + private const UInt32 ValueTypePaddingMax = 0x07FFFFFF; + private const int ValueTypePaddingHighShift = 8; + private const UInt32 ValueTypePaddingAlignmentMask = 0xF8; + private const int ValueTypePaddingAlignmentShift = 3; + + /// <summary> + /// Compute the encoded value type padding and alignment that are stored as optional fields on an + /// <c>EEType</c>. This padding as added to naturally align value types when laid out as fields + /// of objects on the GCHeap. The amount of padding is recorded to allow unboxing to locals / + /// arrays of value types which don't need it. + /// </summary> + internal static UInt32 ComputeValueTypeFieldPaddingFieldValue(UInt32 padding, UInt32 alignment) + { + // For the default case, return 0 + if ((padding == 0) && (alignment == IntPtr.Size)) + return 0; + + UInt32 alignmentLog2 = 0; + Debug.Assert(alignment != 0); + + while ((alignment & 1) == 0) + { + alignmentLog2++; + alignment = alignment >> 1; + } + Debug.Assert(alignment == 1); + + Debug.Assert(ValueTypePaddingMax >= padding); + + // Our alignment values here are adjusted by one to allow for a default of 0 (which represents pointer alignment) + alignmentLog2++; + + UInt32 paddingLowBits = padding & ValueTypePaddingLowMask; + UInt32 paddingHighBits = ((padding & ~ValueTypePaddingLowMask) >> ValueTypePaddingAlignmentShift) << ValueTypePaddingHighShift; + UInt32 alignmentLog2Bits = alignmentLog2 << ValueTypePaddingAlignmentShift; + Debug.Assert((alignmentLog2Bits & ~ValueTypePaddingAlignmentMask) == 0); + return paddingLowBits | paddingHighBits | alignmentLog2Bits; + } + } +}
\ No newline at end of file |