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/ILCompiler.Compiler | |
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/ILCompiler.Compiler')
4 files changed, 99 insertions, 145 deletions
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs index 8778a7587..a06978347 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs @@ -217,127 +217,20 @@ namespace ILCompiler.DependencyAnalysis private void OutputFlags(NodeFactory factory, ref ObjectDataBuilder objData) { + UInt16 flags = EETypeBuilderHelpers.ComputeFlags(_type); + // Todo: RelatedTypeViaIATFlag when we support cross-module EETypes // Todo: GenericVarianceFlag when we support variance // 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; - } - if (_optionalFieldsBuilder.IsAtLeastOneFieldUsed()) { flags |= (UInt16)EETypeFlags.OptionalFieldsFlag; } - 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 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; - } - private static bool ComputeRequiresAlign8(TypeDesc type) { if (type.Context.Target.Architecture != TargetArchitecture.ARM) @@ -627,7 +520,7 @@ namespace ILCompiler.DependencyAnalysis Debug.Assert(defType != null); uint valueTypeFieldPadding = checked((uint)(defType.InstanceByteCount - defType.InstanceByteCountUnaligned)); - uint valueTypeFieldPaddingEncoded = EEType.ComputeValueTypeFieldPaddingFieldValue(valueTypeFieldPadding, (uint)defType.InstanceFieldAlignment); + uint valueTypeFieldPaddingEncoded = EETypeBuilderHelpers.ComputeValueTypeFieldPaddingFieldValue(valueTypeFieldPadding, (uint)defType.InstanceFieldAlignment); if (valueTypeFieldPaddingEncoded != 0) { diff --git a/src/ILCompiler.Compiler/src/CppCodeGen/CppWriter.cs b/src/ILCompiler.Compiler/src/CppCodeGen/CppWriter.cs index 4b3cb7b14..2808f29c9 100644 --- a/src/ILCompiler.Compiler/src/CppCodeGen/CppWriter.cs +++ b/src/ILCompiler.Compiler/src/CppCodeGen/CppWriter.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; +using System.Globalization; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -13,6 +14,8 @@ using ILCompiler.DependencyAnalysisFramework; using Internal.TypeSystem; using Internal.TypeSystem.Ecma; +using Internal.Runtime; + using Internal.IL; using ILCompiler.DependencyAnalysis; @@ -612,30 +615,9 @@ namespace ILCompiler.CppCodeGen { Out.WriteLine(GetCodeForDelegate(t)); } - foreach (var field in t.GetFields()) - { - if (field.IsStatic) - { - TypeDesc fieldType = GetFieldTypeOrPlaceholder(field); - StringBuilder builder; - if (!fieldType.IsValueType) - { - _gcStatics.Append(GetCppSignatureTypeName(fieldType)); - builder = _gcStatics; - } - else - { - // TODO: Valuetype statics with GC references - _statics.Append(GetCppSignatureTypeName(fieldType)); - builder = _statics; - } - builder.AppendLine(" " + GetCppStaticFieldName(field) + ";"); - } - else - { - Out.WriteLine(GetCppSignatureTypeName(GetFieldTypeOrPlaceholder(field)) + " " + GetCppFieldName(field) + ";"); - } - } + + OutputTypeFields(t); + if (t.HasStaticConstructor) { _statics.AppendLine("bool __cctor_" + GetCppTypeName(t).Replace("::", "__") + ";"); @@ -664,6 +646,67 @@ namespace ILCompiler.CppCodeGen Out.WriteLine(); } + private void OutputTypeFields(TypeDesc t) + { + bool explicitLayout = false; + ClassLayoutMetadata classLayoutMetadata = default(ClassLayoutMetadata); + + if (t.IsValueType) + { + MetadataType metadataType = (MetadataType)t; + if (metadataType.IsExplicitLayout) + { + explicitLayout = true; + classLayoutMetadata = metadataType.GetClassLayout(); + } + } + + int instanceFieldIndex = 0; + + if (explicitLayout) + Out.WriteLine("union {"); + + foreach (var field in t.GetFields()) + { + if (field.IsStatic) + { + TypeDesc fieldType = GetFieldTypeOrPlaceholder(field); + StringBuilder builder; + if (!fieldType.IsValueType) + { + _gcStatics.Append(GetCppSignatureTypeName(fieldType)); + builder = _gcStatics; + } + else + { + // TODO: Valuetype statics with GC references + _statics.Append(GetCppSignatureTypeName(fieldType)); + builder = _statics; + } + builder.AppendLine(" " + GetCppStaticFieldName(field) + ";"); + } + else + { + if (explicitLayout) + { + Out.WriteLine("struct {"); + int offset = classLayoutMetadata.Offsets[instanceFieldIndex].Offset; + if (offset > 0) + Out.WriteLine("char __pad" + instanceFieldIndex + "[" + offset + "];"); + } + Out.WriteLine(GetCppSignatureTypeName(GetFieldTypeOrPlaceholder(field)) + " " + GetCppFieldName(field) + ";"); + if (explicitLayout) + { + Out.WriteLine("};"); + } + instanceFieldIndex++; + } + } + + if (explicitLayout) + Out.WriteLine("};"); + } + private void OutputMethod(MethodDesc m) { Out.WriteLine(GetCppMethodDeclaration(m, false)); @@ -803,6 +846,17 @@ namespace ILCompiler.CppCodeGen t = t.BaseType; } + UInt16 flags = 0; + try + { + flags = EETypeBuilderHelpers.ComputeFlags(type); + } + catch + { + // TODO: Handling of missing dependencies + flags = 0; + } + sb.Append("MethodTable * "); sb.Append(GetCppTypeName(type)); sb.AppendLine("::__getMethodTable() {"); @@ -821,30 +875,37 @@ namespace ILCompiler.CppCodeGen if (type.IsString) { // String has non-standard layout - // component size = 2, flags = 0, base size = 2 ptrs + dword + first char - sb.Append("{ sizeof(uint16_t), 0, 2 * sizeof(void*) + sizeof(int32_t) + 2, "); + sb.Append("{ sizeof(uint16_t), 0x"); // EEType::_usComponentSize + sb.Append(flags.ToString("x4", CultureInfo.InvariantCulture)); // EEType::_usFlags + sb.Append(", 2 * sizeof(void*) + sizeof(int32_t) + 2, "); // EEType::_uBaseSize } else if (type.IsArray && ((ArrayType)type).Rank == 1) { sb.Append("{ sizeof("); - sb.Append(GetCppSignatureTypeName(((ArrayType)type).ElementType)); // component size - sb.Append("), 4 /* MTFlag_IsArray */, 3 * sizeof(void*), "); // flags, baseSize + sb.Append(GetCppSignatureTypeName(((ArrayType)type).ElementType)); // EEType::_usComponentSize + sb.Append("), 0x"); + sb.Append(flags.ToString("x4", CultureInfo.InvariantCulture)); // EEType::_usFlags + sb.Append(", 3 * sizeof(void*), "); // EEType::_uBaseSize } else if (type.IsArray) { Debug.Assert(((ArrayType)type).Rank > 1); sb.Append("{ sizeof("); - sb.Append(GetCppSignatureTypeName(((ArrayType)type).ElementType)); // component size - sb.Append("), 4 /* MTFlag_IsArray */, 3 * sizeof(void*) + "); // flags, baseSize + sb.Append(GetCppSignatureTypeName(((ArrayType)type).ElementType)); // EEType::_usComponentSize + sb.Append("), 0x"); + sb.Append(flags.ToString("x4", CultureInfo.InvariantCulture)); // EEType::_usFlags + sb.Append(", 3 * sizeof(void*) + "); // EEType::_uBaseSize sb.Append(((ArrayType)type).Rank.ToString()); sb.Append("* sizeof(int32_t) * 2, "); } else { // sizeof(void*) == size of object header - sb.Append("{ 0, 0, AlignBaseSize(sizeof(void*)+sizeof("); // component size, flags, baseSize + sb.Append("{ 0, 0x"); // EEType::_usComponentSize + sb.Append(flags.ToString("x", CultureInfo.InvariantCulture)); // EEType::_usFlags + sb.Append(", AlignBaseSize(sizeof(void*)+sizeof("); // EEType::_uBaseSize sb.Append(GetCppTypeName(type)); sb.Append(")), "); } diff --git a/src/ILCompiler.Compiler/src/CppCodeGen/ILToCppImporter.cs b/src/ILCompiler.Compiler/src/CppCodeGen/ILToCppImporter.cs index c10e3629e..4a864fe6b 100644 --- a/src/ILCompiler.Compiler/src/CppCodeGen/ILToCppImporter.cs +++ b/src/ILCompiler.Compiler/src/CppCodeGen/ILToCppImporter.cs @@ -946,7 +946,7 @@ namespace Internal.IL thisArgument = thisArgument.MakeByRefType(); } - string typeDefName = "__calli__" + token.ToString("X8", CultureInfo.InvariantCulture); + string typeDefName = "__calli__" + token.ToString("x8", CultureInfo.InvariantCulture); _writer.AppendSignatureTypeDef(_builder, typeDefName, methodSignature, thisArgument); TypeDesc retType = methodSignature.ReturnType; @@ -1016,14 +1016,14 @@ namespace Internal.IL if (value == Int64.MinValue) val = "(int64_t)(0x8000000000000000" + (_msvc ? "i64" : "LL") + ")"; else - val = value.ToString() + (_msvc ? "i64" : "LL"); + val = value.ToString(CultureInfo.InvariantCulture) + (_msvc ? "i64" : "LL"); } else { if (value == Int32.MinValue) val = "(int32_t)(0x80000000)"; else - val = ((int)value).ToString(); + val = ((int)value).ToString(CultureInfo.InvariantCulture); } Push(kind, new Value(val)); diff --git a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj index d0091a8f7..43af2acab 100644 --- a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj +++ b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj @@ -89,7 +89,7 @@ <Compile Include="..\..\Common\src\Internal\Runtime\EETypeOptionalFieldsBuilder.cs"> <Link>Common\EETypeOptionalFieldsBuilder.cs</Link> </Compile> - <Compile Include="..\..\Common\src\Internal\Runtime\EEType.cs"> + <Compile Include="..\..\Common\src\Internal\Runtime\EETypeBuilderHelpers.cs"> <Link>Common\EEType.cs</Link> </Compile> <Compile Include="..\..\Common\src\Internal\NativeFormat\NativeFormatWriter.Primitives.cs"> |