Port the managed type system unit tests and wire them up to build.cmd -test so they run if the clr.tools subset is included in compilation.
Port enough USG layout and `Array<T>` support so we can keep their respective tests running in this repo.
$(CoreClrProjectRoot)src\tools\dotnet-pgo\dotnet-pgo.csproj;
$(CoreClrProjectRoot)src\tools\r2rtest\R2RTest.csproj" Category="clr" BuildInParallel="true" />
<ProjectToBuild Include="$(CoreClrProjectRoot)src\tools\aot\crossgen2\crossgen2.csproj" Category="clr" />
+ <ProjectToBuild Include="$(CoreClrProjectRoot)src\tools\aot\ILCompiler.TypeSystem.ReadyToRun.Tests\ILCompiler.TypeSystem.ReadyToRun.Tests.csproj" Test="true" Category="clr" Condition="'$(__DistroRid)' != 'linux-musl-x64'"/>
</ItemGroup>
<ItemGroup Condition="$(_subset.Contains('+clr.packages+'))">
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Debug = System.Diagnostics.Debug;
+
+namespace Internal.TypeSystem
+{
+ /// <summary>
+ /// RuntimeInterfaces algorithm for for array types which are similar to a generic type
+ /// </summary>
+ public sealed class ArrayOfTRuntimeInterfacesAlgorithm : RuntimeInterfacesAlgorithm
+ {
+ /// <summary>
+ /// Open type to instantiate to get the interfaces associated with an array.
+ /// </summary>
+ private MetadataType _arrayOfTType;
+
+ /// <summary>
+ /// RuntimeInterfaces algorithm for for array types which are similar to a generic type
+ /// </summary>
+ /// <param name="arrayOfTType">Open type to instantiate to get the interfaces associated with an array.</param>
+ public ArrayOfTRuntimeInterfacesAlgorithm(MetadataType arrayOfTType)
+ {
+ _arrayOfTType = arrayOfTType;
+ Debug.Assert(!(arrayOfTType is InstantiatedType));
+ }
+
+ public override DefType[] ComputeRuntimeInterfaces(TypeDesc _type)
+ {
+ ArrayType arrayType = (ArrayType)_type;
+ Debug.Assert(arrayType.IsSzArray);
+ TypeDesc arrayOfTInstantiation = _arrayOfTType.MakeInstantiatedType(arrayType.ElementType);
+
+ return arrayOfTInstantiation.RuntimeInterfaces;
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace Internal.TypeSystem
+{
+ public static class ConstructedTypeRewritingHelpers
+ {
+ /// <summary>
+ /// Determine if the construction of a type contains one of a given set of types. This is a deep
+ /// scan. For instance, given type MyType<SomeGeneric<int[]>>, and a set of typesToFind
+ /// that includes int, this function will return true. Does not detect the open generics that may be
+ /// instantiated over in this type. IsConstructedOverType would return false if only passed MyType,
+ /// or SomeGeneric for the above examplt.
+ /// </summary>
+ /// <param name="type">type to examine</param>
+ /// <param name="typesToFind">types to search for in the construction of type</param>
+ /// <returns>true if a type in typesToFind is found</returns>
+ public static bool IsConstructedOverType(this TypeDesc type, TypeDesc[] typesToFind)
+ {
+ int directDiscoveryIndex = Array.IndexOf(typesToFind, type);
+
+ if (directDiscoveryIndex != -1)
+ return true;
+
+ if (type.HasInstantiation)
+ {
+ for (int instantiationIndex = 0; instantiationIndex < type.Instantiation.Length; instantiationIndex++)
+ {
+ if (type.Instantiation[instantiationIndex].IsConstructedOverType(typesToFind))
+ {
+ return true;
+ }
+ }
+ }
+ else if (type.IsParameterizedType)
+ {
+ ParameterizedType parameterizedType = (ParameterizedType)type;
+ return parameterizedType.ParameterType.IsConstructedOverType(typesToFind);
+ }
+ else if (type.IsFunctionPointer)
+ {
+ MethodSignature functionPointerSignature = ((FunctionPointerType)type).Signature;
+ if (functionPointerSignature.ReturnType.IsConstructedOverType(typesToFind))
+ return true;
+
+ for (int paramIndex = 0; paramIndex < functionPointerSignature.Length; paramIndex++)
+ {
+ if (functionPointerSignature[paramIndex].IsConstructedOverType(typesToFind))
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Replace some of the types in a type's construction with a new set of types. This function does not
+ /// support any situation where there is an instantiated generic that is not represented by an
+ /// InstantiatedType. Does not replace the open generics that may be instantiated over in this type.
+ ///
+ /// For instance, Given MyType<object, int[]>,
+ /// an array of types to replace such as {int,object}, and
+ /// an array of replacement types such as {string,__Canon}.
+ /// The result shall be MyType<__Canon, string[]>
+ ///
+ /// This function cannot be used to replace MyType in the above example.
+ /// </summary>
+ public static TypeDesc ReplaceTypesInConstructionOfType(this TypeDesc type, TypeDesc[] typesToReplace, TypeDesc[] replacementTypes)
+ {
+ int directReplacementIndex = Array.IndexOf(typesToReplace, type);
+
+ if (directReplacementIndex != -1)
+ return replacementTypes[directReplacementIndex];
+
+ if (type.HasInstantiation)
+ {
+ TypeDesc[] newInstantiation = null;
+ Debug.Assert(type is InstantiatedType);
+ int instantiationIndex = 0;
+ for (; instantiationIndex < type.Instantiation.Length; instantiationIndex++)
+ {
+ TypeDesc oldType = type.Instantiation[instantiationIndex];
+ TypeDesc newType = oldType.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes);
+ if ((oldType != newType) || (newInstantiation != null))
+ {
+ if (newInstantiation == null)
+ {
+ newInstantiation = new TypeDesc[type.Instantiation.Length];
+ for (int i = 0; i < instantiationIndex; i++)
+ newInstantiation[i] = type.Instantiation[i];
+ }
+ newInstantiation[instantiationIndex] = newType;
+ }
+ }
+ if (newInstantiation != null)
+ return type.Context.GetInstantiatedType((MetadataType)type.GetTypeDefinition(), new Instantiation(newInstantiation));
+ }
+ else if (type.IsParameterizedType)
+ {
+ ParameterizedType parameterizedType = (ParameterizedType)type;
+ TypeDesc oldParameter = parameterizedType.ParameterType;
+ TypeDesc newParameter = oldParameter.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes);
+ if (oldParameter != newParameter)
+ {
+ if (type.IsArray)
+ {
+ ArrayType arrayType = (ArrayType)type;
+ if (arrayType.IsSzArray)
+ return type.Context.GetArrayType(newParameter);
+ else
+ return type.Context.GetArrayType(newParameter, arrayType.Rank);
+ }
+ else if (type.IsPointer)
+ {
+ return type.Context.GetPointerType(newParameter);
+ }
+ else if (type.IsByRef)
+ {
+ return type.Context.GetByRefType(newParameter);
+ }
+ Debug.Fail("Unknown form of type");
+ }
+ }
+ else if (type.IsFunctionPointer)
+ {
+ MethodSignature oldSig = ((FunctionPointerType)type).Signature;
+ MethodSignatureBuilder sigBuilder = new MethodSignatureBuilder(oldSig);
+ sigBuilder.ReturnType = oldSig.ReturnType.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes);
+ for (int paramIndex = 0; paramIndex < oldSig.Length; paramIndex++)
+ sigBuilder[paramIndex] = oldSig[paramIndex].ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes);
+
+ MethodSignature newSig = sigBuilder.ToSignature();
+ if (newSig != oldSig)
+ return type.Context.GetFunctionPointerType(newSig);
+ }
+
+ return type;
+ }
+
+ /// <summary>
+ /// Replace some of the types in a method's construction with a new set of types.
+ /// Does not replace the open generics that may be instantiated over in this type.
+ ///
+ /// For instance, Given MyType<object, int[]>.Function<short>(),
+ /// an array of types to replace such as {int,short}, and
+ /// an array of replacement types such as {string,char}.
+ /// The result shall be MyType<object, string[]>.Function<char>
+ ///
+ /// This function cannot be used to replace MyType in the above example.
+ /// </summary>
+ public static MethodDesc ReplaceTypesInConstructionOfMethod(this MethodDesc method, TypeDesc[] typesToReplace, TypeDesc[] replacementTypes)
+ {
+ TypeDesc newOwningType = method.OwningType.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes);
+ MethodDesc methodOnOwningType = null;
+ bool owningTypeChanged = false;
+ if (newOwningType == method.OwningType)
+ {
+ methodOnOwningType = method.GetMethodDefinition();
+ }
+ else
+ {
+ methodOnOwningType = TypeSystemHelpers.FindMethodOnExactTypeWithMatchingTypicalMethod(newOwningType, method);
+ owningTypeChanged = true;
+ }
+
+ MethodDesc result;
+ if (!method.HasInstantiation)
+ {
+ result = methodOnOwningType;
+ }
+ else
+ {
+ Debug.Assert(method is InstantiatedMethod);
+
+ TypeDesc[] newInstantiation = null;
+ int instantiationIndex = 0;
+ for (; instantiationIndex < method.Instantiation.Length; instantiationIndex++)
+ {
+ TypeDesc oldType = method.Instantiation[instantiationIndex];
+ TypeDesc newType = oldType.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes);
+ if ((oldType != newType) || (newInstantiation != null))
+ {
+ if (newInstantiation == null)
+ {
+ newInstantiation = new TypeDesc[method.Instantiation.Length];
+ for (int i = 0; i < instantiationIndex; i++)
+ newInstantiation[i] = method.Instantiation[i];
+ }
+ newInstantiation[instantiationIndex] = newType;
+ }
+ }
+
+ if (newInstantiation != null)
+ result = method.Context.GetInstantiatedMethod(methodOnOwningType, new Instantiation(newInstantiation));
+ else if (owningTypeChanged)
+ result = method.Context.GetInstantiatedMethod(methodOnOwningType, method.Instantiation);
+ else
+ result = method;
+ }
+
+ return result;
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+using Internal.NativeFormat;
+
+using Debug = System.Diagnostics.Debug;
+
+namespace Internal.TypeSystem
+{
+ public class UniversalCanonLayoutAlgorithm : FieldLayoutAlgorithm
+ {
+ public static UniversalCanonLayoutAlgorithm Instance = new UniversalCanonLayoutAlgorithm();
+
+ private UniversalCanonLayoutAlgorithm() { }
+
+ public override bool ComputeContainsGCPointers(DefType type)
+ {
+ // This should never be called
+ throw new NotSupportedException();
+ }
+
+ public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType type, InstanceLayoutKind layoutKind)
+ {
+ return new ComputedInstanceFieldLayout()
+ {
+ FieldSize = LayoutInt.Indeterminate,
+ FieldAlignment = LayoutInt.Indeterminate,
+ ByteCountUnaligned = LayoutInt.Indeterminate,
+ ByteCountAlignment = LayoutInt.Indeterminate,
+ Offsets = Array.Empty<FieldAndOffset>()
+ };
+ }
+
+ public override ComputedStaticFieldLayout ComputeStaticFieldLayout(DefType type, StaticLayoutKind layoutKind)
+ {
+ return new ComputedStaticFieldLayout()
+ {
+ NonGcStatics = new StaticsBlock() { Size = LayoutInt.Zero, LargestAlignment = LayoutInt.Zero },
+ GcStatics = new StaticsBlock() { Size = LayoutInt.Zero, LargestAlignment = LayoutInt.Zero },
+ ThreadNonGcStatics = new StaticsBlock() { Size = LayoutInt.Zero, LargestAlignment = LayoutInt.Zero },
+ ThreadGcStatics = new StaticsBlock() { Size = LayoutInt.Zero, LargestAlignment = LayoutInt.Zero },
+ Offsets = Array.Empty<FieldAndOffset>()
+ };
+ }
+
+ public override ValueTypeShapeCharacteristics ComputeValueTypeShapeCharacteristics(DefType type)
+ {
+ return ValueTypeShapeCharacteristics.None;
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using Internal.TypeSystem.Ecma;
+using Internal.TypeSystem;
+
+using Xunit;
+
+namespace TypeSystemTests
+{
+ public class ArchitectureSpecificFieldLayoutTests
+ {
+ TestTypeSystemContext _contextX86;
+ ModuleDesc _testModuleX86;
+ TestTypeSystemContext _contextX64;
+ ModuleDesc _testModuleX64;
+ TestTypeSystemContext _contextARM;
+ ModuleDesc _testModuleARM;
+
+ public ArchitectureSpecificFieldLayoutTests()
+ {
+ _contextX64 = new TestTypeSystemContext(TargetArchitecture.X64);
+ var systemModuleX64 = _contextX64.CreateModuleForSimpleName("CoreTestAssembly");
+ _contextX64.SetSystemModule(systemModuleX64);
+
+ _testModuleX64 = systemModuleX64;
+
+ _contextARM = new TestTypeSystemContext(TargetArchitecture.ARM);
+ var systemModuleARM = _contextARM.CreateModuleForSimpleName("CoreTestAssembly");
+ _contextARM.SetSystemModule(systemModuleARM);
+
+ _testModuleARM = systemModuleARM;
+
+ _contextX86 = new TestTypeSystemContext(TargetArchitecture.X86);
+ var systemModuleX86 = _contextX86.CreateModuleForSimpleName("CoreTestAssembly");
+ _contextX86.SetSystemModule(systemModuleX86);
+
+ _testModuleX86 = systemModuleX86;
+ }
+
+ [Fact]
+ public void TestInstanceLayoutDoubleBool()
+ {
+ MetadataType tX64 = _testModuleX64.GetType("Sequential", "ClassDoubleBool");
+ MetadataType tX86 = _testModuleX86.GetType("Sequential", "ClassDoubleBool");
+ MetadataType tARM = _testModuleARM.GetType("Sequential", "ClassDoubleBool");
+
+ Assert.Equal(0x8, tX64.InstanceByteAlignment.AsInt);
+ Assert.Equal(0x8, tARM.InstanceByteAlignment.AsInt);
+ Assert.Equal(0x4, tX86.InstanceByteAlignment.AsInt);
+
+ Assert.Equal(0x11, tX64.InstanceByteCountUnaligned.AsInt);
+ Assert.Equal(0x11, tARM.InstanceByteCountUnaligned.AsInt);
+ Assert.Equal(0x11, tX86.InstanceByteCountUnaligned.AsInt);
+
+ Assert.Equal(0x18, tX64.InstanceByteCount.AsInt);
+ Assert.Equal(0x18, tARM.InstanceByteCount.AsInt);
+ Assert.Equal(0x14, tX86.InstanceByteCount.AsInt);
+ }
+
+ [Fact]
+ public void TestInstanceLayoutBoolDoubleBool()
+ {
+ MetadataType tX64 = _testModuleX64.GetType("Sequential", "ClassBoolDoubleBool");
+ MetadataType tX86 = _testModuleX86.GetType("Sequential", "ClassBoolDoubleBool");
+ MetadataType tARM = _testModuleARM.GetType("Sequential", "ClassBoolDoubleBool");
+
+ Assert.Equal(0x8, tX64.InstanceByteAlignment.AsInt);
+ Assert.Equal(0x8, tARM.InstanceByteAlignment.AsInt);
+ Assert.Equal(0x4, tX86.InstanceByteAlignment.AsInt);
+
+ Assert.Equal(0x19, tX64.InstanceByteCountUnaligned.AsInt);
+ Assert.Equal(0x11, tARM.InstanceByteCountUnaligned.AsInt);
+ Assert.Equal(0x11, tX86.InstanceByteCountUnaligned.AsInt);
+
+ Assert.Equal(0x20, tX64.InstanceByteCount.AsInt);
+ Assert.Equal(0x18, tARM.InstanceByteCount.AsInt);
+ Assert.Equal(0x14, tX86.InstanceByteCount.AsInt);
+ }
+ }
+}
--- /dev/null
+// Licensed to the.NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+using Internal.TypeSystem;
+
+using Xunit;
+
+namespace TypeSystemTests
+{
+ public class CanonicalizationTests
+ {
+ private TestTypeSystemContext _context;
+ private ModuleDesc _testModule;
+
+ private MetadataType _referenceType;
+ private MetadataType _otherReferenceType;
+ private MetadataType _structType;
+ private MetadataType _otherStructType;
+ private MetadataType _genericReferenceType;
+ private MetadataType _genericStructType;
+ private MetadataType _genericReferenceTypeWithThreeParams;
+ private MetadataType _genericStructTypeWithThreeParams;
+
+ public CanonicalizationTests()
+ {
+ _context = new TestTypeSystemContext(TargetArchitecture.Unknown);
+ var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly");
+ _context.SetSystemModule(systemModule);
+
+ _testModule = systemModule;
+
+ _referenceType = _testModule.GetType("Canonicalization", "ReferenceType");
+ _otherReferenceType = _testModule.GetType("Canonicalization", "OtherReferenceType");
+ _structType = _testModule.GetType("Canonicalization", "StructType");
+ _otherStructType = _testModule.GetType("Canonicalization", "OtherStructType");
+ _genericReferenceType = _testModule.GetType("Canonicalization", "GenericReferenceType`1");
+ _genericStructType = _testModule.GetType("Canonicalization", "GenericStructType`1");
+ _genericReferenceTypeWithThreeParams = _testModule.GetType("Canonicalization", "GenericReferenceTypeWithThreeParams`3");
+ _genericStructTypeWithThreeParams = _testModule.GetType("Canonicalization", "GenericStructTypeWithThreeParams`3");
+ }
+
+ [Theory]
+ [InlineData(CanonicalizationMode.Standard)]
+ [InlineData(CanonicalizationMode.RuntimeDetermined)]
+ public void TestGenericTypes(CanonicalizationMode algorithmType)
+ {
+ _context.CanonMode = algorithmType;
+
+ // Canonical forms of reference type over two different reference types are equivalent
+ var referenceOverReference = _genericReferenceType.MakeInstantiatedType(_referenceType);
+ var referenceOverOtherReference = _genericReferenceType.MakeInstantiatedType(_otherReferenceType);
+ Assert.Same(
+ referenceOverReference.ConvertToCanonForm(CanonicalFormKind.Specific),
+ referenceOverOtherReference.ConvertToCanonForm(CanonicalFormKind.Specific));
+ Assert.Same(
+ referenceOverReference.ConvertToCanonForm(CanonicalFormKind.Universal),
+ referenceOverOtherReference.ConvertToCanonForm(CanonicalFormKind.Universal));
+
+ var referenceOverReferenceOverReference = _genericReferenceType.MakeInstantiatedType(referenceOverReference);
+ Assert.Same(
+ referenceOverReference.ConvertToCanonForm(CanonicalFormKind.Specific),
+ referenceOverReferenceOverReference.ConvertToCanonForm(CanonicalFormKind.Specific));
+ Assert.Same(
+ referenceOverReference.ConvertToCanonForm(CanonicalFormKind.Universal),
+ referenceOverReferenceOverReference.ConvertToCanonForm(CanonicalFormKind.Universal));
+
+ var threeParamReferenceOverS1R1S1 = _genericReferenceTypeWithThreeParams.MakeInstantiatedType(
+ _structType, _referenceType, _structType);
+ var threeParamReferenceOverS1R2S1 = _genericReferenceTypeWithThreeParams.MakeInstantiatedType(
+ _structType, _otherReferenceType, _structType);
+ var threeParamReferenceOverS1R2S2 = _genericReferenceTypeWithThreeParams.MakeInstantiatedType(
+ _structType, _otherReferenceType, _otherStructType);
+ Assert.Same(
+ threeParamReferenceOverS1R1S1.ConvertToCanonForm(CanonicalFormKind.Specific),
+ threeParamReferenceOverS1R2S1.ConvertToCanonForm(CanonicalFormKind.Specific));
+ Assert.Same(
+ threeParamReferenceOverS1R1S1.ConvertToCanonForm(CanonicalFormKind.Universal),
+ threeParamReferenceOverS1R2S1.ConvertToCanonForm(CanonicalFormKind.Universal));
+ Assert.Same(
+ threeParamReferenceOverS1R1S1.ConvertToCanonForm(CanonicalFormKind.Universal),
+ threeParamReferenceOverS1R2S2.ConvertToCanonForm(CanonicalFormKind.Universal));
+
+ // Universal canonical forms of reference type over reference and value types are equivalent
+ var referenceOverStruct = _genericReferenceType.MakeInstantiatedType(_structType);
+ var referenceOverOtherStruct = _genericReferenceType.MakeInstantiatedType(_otherStructType);
+ Assert.Same(
+ referenceOverStruct.ConvertToCanonForm(CanonicalFormKind.Universal),
+ referenceOverOtherStruct.ConvertToCanonForm(CanonicalFormKind.Universal));
+
+ // Canon forms of reference type instantiated over a generic valuetype over any reference type
+ var genericStructOverReference = _genericStructType.MakeInstantiatedType(_referenceType);
+ var genericStructOverOtherReference = _genericStructType.MakeInstantiatedType(_otherReferenceType);
+ var referenceOverGenericStructOverReference = _genericReferenceType.MakeInstantiatedType(genericStructOverReference);
+ var referenceOverGenericStructOverOtherReference = _genericReferenceType.MakeInstantiatedType(genericStructOverOtherReference);
+ Assert.Same(
+ referenceOverGenericStructOverReference.ConvertToCanonForm(CanonicalFormKind.Specific),
+ referenceOverGenericStructOverOtherReference.ConvertToCanonForm(CanonicalFormKind.Specific));
+ Assert.NotSame(
+ referenceOverGenericStructOverReference.ConvertToCanonForm(CanonicalFormKind.Specific),
+ referenceOverReference.ConvertToCanonForm(CanonicalFormKind.Specific));
+ Assert.Same(
+ referenceOverGenericStructOverReference.ConvertToCanonForm(CanonicalFormKind.Universal),
+ referenceOverGenericStructOverOtherReference.ConvertToCanonForm(CanonicalFormKind.Universal));
+ Assert.Same(
+ referenceOverGenericStructOverReference.ConvertToCanonForm(CanonicalFormKind.Universal),
+ referenceOverReference.ConvertToCanonForm(CanonicalFormKind.Universal));
+
+ // Canon of a type instantiated over a signature variable is the same type when just canonicalizing as specific,
+ // but the universal canon form when performing universal canonicalization.
+ var genericStructOverSignatureVariable = _genericStructType.MakeInstantiatedType(_context.GetSignatureVariable(0, false));
+ Assert.Same(
+ genericStructOverSignatureVariable,
+ genericStructOverSignatureVariable.ConvertToCanonForm(CanonicalFormKind.Specific));
+ Assert.NotSame(
+ genericStructOverSignatureVariable,
+ genericStructOverSignatureVariable.ConvertToCanonForm(CanonicalFormKind.Universal));
+ }
+
+ [Theory]
+ [InlineData(CanonicalizationMode.Standard)]
+ [InlineData(CanonicalizationMode.RuntimeDetermined)]
+ public void TestGenericTypesNegative(CanonicalizationMode algorithmType)
+ {
+ _context.CanonMode = algorithmType;
+
+ // Two different types instantiated over the same type are not canonically equivalent
+ var referenceOverReference = _genericReferenceType.MakeInstantiatedType(_referenceType);
+ var structOverReference = _genericStructType.MakeInstantiatedType(_referenceType);
+ Assert.NotSame(
+ referenceOverReference.ConvertToCanonForm(CanonicalFormKind.Specific),
+ structOverReference.ConvertToCanonForm(CanonicalFormKind.Specific));
+ Assert.NotSame(
+ referenceOverReference.ConvertToCanonForm(CanonicalFormKind.Universal),
+ structOverReference.ConvertToCanonForm(CanonicalFormKind.Universal));
+
+ // Specific canonical forms of reference type over reference and value types are not equivalent
+ var referenceOverStruct = _genericReferenceType.MakeInstantiatedType(_structType);
+ var referenceOverOtherStruct = _genericReferenceType.MakeInstantiatedType(_otherStructType);
+ Assert.NotSame(
+ referenceOverStruct.ConvertToCanonForm(CanonicalFormKind.Specific),
+ referenceOverOtherStruct.ConvertToCanonForm(CanonicalFormKind.Specific));
+
+ var threeParamReferenceOverS1R2S1 = _genericReferenceTypeWithThreeParams.MakeInstantiatedType(
+ _structType, _otherReferenceType, _structType);
+ var threeParamReferenceOverS1R2S2 = _genericReferenceTypeWithThreeParams.MakeInstantiatedType(
+ _structType, _otherReferenceType, _otherStructType);
+ Assert.NotSame(
+ threeParamReferenceOverS1R2S1.ConvertToCanonForm(CanonicalFormKind.Specific),
+ threeParamReferenceOverS1R2S2.ConvertToCanonForm(CanonicalFormKind.Specific));
+ }
+
+ [Theory]
+ [InlineData(CanonicalizationMode.Standard)]
+ [InlineData(CanonicalizationMode.RuntimeDetermined)]
+ public void TestArrayTypes(CanonicalizationMode algorithmType)
+ {
+ _context.CanonMode = algorithmType;
+
+ // Generic type instantiated over an array has the same canonical form as generic type over any other reference type
+ var genericStructOverArrayOfInt = _genericStructType.MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.Int32).MakeArrayType());
+ var genericStructOverReferenceType = _genericStructType.MakeInstantiatedType(_referenceType);
+ Assert.Same(
+ genericStructOverArrayOfInt.ConvertToCanonForm(CanonicalFormKind.Specific),
+ genericStructOverReferenceType.ConvertToCanonForm(CanonicalFormKind.Specific));
+ Assert.Same(
+ genericStructOverArrayOfInt.ConvertToCanonForm(CanonicalFormKind.Universal),
+ genericStructOverReferenceType.ConvertToCanonForm(CanonicalFormKind.Universal));
+
+ // Canonical form of SzArray and Multidim array are not the same
+ var arrayOfReferenceType = _referenceType.MakeArrayType();
+ var mdArrayOfReferenceType = _referenceType.MakeArrayType(1);
+ Assert.NotSame(
+ arrayOfReferenceType.ConvertToCanonForm(CanonicalFormKind.Specific),
+ mdArrayOfReferenceType.ConvertToCanonForm(CanonicalFormKind.Specific));
+ Assert.NotSame(
+ arrayOfReferenceType.ConvertToCanonForm(CanonicalFormKind.Universal),
+ mdArrayOfReferenceType.ConvertToCanonForm(CanonicalFormKind.Universal));
+
+ // Canonical forms of arrays over different reference types are same
+ var arrayOfOtherReferenceType = _otherReferenceType.MakeArrayType();
+ Assert.Same(
+ arrayOfReferenceType.ConvertToCanonForm(CanonicalFormKind.Specific),
+ arrayOfOtherReferenceType.ConvertToCanonForm(CanonicalFormKind.Specific));
+ Assert.Same(
+ arrayOfReferenceType.ConvertToCanonForm(CanonicalFormKind.Universal),
+ arrayOfOtherReferenceType.ConvertToCanonForm(CanonicalFormKind.Universal));
+
+ // Canonical forms of arrays of value types are only same for universal canon form
+ var arrayOfStruct = _structType.MakeArrayType();
+ Assert.NotSame(
+ arrayOfReferenceType.ConvertToCanonForm(CanonicalFormKind.Specific),
+ arrayOfStruct.ConvertToCanonForm(CanonicalFormKind.Specific));
+ Assert.Same(
+ arrayOfReferenceType.ConvertToCanonForm(CanonicalFormKind.Universal),
+ arrayOfStruct.ConvertToCanonForm(CanonicalFormKind.Universal));
+ }
+
+ [Theory]
+ [InlineData(CanonicalizationMode.Standard)]
+ [InlineData(CanonicalizationMode.RuntimeDetermined)]
+ public void TestMethodsOnGenericTypes(CanonicalizationMode algorithmType)
+ {
+ _context.CanonMode = algorithmType;
+
+ var referenceOverReference = _genericReferenceType.MakeInstantiatedType(_referenceType);
+ var referenceOverOtherReference = _genericReferenceType.MakeInstantiatedType(_otherReferenceType);
+ Assert.NotSame(
+ referenceOverReference.GetMethod("Method", null),
+ referenceOverOtherReference.GetMethod("Method", null));
+ Assert.Same(
+ referenceOverReference.GetMethod("Method", null).GetCanonMethodTarget(CanonicalFormKind.Specific),
+ referenceOverOtherReference.GetMethod("Method", null).GetCanonMethodTarget(CanonicalFormKind.Specific));
+ Assert.Same(
+ referenceOverReference.GetMethod("Method", null).GetCanonMethodTarget(CanonicalFormKind.Universal),
+ referenceOverOtherReference.GetMethod("Method", null).GetCanonMethodTarget(CanonicalFormKind.Universal));
+
+ var referenceOverStruct = _genericReferenceType.MakeInstantiatedType(_structType);
+ Assert.NotSame(
+ referenceOverReference.GetMethod("Method", null).GetCanonMethodTarget(CanonicalFormKind.Specific),
+ referenceOverStruct.GetMethod("Method", null).GetCanonMethodTarget(CanonicalFormKind.Specific));
+ Assert.Same(
+ referenceOverReference.GetMethod("Method", null).GetCanonMethodTarget(CanonicalFormKind.Universal),
+ referenceOverStruct.GetMethod("Method", null).GetCanonMethodTarget(CanonicalFormKind.Universal));
+
+ Assert.Same(
+ referenceOverReference.GetMethod("GenericMethod", null).MakeInstantiatedMethod(_referenceType).GetCanonMethodTarget(CanonicalFormKind.Specific),
+ referenceOverOtherReference.GetMethod("GenericMethod", null).MakeInstantiatedMethod(_otherReferenceType).GetCanonMethodTarget(CanonicalFormKind.Specific));
+ Assert.Same(
+ referenceOverReference.GetMethod("GenericMethod", null).MakeInstantiatedMethod(_referenceType).GetCanonMethodTarget(CanonicalFormKind.Universal),
+ referenceOverOtherReference.GetMethod("GenericMethod", null).MakeInstantiatedMethod(_otherReferenceType).GetCanonMethodTarget(CanonicalFormKind.Universal));
+
+ Assert.NotSame(
+ referenceOverReference.GetMethod("GenericMethod", null).MakeInstantiatedMethod(_referenceType).GetCanonMethodTarget(CanonicalFormKind.Specific),
+ referenceOverOtherReference.GetMethod("GenericMethod", null).MakeInstantiatedMethod(_structType).GetCanonMethodTarget(CanonicalFormKind.Specific));
+ Assert.Same(
+ referenceOverReference.GetMethod("GenericMethod", null).MakeInstantiatedMethod(_referenceType).GetCanonMethodTarget(CanonicalFormKind.Universal),
+ referenceOverOtherReference.GetMethod("GenericMethod", null).MakeInstantiatedMethod(_structType).GetCanonMethodTarget(CanonicalFormKind.Universal));
+
+ Assert.NotSame(
+ referenceOverStruct.GetMethod("GenericMethod", null).MakeInstantiatedMethod(_referenceType).GetCanonMethodTarget(CanonicalFormKind.Specific),
+ referenceOverOtherReference.GetMethod("GenericMethod", null).MakeInstantiatedMethod(_structType).GetCanonMethodTarget(CanonicalFormKind.Specific));
+ Assert.Same(
+ referenceOverStruct.GetMethod("GenericMethod", null).MakeInstantiatedMethod(_referenceType).GetCanonMethodTarget(CanonicalFormKind.Universal),
+ referenceOverOtherReference.GetMethod("GenericMethod", null).MakeInstantiatedMethod(_structType).GetCanonMethodTarget(CanonicalFormKind.Universal));
+
+ Assert.NotSame(
+ referenceOverReference.GetMethod("GenericMethod", null).MakeInstantiatedMethod(_structType),
+ referenceOverReference.GetMethod("GenericMethod", null).MakeInstantiatedMethod(_structType).GetCanonMethodTarget(CanonicalFormKind.Specific));
+ }
+
+ [Theory]
+ [InlineData(CanonicalizationMode.Standard)]
+ [InlineData(CanonicalizationMode.RuntimeDetermined)]
+ public void TestArrayMethods(CanonicalizationMode algorithmType)
+ {
+ _context.CanonMode = algorithmType;
+
+ var arrayOfReferenceType = _referenceType.MakeArrayType(1);
+ var arrayOfOtherReferenceType = _otherReferenceType.MakeArrayType(1);
+
+ Assert.Same(
+ arrayOfReferenceType.GetMethod("Set", null).GetCanonMethodTarget(CanonicalFormKind.Specific),
+ arrayOfOtherReferenceType.GetMethod("Set", null).GetCanonMethodTarget(CanonicalFormKind.Specific));
+ Assert.Same(
+ arrayOfReferenceType.GetMethod("Set", null).GetCanonMethodTarget(CanonicalFormKind.Universal),
+ arrayOfOtherReferenceType.GetMethod("Set", null).GetCanonMethodTarget(CanonicalFormKind.Universal));
+
+ var arrayOfStruct = _structType.MakeArrayType(1);
+
+ Assert.NotSame(
+ arrayOfReferenceType.GetMethod("Set", null).GetCanonMethodTarget(CanonicalFormKind.Specific),
+ arrayOfStruct.GetMethod("Set", null).GetCanonMethodTarget(CanonicalFormKind.Specific));
+ Assert.Same(
+ arrayOfReferenceType.GetMethod("Set", null).GetCanonMethodTarget(CanonicalFormKind.Universal),
+ arrayOfStruct.GetMethod("Set", null).GetCanonMethodTarget(CanonicalFormKind.Universal));
+ }
+
+ [Theory]
+ [InlineData(CanonicalizationMode.Standard)]
+ [InlineData(CanonicalizationMode.RuntimeDetermined)]
+ public void TestUpgradeToUniversalCanon(CanonicalizationMode algorithmType)
+ {
+ _context.CanonMode = algorithmType;
+
+ var gstOverUniversalCanon = _genericStructType.MakeInstantiatedType(_context.UniversalCanonType);
+ var grtOverRtRtStOverUniversal = _genericReferenceTypeWithThreeParams.MakeInstantiatedType(
+ _referenceType, _referenceType, gstOverUniversalCanon);
+ var grtOverRtRtStOverUniversalCanon = grtOverRtRtStOverUniversal.ConvertToCanonForm(CanonicalFormKind.Specific);
+
+ // Specific form gets upgraded to universal in the presence of universal canon.
+ // GenericReferenceTypeWithThreeParams<ReferenceType, ReferenceType, GenericStructType<__UniversalCanon>> is
+ // GenericReferenceTypeWithThreeParams<T__UniversalCanon, U__UniversalCanon, V__UniversalCanon>
+ Assert.Same(_context.UniversalCanonType, grtOverRtRtStOverUniversalCanon.Instantiation[0]);
+ Assert.Same(_context.UniversalCanonType, grtOverRtRtStOverUniversalCanon.Instantiation[2]);
+ }
+
+ [Theory]
+ [InlineData(CanonicalizationMode.Standard)]
+ [InlineData(CanonicalizationMode.RuntimeDetermined)]
+ public void TestDowngradeFromUniversalCanon(CanonicalizationMode algorithmType)
+ {
+ _context.CanonMode = algorithmType;
+ var grtOverUniversalCanon = _genericReferenceType.MakeInstantiatedType(_context.UniversalCanonType);
+ var gstOverGrtOverUniversalCanon = _genericStructType.MakeInstantiatedType(grtOverUniversalCanon);
+ var gstOverCanon = _genericStructType.MakeInstantiatedType(_context.CanonType);
+ Assert.Same(gstOverCanon, gstOverGrtOverUniversalCanon.ConvertToCanonForm(CanonicalFormKind.Specific));
+
+ var gstOverGstOverGrtOverUniversalCanon = _genericStructType.MakeInstantiatedType(gstOverGrtOverUniversalCanon);
+ var gstOverGstOverCanon = _genericStructType.MakeInstantiatedType(gstOverCanon);
+ Assert.Same(gstOverGstOverCanon, gstOverGstOverGrtOverUniversalCanon.ConvertToCanonForm(CanonicalFormKind.Specific));
+ }
+
+ [Fact]
+ public void TestCanonicalizationOfRuntimeDeterminedUniversalGeneric()
+ {
+ var gstOverUniversalCanon = _genericStructType.MakeInstantiatedType(_context.UniversalCanonType);
+ var rdtUniversalCanon = (RuntimeDeterminedType)gstOverUniversalCanon.ConvertToSharedRuntimeDeterminedForm().Instantiation[0];
+ Assert.Same(_context.UniversalCanonType, rdtUniversalCanon.CanonicalType);
+
+ var gstOverRdtUniversalCanon = _genericStructType.MakeInstantiatedType(rdtUniversalCanon);
+ Assert.Same(gstOverUniversalCanon, gstOverRdtUniversalCanon.ConvertToCanonForm(CanonicalFormKind.Specific));
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Internal.TypeSystem;
+
+using Xunit;
+
+namespace TypeSystemTests
+{
+ public class CastingTests
+ {
+ private TestTypeSystemContext _context;
+ private ModuleDesc _testModule;
+
+ public CastingTests()
+ {
+ _context = new TestTypeSystemContext(TargetArchitecture.X64);
+ var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly");
+ _context.SetSystemModule(systemModule);
+
+ _testModule = systemModule;
+ }
+
+ [Fact]
+ public void TestCastingInHierarchy()
+ {
+ TypeDesc objectType = _context.GetWellKnownType(WellKnownType.Object);
+ TypeDesc stringType = _context.GetWellKnownType(WellKnownType.String);
+ TypeDesc intType = _context.GetWellKnownType(WellKnownType.Int32);
+ TypeDesc uintType = _context.GetWellKnownType(WellKnownType.UInt32);
+
+ Assert.True(stringType.CanCastTo(objectType));
+ Assert.True(objectType.CanCastTo(objectType));
+ Assert.True(intType.CanCastTo(objectType));
+
+ Assert.False(objectType.CanCastTo(stringType));
+ Assert.False(intType.CanCastTo(uintType));
+ Assert.False(uintType.CanCastTo(intType));
+ }
+
+ [Fact]
+ public void TestInterfaceCasting()
+ {
+ TypeDesc iFooType = _testModule.GetType("Casting", "IFoo");
+ TypeDesc classImplementingIFooType =
+ _testModule.GetType("Casting", "ClassImplementingIFoo");
+ TypeDesc classImplementingIFooIndirectlyType =
+ _testModule.GetType("Casting", "ClassImplementingIFooIndirectly");
+ TypeDesc objectType = _context.GetWellKnownType(WellKnownType.Object);
+
+ Assert.True(classImplementingIFooType.CanCastTo(iFooType));
+ Assert.True(classImplementingIFooIndirectlyType.CanCastTo(iFooType));
+ Assert.True(iFooType.CanCastTo(objectType));
+
+ Assert.False(objectType.CanCastTo(iFooType));
+ }
+
+ [Fact]
+ public void TestSameSizeArrayTypeCasting()
+ {
+ TypeDesc intType = _context.GetWellKnownType(WellKnownType.Int32);
+ TypeDesc uintType = _context.GetWellKnownType(WellKnownType.UInt32);
+ TypeDesc byteType = _context.GetWellKnownType(WellKnownType.Byte);
+ TypeDesc sbyteType = _context.GetWellKnownType(WellKnownType.SByte);
+ TypeDesc intPtrType = _context.GetWellKnownType(WellKnownType.IntPtr);
+ TypeDesc ulongType = _context.GetWellKnownType(WellKnownType.UInt64);
+
+ TypeDesc doubleType = _context.GetWellKnownType(WellKnownType.Double);
+ TypeDesc boolType = _context.GetWellKnownType(WellKnownType.Boolean);
+
+ TypeDesc intBasedEnumType = _testModule.GetType("Casting", "IntBasedEnum");
+ TypeDesc uintBasedEnumType = _testModule.GetType("Casting", "UIntBasedEnum");
+ TypeDesc shortBasedEnumType = _testModule.GetType("Casting", "ShortBasedEnum");
+
+ Assert.True(intType.MakeArrayType().CanCastTo(uintType.MakeArrayType()));
+ Assert.True(intType.MakeArrayType().CanCastTo(uintType.MakeArrayType(1)));
+ Assert.False(intType.CanCastTo(uintType));
+
+ Assert.True(byteType.MakeArrayType().CanCastTo(sbyteType.MakeArrayType()));
+ Assert.False(byteType.CanCastTo(sbyteType));
+
+ Assert.True(intPtrType.MakeArrayType().CanCastTo(ulongType.MakeArrayType()));
+ Assert.False(intPtrType.CanCastTo(ulongType));
+
+ // These are same size, but not allowed to cast
+ Assert.False(doubleType.MakeArrayType().CanCastTo(ulongType.MakeArrayType()));
+ Assert.False(boolType.MakeArrayType().CanCastTo(byteType.MakeArrayType()));
+
+ Assert.True(intBasedEnumType.MakeArrayType().CanCastTo(uintType.MakeArrayType()));
+ Assert.True(intBasedEnumType.MakeArrayType().CanCastTo(uintBasedEnumType.MakeArrayType()));
+ Assert.False(shortBasedEnumType.MakeArrayType().CanCastTo(intType.MakeArrayType()));
+ }
+
+ [Fact]
+ public void TestArrayInterfaceCasting()
+ {
+ TypeDesc intType = _context.GetWellKnownType(WellKnownType.Int32);
+ MetadataType iListType = _context.SystemModule.GetType("System.Collections", "IList");
+ MetadataType iListOfTType = _context.SystemModule.GetType("System.Collections.Generic", "IList`1");
+
+ InstantiatedType iListOfIntType = iListOfTType.MakeInstantiatedType(intType);
+ TypeDesc intSzArrayType = intType.MakeArrayType();
+ TypeDesc intArrayType = intType.MakeArrayType(1);
+
+ Assert.True(intSzArrayType.CanCastTo(iListOfIntType));
+ Assert.True(intSzArrayType.CanCastTo(iListType));
+
+ Assert.False(intArrayType.CanCastTo(iListOfIntType));
+ Assert.True(intArrayType.CanCastTo(iListType));
+ }
+
+ [Fact]
+ public void TestArrayCasting()
+ {
+ TypeDesc intType = _context.GetWellKnownType(WellKnownType.Int32);
+ TypeDesc stringType = _context.GetWellKnownType(WellKnownType.String);
+ TypeDesc objectType = _context.GetWellKnownType(WellKnownType.Object);
+ TypeDesc arrayType = _context.GetWellKnownType(WellKnownType.Array);
+ TypeDesc intSzArrayType = intType.MakeArrayType();
+ TypeDesc intArray1Type = intType.MakeArrayType(1);
+ TypeDesc intArray2Type = intType.MakeArrayType(2);
+ TypeDesc stringSzArrayType = stringType.MakeArrayType();
+ TypeDesc objectSzArrayType = objectType.MakeArrayType();
+
+ Assert.True(intSzArrayType.CanCastTo(intArray1Type));
+ Assert.False(intArray1Type.CanCastTo(intSzArrayType));
+
+ Assert.False(intArray1Type.CanCastTo(intArray2Type));
+
+ Assert.True(intSzArrayType.CanCastTo(arrayType));
+ Assert.True(intArray1Type.CanCastTo(arrayType));
+
+ Assert.True(stringSzArrayType.CanCastTo(objectSzArrayType));
+ Assert.False(intSzArrayType.CanCastTo(objectSzArrayType));
+ }
+
+ [Fact]
+ public void TestGenericParameterCasting()
+ {
+ TypeDesc paramWithNoConstraint =
+ _testModule.GetType("Casting", "ClassWithNoConstraint`1").Instantiation[0];
+ TypeDesc paramWithValueTypeConstraint =
+ _testModule.GetType("Casting", "ClassWithValueTypeConstraint`1").Instantiation[0];
+ TypeDesc paramWithInterfaceConstraint =
+ _testModule.GetType("Casting", "ClassWithInterfaceConstraint`1").Instantiation[0];
+
+ TypeDesc objectType = _context.GetWellKnownType(WellKnownType.Object);
+ TypeDesc valueTypeType = _context.GetWellKnownType(WellKnownType.ValueType);
+ TypeDesc iFooType = _testModule.GetType("Casting", "IFoo");
+ TypeDesc classImplementingIFooType = _testModule.GetType("Casting", "ClassImplementingIFoo");
+ TypeDesc classImplementingIFooIndirectlyType =
+ _testModule.GetType("Casting", "ClassImplementingIFooIndirectly");
+
+ Assert.True(paramWithNoConstraint.CanCastTo(objectType));
+ Assert.False(paramWithNoConstraint.CanCastTo(valueTypeType));
+ Assert.False(paramWithNoConstraint.CanCastTo(iFooType));
+ Assert.False(paramWithNoConstraint.CanCastTo(classImplementingIFooType));
+
+ Assert.True(paramWithValueTypeConstraint.CanCastTo(objectType));
+ Assert.True(paramWithValueTypeConstraint.CanCastTo(valueTypeType));
+ Assert.False(paramWithValueTypeConstraint.CanCastTo(iFooType));
+ Assert.False(paramWithValueTypeConstraint.CanCastTo(classImplementingIFooType));
+
+ Assert.True(paramWithInterfaceConstraint.CanCastTo(objectType));
+ Assert.False(paramWithInterfaceConstraint.CanCastTo(valueTypeType));
+ Assert.True(paramWithInterfaceConstraint.CanCastTo(iFooType));
+ Assert.False(paramWithInterfaceConstraint.CanCastTo(classImplementingIFooType));
+ }
+
+ [Fact]
+ public void TestVariantCasting()
+ {
+ TypeDesc stringType = _context.GetWellKnownType(WellKnownType.String);
+ TypeDesc objectType = _context.GetWellKnownType(WellKnownType.Object);
+ TypeDesc exceptionType = _context.GetWellKnownType(WellKnownType.Exception);
+
+ TypeDesc stringSzArrayType = stringType.MakeArrayType();
+
+ MetadataType iEnumerableOfTType =
+ _context.SystemModule.GetType("System.Collections.Generic", "IEnumerable`1");
+ InstantiatedType iEnumerableOfObjectType = iEnumerableOfTType.MakeInstantiatedType(objectType);
+ InstantiatedType iEnumerableOfExceptionType = iEnumerableOfTType.MakeInstantiatedType(exceptionType);
+
+ Assert.True(stringSzArrayType.CanCastTo(iEnumerableOfObjectType));
+ Assert.False(stringSzArrayType.CanCastTo(iEnumerableOfExceptionType));
+
+ MetadataType iContravariantOfTType = _testModule.GetType("Casting", "IContravariant`1");
+ InstantiatedType iContravariantOfObjectType = iContravariantOfTType.MakeInstantiatedType(objectType);
+ InstantiatedType iEnumerableOfStringType = iEnumerableOfTType.MakeInstantiatedType(stringType);
+
+ Assert.True(iContravariantOfObjectType.CanCastTo(objectType));
+ Assert.True(iEnumerableOfStringType.CanCastTo(objectType));
+ }
+
+ [Fact]
+ public void TestNullableCasting()
+ {
+ TypeDesc intType = _context.GetWellKnownType(WellKnownType.Int32);
+ MetadataType nullableType = (MetadataType)_context.GetWellKnownType(WellKnownType.Nullable);
+ TypeDesc nullableOfIntType = nullableType.MakeInstantiatedType(intType);
+
+ Assert.True(intType.CanCastTo(nullableOfIntType));
+ }
+
+ [Fact]
+ public void TestRecursiveCanCast()
+ {
+ // Tests the stack overflow protection in CanCastTo
+
+ TypeDesc classWithRecursiveImplementation = _testModule.GetType("Casting", "ClassWithRecursiveImplementation");
+ MetadataType iContravariantOfTType = (MetadataType)_testModule.GetType("Casting", "IContravariant`1");
+
+ TypeDesc testType = iContravariantOfTType.MakeInstantiatedType(classWithRecursiveImplementation);
+
+ Assert.False(classWithRecursiveImplementation.CanCastTo(testType));
+ }
+ }
+}
--- /dev/null
+// Licensed to the.NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Internal.TypeSystem;
+
+using Xunit;
+
+namespace TypeSystemTests
+{
+ public class ConstraintsValidationTest
+ {
+ private TestTypeSystemContext _context;
+ private ModuleDesc _testModule;
+
+ private MetadataType _iNonGenType;
+ private MetadataType _iGenType;
+ private MetadataType _arg1Type;
+ private MetadataType _arg2Type;
+ private MetadataType _arg3Type;
+ private MetadataType _structArgWithDefaultCtorType;
+ private MetadataType _structArgWithoutDefaultCtorType;
+ private MetadataType _classArgWithDefaultCtorType;
+ private MetadataType _classArgWithPrivateDefaultCtorType;
+ private MetadataType _abstractClassArgWithDefaultCtorType;
+ private MetadataType _classArgWithoutDefaultCtorType;
+ private MetadataType _referenceTypeConstraintType;
+ private MetadataType _defaultConstructorConstraintType;
+ private MetadataType _notNullableValueTypeConstraintType;
+ private MetadataType _simpleTypeConstraintType;
+ private MetadataType _doubleSimpleTypeConstraintType;
+ private MetadataType _simpleGenericConstraintType;
+ private MetadataType _complexGenericConstraint1Type;
+ private MetadataType _complexGenericConstraint2Type;
+ private MetadataType _complexGenericConstraint3Type;
+ private MetadataType _complexGenericConstraint4Type;
+ private MetadataType _multipleConstraintsType;
+
+ private MetadataType _genericMethodsType;
+ private MethodDesc _simpleGenericConstraintMethod;
+ private MethodDesc _complexGenericConstraintMethod;
+
+ public ConstraintsValidationTest()
+ {
+ _context = new TestTypeSystemContext(TargetArchitecture.Unknown);
+ var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly");
+ _context.SetSystemModule(systemModule);
+
+ _testModule = systemModule;
+
+ _iNonGenType = _testModule.GetType("GenericConstraints", "INonGen");
+ _iGenType = _testModule.GetType("GenericConstraints", "IGen`1");
+ _arg1Type = _testModule.GetType("GenericConstraints", "Arg1");
+ _arg2Type = _testModule.GetType("GenericConstraints", "Arg2`1");
+ _arg3Type = _testModule.GetType("GenericConstraints", "Arg3`1");
+ _structArgWithDefaultCtorType = _testModule.GetType("GenericConstraints", "StructArgWithDefaultCtor");
+ _structArgWithoutDefaultCtorType = _testModule.GetType("GenericConstraints", "StructArgWithoutDefaultCtor");
+ _classArgWithDefaultCtorType = _testModule.GetType("GenericConstraints", "ClassArgWithDefaultCtor");
+ _classArgWithPrivateDefaultCtorType = _testModule.GetType("GenericConstraints", "ClassArgWithPrivateDefaultCtor");
+ _abstractClassArgWithDefaultCtorType = _testModule.GetType("GenericConstraints", "AbstractClassArgWithDefaultCtor");
+ _classArgWithoutDefaultCtorType = _testModule.GetType("GenericConstraints", "ClassArgWithoutDefaultCtor");
+
+ _referenceTypeConstraintType = _testModule.GetType("GenericConstraints", "ReferenceTypeConstraint`1");
+ _defaultConstructorConstraintType = _testModule.GetType("GenericConstraints", "DefaultConstructorConstraint`1");
+ _notNullableValueTypeConstraintType = _testModule.GetType("GenericConstraints", "NotNullableValueTypeConstraint`1");
+ _simpleTypeConstraintType = _testModule.GetType("GenericConstraints", "SimpleTypeConstraint`1");
+ _doubleSimpleTypeConstraintType = _testModule.GetType("GenericConstraints", "DoubleSimpleTypeConstraint`1");
+ _simpleGenericConstraintType = _testModule.GetType("GenericConstraints", "SimpleGenericConstraint`2");
+ _complexGenericConstraint1Type = _testModule.GetType("GenericConstraints", "ComplexGenericConstraint1`2");
+ _complexGenericConstraint2Type = _testModule.GetType("GenericConstraints", "ComplexGenericConstraint2`2");
+ _complexGenericConstraint3Type = _testModule.GetType("GenericConstraints", "ComplexGenericConstraint3`2");
+ _complexGenericConstraint4Type = _testModule.GetType("GenericConstraints", "ComplexGenericConstraint4`2");
+ _multipleConstraintsType = _testModule.GetType("GenericConstraints", "MultipleConstraints`2");
+
+ _genericMethodsType = _testModule.GetType("GenericConstraints", "GenericMethods");
+ _simpleGenericConstraintMethod = _genericMethodsType.GetMethod("SimpleGenericConstraintMethod", null);
+ _complexGenericConstraintMethod = _genericMethodsType.GetMethod("ComplexGenericConstraintMethod", null);
+ }
+
+ [Fact]
+ public void TestTypeConstraints()
+ {
+ TypeDesc instantiatedType;
+ MethodDesc instantiatedMethod;
+
+ MetadataType arg2OfInt = _arg2Type.MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.Int32));
+ MetadataType arg2OfBool = _arg2Type.MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.Boolean));
+ MetadataType arg2OfObject = _arg2Type.MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.Object));
+
+ // ReferenceTypeConstraint
+ {
+ instantiatedType = _referenceTypeConstraintType.MakeInstantiatedType(_arg1Type);
+ Assert.True(instantiatedType.CheckConstraints());
+
+ instantiatedType = _referenceTypeConstraintType.MakeInstantiatedType(_iNonGenType);
+ Assert.True(instantiatedType.CheckConstraints());
+
+ instantiatedType = _referenceTypeConstraintType.MakeInstantiatedType(_structArgWithDefaultCtorType);
+ Assert.False(instantiatedType.CheckConstraints());
+
+ instantiatedType = _referenceTypeConstraintType.MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.Int32));
+ Assert.False(instantiatedType.CheckConstraints());
+ }
+
+ // DefaultConstructorConstraint
+ {
+ instantiatedType = _defaultConstructorConstraintType.MakeInstantiatedType(_arg1Type);
+ Assert.True(instantiatedType.CheckConstraints());
+
+ instantiatedType = _defaultConstructorConstraintType.MakeInstantiatedType(_classArgWithDefaultCtorType);
+ Assert.True(instantiatedType.CheckConstraints());
+
+ instantiatedType = _defaultConstructorConstraintType.MakeInstantiatedType(_classArgWithPrivateDefaultCtorType);
+ Assert.False(instantiatedType.CheckConstraints());
+
+ instantiatedType = _defaultConstructorConstraintType.MakeInstantiatedType(_abstractClassArgWithDefaultCtorType);
+ Assert.False(instantiatedType.CheckConstraints());
+
+ instantiatedType = _defaultConstructorConstraintType.MakeInstantiatedType(_classArgWithoutDefaultCtorType);
+ Assert.False(instantiatedType.CheckConstraints());
+
+ instantiatedType = _defaultConstructorConstraintType.MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.Int32));
+ Assert.True(instantiatedType.CheckConstraints());
+
+ instantiatedType = _defaultConstructorConstraintType.MakeInstantiatedType(_structArgWithDefaultCtorType);
+ Assert.True(instantiatedType.CheckConstraints());
+
+ // Structs always have implicit default constructors
+ instantiatedType = _defaultConstructorConstraintType.MakeInstantiatedType(_structArgWithoutDefaultCtorType);
+ Assert.True(instantiatedType.CheckConstraints());
+ }
+
+ // NotNullableValueTypeConstraint
+ {
+ instantiatedType = _notNullableValueTypeConstraintType.MakeInstantiatedType(_arg1Type);
+ Assert.False(instantiatedType.CheckConstraints());
+
+ instantiatedType = _notNullableValueTypeConstraintType.MakeInstantiatedType(_structArgWithDefaultCtorType);
+ Assert.True(instantiatedType.CheckConstraints());
+
+ MetadataType nullable = (MetadataType)_context.GetWellKnownType(WellKnownType.Nullable);
+ MetadataType nullableOfInt = nullable.MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.Int32));
+
+ instantiatedType = _notNullableValueTypeConstraintType.MakeInstantiatedType(nullableOfInt);
+ Assert.False(instantiatedType.CheckConstraints());
+ }
+
+ // Special constraints instantiated with generic parameter
+ {
+ instantiatedType = _referenceTypeConstraintType.MakeInstantiatedType(_referenceTypeConstraintType.Instantiation[0]);
+ Assert.True(instantiatedType.CheckConstraints());
+
+ instantiatedType = _defaultConstructorConstraintType.MakeInstantiatedType(_defaultConstructorConstraintType.Instantiation[0]);
+ Assert.True(instantiatedType.CheckConstraints());
+
+ instantiatedType = _notNullableValueTypeConstraintType.MakeInstantiatedType(_notNullableValueTypeConstraintType.Instantiation[0]);
+ Assert.True(instantiatedType.CheckConstraints());
+
+ instantiatedType = _defaultConstructorConstraintType.MakeInstantiatedType(_notNullableValueTypeConstraintType.Instantiation[0]);
+ Assert.True(instantiatedType.CheckConstraints());
+
+ instantiatedType = _referenceTypeConstraintType.MakeInstantiatedType(_arg2Type.Instantiation[0]);
+ Assert.False(instantiatedType.CheckConstraints());
+
+ instantiatedType = _defaultConstructorConstraintType.MakeInstantiatedType(_arg2Type.Instantiation[0]);
+ Assert.False(instantiatedType.CheckConstraints());
+
+ instantiatedType = _notNullableValueTypeConstraintType.MakeInstantiatedType(_arg2Type.Instantiation[0]);
+ Assert.False(instantiatedType.CheckConstraints());
+
+ instantiatedType = _referenceTypeConstraintType.MakeInstantiatedType(_simpleTypeConstraintType.Instantiation[0]);
+ Assert.True(instantiatedType.CheckConstraints());
+
+ instantiatedType = _defaultConstructorConstraintType.MakeInstantiatedType(_simpleTypeConstraintType.Instantiation[0]);
+ Assert.False(instantiatedType.CheckConstraints());
+
+ instantiatedType = _notNullableValueTypeConstraintType.MakeInstantiatedType(_simpleTypeConstraintType.Instantiation[0]);
+ Assert.False(instantiatedType.CheckConstraints());
+ }
+
+ // SimpleTypeConstraint and DoubleSimpleTypeConstraint
+ foreach(var genType in new MetadataType[] { _simpleTypeConstraintType , _doubleSimpleTypeConstraintType })
+ {
+ instantiatedType = genType.MakeInstantiatedType(_arg1Type);
+ Assert.True(instantiatedType.CheckConstraints());
+
+ instantiatedType = genType.MakeInstantiatedType(_iNonGenType);
+ Assert.False(instantiatedType.CheckConstraints());
+
+ instantiatedType = genType.MakeInstantiatedType(_classArgWithDefaultCtorType);
+ Assert.False(instantiatedType.CheckConstraints());
+ }
+
+ // SimpleGenericConstraint
+ {
+ instantiatedType = _simpleGenericConstraintType.MakeInstantiatedType(_arg1Type, _arg1Type);
+ Assert.True(instantiatedType.CheckConstraints());
+
+ instantiatedType = _simpleGenericConstraintType.MakeInstantiatedType(_arg1Type, _iNonGenType);
+ Assert.True(instantiatedType.CheckConstraints());
+
+ instantiatedType = _simpleGenericConstraintType.MakeInstantiatedType(_classArgWithDefaultCtorType, _classArgWithoutDefaultCtorType);
+ Assert.False(instantiatedType.CheckConstraints());
+
+ instantiatedType = _simpleGenericConstraintType.MakeInstantiatedType(_arg1Type, _context.GetWellKnownType(WellKnownType.Object));
+ Assert.True(instantiatedType.CheckConstraints());
+
+ instantiatedType = _simpleGenericConstraintType.MakeInstantiatedType(_structArgWithDefaultCtorType, _context.GetWellKnownType(WellKnownType.ValueType));
+ Assert.True(instantiatedType.CheckConstraints());
+
+ instantiatedType = _simpleGenericConstraintType.MakeInstantiatedType(_arg1Type, _context.GetWellKnownType(WellKnownType.ValueType));
+ Assert.False(instantiatedType.CheckConstraints());
+
+ instantiatedType = _simpleGenericConstraintType.MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.UInt16), _context.GetWellKnownType(WellKnownType.UInt32));
+ Assert.False(instantiatedType.CheckConstraints());
+
+ instantiatedType = _simpleGenericConstraintType.MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.UInt16), _context.GetWellKnownType(WellKnownType.ValueType));
+ Assert.True(instantiatedType.CheckConstraints());
+ }
+
+ // ComplexGenericConstraint1
+ {
+ instantiatedType = _complexGenericConstraint1Type.MakeInstantiatedType(_arg1Type, _arg1Type /* uninteresting */);
+ Assert.False(instantiatedType.CheckConstraints());
+
+ instantiatedType = _complexGenericConstraint1Type.MakeInstantiatedType(arg2OfInt, _arg1Type /* uninteresting */);
+ Assert.True(instantiatedType.CheckConstraints());
+
+ instantiatedType = _complexGenericConstraint1Type.MakeInstantiatedType(arg2OfBool, _arg1Type /* uninteresting */);
+ Assert.False(instantiatedType.CheckConstraints());
+
+ instantiatedType = _complexGenericConstraint1Type.MakeInstantiatedType(arg2OfObject, _arg1Type /* uninteresting */);
+ Assert.False(instantiatedType.CheckConstraints());
+ }
+
+ // ComplexGenericConstraint2
+ {
+ MetadataType arg2OfArg2OfInt = _arg2Type.MakeInstantiatedType(arg2OfInt);
+ MetadataType arg2OfArg2OfBool = _arg2Type.MakeInstantiatedType(arg2OfBool);
+ MetadataType arg2OfArg2OfObject = _arg2Type.MakeInstantiatedType(arg2OfObject);
+
+ instantiatedType = _complexGenericConstraint2Type.MakeInstantiatedType(_arg1Type, _context.GetWellKnownType(WellKnownType.Int32));
+ Assert.False(instantiatedType.CheckConstraints());
+
+ instantiatedType = _complexGenericConstraint2Type.MakeInstantiatedType(arg2OfArg2OfInt, _context.GetWellKnownType(WellKnownType.Int32));
+ Assert.True(instantiatedType.CheckConstraints());
+ instantiatedType = _complexGenericConstraint2Type.MakeInstantiatedType(arg2OfArg2OfBool, _context.GetWellKnownType(WellKnownType.Int32));
+ Assert.False(instantiatedType.CheckConstraints());
+ instantiatedType = _complexGenericConstraint2Type.MakeInstantiatedType(arg2OfArg2OfObject, _context.GetWellKnownType(WellKnownType.Int32));
+ Assert.False(instantiatedType.CheckConstraints());
+
+ instantiatedType = _complexGenericConstraint2Type.MakeInstantiatedType(arg2OfArg2OfInt, _context.GetWellKnownType(WellKnownType.Object));
+ Assert.False(instantiatedType.CheckConstraints());
+ instantiatedType = _complexGenericConstraint2Type.MakeInstantiatedType(arg2OfArg2OfBool, _context.GetWellKnownType(WellKnownType.Object));
+ Assert.False(instantiatedType.CheckConstraints());
+ instantiatedType = _complexGenericConstraint2Type.MakeInstantiatedType(arg2OfArg2OfObject, _context.GetWellKnownType(WellKnownType.Object));
+ Assert.True(instantiatedType.CheckConstraints());
+
+ instantiatedType = _complexGenericConstraint2Type.MakeInstantiatedType(arg2OfArg2OfInt, _context.GetWellKnownType(WellKnownType.Boolean));
+ Assert.False(instantiatedType.CheckConstraints());
+ instantiatedType = _complexGenericConstraint2Type.MakeInstantiatedType(arg2OfArg2OfBool, _context.GetWellKnownType(WellKnownType.Boolean));
+ Assert.True(instantiatedType.CheckConstraints());
+ instantiatedType = _complexGenericConstraint2Type.MakeInstantiatedType(arg2OfArg2OfObject, _context.GetWellKnownType(WellKnownType.Boolean));
+ Assert.False(instantiatedType.CheckConstraints());
+ }
+
+ // ComplexGenericConstraint3
+ {
+ MetadataType igenOfObject = _iGenType.MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.Object));
+
+ instantiatedType = _complexGenericConstraint3Type.MakeInstantiatedType(igenOfObject, _context.GetWellKnownType(WellKnownType.Object));
+ Assert.True(instantiatedType.CheckConstraints());
+
+ // Variance-compatible instantiation argument
+ instantiatedType = _complexGenericConstraint3Type.MakeInstantiatedType(igenOfObject, _context.GetWellKnownType(WellKnownType.String));
+ Assert.True(instantiatedType.CheckConstraints());
+
+ // Type that implements the interface
+ var arg3OfObject = _arg3Type.MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.Object));
+ instantiatedType = _complexGenericConstraint3Type.MakeInstantiatedType(arg3OfObject, _context.GetWellKnownType(WellKnownType.Object));
+ Assert.True(instantiatedType.CheckConstraints());
+
+ // Type that implements a variant compatible interface
+ instantiatedType = _complexGenericConstraint3Type.MakeInstantiatedType(arg3OfObject, _context.GetWellKnownType(WellKnownType.String));
+ Assert.True(instantiatedType.CheckConstraints());
+ }
+
+ // Constraints requiring InstantiationContext
+ {
+ // Instantiate type / method with own generic parameters
+ instantiatedType = _complexGenericConstraint3Type.MakeInstantiatedType(_complexGenericConstraint3Type.Instantiation[0], _complexGenericConstraint3Type.Instantiation[1]);
+ Assert.True(instantiatedType.CheckConstraints(new InstantiationContext(instantiatedType.Instantiation, default(Instantiation))));
+
+ instantiatedType = _complexGenericConstraint4Type.MakeInstantiatedType(_complexGenericConstraint4Type.Instantiation[0], _complexGenericConstraint4Type.Instantiation[1]);
+ Assert.True(instantiatedType.CheckConstraints(new InstantiationContext(instantiatedType.Instantiation, default(Instantiation))));
+
+ instantiatedMethod = _simpleGenericConstraintMethod.MakeInstantiatedMethod(_simpleGenericConstraintMethod.Instantiation);
+ Assert.True(instantiatedMethod.CheckConstraints(new InstantiationContext(default(Instantiation), instantiatedMethod.Instantiation)));
+
+ instantiatedMethod = _complexGenericConstraintMethod.MakeInstantiatedMethod(_complexGenericConstraintMethod.Instantiation);
+ Assert.True(instantiatedMethod.CheckConstraints(new InstantiationContext(default(Instantiation), instantiatedMethod.Instantiation)));
+
+ // Instantiate type with generic parameters of method
+ instantiatedType = _simpleGenericConstraintType.MakeInstantiatedType(_simpleGenericConstraintMethod.Instantiation);
+ Assert.True(instantiatedType.CheckConstraints(new InstantiationContext(default(Instantiation), _simpleGenericConstraintMethod.Instantiation)));
+
+ instantiatedType = _complexGenericConstraint4Type.MakeInstantiatedType(_complexGenericConstraintMethod.Instantiation);
+ Assert.True(instantiatedType.CheckConstraints(new InstantiationContext(default(Instantiation), _complexGenericConstraintMethod.Instantiation)));
+
+ // Instantiate method with generic parameters of type
+ instantiatedMethod = _simpleGenericConstraintMethod.MakeInstantiatedMethod(_simpleGenericConstraintType.Instantiation);
+ Assert.True(instantiatedMethod.CheckConstraints(new InstantiationContext(_simpleGenericConstraintType.Instantiation, default(Instantiation))));
+
+ instantiatedMethod = _complexGenericConstraintMethod.MakeInstantiatedMethod(_complexGenericConstraint4Type.Instantiation);
+ Assert.True(instantiatedMethod.CheckConstraints(new InstantiationContext(_complexGenericConstraint4Type.Instantiation, default(Instantiation))));
+ }
+
+ // MultipleConstraints
+ {
+ // Violate the class constraint
+ instantiatedType = _multipleConstraintsType.MakeInstantiatedType(_structArgWithDefaultCtorType, _context.GetWellKnownType(WellKnownType.Object));
+ Assert.False(instantiatedType.CheckConstraints());
+
+ // Violate the new() constraint
+ instantiatedType = _multipleConstraintsType.MakeInstantiatedType(_classArgWithoutDefaultCtorType, _context.GetWellKnownType(WellKnownType.Object));
+ Assert.False(instantiatedType.CheckConstraints());
+
+ // Violate the IGen<U> constraint
+ instantiatedType = _multipleConstraintsType.MakeInstantiatedType(_arg1Type, _context.GetWellKnownType(WellKnownType.Object));
+ Assert.False(instantiatedType.CheckConstraints());
+
+ // Satisfy all constraints
+ instantiatedType = _multipleConstraintsType.MakeInstantiatedType(_classArgWithDefaultCtorType, _context.GetWellKnownType(WellKnownType.Object));
+ Assert.True(instantiatedType.CheckConstraints());
+ }
+
+ // InvalidInstantiationArgs
+ {
+ var pointer = _context.GetWellKnownType(WellKnownType.Int16).MakePointerType();
+ var byref = _context.GetWellKnownType(WellKnownType.Int16).MakeByRefType();
+
+ Assert.False(_iGenType.Instantiation.CheckValidInstantiationArguments());
+
+ instantiatedType = _iGenType.MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.Void));
+ Assert.False(instantiatedType.Instantiation.CheckValidInstantiationArguments());
+
+ instantiatedType = _iGenType.MakeInstantiatedType(pointer);
+ Assert.False(instantiatedType.Instantiation.CheckValidInstantiationArguments());
+
+ instantiatedType = _iGenType.MakeInstantiatedType(byref);
+ Assert.False(instantiatedType.Instantiation.CheckValidInstantiationArguments());
+
+ instantiatedType = _iGenType.MakeInstantiatedType(byref);
+ instantiatedType = _iGenType.MakeInstantiatedType(instantiatedType);
+ Assert.False(instantiatedType.Instantiation.CheckValidInstantiationArguments());
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Canonicalization
+{
+ class ReferenceType
+ {
+ void Method()
+ {
+ }
+
+ void GenericMethod<U>()
+ {
+ }
+ }
+
+ class OtherReferenceType
+ {
+ }
+
+ struct StructType
+ {
+ void Method()
+ {
+ }
+
+ void GenericMethod<U>()
+ {
+ }
+ }
+
+ struct OtherStructType
+ {
+ }
+
+ class GenericReferenceType<T>
+ {
+ void Method()
+ {
+ }
+
+ void GenericMethod<U>()
+ {
+ }
+ }
+
+ struct GenericStructType<T>
+ {
+ void Method()
+ {
+ }
+
+ void GenericMethod<U>()
+ {
+ }
+ }
+
+ class GenericReferenceTypeWithThreeParams<T, U, V>
+ {
+ }
+
+ class GenericStructTypeWithThreeParams<T, U, V>
+ {
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Casting
+{
+ interface IFoo { }
+
+ interface IContravariant<in T> { }
+
+ class ClassImplementingIFoo : IFoo { }
+
+ class ClassImplementingIFooIndirectly : ClassImplementingIFoo { }
+
+ enum IntBasedEnum : int { }
+
+ enum UIntBasedEnum : uint { }
+
+ enum ShortBasedEnum : short { }
+
+ class ClassWithNoConstraint<T> { }
+
+ class ClassWithValueTypeConstraint<T> where T : struct { }
+
+ class ClassWithInterfaceConstraint<T> where T : IFoo { }
+
+ class ClassWithRecursiveImplementation : IContravariant<IContravariant<ClassWithRecursiveImplementation>> { }
+}
\ No newline at end of file
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <OutputType>Library</OutputType>
+ <AssemblyName>CoreTestAssembly</AssemblyName>
+ <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
+ <IsCoreAssembly>true</IsCoreAssembly>
+ <SkipTestRun>true</SkipTestRun>
+ <TargetFramework>netstandard2.0</TargetFramework>
+ <!-- Don't add references to the netstandard platform since this is a core assembly -->
+ <DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>
+ <!-- CSC needs explicit metadata version when it has no core library to reference -->
+ <RuntimeMetadataVersion>v4.0.30319</RuntimeMetadataVersion>
+ <GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
+ </PropertyGroup>
+</Project>
\ No newline at end of file
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+#pragma warning disable 169 // Field 'blah' is never used
+
+namespace GCPointerMap
+{
+ [StructLayout(LayoutKind.Sequential)]
+ class ClassWithArrayFields
+ {
+ int[] a1;
+ string[] a2;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ class ClassWithStringField
+ {
+ static string dummy;
+ int i;
+ string s;
+ bool z;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct MixedStruct
+ {
+ public int X;
+ public object Y;
+ public int Z;
+ public byte U;
+ public object V;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct Struct4GcPointers
+ {
+ public object o1;
+ public object o2;
+ public object o3;
+ public object o4;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct Struct32GcPointers
+ {
+ public Struct4GcPointers x1;
+ public Struct4GcPointers x2;
+ public Struct4GcPointers x3;
+ public Struct4GcPointers x4;
+ public Struct4GcPointers x5;
+ public Struct4GcPointers x6;
+ public Struct4GcPointers x7;
+ public Struct4GcPointers x8;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct StructWithSameGCLayoutAsMixedStruct
+ {
+ MixedStruct s;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct DoubleMixedStructLayout
+ {
+ StructWithSameGCLayoutAsMixedStruct X;
+ MixedStruct Y;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ struct ExplicitlyFarPointer
+ {
+ [FieldOffset(0)]
+ object X;
+
+ [FieldOffset(32 * 8)]
+ object Y;
+
+ [FieldOffset(40 * 8)]
+ object Z;
+
+ [FieldOffset(56 * 8)]
+ MixedStruct W;
+ }
+
+ class MixedStaticClass
+ {
+ object dummy1;
+ static object o;
+ static int dummy2;
+ const string dummy3 = "Hello";
+ static StructWithSameGCLayoutAsMixedStruct m1;
+ static MixedStruct m2;
+ }
+
+ class MixedThreadStaticClass
+ {
+ object dummy1;
+ static object dummy2;
+
+ [ThreadStatic]
+ static int i;
+
+ [ThreadStatic]
+ static StructWithSameGCLayoutAsMixedStruct m1;
+
+ [ThreadStatic]
+ static MixedStruct m2;
+
+ [ThreadStatic]
+ static object o;
+
+ [ThreadStatic]
+ static short s;
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace GenericConstraints
+{
+ public interface INonGen { }
+
+ public interface IGen<in T> { }
+
+ public class Arg1 : INonGen { }
+
+ public class Arg2<T> { }
+
+ public class Arg3<T> : IGen<T> { }
+
+ public struct StructArgWithDefaultCtor { }
+
+ public struct StructArgWithoutDefaultCtor
+ {
+ public StructArgWithoutDefaultCtor(int argument) { }
+ }
+
+ public class ClassArgWithDefaultCtor : IGen<object>
+ {
+ public ClassArgWithDefaultCtor() { }
+ }
+
+ public abstract class AbstractClassArgWithDefaultCtor : IGen<object>
+ {
+ public AbstractClassArgWithDefaultCtor() { }
+ }
+
+ public class ClassArgWithPrivateDefaultCtor : IGen<object>
+ {
+ private ClassArgWithPrivateDefaultCtor() { }
+ }
+
+ public class ClassArgWithoutDefaultCtor : IGen<object>
+ {
+ public ClassArgWithoutDefaultCtor(int argument) { }
+ }
+
+ public class ReferenceTypeConstraint<T> where T : class { }
+
+ public class DefaultConstructorConstraint<T> where T : new() { }
+
+ public class NotNullableValueTypeConstraint<T> where T : struct { }
+
+ public class SimpleTypeConstraint<T> where T : Arg1 { }
+
+ public class DoubleSimpleTypeConstraint<T> where T : Arg1, INonGen { }
+
+ public class SimpleGenericConstraint<T, U> where T : U { }
+
+ public class ComplexGenericConstraint1<T, U> where T : Arg2<int> { }
+
+ public class ComplexGenericConstraint2<T, U> where T : Arg2<Arg2<U>> { }
+
+ public class ComplexGenericConstraint3<T, U> where T : IGen<U> { }
+
+ public class ComplexGenericConstraint4<T, U> where T : U where U : IGen<T> { }
+
+ public class MultipleConstraints<T, U> where T : class, IGen<U>, new() { }
+
+ public class GenericMethods
+ {
+ public static void SimpleGenericConstraintMethod<T, U>() where T : U { }
+
+ public static void ComplexGenericConstraintMethod<T, U>() where T : U where U : IGen<T> { }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+
+namespace GenericTypes
+{
+ /// <summary>
+ /// Generic class to be used for testing.
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ public abstract class GenericClass<T>
+ {
+ /// <summary>
+ /// Purpose is to manipulate a method involving a generic parameter in its return type.
+ /// </summary>
+ public abstract T Foo();
+ /// <summary>
+ /// Purpose is to manipulate a method involving a generic parameter in its parameter list.
+ /// </summary>
+ public void Bar(T a)
+ {
+ }
+
+ ~GenericClass()
+ { }
+ }
+
+ public class DerivedGenericClass<T> : GenericClass<T>
+ {
+ public override sealed T Foo()
+ {
+ return default(T);
+ }
+ }
+ /// <summary>
+ /// Generic class with multiple parameters to be used for testing.
+ /// </summary>
+ public class TwoParamGenericClass<T,U>
+ {
+ /// <summary>
+ /// Purpose is to allow testing of the properties of non-generic methods on generic types
+ /// </summary>
+ public void NonGenericFunction()
+ {
+ }
+
+ /// <summary>
+ /// Purpose is to allow testing of the properties of generic methods on generic types
+ /// </summary>
+ public void GenericFunction<K, V>()
+ {
+ }
+ }
+
+ /// <summary>
+ /// Non-generic type which has a generic method in it
+ /// </summary>
+ public class NonGenericClass
+ {
+ /// <summary>
+ /// Purpose is to allow testing the properties of generic methods on nongeneric types
+ /// </summary>
+ /// <typeparam name="K"></typeparam>
+ /// <typeparam name="V"></typeparam>
+ public void GenericFunction<K, V>()
+ {
+ }
+ }
+
+ /// <summary>
+ /// Generic structure with 3 fields all defined by type parameters
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential)]
+ public struct GenStruct<A,B,C>
+ {
+ A _a;
+ B _b;
+ C _c;
+ }
+
+ public class GenClass<A>
+ {
+#pragma warning disable 169
+ A _a;
+#pragma warning restore 169
+ }
+
+ public class GenDerivedClass<A,B> : GenClass<A>
+ {
+#pragma warning disable 169
+ B _b;
+#pragma warning restore 169
+ }
+}
\ No newline at end of file
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace Hashcode
+{
+ class NonNestedType
+ {
+ class NestedType
+ {
+
+ }
+
+ void GenericMethod<T>()
+ { }
+ }
+
+ class GenericType<X,Y>
+ {
+ void GenericMethod<T>()
+ {
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+#pragma warning disable 169
+
+namespace ContainsGCPointers
+{
+ struct NoPointers
+ {
+ int int1;
+ byte byte1;
+ char char1;
+ }
+
+ struct StillNoPointers
+ {
+ NoPointers noPointers1;
+ bool bool1;
+ }
+
+ class ClassNoPointers
+ {
+ char char1;
+ }
+
+ struct HasPointers
+ {
+ string string1;
+ }
+
+ struct FieldHasPointers
+ {
+ HasPointers hasPointers1;
+ }
+
+ class ClassHasPointers
+ {
+ ClassHasPointers classHasPointers1;
+ }
+
+ class BaseClassHasPointers : ClassHasPointers
+ {
+ }
+
+ public class ClassHasIntArray
+ {
+ int[] intArrayField;
+ }
+
+ public class ClassHasArrayOfClassType
+ {
+ ClassNoPointers[] classTypeArray;
+ }
+}
+
+namespace Explicit
+{
+ [StructLayout(LayoutKind.Explicit)]
+ class Class1
+ {
+ static int Stat;
+ [FieldOffset(4)]
+ bool Bar;
+ [FieldOffset(10)]
+ char Baz;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ class Class2 : Class1
+ {
+ [FieldOffset(0)]
+ int Lol;
+ [FieldOffset(20)]
+ byte Omg;
+ }
+
+ [StructLayout(LayoutKind.Explicit, Size = 40)]
+ class ExplicitSize : Class1
+ {
+ [FieldOffset(0)]
+ int Lol;
+ [FieldOffset(20)]
+ byte Omg;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ public class ExplicitEmptyClass
+ {
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ public struct ExplicitEmptyStruct
+ {
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ ref struct MisalignedPointer
+ {
+ [FieldOffset(2)]
+ public object O;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ ref struct MisalignedByRef
+ {
+ [FieldOffset(2)]
+ public ByRefStruct O;
+ }
+
+ ref struct ByRefStruct
+ {
+ }
+}
+
+namespace Sequential
+{
+ [StructLayout(LayoutKind.Sequential)]
+ class Class1
+ {
+ int MyInt;
+ bool MyBool;
+ char MyChar;
+ string MyString;
+ byte[] MyByteArray;
+ Class1 MyClass1SelfRef;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ class Class2 : Class1
+ {
+ int MyInt2;
+ }
+
+ // [StructLayout(LayoutKind.Sequential)] is applied by default by the C# compiler
+ struct Struct0
+ {
+ bool b1;
+ bool b2;
+ bool b3;
+ int i1;
+ string s1;
+ }
+
+ // [StructLayout(LayoutKind.Sequential)] is applied by default by the C# compiler
+ struct Struct1
+ {
+ Struct0 MyStruct0;
+ bool MyBool;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public class ClassDoubleBool
+ {
+ double double1;
+ bool bool1;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public class ClassBoolDoubleBool
+ {
+ bool bool1;
+ double double1;
+ bool bool2;
+ }
+}
+
+namespace Auto
+{
+ [StructLayout(LayoutKind.Auto)]
+ struct StructWithBool
+ {
+ bool MyStructBool;
+ }
+
+ [StructLayout(LayoutKind.Auto)]
+ struct StructWithIntChar
+ {
+ char MyStructChar;
+ int MyStructInt;
+ }
+
+ [StructLayout(LayoutKind.Auto)]
+ struct StructWithChar
+ {
+ char MyStructChar;
+ }
+
+ class ClassContainingStructs
+ {
+ static int MyStaticInt;
+
+ StructWithBool MyStructWithBool;
+ bool MyBool1;
+ char MyChar1;
+ int MyInt;
+ double MyDouble;
+ long MyLong;
+ byte[] MyByteArray;
+ string MyString1;
+ bool MyBool2;
+ StructWithIntChar MyStructWithIntChar;
+ StructWithChar MyStructWithChar;
+ }
+
+ class BaseClass7BytesRemaining
+ {
+ bool MyBool1;
+ double MyDouble1;
+ long MyLong1;
+ byte[] MyByteArray1;
+ string MyString1;
+ }
+
+ class BaseClass4BytesRemaining
+ {
+ long MyLong1;
+ uint MyUint1;
+ }
+
+ class BaseClass3BytesRemaining
+ {
+ int MyInt1;
+ string MyString1;
+ bool MyBool1;
+ }
+
+ class OptimizePartial : BaseClass7BytesRemaining
+ {
+ bool OptBool;
+ char OptChar;
+ long NoOptLong;
+ string NoOptString;
+ }
+
+ class Optimize7Bools : BaseClass7BytesRemaining
+ {
+ bool OptBool1;
+ bool OptBool2;
+ bool OptBool3;
+ bool OptBool4;
+ bool OptBool5;
+ bool OptBool6;
+ bool OptBool7;
+ bool NoOptBool8;
+ string NoOptString;
+ }
+
+ class OptimizeAlignedFields : BaseClass7BytesRemaining
+ {
+ bool OptBool1;
+ bool OptBool2;
+ bool OptBool3;
+ bool NoOptBool4;
+ char OptChar1;
+ char OptChar2;
+ string NoOptString;
+ }
+
+ class OptimizeLargestField : BaseClass4BytesRemaining
+ {
+ bool NoOptBool;
+ char NoOptChar;
+ int OptInt;
+ string NoOptString;
+ }
+
+ class NoOptimizeMisaligned : BaseClass3BytesRemaining
+ {
+ char NoOptChar;
+ int NoOptInt;
+ string NoOptString;
+ }
+
+ class NoOptimizeCharAtSize2Alignment : BaseClass3BytesRemaining
+ {
+ char NoOptChar;
+ }
+
+ [StructLayout(LayoutKind.Auto, Pack = 1)]
+ struct MinPacking<T>
+ {
+ public byte _byte;
+ public T _value;
+ }
+}
+
+namespace IsByRefLike
+{
+ public ref struct ByRefLikeStruct
+ {
+ ByReference<object> ByRef;
+ }
+
+ public struct NotByRefLike
+ {
+ int X;
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace InterfaceArrangements
+{
+ interface I1 { }
+
+ interface I2 : I1 { }
+
+ interface IGen1<T> { }
+
+ class NoInterfaces { }
+
+ class OneInterface : I1 { }
+
+ class Base<T> : IGen1<T>, I1 { }
+
+ class Mid<U,V> : Base<U>, IGen1<V> { }
+
+ class DerivedFromMid : Mid<string, string>, IGen1<string> { }
+
+ interface IFoo<out U>
+ {
+ void IMethod();
+ }
+
+ class Foo : IFoo<string>, IFoo<int>
+ {
+ public virtual void IMethod() { }
+ }
+
+ class DerivedFromFoo : Foo, IFoo<string>, IFoo<int>
+ {
+ void IFoo<string>.IMethod() { }
+ }
+
+ class SuperDerivedFromFoo : DerivedFromFoo, IFoo<string>, IFoo<int>
+ {
+ void IFoo<int>.IMethod() { }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#pragma warning disable 649
+#pragma warning disable 169
+
+namespace System
+{
+ // Dummy core types to allow us compiling this assembly as a core library so that the type
+ // system tests don't have a dependency on a real core library.
+
+ public class Object
+ {
+ internal IntPtr m_pEEType;
+
+ public virtual bool Equals(object other)
+ {
+ return false;
+ }
+
+ public virtual int GetHashCode()
+ {
+ return 0;
+ }
+
+ public virtual string ToString() { return null; }
+
+ ~Object()
+ {
+ }
+ }
+
+ public struct Void { }
+ public struct Boolean { }
+ public struct Char { }
+ public struct SByte { }
+ public struct Byte { }
+ public struct Int16 { }
+ public struct UInt16 { }
+ public struct Int32 { }
+ public struct UInt32 { }
+ public struct Int64 { }
+ public struct UInt64 { }
+ public struct IntPtr { }
+ public struct UIntPtr { }
+ public struct Single { }
+ public struct Double { }
+ public abstract class ValueType { }
+ public abstract class Enum : ValueType { }
+ public struct Nullable<T> where T : struct { }
+
+ public sealed class String { }
+ public abstract class Array : System.Collections.IList { }
+ public abstract class Delegate { }
+ public abstract class MulticastDelegate : Delegate { }
+
+ public struct RuntimeTypeHandle { }
+ public struct RuntimeMethodHandle { }
+ public struct RuntimeFieldHandle { }
+
+ public class Attribute { }
+
+ public class ThreadStaticAttribute : Attribute { }
+
+ public class Array<T> : Array, System.Collections.Generic.IList<T> { }
+
+ public class Exception { }
+
+ public ref struct TypedReference
+ {
+ private readonly ByReference<byte> _value;
+ private readonly RuntimeTypeHandle _typeHandle;
+ }
+
+ public ref struct ByReference<T> { }
+}
+
+namespace System.Collections
+{
+ interface IEnumerable { }
+
+ interface ICollection : IEnumerable { }
+
+ interface IList : ICollection { }
+}
+
+namespace System.Collections.Generic
+{
+ interface IEnumerable<out T> { }
+
+ interface ICollection<T> : IEnumerable<T> { }
+
+ interface IList<T> : ICollection<T> { }
+}
+
+namespace System.Runtime.InteropServices
+{
+ public enum LayoutKind
+ {
+ Sequential = 0, // 0x00000008,
+ Explicit = 2, // 0x00000010,
+ Auto = 3, // 0x00000000,
+ }
+
+ public sealed class StructLayoutAttribute : Attribute
+ {
+ internal LayoutKind _val;
+
+ public StructLayoutAttribute(LayoutKind layoutKind)
+ {
+ _val = layoutKind;
+ }
+
+ public LayoutKind Value { get { return _val; } }
+ public int Pack;
+ public int Size;
+ }
+
+ public sealed class FieldOffsetAttribute : Attribute
+ {
+ private int _val;
+ public FieldOffsetAttribute(int offset)
+ {
+ _val = offset;
+ }
+ public int Value { get { return _val; } }
+ }
+}
+
+namespace System.Runtime.CompilerServices
+{
+ public sealed class IsByRefLikeAttribute : Attribute
+ {
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+#pragma warning disable 169
+
+namespace StaticFieldLayout
+{
+ struct NoPointers
+ {
+ static int int1;
+ static byte byte1;
+ static char char1;
+ }
+
+ struct StillNoPointers
+ {
+ NoPointers noPointers1;
+ static bool bool1;
+ }
+
+ class ClassNoPointers
+ {
+ static int int1;
+ static byte byte1;
+ static char char1;
+ }
+
+ struct HasPointers
+ {
+ bool bool1;
+ static string string1;
+ static ClassNoPointers class1;
+ char char1;
+ }
+
+ class MixPointersAndNonPointers
+ {
+ static string string1;
+ static int int1;
+ static ClassNoPointers class1;
+ static int int2;
+ static string string2;
+ }
+
+ class EnsureInheritanceResetsStaticOffsets : MixPointersAndNonPointers
+ {
+ static int int3;
+ static string string3;
+ }
+
+ class LiteralFieldsDontAffectLayout
+ {
+ const int IntConstant = 0;
+ const string StringConstant = null;
+ static int Int1;
+ static string String1;
+ }
+
+ class RvaTestClass
+ {
+ static void RvaTest()
+ {
+ int[] foo = new int[] { 0, 1, 2, 3, 4, 45, 5, 5 };
+ }
+
+ }
+
+ struct StaticSelfRef
+ {
+ static StaticSelfRef selfRef1;
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace SyntheticVirtualOverride
+{
+ struct StructWithNoEqualsAndGetHashCode
+ {
+ }
+
+ class ClassWithInjectedEqualsAndGetHashCode
+ {
+ }
+
+ class ClassOverridingEqualsAndGetHashCode : ClassWithInjectedEqualsAndGetHashCode
+ {
+ public override bool Equals(object other)
+ {
+ return false;
+ }
+
+ public override int GetHashCode()
+ {
+ return 0;
+ }
+ }
+
+ class ClassNotOverridingEqualsAndGetHashCode : ClassWithInjectedEqualsAndGetHashCode
+ {
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+public class NonNamespaceQualifiedType
+{
+
+}
+
+namespace TypeNameParsing
+{
+ public class Generic<T>
+ {
+ public class NestedNongeneric
+ {
+ }
+
+ public class NestedGeneric<U>
+ {
+ }
+ }
+
+ public class VeryGeneric<T, U, V>
+ {
+ }
+
+ public class Simple
+ {
+ public class Nested
+ {
+ public class NestedTwice
+ {
+ }
+ }
+ }
+
+ public struct Struct
+ {
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+#pragma warning disable 169
+
+namespace ValueTypeShapeCharacteristics
+{
+ struct SimpleHfaFloatStruct
+ {
+ static int irrelevantField;
+ float field;
+ }
+
+ struct SimpleHfaFloatStructWithManyFields
+ {
+ float field1;
+ float field2;
+ float field3;
+ float field4;
+ }
+
+ struct SimpleHfaDoubleStruct
+ {
+ double field;
+ static int irrelevantField;
+ }
+
+ struct CompositeHfaFloatStruct
+ {
+ SimpleHfaFloatStruct field1;
+ float field2;
+ SimpleHfaFloatStruct field3;
+ }
+
+ struct CompositeHfaDoubleStruct
+ {
+ SimpleHfaDoubleStruct field1;
+ SimpleHfaDoubleStruct field2;
+ SimpleHfaDoubleStruct field3;
+ SimpleHfaDoubleStruct field4;
+ }
+
+ struct NonHAEmptyStruct
+ {
+ }
+
+ struct NonHAStruct
+ {
+ float field1;
+ int field2;
+ }
+
+ struct NonHAMixedStruct
+ {
+ float field1;
+ double field2;
+ }
+
+ struct NonHACompositeStruct
+ {
+ SimpleHfaDoubleStruct field1;
+ SimpleHfaFloatStruct field2;
+ }
+
+ struct NonHAStructWithManyFields
+ {
+ float field1;
+ float field2;
+ float field3;
+ float field4;
+ float field5;
+ }
+}
--- /dev/null
+using System;
+
+namespace VirtualFunctionOverride
+{
+ interface IIFaceWithGenericMethod
+ {
+ void GenMethod<T>();
+ }
+
+ class HasMethodInterfaceOverrideOfGenericMethod : IIFaceWithGenericMethod
+ {
+ void IIFaceWithGenericMethod.GenMethod<T>() { }
+ }
+
+ class SimpleGeneric<T>
+ {
+ public override string ToString()
+ {
+ return null;
+ }
+ }
+
+ class BaseGenericWithOverload<T>
+ {
+ public virtual void MyMethod(string s) { }
+ public virtual void MyMethod(T s) { }
+ }
+
+ class DerivedGenericWithOverload<U> : BaseGenericWithOverload<U>
+ {
+ public override void MyMethod(string s) { }
+ public override void MyMethod(U s) { }
+ }
+
+ class ClassWithFinalizer
+ {
+ ~ClassWithFinalizer()
+ {
+
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Internal.TypeSystem;
+
+using Xunit;
+
+namespace TypeSystemTests
+{
+ public class GCPointerMapTests
+ {
+ TestTypeSystemContext _context;
+ ModuleDesc _testModule;
+
+ public GCPointerMapTests()
+ {
+ _context = new TestTypeSystemContext(TargetArchitecture.X86);
+ var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly");
+ _context.SetSystemModule(systemModule);
+
+ _testModule = systemModule;
+ }
+
+ [Fact]
+ public void TestInstanceMap()
+ {
+ MetadataType classWithArrayFields = _testModule.GetType("GCPointerMap", "ClassWithArrayFields");
+ MetadataType classWithStringField = _testModule.GetType("GCPointerMap", "ClassWithStringField");
+ MetadataType mixedStruct = _testModule.GetType("GCPointerMap", "MixedStruct");
+ MetadataType structWithSameGCLayoutAsMixedStruct = _testModule.GetType("GCPointerMap", "StructWithSameGCLayoutAsMixedStruct");
+ MetadataType doubleMixedStructLayout = _testModule.GetType("GCPointerMap", "DoubleMixedStructLayout");
+ MetadataType explicitlyFarPointer = _testModule.GetType("GCPointerMap", "ExplicitlyFarPointer");
+ MetadataType struct32GcPointers = _testModule.GetType("GCPointerMap", "Struct32GcPointers");
+
+ {
+ var map = GCPointerMap.FromInstanceLayout(classWithArrayFields);
+ Assert.Equal(3, map.Size);
+ Assert.Equal("011", map.ToString());
+ }
+
+ {
+ var map = GCPointerMap.FromInstanceLayout(classWithStringField);
+ Assert.Equal(4, map.Size);
+ Assert.Equal("0010", map.ToString());
+ }
+
+ {
+ var map = GCPointerMap.FromInstanceLayout(mixedStruct);
+ Assert.Equal(5, map.Size);
+ Assert.Equal("01001", map.ToString());
+ }
+
+ {
+ var map1 = GCPointerMap.FromInstanceLayout(mixedStruct);
+ var map2 = GCPointerMap.FromInstanceLayout(structWithSameGCLayoutAsMixedStruct);
+ Assert.Equal(map1.Size, map2.Size);
+ Assert.Equal(map1.ToString(), map2.ToString());
+ }
+
+ {
+ var map = GCPointerMap.FromInstanceLayout(doubleMixedStructLayout);
+ Assert.Equal(10, map.Size);
+ Assert.Equal("0100101001", map.ToString());
+ }
+
+ {
+ var map = GCPointerMap.FromInstanceLayout(explicitlyFarPointer);
+ Assert.Equal(117, map.Size);
+ Assert.Equal("100000000000000000000000000000000000000000000000000000000000000010000000000000001000000000000000000000000000000001001", map.ToString());
+ }
+
+ {
+ var map = GCPointerMap.FromInstanceLayout(struct32GcPointers);
+ Assert.Equal(32, map.Size);
+ Assert.Equal("11111111111111111111111111111111", map.ToString());
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Linq;
+using Internal.TypeSystem;
+using Xunit;
+
+namespace TypeSystemTests
+{
+ public class GenericMethodTests
+ {
+ private TestTypeSystemContext _context;
+ private ModuleDesc _testModule;
+
+ public GenericMethodTests()
+ {
+ _context = new TestTypeSystemContext(TargetArchitecture.Unknown);
+ var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly");
+ _context.SetSystemModule(systemModule);
+
+ _testModule = systemModule;
+ }
+
+ /// <summary>
+ /// Testing proper instantiation of types and methods involving generic parameters in their signature.
+ /// </summary>
+ [Fact]
+ public void TestInstantiation()
+ {
+ MetadataType t = _testModule.GetType("GenericTypes", "GenericClass`1");
+
+ // Verify that we get just type definitions.
+ Assert.NotNull(t);
+ Assert.True(t.IsTypeDefinition);
+ Assert.Equal(1, t.Instantiation.Length);
+ Assert.True(t.Instantiation[0].IsTypeDefinition);
+
+ // Verify that we got a method definition
+ MethodDesc fooMethod = t.GetMethods().First(m => m.Name == "Foo");
+ Assert.True(fooMethod.IsTypicalMethodDefinition);
+
+ // Verify that instantiating a method definition has no effect
+ MethodDesc instantiatedMethod = fooMethod.InstantiateSignature(new Instantiation(_context.GetWellKnownType(WellKnownType.Int32)), Instantiation.Empty);
+ Assert.Same(fooMethod, instantiatedMethod);
+
+ MetadataType instantiatedType = t.MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.Int32));
+
+ // Verify properties of the instantiated type
+ Assert.NotNull(instantiatedType);
+ Assert.False(instantiatedType.IsTypeDefinition);
+ Assert.Equal(1, instantiatedType.Instantiation.Length);
+ Assert.Equal(_context.GetWellKnownType(WellKnownType.Int32), instantiatedType.Instantiation[0]);
+
+ // Verify that we get an instantiated method with the proper signature
+ MethodDesc fooInstantiatedMethod = instantiatedType.GetMethods().First(m => m.Name == "Foo");
+ Assert.False(fooInstantiatedMethod.IsTypicalMethodDefinition);
+ Assert.Equal(_context.GetWellKnownType(WellKnownType.Int32), fooInstantiatedMethod.Signature.ReturnType);
+ Assert.Same(fooInstantiatedMethod.GetTypicalMethodDefinition(), fooMethod);
+ // This is not a generic method, so they should be the same
+ Assert.Same(fooInstantiatedMethod.GetMethodDefinition(), fooInstantiatedMethod);
+
+ // Verify that instantiating a type definition has no effect
+ TypeDesc newType = t.InstantiateSignature(new Instantiation(_context.GetWellKnownType(WellKnownType.Int32)), Instantiation.Empty);
+ Assert.NotNull(newType);
+ Assert.Same(newType, t);
+ }
+
+ [Fact]
+ public void TestMethodAttributes()
+ {
+ MetadataType tGen = _testModule.GetType("GenericTypes", "GenericClass`1");
+ MetadataType tDerivedGen = _testModule.GetType("GenericTypes", "DerivedGenericClass`1");
+ InstantiatedType genOfInt = tGen.MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.Int32));
+ InstantiatedType derivedGenOfInt = tDerivedGen.MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.Int32));
+ MethodDesc fooInstantiatedMethod = genOfInt.GetMethods().First(m => m.Name == "Foo");
+ MethodDesc barInstantiatedMethod = genOfInt.GetMethods().First(m => m.Name == "Bar");
+ MethodDesc fooDerivedInstantiatedMethod = derivedGenOfInt.GetMethods().First(m => m.Name == "Foo");
+
+ Assert.False(barInstantiatedMethod.IsVirtual);
+ Assert.False(barInstantiatedMethod.IsNewSlot);
+ Assert.False(barInstantiatedMethod.IsFinal);
+ Assert.False(barInstantiatedMethod.IsAbstract);
+
+ Assert.True(fooInstantiatedMethod.IsVirtual);
+ Assert.True(fooInstantiatedMethod.IsNewSlot);
+ Assert.False(fooInstantiatedMethod.IsFinal);
+ Assert.True(fooInstantiatedMethod.IsAbstract);
+
+ Assert.True(fooDerivedInstantiatedMethod.IsVirtual);
+ Assert.False(fooDerivedInstantiatedMethod.IsNewSlot);
+ Assert.True(fooDerivedInstantiatedMethod.IsFinal);
+ Assert.False(fooDerivedInstantiatedMethod.IsAbstract);
+ }
+
+ [Fact]
+ public void TestFinalize()
+ {
+ MetadataType tGen = _testModule.GetType("GenericTypes", "GenericClass`1");
+ MetadataType tDerivedGen = _testModule.GetType("GenericTypes", "DerivedGenericClass`1");
+ InstantiatedType genOfInt = tGen.MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.Int32));
+ InstantiatedType derivedGenOfInt = tDerivedGen.MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.Int32));
+ MethodDesc finalizeInstantiatedMethod = genOfInt.GetMethods().First(m => m.Name == "Finalize");
+
+ Assert.Equal(finalizeInstantiatedMethod, genOfInt.GetFinalizer());
+ Assert.Equal(finalizeInstantiatedMethod, derivedGenOfInt.GetFinalizer());
+ }
+
+ /// <summary>
+ /// Testing lookup up of a method in an instantiated type.
+ /// </summary>
+ [Fact]
+ [ActiveIssue("")]
+ public void TestMethodLookup()
+ {
+ MetadataType t = _testModule.GetType("GenericTypes", "GenericClass`1").MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.Int32));
+
+ MethodSignature sig = new MethodSignature(MethodSignatureFlags.None, 0, t.Instantiation[0], new TypeDesc[0] { });
+ MethodDesc fooMethod = t.GetMethod("Foo", sig);
+ Assert.NotNull(fooMethod);
+ }
+
+ [Fact]
+ public void TestConstructedTypeAdjustment()
+ {
+ TypeDesc intType = _context.GetWellKnownType(WellKnownType.Int32);
+ TypeDesc stringType = _context.GetWellKnownType(WellKnownType.String);
+ TypeDesc charType = _context.GetWellKnownType(WellKnownType.Char);
+ TypeDesc objectType = _context.GetWellKnownType(WellKnownType.Object);
+
+ MetadataType genericOpenType = _testModule.GetType("GenericTypes", "TwoParamGenericClass`2");
+
+ InstantiatedType genericOfCharObject = genericOpenType.MakeInstantiatedType(charType, objectType);
+ InstantiatedType genericOfCharString = genericOpenType.MakeInstantiatedType(charType, stringType);
+ InstantiatedType genericOfIntString = genericOpenType.MakeInstantiatedType(intType, stringType);
+ InstantiatedType genericOfIntObject = genericOpenType.MakeInstantiatedType(intType, objectType);
+
+ Assert.True(genericOfCharObject.IsConstructedOverType(new TypeDesc[] { charType }));
+ Assert.True(genericOfCharObject.IsConstructedOverType(new TypeDesc[] { objectType }));
+ Assert.False(genericOfCharObject.IsConstructedOverType(new TypeDesc[] { intType }));
+ Assert.False(genericOfCharObject.IsConstructedOverType(new TypeDesc[] { stringType }));
+ Assert.False(genericOfCharObject.IsConstructedOverType(new TypeDesc[] { genericOpenType }));
+
+ Assert.True(genericOfCharString.IsConstructedOverType(new TypeDesc[] { charType }));
+ Assert.False(genericOfCharString.IsConstructedOverType(new TypeDesc[] { objectType }));
+ Assert.False(genericOfCharString.IsConstructedOverType(new TypeDesc[] { intType }));
+ Assert.True(genericOfCharString.IsConstructedOverType(new TypeDesc[] { stringType }));
+
+ // Test direct replacement
+ TypeDesc testDirectReplaceAllTypes = genericOfCharObject.ReplaceTypesInConstructionOfType(new TypeDesc[] { charType, objectType }, new TypeDesc[] { intType, stringType });
+ Assert.Equal(genericOfIntString, testDirectReplaceAllTypes);
+
+ // Test direct replacement where not all types are replaced
+ TypeDesc testDirectReplaceFirstType = genericOfCharObject.ReplaceTypesInConstructionOfType(new TypeDesc[] { charType }, new TypeDesc[] { intType });
+ Assert.Equal(genericOfIntObject, testDirectReplaceFirstType);
+
+ TypeDesc testDirectReplaceSecondType = genericOfCharObject.ReplaceTypesInConstructionOfType(new TypeDesc[] { objectType }, new TypeDesc[] { stringType });
+ Assert.Equal(genericOfCharString, testDirectReplaceSecondType);
+
+ // Test Arrays
+ TypeDesc arrayChar = _context.GetArrayType(charType);
+ Assert.False(arrayChar.IsMdArray);
+ Assert.True(arrayChar.IsSzArray);
+ Assert.True(arrayChar.IsArray);
+
+ TypeDesc arrayInt = _context.GetArrayType(intType);
+ Assert.False(arrayInt.IsMdArray);
+ Assert.True(arrayInt.IsSzArray);
+ Assert.True(arrayInt.IsArray);
+
+ InstantiatedType genericOfCharArrayObject = genericOpenType.MakeInstantiatedType(arrayChar, objectType);
+ InstantiatedType genericOfIntArrayObject = genericOpenType.MakeInstantiatedType(arrayInt, objectType);
+ TypeDesc testReplaceTypeInArrayInGeneric = genericOfCharArrayObject.ReplaceTypesInConstructionOfType(new TypeDesc[] { charType }, new TypeDesc[] { intType });
+ Assert.Equal(genericOfIntArrayObject, testReplaceTypeInArrayInGeneric);
+
+ // Test multidimensional arrays
+ TypeDesc mdArrayChar = _context.GetArrayType(charType, 3);
+ Assert.True(mdArrayChar.IsMdArray);
+ Assert.False(mdArrayChar.IsSzArray);
+ Assert.True(mdArrayChar.IsArray);
+
+ TypeDesc mdArrayInt = _context.GetArrayType(intType, 3);
+ Assert.True(mdArrayInt.IsMdArray);
+ Assert.False(mdArrayInt.IsSzArray);
+ Assert.True(mdArrayInt.IsArray);
+
+ InstantiatedType genericOfCharMdArrayObject = genericOpenType.MakeInstantiatedType(mdArrayChar, objectType);
+ InstantiatedType genericOfIntMdArrayObject = genericOpenType.MakeInstantiatedType(mdArrayInt, objectType);
+ TypeDesc testReplaceTypeInMdArrayInGeneric = genericOfCharMdArrayObject.ReplaceTypesInConstructionOfType(new TypeDesc[] { charType }, new TypeDesc[] { intType });
+ Assert.Equal(genericOfIntMdArrayObject, testReplaceTypeInMdArrayInGeneric);
+
+ // Test pointers
+ TypeDesc charPointer = _context.GetPointerType(charType);
+ TypeDesc intPointer = _context.GetPointerType(intType);
+ TypeDesc testReplaceTypeInPointer = charPointer.ReplaceTypesInConstructionOfType(new TypeDesc[] { charType }, new TypeDesc[] { intType });
+ Assert.Equal(intPointer, testReplaceTypeInPointer);
+
+ Assert.True(charPointer.IsConstructedOverType(new TypeDesc[] { charType }));
+ Assert.False(charPointer.IsConstructedOverType(new TypeDesc[] { intType }));
+
+ // Test byref
+ TypeDesc charByRef = _context.GetByRefType(charType);
+ TypeDesc intByRef = _context.GetByRefType(intType);
+ TypeDesc testReplaceTypeInByRef = charByRef.ReplaceTypesInConstructionOfType(new TypeDesc[] { charType }, new TypeDesc[] { intType });
+ Assert.Equal(intByRef, testReplaceTypeInByRef);
+
+ Assert.True(charByRef.IsConstructedOverType(new TypeDesc[] { charType }));
+ Assert.False(charByRef.IsConstructedOverType(new TypeDesc[] { intType }));
+
+ // Test replace type entirely
+ TypeDesc testReplaceTypeEntirely = charByRef.ReplaceTypesInConstructionOfType(new TypeDesc[] { charByRef }, new TypeDesc[] { intByRef });
+ Assert.Equal(intByRef, testReplaceTypeEntirely);
+ Assert.True(charByRef.IsConstructedOverType(new TypeDesc[] { charByRef }));
+ }
+
+ [Fact]
+ public void TestConstructedMethodAdjustment()
+ {
+ TypeDesc intType = _context.GetWellKnownType(WellKnownType.Int32);
+ TypeDesc stringType = _context.GetWellKnownType(WellKnownType.String);
+ TypeDesc charType = _context.GetWellKnownType(WellKnownType.Char);
+ TypeDesc objectType = _context.GetWellKnownType(WellKnownType.Object);
+
+ MetadataType genericOpenType = _testModule.GetType("GenericTypes", "TwoParamGenericClass`2");
+ MetadataType nonGenericType = _testModule.GetType("GenericTypes", "NonGenericClass");
+
+ MethodDesc nonGenericOnGeneric = genericOpenType.GetMethod("NonGenericFunction", null);
+ MethodDesc genericOnGeneric = genericOpenType.GetMethod("GenericFunction", null);
+ MethodDesc genericOnNonGeneric = nonGenericType.GetMethod("GenericFunction", null);
+
+ InstantiatedType genericIntString = genericOpenType.MakeInstantiatedType(intType, stringType);
+ InstantiatedType genericCharString = genericOpenType.MakeInstantiatedType(charType, stringType);
+ InstantiatedType genericCharObject = genericOpenType.MakeInstantiatedType(charType, objectType);
+
+ MethodDesc nonGenericOnGenericIntString = genericIntString.GetMethod("NonGenericFunction", null);
+ MethodDesc nonGenericOnGenericCharString = genericCharString.GetMethod("NonGenericFunction", null);
+ MethodDesc nonGenericOnGenericCharObject = genericCharObject.GetMethod("NonGenericFunction", null);
+
+ MethodDesc genericIntStringOnGenericIntString = genericIntString.GetMethod("GenericFunction", null).MakeInstantiatedMethod(intType, stringType);
+ MethodDesc genericCharStringOnGenericCharString = genericCharString.GetMethod("GenericFunction", null).MakeInstantiatedMethod(charType, stringType);
+ MethodDesc genericCharObjectOnGenericCharObject = genericCharObject.GetMethod("GenericFunction", null).MakeInstantiatedMethod(charType, objectType);
+
+ MethodDesc genericIntStringOnNonGeneric = genericOnNonGeneric.MakeInstantiatedMethod(intType, stringType);
+ MethodDesc genericCharStringOnNonGeneric = genericOnNonGeneric.MakeInstantiatedMethod(charType, stringType);
+ MethodDesc genericCharObjectOnNonGeneric = genericOnNonGeneric.MakeInstantiatedMethod(charType, objectType);
+
+ // Test complete replacement
+ MethodDesc testDirectReplacementNonGenericOnGeneric = nonGenericOnGenericIntString.ReplaceTypesInConstructionOfMethod(new TypeDesc[] { intType, stringType }, new TypeDesc[] { charType, objectType });
+ Assert.Equal(nonGenericOnGenericCharObject, testDirectReplacementNonGenericOnGeneric);
+ MethodDesc testDirectReplacementGenericOnGeneric = genericIntStringOnGenericIntString.ReplaceTypesInConstructionOfMethod(new TypeDesc[] { intType, stringType }, new TypeDesc[] { charType, objectType });
+ Assert.Equal(genericCharObjectOnGenericCharObject, testDirectReplacementGenericOnGeneric);
+ MethodDesc testDirectReplacementGenericOnNonGeneric = genericIntStringOnNonGeneric.ReplaceTypesInConstructionOfMethod(new TypeDesc[] { intType, stringType }, new TypeDesc[] { charType, objectType });
+ Assert.Equal(genericCharObjectOnNonGeneric, testDirectReplacementGenericOnNonGeneric);
+
+ // Test replace first type in instantiation
+ MethodDesc testPartialReplacementNonGenericOnGeneric = nonGenericOnGenericIntString.ReplaceTypesInConstructionOfMethod(new TypeDesc[] { intType }, new TypeDesc[] { charType });
+ Assert.Equal(nonGenericOnGenericCharString, testPartialReplacementNonGenericOnGeneric);
+ MethodDesc testPartialReplacementGenericOnGeneric = genericIntStringOnGenericIntString.ReplaceTypesInConstructionOfMethod(new TypeDesc[] { intType }, new TypeDesc[] { charType });
+ Assert.Equal(genericCharStringOnGenericCharString, testPartialReplacementGenericOnGeneric);
+ MethodDesc testPartialReplacementGenericOnNonGeneric = genericIntStringOnNonGeneric.ReplaceTypesInConstructionOfMethod(new TypeDesc[] { intType }, new TypeDesc[] { charType });
+ Assert.Equal(genericCharStringOnNonGeneric, testPartialReplacementGenericOnNonGeneric);
+
+ // Test ArrayMethod case
+ ArrayType mdArrayChar = _context.GetArrayType(charType, 3);
+ ArrayType mdArrayInt = _context.GetArrayType(intType, 3);
+
+ MethodDesc getMethodOnMDIntArray = mdArrayInt.GetArrayMethod(ArrayMethodKind.Get);
+ MethodDesc getMethodOnMDCharArray = mdArrayChar.GetArrayMethod(ArrayMethodKind.Get);
+
+ MethodDesc testArrayMethodCase = getMethodOnMDIntArray.ReplaceTypesInConstructionOfMethod(new TypeDesc[] { intType }, new TypeDesc[] { charType });
+ Assert.Equal(getMethodOnMDCharArray, testArrayMethodCase);
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+using Internal.TypeSystem;
+using Internal.NativeFormat;
+
+using Xunit;
+
+namespace TypeSystemTests
+{
+ public class HashcodeTests
+ {
+ TestTypeSystemContext _context;
+ ModuleDesc _testModule;
+
+ public HashcodeTests()
+ {
+ _context = new TestTypeSystemContext(TargetArchitecture.X64);
+ var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly");
+ _context.SetSystemModule(systemModule);
+
+ _testModule = systemModule;
+ }
+
+ [Fact]
+ public void TestMultidimensionalArrays()
+ {
+ DefType systemArrayType = _context.GetWellKnownType(WellKnownType.Array);
+ TypeDesc objectType = _context.GetWellKnownType(WellKnownType.Object);
+
+ ArrayType objectMDArrayRank1 = _context.GetArrayType(objectType, 1);
+ ArrayType objectMDArrayRank2 = _context.GetArrayType(objectType, 2);
+ ArrayType objectMDArrayRank3 = _context.GetArrayType(objectType, 3);
+
+ Assert.Equal(TypeHashingAlgorithms.ComputeArrayTypeHashCode(objectType.GetHashCode(), 1), objectMDArrayRank1.GetHashCode());
+ Assert.Equal(TypeHashingAlgorithms.ComputeArrayTypeHashCode(objectType.GetHashCode(), 2), objectMDArrayRank2.GetHashCode());
+ Assert.Equal(TypeHashingAlgorithms.ComputeArrayTypeHashCode(objectType.GetHashCode(), 3), objectMDArrayRank3.GetHashCode());
+ }
+
+ [Fact]
+ public void TestSingleDimensionalArrays()
+ {
+ DefType systemArrayType = _context.GetWellKnownType(WellKnownType.Array);
+
+ TypeDesc objectType = _context.GetWellKnownType(WellKnownType.Object);
+
+ ArrayType objectArray = _context.GetArrayType(objectType);
+
+ Assert.Equal(TypeHashingAlgorithms.ComputeArrayTypeHashCode(objectType.GetHashCode(), -1), objectArray.GetHashCode());
+ }
+
+ [Fact]
+ public void TestNonGenericTypes()
+ {
+ DefType systemArrayType = _context.GetWellKnownType(WellKnownType.Array);
+ MetadataType nonNestedType = (MetadataType)_testModule.GetType("Hashcode", "NonNestedType");
+ TypeDesc nestedType = nonNestedType.GetNestedType("NestedType");
+
+ int expectedNonNestedTypeHashcode = TypeHashingAlgorithms.ComputeNameHashCode("Hashcode.NonNestedType");
+ int expectedNestedTypeNameHashcode = TypeHashingAlgorithms.ComputeNameHashCode("NestedType");
+ int expectedNestedTypeHashcode = TypeHashingAlgorithms.ComputeNestedTypeHashCode(expectedNonNestedTypeHashcode, expectedNestedTypeNameHashcode);
+
+ Assert.Equal(expectedNonNestedTypeHashcode, nonNestedType.GetHashCode());
+ Assert.Equal(expectedNestedTypeHashcode, nestedType.GetHashCode());
+ }
+
+ [Fact]
+ void TestGenericTypes()
+ {
+ MetadataType ilistType = (MetadataType)_testModule.GetType("System.Collections.Generic", "IList`1");
+ DefType systemArrayType = _context.GetWellKnownType(WellKnownType.Array);
+ DefType ilistOfSystemArray = ilistType.MakeInstantiatedType(systemArrayType);
+
+ int expectedIListOfTHashcode = TypeHashingAlgorithms.ComputeNameHashCode("System.Collections.Generic.IList`1");
+ int expectedSystemArrayHashcode = TypeHashingAlgorithms.ComputeNameHashCode("System.Array");
+ Assert.Equal(expectedIListOfTHashcode, ilistType.GetHashCode());
+ Assert.Equal(TypeHashingAlgorithms.ComputeGenericInstanceHashCode(expectedIListOfTHashcode, new int[] { expectedSystemArrayHashcode }), ilistOfSystemArray.GetHashCode());
+ }
+
+ [Fact]
+ public void TestInstantiatedMethods()
+ {
+ MetadataType nonNestedType = (MetadataType)_testModule.GetType("Hashcode", "NonNestedType");
+ MetadataType genericType = (MetadataType)_testModule.GetType("Hashcode", "GenericType`2");
+ DefType intType = _context.GetWellKnownType(WellKnownType.Int32);
+ DefType stringType = _context.GetWellKnownType(WellKnownType.String);
+
+ MetadataType genericTypeOfIntString = genericType.MakeInstantiatedType(intType, stringType);
+ MetadataType genericTypeOfStringInt = genericType.MakeInstantiatedType(stringType, intType);
+
+ // build up expected hash codes for the above
+ int expHashNonNestedType = TypeHashingAlgorithms.ComputeNameHashCode("Hashcode.NonNestedType");
+ Assert.Equal(expHashNonNestedType, nonNestedType.GetHashCode());
+ int expHashGenType = TypeHashingAlgorithms.ComputeNameHashCode("Hashcode.GenericType`2");
+ Assert.Equal(expHashGenType, genericType.GetHashCode());
+ int expHashInt = TypeHashingAlgorithms.ComputeNameHashCode("System.Int32");
+ Assert.Equal(expHashInt, intType.GetHashCode());
+ int expHashString = TypeHashingAlgorithms.ComputeNameHashCode("System.String");
+ Assert.Equal(expHashString, stringType.GetHashCode());
+ int expHashGenTypeOfIS = TypeHashingAlgorithms.ComputeGenericInstanceHashCode(expHashGenType, new int[] { expHashInt, expHashString });
+ Assert.Equal(expHashGenTypeOfIS, genericTypeOfIntString.GetHashCode());
+ int expHashGenTypeOfSI = TypeHashingAlgorithms.ComputeGenericInstanceHashCode(expHashGenType, new int[] { expHashString, expHashInt });
+ Assert.Equal(expHashGenTypeOfSI, genericTypeOfStringInt.GetHashCode());
+
+ // Test that instantiated method's have the right hashes
+
+ int genMethodNameHash = TypeHashingAlgorithms.ComputeNameHashCode("GenericMethod");
+ int genMethodNameAndIHash = TypeHashingAlgorithms.ComputeGenericInstanceHashCode(genMethodNameHash, new int[] { expHashInt });
+ int genMethodNameAndSHash = TypeHashingAlgorithms.ComputeGenericInstanceHashCode(genMethodNameHash, new int[] { expHashString });
+
+
+ Action<MetadataType, int> testSequence = (MetadataType typeWithGenericMethod, int expectedTypeHash) =>
+ {
+ // Uninstantiated Generic method
+ MethodDesc genMethod = typeWithGenericMethod.GetMethod("GenericMethod", null);
+ Assert.Equal(TypeHashingAlgorithms.ComputeMethodHashCode(expectedTypeHash, genMethodNameHash), genMethod.GetHashCode());
+
+ // Instantiated over int
+ MethodDesc genMethodI = genMethod.MakeInstantiatedMethod(intType);
+ Assert.Equal(TypeHashingAlgorithms.ComputeMethodHashCode(expectedTypeHash, genMethodNameAndIHash), genMethodI.GetHashCode());
+
+ // Instantiated over string
+ MethodDesc genMethodS = genMethod.MakeInstantiatedMethod(stringType);
+ Assert.Equal(TypeHashingAlgorithms.ComputeMethodHashCode(expectedTypeHash, genMethodNameAndSHash), genMethodS.GetHashCode());
+
+ // Assert they aren't the same as the other hashes
+ Assert.NotEqual(genMethodI.GetHashCode(), genMethodS.GetHashCode());
+ Assert.NotEqual(genMethodI.GetHashCode(), genMethod.GetHashCode());
+ Assert.NotEqual(genMethodS.GetHashCode(), genMethod.GetHashCode());
+ };
+
+ // Test cases on non-generic type
+ testSequence(nonNestedType, expHashNonNestedType);
+
+ // Test cases on generic type
+ testSequence(genericType, expHashGenType);
+
+ // Test cases on instantiated generic type
+ testSequence(genericTypeOfIntString, expHashGenTypeOfIS);
+ testSequence(genericTypeOfStringInt, expHashGenTypeOfSI);
+ }
+
+ [Fact]
+ public void TestPointerTypes()
+ {
+ DefType intType = _context.GetWellKnownType(WellKnownType.Int32);
+
+ int expHashInt = TypeHashingAlgorithms.ComputeNameHashCode("System.Int32");
+ Assert.Equal(expHashInt, intType.GetHashCode());
+
+ int expHashIntPointer = TypeHashingAlgorithms.ComputePointerTypeHashCode(expHashInt);
+ TypeDesc intPointerType = _context.GetPointerType(intType);
+ Assert.Equal(expHashIntPointer, intPointerType.GetHashCode());
+ }
+
+ [Fact]
+ public void TestFunctionPointerTypes()
+ {
+ DefType intType = _context.GetWellKnownType(WellKnownType.Int32);
+ DefType objectType = _context.GetWellKnownType(WellKnownType.Object);
+
+ int expHashInt = TypeHashingAlgorithms.ComputeNameHashCode("System.Int32");
+ int expHashObject = TypeHashingAlgorithms.ComputeNameHashCode("System.Object");
+
+ int expHashFnPtr = TypeHashingAlgorithms.ComputeMethodSignatureHashCode(expHashInt, new[] { expHashObject });
+
+ MethodSignature fnPtrSig = new MethodSignature(MethodSignatureFlags.None, 0, intType, new TypeDesc[] { objectType });
+ var fnPtrType = _context.GetFunctionPointerType(fnPtrSig);
+ Assert.Equal(expHashFnPtr, fnPtrType.GetHashCode());
+ }
+
+ [Fact]
+ public void TestByRefTypes()
+ {
+ DefType intType = _context.GetWellKnownType(WellKnownType.Int32);
+
+ int expHashInt = TypeHashingAlgorithms.ComputeNameHashCode("System.Int32");
+ Assert.Equal(expHashInt, intType.GetHashCode());
+
+ int expHashIntByRef = TypeHashingAlgorithms.ComputeByrefTypeHashCode(expHashInt);
+ TypeDesc intByRefType = _context.GetByRefType(intType);
+ Assert.Equal(expHashIntByRef, intByRefType.GetHashCode());
+ }
+
+ [Fact]
+ public void TestHashCodeBuilder()
+ {
+ {
+ var builder = new TypeHashingAlgorithms.HashCodeBuilder("Xy");
+ Assert.Equal(TypeHashingAlgorithms.ComputeNameHashCode("Xy"), builder.ToHashCode());
+ }
+
+ {
+ var builder = new TypeHashingAlgorithms.HashCodeBuilder("Xyz");
+ Assert.Equal(TypeHashingAlgorithms.ComputeNameHashCode("Xyz"), builder.ToHashCode());
+ }
+
+ {
+ var builder = new TypeHashingAlgorithms.HashCodeBuilder("Xy");
+ builder.Append("");
+ Assert.Equal(TypeHashingAlgorithms.ComputeNameHashCode("Xy"), builder.ToHashCode());
+ }
+
+ {
+ var builder = new TypeHashingAlgorithms.HashCodeBuilder("Xy");
+ builder.Append(".");
+ Assert.Equal(TypeHashingAlgorithms.ComputeNameHashCode("Xy."), builder.ToHashCode());
+ }
+
+ {
+ var builder = new TypeHashingAlgorithms.HashCodeBuilder("Xyz");
+ builder.Append(".");
+ Assert.Equal(TypeHashingAlgorithms.ComputeNameHashCode("Xyz."), builder.ToHashCode());
+ }
+
+ {
+ var builder = new TypeHashingAlgorithms.HashCodeBuilder("Xy");
+ builder.Append("..");
+ Assert.Equal(TypeHashingAlgorithms.ComputeNameHashCode("Xy.."), builder.ToHashCode());
+ }
+
+ {
+ var builder = new TypeHashingAlgorithms.HashCodeBuilder("Xyz");
+ builder.Append("..");
+ Assert.Equal(TypeHashingAlgorithms.ComputeNameHashCode("Xyz.."), builder.ToHashCode());
+ }
+
+ {
+ var builder = new TypeHashingAlgorithms.HashCodeBuilder("Xy");
+ builder.Append(".");
+ builder.Append("Ab");
+ Assert.Equal(TypeHashingAlgorithms.ComputeNameHashCode("Xy.Ab"), builder.ToHashCode());
+ }
+
+ {
+ var builder = new TypeHashingAlgorithms.HashCodeBuilder("Xy");
+ builder.Append(".");
+ builder.Append("Abc");
+ Assert.Equal(TypeHashingAlgorithms.ComputeNameHashCode("Xy.Abc"), builder.ToHashCode());
+ }
+
+ {
+ var builder = new TypeHashingAlgorithms.HashCodeBuilder("Xyz");
+ builder.Append(".");
+ builder.Append("Abc");
+ Assert.Equal(TypeHashingAlgorithms.ComputeNameHashCode("Xyz.Abc"), builder.ToHashCode());
+ }
+ }
+ }
+}
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <AssemblyName>ILCompiler.TypeSystem.ReadyToRun.Tests</AssemblyName>
+ <TargetFramework>netstandard2.0</TargetFramework>
+ <Configurations>Debug;Release;Checked</Configurations>
+ <!-- This seems to be required for supporting assemblies to be copied into the output -->
+ <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
+ <TestRunnerAdditionalArguments>-notrait category=failing</TestRunnerAdditionalArguments>
+ <!-- xunit.runner.visualstudio is restored for .NET Framework instead of Core-->
+ <NoWarn>$(NoWarn);NU1701</NoWarn>
+ <!-- By default the subdirectories containing CoreTestAssembly and ILTestAssembly would be
+ included in compilation of this project -->
+ <EnableDefaultItems>false</EnableDefaultItems>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <PackageReference Include="xunit.core" Version="$(XUnitVersion)" ExcludeAssets="build" />
+ <PackageReference Include="Microsoft.DotNet.XUnitExtensions" Version="$(MicrosoftDotNetXUnitExtensionsVersion)" />
+ <PackageReference Include="System.Reflection.Metadata" Version="1.8.1" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\ILCompiler.TypeSystem.ReadyToRun\ILCompiler.TypeSystem.ReadyToRun.csproj" />
+ <!-- Make sure the test data gets built -->
+ <ProjectReference Include="CoreTestAssembly\CoreTestAssembly.csproj">
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <OutputItemType>Content</OutputItemType>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </ProjectReference>
+ <ProjectReference Include="ILTestAssembly\ILTestAssembly.ilproj">
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <OutputItemType>Content</OutputItemType>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="ArchitectureSpecificFieldLayoutTests.cs" />
+ <Compile Include="CanonicalizationTests.cs" />
+ <Compile Include="ConstraintsValidationTest.cs" />
+ <Compile Include="GCPointerMapTests.cs" />
+ <Compile Include="GenericTypeAndMethodTests.cs" />
+ <Compile Include="CastingTests.cs" />
+ <Compile Include="HashcodeTests.cs" />
+ <Compile Include="ILDisassemblerTests.cs" />
+ <Compile Include="InterfacesTests.cs" />
+ <Compile Include="RuntimeDeterminedTypesTests.cs" />
+ <Compile Include="SyntheticVirtualOverrideTests.cs" />
+ <Compile Include="TestMetadataFieldLayoutAlgorithm.cs" />
+ <Compile Include="TypeNameParsingTests.cs" />
+ <Compile Include="UniversalGenericFieldLayoutTests.cs" />
+ <Compile Include="ValueTypeShapeCharacteristicsTests.cs" />
+ <Compile Include="VirtualFunctionOverrideTests.cs" />
+ <Compile Include="InstanceFieldLayoutTests.cs" />
+ <Compile Include="StaticFieldLayoutTests.cs" />
+ <Compile Include="TestTypeSystemContext.cs" />
+ <Compile Include="WellKnownTypeTests.cs" />
+ </ItemGroup>
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+
+using Internal.IL;
+using Internal.TypeSystem;
+using Internal.TypeSystem.Ecma;
+
+using Xunit;
+
+namespace TypeSystemTests
+{
+ public class ILDisassemblerTests
+ {
+ private TestTypeSystemContext _context;
+ private ModuleDesc _testModule;
+
+ public ILDisassemblerTests()
+ {
+ _context = new TestTypeSystemContext(TargetArchitecture.X64);
+ var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly");
+ _context.SetSystemModule(systemModule);
+
+ _testModule = _context.GetModuleForSimpleName("ILTestAssembly");
+ }
+
+ [Fact]
+ public void TestGenericNameFormatting()
+ {
+ MetadataType testClass = _testModule.GetType("ILDisassembler", "TestGenericClass`1");
+ EcmaMethod testMethod = (EcmaMethod)testClass.GetMethod("TestMethod", null);
+ EcmaMethodIL methodIL = EcmaMethodIL.Create(testMethod);
+
+ Dictionary<int, string> interestingLines = new Dictionary<int, string>
+ {
+ { 4, "IL_0003: ldstr \"Hello \\\"World\\\"!\\n\"" },
+ { 9, "IL_000D: call instance void class ILDisassembler.TestGenericClass`1<!TClassParam>::VoidGenericMethod<string, valuetype ILDisassembler.TestStruct>(!!0, int32, native int, class ILDisassembler.TestClass&)" },
+ { 14, "IL_0017: initobj !TClassParam" },
+ { 16, "IL_001E: call !!0 class ILDisassembler.TestGenericClass`1<!TClassParam>::MethodParamGenericMethod<class ILDisassembler.TestClass>(class ILDisassembler.TestGenericClass`1<!!0>, class ILDisassembler.TestGenericClass`1/Nested<!0>, valuetype ILDisassembler.TestStruct*[], !0)" },
+ { 24, "IL_0030: call !!0 class ILDisassembler.TestGenericClass`1<!TClassParam>::MethodParamGenericMethod<!0>(class ILDisassembler.TestGenericClass`1<!!0>, class ILDisassembler.TestGenericClass`1/Nested<!0>, valuetype ILDisassembler.TestStruct*[], !0)" },
+ { 26, "IL_0036: ldtoken !TClassParam" },
+ { 28, "IL_003C: ldtoken valuetype [CoreTestAssembly]System.Nullable`1<int32>" },
+ { 31, "IL_0043: ldc.r8 3.14" },
+ { 32, "IL_004C: ldc.r4 1.68" },
+ { 34, "IL_0053: call instance valuetype ILDisassembler.TestStruct class ILDisassembler.TestGenericClass`1<!TClassParam>::NonGenericMethod(float64, float32, int16)" },
+ { 37, "IL_005A: ldflda !0 class ILDisassembler.TestGenericClass`1<!TClassParam>::somefield" },
+ { 41, "IL_0067: stfld class ILDisassembler.TestClass class ILDisassembler.TestGenericClass`1<!TClassParam>::otherfield" },
+ { 44, "IL_006E: stfld class ILDisassembler.TestGenericClass`1<class ILDisassembler.TestGenericClass`1<class ILDisassembler.TestClass>> class ILDisassembler.TestGenericClass`1<!TClassParam>::genericfield" },
+ { 47, "IL_0075: stfld !0[] class ILDisassembler.TestGenericClass`1<!TClassParam>::arrayfield" },
+ { 48, "IL_007A: call void ILDisassembler.TestClass::NonGenericMethod()" },
+ { 49, "IL_007F: ldsflda valuetype ILDisassembler.TestStruct ILDisassembler.TestClass::somefield" },
+ { 50, "IL_0084: initobj ILDisassembler.TestStruct" }
+ };
+
+ ILDisassembler disasm = new ILDisassembler(methodIL);
+
+ int numLines = 1;
+ while (disasm.HasNextInstruction)
+ {
+ string line = disasm.GetNextInstruction();
+ string expectedLine;
+ if (interestingLines.TryGetValue(numLines, out expectedLine))
+ {
+ Assert.Equal(expectedLine, line);
+ }
+ numLines++;
+ }
+
+ Assert.Equal(52, numLines);
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// While this is all expressible in C#, we need a deterministic IL to test the disassembler, hence
+// this is in IL.
+
+.class private sequential ansi sealed beforefieldinit ILDisassembler.TestStruct
+ extends [CoreTestAssembly]System.ValueType
+{
+ .pack 0
+ .size 1
+} // end of class ILDisassembler.TestStruct
+
+.class private auto ansi beforefieldinit ILDisassembler.TestClass
+ extends [CoreTestAssembly]System.Object
+{
+ .field public static valuetype ILDisassembler.TestStruct somefield
+ .method public hidebysig static void NonGenericMethod() cil managed
+ {
+ // Code size 1 (0x1)
+ .maxstack 8
+ ret
+ } // end of method TestClass::NonGenericMethod
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ ldarg.0
+ call instance void [CoreTestAssembly]System.Object::.ctor()
+ ret
+ } // end of method TestClass::.ctor
+
+} // end of class ILDisassembler.TestClass
+
+.class private auto ansi beforefieldinit ILDisassembler.TestGenericClass`1<TClassParam>
+ extends [CoreTestAssembly]System.Object
+{
+ .class auto ansi nested public beforefieldinit Nested<TClassParam>
+ extends [CoreTestAssembly]System.Object
+ {
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ ldarg.0
+ call instance void [CoreTestAssembly]System.Object::.ctor()
+ ret
+ } // end of method Nested::.ctor
+
+ } // end of class Nested
+
+ .field private !TClassParam somefield
+ .field private class ILDisassembler.TestClass otherfield
+ .field private class ILDisassembler.TestGenericClass`1<class ILDisassembler.TestGenericClass`1<class ILDisassembler.TestClass>> genericfield
+ .field private !TClassParam[] arrayfield
+ .method public hidebysig instance void
+ VoidGenericMethod<TMethodParam1,MethodParam2>(!!TMethodParam1 p,
+ int32 x,
+ native int y,
+ class ILDisassembler.TestClass& z) cil managed
+ {
+ // Code size 1 (0x1)
+ .maxstack 8
+ ret
+ } // end of method TestGenericClass`1::VoidGenericMethod
+
+ .method public hidebysig static !!TMethodParam
+ MethodParamGenericMethod<TMethodParam>(class ILDisassembler.TestGenericClass`1<!!TMethodParam> x,
+ class ILDisassembler.TestGenericClass`1/Nested<!TClassParam> y,
+ valuetype ILDisassembler.TestStruct*[] z,
+ !TClassParam w) cil managed
+ {
+ // Code size 10 (0xa)
+ .maxstack 1
+ .locals init ([0] !!TMethodParam V_0)
+ ldloca.s V_0
+ initobj !!TMethodParam
+ ldloc.0
+ ret
+ } // end of method TestGenericClass`1::MethodParamGenericMethod
+
+ .method public hidebysig instance valuetype ILDisassembler.TestStruct
+ NonGenericMethod(float64 x,
+ float32 y,
+ int16 z) cil managed
+ {
+ // Code size 10 (0xa)
+ .maxstack 1
+ .locals init ([0] valuetype ILDisassembler.TestStruct V_0)
+ ldloca.s V_0
+ initobj ILDisassembler.TestStruct
+ ldloc.0
+ ret
+ } // end of method TestGenericClass`1::NonGenericMethod
+
+ .method public hidebysig instance void
+ TestMethod() cil managed
+ {
+ // Code size 162 (0xa2)
+ .maxstack 5
+ .locals init ([0] class ILDisassembler.TestClass t,
+ [1] !TClassParam V_1)
+ ldnull
+ stloc.0
+ ldarg.0
+ ldstr "Hello \"World\"!\n"
+ ldc.i4.0
+ ldc.i4.0
+ conv.i
+ ldloca.s t
+ call instance void class ILDisassembler.TestGenericClass`1<!TClassParam>::VoidGenericMethod<string,valuetype ILDisassembler.TestStruct>(!!0,
+ int32,
+ native int,
+ class ILDisassembler.TestClass&)
+ ldnull
+ ldnull
+ ldnull
+ ldloca.s V_1
+ initobj !TClassParam
+ ldloc.1
+ call !!0 class ILDisassembler.TestGenericClass`1<!TClassParam>::MethodParamGenericMethod<class ILDisassembler.TestClass>(class ILDisassembler.TestGenericClass`1<!!0>,
+ class ILDisassembler.TestGenericClass`1/Nested<!0>,
+ valuetype ILDisassembler.TestStruct*[],
+ !0)
+ pop
+ ldnull
+ ldnull
+ ldnull
+ ldloca.s V_1
+ initobj !TClassParam
+ ldloc.1
+ call !!0 class ILDisassembler.TestGenericClass`1<!TClassParam>::MethodParamGenericMethod<!0>(class ILDisassembler.TestGenericClass`1<!!0>,
+ class ILDisassembler.TestGenericClass`1/Nested<!0>,
+ valuetype ILDisassembler.TestStruct*[],
+ !0)
+ pop
+ ldtoken !TClassParam
+ pop
+ ldtoken valuetype [CoreTestAssembly]System.Nullable`1<int32>
+ pop
+ ldarg.0
+ ldc.r8 3.1400000000000001
+ ldc.r4 1.6799999
+ ldc.i4.s 42
+ call instance valuetype ILDisassembler.TestStruct class ILDisassembler.TestGenericClass`1<!TClassParam>::NonGenericMethod(float64,
+ float32,
+ int16)
+ pop
+ ldarg.0
+ ldflda !0 class ILDisassembler.TestGenericClass`1<!TClassParam>::somefield
+ initobj !TClassParam
+ ldarg.0
+ ldnull
+ stfld class ILDisassembler.TestClass class ILDisassembler.TestGenericClass`1<!TClassParam>::otherfield
+ ldarg.0
+ ldnull
+ stfld class ILDisassembler.TestGenericClass`1<class ILDisassembler.TestGenericClass`1<class ILDisassembler.TestClass>> class ILDisassembler.TestGenericClass`1<!TClassParam>::genericfield
+ ldarg.0
+ ldnull
+ stfld !0[] class ILDisassembler.TestGenericClass`1<!TClassParam>::arrayfield
+ call void ILDisassembler.TestClass::NonGenericMethod()
+ ldsflda valuetype ILDisassembler.TestStruct ILDisassembler.TestClass::somefield
+ initobj ILDisassembler.TestStruct
+ ret
+ } // end of method TestGenericClass`1::TestMethod
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ ldarg.0
+ call instance void [CoreTestAssembly]System.Object::.ctor()
+ ret
+ } // end of method TestGenericClass`1::.ctor
+
+} // end of class ILDisassembler.TestGenericClass`1
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk.IL">
+
+ <PropertyGroup>
+ <OutputType>Library</OutputType>
+ <AssemblyName>ILTestAssembly</AssemblyName>
+ <SkipTestRun>true</SkipTestRun>
+ <TargetFramework>netstandard2.0</TargetFramework>
+ <EnableDefaultItems>false</EnableDefaultItems>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <!-- Main has to be the first file. Do not put anything before Main.il -->
+ <Compile Include="Main.il" />
+
+ <Compile Include="ILDisassembler.il" />
+ <Compile Include="InstanceFieldLayout.il" />
+ <Compile Include="StaticFieldLayout.il" />
+ <Compile Include="VirtualFunctionOverride.il" />
+ </ItemGroup>
+
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.class public sequential ansi sealed beforefieldinit IsByRefLike.InvalidStruct
+ extends [CoreTestAssembly]System.ValueType
+{
+ .field private valuetype [CoreTestAssembly]System.ByReference`1<object> ByRef
+}
+
+.class public auto ansi beforefieldinit IsByRefLike.InvalidClass1
+ extends [CoreTestAssembly]System.Object
+{
+ .field private valuetype [CoreTestAssembly]System.ByReference`1<object> ByRef
+}
+
+.class public auto ansi beforefieldinit IsByRefLike.InvalidClass2
+ extends [CoreTestAssembly]System.Object
+{
+ .custom instance void [CoreTestAssembly]System.Runtime.CompilerServices.IsByRefLikeAttribute::.ctor() = ( 01 00 00 00 )
+ .field private valuetype [CoreTestAssembly]System.ByReference`1<object> ByRef
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern CoreTestAssembly
+{
+}
+
+.assembly ILTestAssembly
+{
+}
+
+// Mark this as core library so that ILASM doesn't take the code paths that
+// 'fix' all the references to e.g. System.Object to be mscorlib.
+.mscorlib
+
+
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.class public auto ansi beforefieldinit StaticFieldLayout.RvaStatics
+ extends [CoreTestAssembly]System.Object
+{
+ .field private static int32 StaticInitedInt at D_00004000
+ .data D_00004000 = bytearray (12 34 56 78)
+}
+
+.class public auto ansi beforefieldinit StaticFieldLayout.FunctionPointerType
+ extends [CoreTestAssembly]System.Object
+{
+ .field private static int32 StaticIntField;
+ .field private static method object *(object) StaticMethodField;
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.class public auto ansi beforefieldinit VirtualFunctionOverride.ExplicitOverride
+ extends [CoreTestAssembly]System.Object
+{
+ .method public virtual int32 MyGetHashCode()
+ {
+ .override [CoreTestAssembly]System.Object::GetHashCode
+
+ ldc.i4 42
+ ret
+ }
+}
+
+.class private auto ansi beforefieldinit VirtualFunctionOverride.MyBase
+ extends [CoreTestAssembly]System.Object
+{
+ .method public hidebysig newslot specialname virtual
+ instance int32 get_foo() cil managed
+ {
+ ldc.i4 42
+ ret
+ }
+
+ .property instance int32 foo()
+ {
+ .get instance int32 VirtualFunctionOverride.MyBase::get_foo()
+ }
+}
+
+.class private auto ansi beforefieldinit VirtualFunctionOverride.MyDerived2
+ extends VirtualFunctionOverride.MyBase
+{
+ .method public hidebysig newslot specialname virtual
+ instance int32 get_foo() cil managed
+ {
+ .override VirtualFunctionOverride.MyBase::get_foo
+
+ ldc.i4 42
+ ret
+ }
+
+ .property instance int32 foo()
+ {
+ .get instance int32 VirtualFunctionOverride.MyDerived2::get_foo()
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+
+using Internal.TypeSystem;
+
+using Xunit;
+
+namespace TypeSystemTests
+{
+ public class InstanceFieldLayoutTests
+ {
+ TestTypeSystemContext _context;
+ ModuleDesc _testModule;
+ ModuleDesc _ilTestModule;
+
+ public InstanceFieldLayoutTests()
+ {
+ _context = new TestTypeSystemContext(TargetArchitecture.X64);
+ var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly");
+ _context.SetSystemModule(systemModule);
+
+ _testModule = systemModule;
+ _ilTestModule = _context.CreateModuleForSimpleName("ILTestAssembly");
+ }
+
+ [Fact]
+ public void TestExplicitLayout()
+ {
+ MetadataType t = _testModule.GetType("Explicit", "Class1");
+
+ // With 64bit, there should be 8 bytes for the System.Object EE data pointer +
+ // 10 bytes up until the offset of the char field + the char size of 2 + we
+ // round up the whole instance size to the next pointer size (+4) = 24
+ Assert.Equal(24, t.InstanceByteCount.AsInt);
+
+ foreach (var field in t.GetFields())
+ {
+ if (field.IsStatic)
+ continue;
+
+ if (field.Name == "Bar")
+ {
+ // Bar has explicit offset 4 and is in a class (with S.O size overhead of <pointer size>)
+ // Therefore it should have offset 4 + 8 = 12
+ Assert.Equal(12, field.Offset.AsInt);
+ }
+ else if (field.Name == "Baz")
+ {
+ // Baz has explicit offset 10. 10 + 8 = 18
+ Assert.Equal(18, field.Offset.AsInt);
+ }
+ else
+ {
+ Assert.True(false);
+ }
+ }
+ }
+
+ [Fact]
+ public void TestExplicitLayoutThatIsEmpty()
+ {
+ var explicitEmptyClassType = _testModule.GetType("Explicit", "ExplicitEmptyClass");
+
+ // ExplicitEmpty class has 8 from System.Object overhead = 8
+ Assert.Equal(8, explicitEmptyClassType.InstanceByteCount.AsInt);
+
+ var explicitEmptyStructType = _testModule.GetType("Explicit", "ExplicitEmptyStruct");
+
+ // ExplicitEmpty class has 0 bytes in it... so instance field size gets pushed up to 1.
+ Assert.Equal(1, explicitEmptyStructType.InstanceFieldSize.AsInt);
+ }
+
+ [Fact]
+ public void TestExplicitTypeLayoutWithSize()
+ {
+ var explicitSizeType = _testModule.GetType("Explicit", "ExplicitSize");
+ Assert.Equal(48, explicitSizeType.InstanceByteCount.AsInt);
+ }
+
+ [Fact]
+ public void TestExplicitTypeLayoutWithInheritance()
+ {
+ MetadataType class2Type = _testModule.GetType("Explicit", "Class2");
+
+ // Class1 has size 24 which Class2 inherits from. Class2 adds a byte at offset 20, so + 21
+ // = 45, rounding up to the next pointer size = 48
+ Assert.Equal(48, class2Type.InstanceByteCount.AsInt);
+
+ foreach (var f in class2Type.GetFields())
+ {
+ if (f.IsStatic)
+ continue;
+
+ if (f.Name == "Lol")
+ {
+ // First field after base class, with offset 0 so it should lie on the byte count of
+ // the base class = 24
+ Assert.Equal(24, f.Offset.AsInt);
+ }
+ else if (f.Name == "Omg")
+ {
+ // Offset 20 from base class byte count = 44
+ Assert.Equal(44, f.Offset.AsInt);
+ }
+ else
+ {
+ Assert.True(false);
+ }
+ }
+ }
+
+ [Fact]
+ public void TestInvalidExplicitTypeLayout()
+ {
+ {
+ DefType type = _testModule.GetType("Explicit", "MisalignedPointer");
+ Assert.Throws<TypeSystemException.TypeLoadException>(() => type.ComputeInstanceLayout(InstanceLayoutKind.TypeAndFields));
+ }
+
+ {
+ DefType type = _testModule.GetType("Explicit", "MisalignedByRef");
+ Assert.Throws<TypeSystemException.TypeLoadException>(() => type.ComputeInstanceLayout(InstanceLayoutKind.TypeAndFields));
+ }
+ }
+
+ [Fact]
+ public void TestSequentialTypeLayout()
+ {
+ MetadataType class1Type = _testModule.GetType("Sequential", "Class1");
+
+ // Byte count
+ // Base Class 8
+ // MyInt 4
+ // MyBool 1 + 1 padding
+ // MyChar 2
+ // MyString 8
+ // MyByteArray 8
+ // MyClass1SelfRef 8
+ // -------------------
+ // 40 (0x28)
+ Assert.Equal(0x28, class1Type.InstanceByteCount.AsInt);
+
+ foreach (var f in class1Type.GetFields())
+ {
+ if (f.IsStatic)
+ continue;
+
+ switch (f.Name)
+ {
+ case "MyInt":
+ Assert.Equal(0x8, f.Offset.AsInt);
+ break;
+ case "MyBool":
+ Assert.Equal(0xC, f.Offset.AsInt);
+ break;
+ case "MyChar":
+ Assert.Equal(0xE, f.Offset.AsInt);
+ break;
+ case "MyString":
+ Assert.Equal(0x10, f.Offset.AsInt);
+ break;
+ case "MyByteArray":
+ Assert.Equal(0x18, f.Offset.AsInt);
+ break;
+ case "MyClass1SelfRef":
+ Assert.Equal(0x20, f.Offset.AsInt);
+ break;
+ default:
+ Assert.True(false);
+ break;
+ }
+ }
+ }
+
+ [Fact]
+ public void TestSequentialTypeLayoutInheritance()
+ {
+ MetadataType class2Type = _testModule.GetType("Sequential", "Class2");
+
+ // Byte count
+ // Base Class 40
+ // MyInt2 4 + 4 byte padding to make class size % pointer size == 0
+ // -------------------
+ // 48 (0x30)
+ Assert.Equal(0x30, class2Type.InstanceByteCount.AsInt);
+
+ foreach (var f in class2Type.GetFields())
+ {
+ if (f.IsStatic)
+ continue;
+
+ switch (f.Name)
+ {
+ case "MyInt2":
+ Assert.Equal(0x28, f.Offset.AsInt);
+ break;
+ default:
+ Assert.True(false);
+ break;
+ }
+ }
+ }
+
+ [Fact]
+ public void TestSequentialTypeLayoutStruct()
+ {
+ MetadataType struct0Type = _testModule.GetType("Sequential", "Struct0");
+
+ // Byte count
+ // bool b1 1
+ // bool b2 1
+ // bool b3 1 + 1 padding for int alignment
+ // int i1 4
+ // string s1 8
+ // -------------------
+ // 16 (0x10)
+ Assert.Equal(0x10, struct0Type.InstanceByteCount.AsInt);
+
+ foreach (var f in struct0Type.GetFields())
+ {
+ if (f.IsStatic)
+ continue;
+
+ switch (f.Name)
+ {
+ case "b1":
+ Assert.Equal(0x0, f.Offset.AsInt);
+ break;
+ case "b2":
+ Assert.Equal(0x1, f.Offset.AsInt);
+ break;
+ case "b3":
+ Assert.Equal(0x2, f.Offset.AsInt);
+ break;
+ case "i1":
+ Assert.Equal(0x4, f.Offset.AsInt);
+ break;
+ case "s1":
+ Assert.Equal(0x8, f.Offset.AsInt);
+ break;
+ default:
+ Assert.True(false);
+ break;
+ }
+ }
+ }
+
+ [Fact]
+ // Test that when a struct is used as a field, we use its instance byte size as the size (ie, treat it
+ // as a value type) and not a pointer size.
+ public void TestSequentialTypeLayoutStructEmbedded()
+ {
+ MetadataType struct1Type = _testModule.GetType("Sequential", "Struct1");
+
+ // Byte count
+ // struct MyStruct0 16
+ // bool MyBool 1
+ // -----------------------
+ // 24 (0x18)
+ Assert.Equal(0x18, struct1Type.InstanceByteCount.AsInt);
+
+ foreach (var f in struct1Type.GetFields())
+ {
+ if (f.IsStatic)
+ continue;
+
+ switch (f.Name)
+ {
+ case "MyStruct0":
+ Assert.Equal(0x0, f.Offset.AsInt);
+ break;
+ case "MyBool":
+ Assert.Equal(0x10, f.Offset.AsInt);
+ break;
+ default:
+ Assert.True(false);
+ break;
+ }
+ }
+ }
+
+ [Fact]
+ public void TestAutoLayoutStruct()
+ {
+ MetadataType structWithIntCharType = _testModule.GetType("Auto", "StructWithIntChar");
+
+ // Byte count
+ // MyStructInt 4
+ // MyStructChar 2
+ // -------------------
+ // 8 (0x08)
+ Assert.Equal(0x08, structWithIntCharType.InstanceByteCount.AsInt);
+
+ foreach (var f in structWithIntCharType.GetFields())
+ {
+ if (f.IsStatic)
+ continue;
+
+ switch (f.Name)
+ {
+ case "MyStructInt":
+ Assert.Equal(0x00, f.Offset.AsInt);
+ break;
+ case "MyStructChar":
+ Assert.Equal(0x04, f.Offset.AsInt);
+ break;
+ default:
+ Assert.True(false);
+ break;
+ }
+ }
+ }
+
+ [Fact]
+ public void TestAutoTypeLayoutClassContainingStructs()
+ {
+ MetadataType classContainingStructsType = _testModule.GetType("Auto", "ClassContainingStructs");
+
+ // Byte count
+ // Base Class 8
+ // MyByteArray 8
+ // MyString1 8
+ // MyDouble 8
+ // MyLong 8
+ // MyInt 4
+ // MyChar1 2
+ // MyBool1 1
+ // MyBool2 1
+ // MyStructWithBool 1 + 3 to align up to the next multiple of 4 after placing a value class
+ // 4 byte padding to make offset % pointer size == 0 before placing the next value class
+ // MyStructWithIntChar 6 + 2 to align up to the next multiple of 4 after placing a value class
+ // MyStructWithChar 2 + 2 to align up to the next multiple of 4 after placing a value class + 4 byte padding to make class size % pointer size == 0
+ // -------------------
+ // 72 (0x48)
+ Assert.Equal(0x48, classContainingStructsType.InstanceByteCount.AsInt);
+
+ foreach (var f in classContainingStructsType.GetFields())
+ {
+ if (f.IsStatic)
+ continue;
+
+ switch (f.Name)
+ {
+ case "MyByteArray":
+ Assert.Equal(0x08, f.Offset.AsInt);
+ break;
+ case "MyString1":
+ Assert.Equal(0x10, f.Offset.AsInt);
+ break;
+ case "MyDouble":
+ Assert.Equal(0x18, f.Offset.AsInt);
+ break;
+ case "MyLong":
+ Assert.Equal(0x20, f.Offset.AsInt);
+ break;
+ case "MyInt":
+ Assert.Equal(0x28, f.Offset.AsInt);
+ break;
+ case "MyChar1":
+ Assert.Equal(0x2C, f.Offset.AsInt);
+ break;
+ case "MyBool1":
+ Assert.Equal(0x2E, f.Offset.AsInt);
+ break;
+ case "MyBool2":
+ Assert.Equal(0x2F, f.Offset.AsInt);
+ break;
+ case "MyStructWithBool":
+ Assert.Equal(0x30, f.Offset.AsInt);
+ break;
+ case "MyStructWithIntChar":
+ Assert.Equal(0x38, f.Offset.AsInt);
+ break;
+ case "MyStructWithChar":
+ Assert.Equal(0x40, f.Offset.AsInt);
+ break;
+ default:
+ Assert.True(false);
+ break;
+ }
+ }
+ }
+
+ [Fact]
+ public void TestAutoTypeLayoutBaseClass7BytesRemaining()
+ {
+ MetadataType baseClass7BytesRemainingType = _testModule.GetType("Auto", "BaseClass7BytesRemaining");
+
+ // Byte count
+ // Base Class 8
+ // MyByteArray1 8
+ // MyString1 8
+ // MyDouble1 8
+ // MyLong1 8
+ // MyBool1 1 + 7 byte padding to make class size % pointer size == 0
+ // -------------------
+ // 48 (0x30)
+ Assert.Equal(0x30, baseClass7BytesRemainingType.InstanceByteCount.AsInt);
+
+ foreach (var f in baseClass7BytesRemainingType.GetFields())
+ {
+ if (f.IsStatic)
+ continue;
+
+ switch (f.Name)
+ {
+ case "MyByteArray1":
+ Assert.Equal(0x08, f.Offset.AsInt);
+ break;
+ case "MyString1":
+ Assert.Equal(0x10, f.Offset.AsInt);
+ break;
+ case "MyDouble1":
+ Assert.Equal(0x18, f.Offset.AsInt);
+ break;
+ case "MyLong1":
+ Assert.Equal(0x20, f.Offset.AsInt);
+ break;
+ case "MyBool1":
+ Assert.Equal(0x28, f.Offset.AsInt);
+ break;
+ default:
+ Assert.True(false);
+ break;
+ }
+ }
+ }
+
+ [Fact]
+ public void TestAutoTypeLayoutBaseClass4BytesRemaining()
+ {
+ MetadataType baseClass4BytesRemainingType = _testModule.GetType("Auto", "BaseClass4BytesRemaining");
+
+ // Byte count
+ // Base Class 8
+ // MyLong1 8
+ // MyUint1 4 + 4 byte padding to make class size % pointer size == 0
+ // -------------------
+ // 24 (0x18)
+ Assert.Equal(0x18, baseClass4BytesRemainingType.InstanceByteCount.AsInt);
+
+ foreach (var f in baseClass4BytesRemainingType.GetFields())
+ {
+ if (f.IsStatic)
+ continue;
+
+ switch (f.Name)
+ {
+ case "MyLong1":
+ Assert.Equal(0x08, f.Offset.AsInt);
+ break;
+ case "MyUint1":
+ Assert.Equal(0x10, f.Offset.AsInt);
+ break;
+ default:
+ Assert.True(false);
+ break;
+ }
+ }
+ }
+
+ [Fact]
+ public void TestAutoTypeLayoutBaseClass3BytesRemaining()
+ {
+ MetadataType baseClass3BytesRemainingType = _testModule.GetType("Auto", "BaseClass3BytesRemaining");
+
+ // Byte count
+ // Base Class 8
+ // MyString1 8
+ // MyInt1 4
+ // MyBool1 1 + 3 byte padding to make class size % pointer size == 0
+ // -------------------
+ // 24 (0x18)
+ Assert.Equal(0x18, baseClass3BytesRemainingType.InstanceByteCount.AsInt);
+
+ foreach (var f in baseClass3BytesRemainingType.GetFields())
+ {
+ if (f.IsStatic)
+ continue;
+
+ switch (f.Name)
+ {
+ case "MyString1":
+ Assert.Equal(0x08, f.Offset.AsInt);
+ break;
+ case "MyInt1":
+ Assert.Equal(0x10, f.Offset.AsInt);
+ break;
+ case "MyBool1":
+ Assert.Equal(0x14, f.Offset.AsInt);
+ break;
+ default:
+ Assert.True(false);
+ break;
+ }
+ }
+ }
+
+ [Fact]
+ public void TestAutoTypeLayoutOptimizePartial()
+ {
+ MetadataType optimizePartialType = _testModule.GetType("Auto", "OptimizePartial");
+
+ // Byte count
+ // Base Class 41 (unaligned)
+ // OptBool 1
+ // OptChar 2 + 4 byte padding to make class size % pointer size == 0
+ // NoOptString 8
+ // NoOptLong 8
+ // -------------------
+ // 64 (0x40)
+ Assert.Equal(0x40, optimizePartialType.InstanceByteCount.AsInt);
+
+ foreach (var f in optimizePartialType.GetFields())
+ {
+ if (f.IsStatic)
+ continue;
+
+ switch (f.Name)
+ {
+ case "OptBool":
+ Assert.Equal(0x29, f.Offset.AsInt);
+ break;
+ case "OptChar":
+ Assert.Equal(0x2A, f.Offset.AsInt);
+ break;
+ case "NoOptString":
+ Assert.Equal(0x30, f.Offset.AsInt);
+ break;
+ case "NoOptLong":
+ Assert.Equal(0x38, f.Offset.AsInt);
+ break;
+ default:
+ Assert.True(false);
+ break;
+ }
+ }
+ }
+
+ [Fact]
+ public void TestAutoTypeLayoutOptimize7Bools()
+ {
+ MetadataType optimize7BoolsType = _testModule.GetType("Auto", "Optimize7Bools");
+
+ // Byte count
+ // Base Class 41 (unaligned)
+ // OptBool1 1
+ // OptBool2 1
+ // OptBool3 1
+ // OptBool4 1
+ // OptBool5 1
+ // OptBool6 1
+ // OptBool7 1
+ // NoOptString 8
+ // NoOptBool8 1 + 7 byte padding to make class size % pointer size == 0
+ // -------------------
+ // 64 (0x40)
+ Assert.Equal(0x40, optimize7BoolsType.InstanceByteCount.AsInt);
+
+ foreach (var f in optimize7BoolsType.GetFields())
+ {
+ if (f.IsStatic)
+ continue;
+
+ switch (f.Name)
+ {
+ case "OptBool1":
+ Assert.Equal(0x29, f.Offset.AsInt);
+ break;
+ case "OptBool2":
+ Assert.Equal(0x2A, f.Offset.AsInt);
+ break;
+ case "OptBool3":
+ Assert.Equal(0x2B, f.Offset.AsInt);
+ break;
+ case "OptBool4":
+ Assert.Equal(0x2C, f.Offset.AsInt);
+ break;
+ case "OptBool5":
+ Assert.Equal(0x2D, f.Offset.AsInt);
+ break;
+ case "OptBool6":
+ Assert.Equal(0x2E, f.Offset.AsInt);
+ break;
+ case "OptBool7":
+ Assert.Equal(0x2F, f.Offset.AsInt);
+ break;
+ case "NoOptString":
+ Assert.Equal(0x30, f.Offset.AsInt);
+ break;
+ case "NoOptBool8":
+ Assert.Equal(0x38, f.Offset.AsInt);
+ break;
+ default:
+ Assert.True(false);
+ break;
+ }
+ }
+ }
+
+ [Fact]
+ public void TestAutoTypeLayoutOptimizeAlignedFields()
+ {
+ MetadataType optimizeAlignedFieldsType = _testModule.GetType("Auto", "OptimizeAlignedFields");
+
+ // Byte count
+ // Base Class 41 (unaligned)
+ // OptBool1 1
+ // OptChar1 2
+ // OptChar2 2
+ // OptBool2 1
+ // OptBool3 1
+ // NoOptString 8
+ // NoOptBool4 1 + 7 byte padding to make class size % pointer size == 0
+ // -------------------
+ // 64 (0x40)
+ Assert.Equal(0x40, optimizeAlignedFieldsType.InstanceByteCount.AsInt);
+
+ foreach (var f in optimizeAlignedFieldsType.GetFields())
+ {
+ if (f.IsStatic)
+ continue;
+
+ switch (f.Name)
+ {
+ case "OptBool1":
+ Assert.Equal(0x29, f.Offset.AsInt);
+ break;
+ case "OptChar1":
+ Assert.Equal(0x2A, f.Offset.AsInt);
+ break;
+ case "OptChar2":
+ Assert.Equal(0x2C, f.Offset.AsInt);
+ break;
+ case "OptBool2":
+ Assert.Equal(0x2E, f.Offset.AsInt);
+ break;
+ case "OptBool3":
+ Assert.Equal(0x2F, f.Offset.AsInt);
+ break;
+ case "NoOptString":
+ Assert.Equal(0x30, f.Offset.AsInt);
+ break;
+ case "NoOptBool4":
+ Assert.Equal(0x38, f.Offset.AsInt);
+ break;
+ default:
+ Assert.True(false);
+ break;
+ }
+ }
+ }
+
+ [Fact]
+ public void TestAutoTypeLayoutOptimizeLargestField()
+ {
+ MetadataType optimizeLargestFieldType = _testModule.GetType("Auto", "OptimizeLargestField");
+
+ // Byte count
+ // Base Class 20 (unaligned)
+ // OptInt 4
+ // NoOptString 8
+ // NoOptChar 2
+ // NoOptBool 1 + 5 byte padding to make class size % pointer size == 0
+ // -------------------
+ // 40 (0x28)
+ Assert.Equal(0x28, optimizeLargestFieldType.InstanceByteCount.AsInt);
+
+ foreach (var f in optimizeLargestFieldType.GetFields())
+ {
+ if (f.IsStatic)
+ continue;
+
+ switch (f.Name)
+ {
+ case "OptInt":
+ Assert.Equal(0x14, f.Offset.AsInt);
+ break;
+ case "NoOptString":
+ Assert.Equal(0x18, f.Offset.AsInt);
+ break;
+ case "NoOptChar":
+ Assert.Equal(0x20, f.Offset.AsInt);
+ break;
+ case "NoOptBool":
+ Assert.Equal(0x22, f.Offset.AsInt);
+ break;
+ default:
+ Assert.True(false);
+ break;
+ }
+ }
+ }
+
+ [Fact]
+ public void TestAutoTypeLayoutNoOptimizeMisaligned()
+ {
+ MetadataType noOptimizeMisalignedType = _testModule.GetType("Auto", "NoOptimizeMisaligned");
+
+ // Byte count
+ // Base Class 21 (unaligned) + 3 byte padding to make class size % pointer size == 0
+ // NoOptString 8
+ // NoOptInt 4
+ // NoOptChar 2 + 2 byte padding to make class size % pointer size == 0
+ // -------------------
+ // 40 (0x28)
+ Assert.Equal(0x28, noOptimizeMisalignedType.InstanceByteCount.AsInt);
+
+ foreach (var f in noOptimizeMisalignedType.GetFields())
+ {
+ if (f.IsStatic)
+ continue;
+
+ switch (f.Name)
+ {
+ case "NoOptString":
+ Assert.Equal(0x18, f.Offset.AsInt);
+ break;
+ case "NoOptInt":
+ Assert.Equal(0x20, f.Offset.AsInt);
+ break;
+ case "NoOptChar":
+ Assert.Equal(0x24, f.Offset.AsInt);
+ break;
+ default:
+ Assert.True(false);
+ break;
+ }
+ }
+ }
+
+ [Fact]
+ public void TestAutoTypeLayoutNoOptimizeCharAtSize2Alignment()
+ {
+ MetadataType noOptimizeCharAtSize2AlignmentType = _testModule.GetType("Auto", "NoOptimizeCharAtSize2Alignment");
+
+ // Byte count
+ // Base Class 21 (unaligned) + 1 byte padding to align char
+ // NoOptChar 2
+ // -------------------
+ // 24 (0x18)
+ Assert.Equal(0x18, noOptimizeCharAtSize2AlignmentType.InstanceByteCount.AsInt);
+
+ foreach (var f in noOptimizeCharAtSize2AlignmentType.GetFields())
+ {
+ if (f.IsStatic)
+ continue;
+
+ switch (f.Name)
+ {
+ case "NoOptChar":
+ Assert.Equal(0x16, f.Offset.AsInt);
+ break;
+ default:
+ Assert.True(false);
+ break;
+ }
+ }
+ }
+
+ public static IEnumerable<object[]> AutoTypeLayoutMinPackingData()
+ {
+ yield return new object[] { WellKnownType.Boolean, 2 };
+ yield return new object[] { WellKnownType.Byte, 2 };
+ yield return new object[] { WellKnownType.Char, 4 };
+ yield return new object[] { WellKnownType.Double, 16 };
+ yield return new object[] { WellKnownType.Int16, 4 };
+ yield return new object[] { WellKnownType.Int32, 8 };
+ yield return new object[] { WellKnownType.Int64, 16 };
+ yield return new object[] { WellKnownType.IntPtr, 16 };
+ yield return new object[] { WellKnownType.Single, 8 };
+ }
+
+ [Theory]
+ [MemberData(nameof(AutoTypeLayoutMinPackingData))]
+ public void TestAutoTypeLayoutMinPacking(WellKnownType type, int expectedSize)
+ {
+ MetadataType minPackingType = _testModule.GetType("Auto", "MinPacking`1");
+ InstantiatedType inst = minPackingType.MakeInstantiatedType(_context.GetWellKnownType(type));
+ Assert.Equal(expectedSize, inst.InstanceFieldSize.AsInt);
+ }
+
+ [Fact]
+ public void TestTypeContainsGCPointers()
+ {
+ MetadataType type = _testModule.GetType("ContainsGCPointers", "NoPointers");
+ Assert.False(type.ContainsGCPointers);
+
+ type = _testModule.GetType("ContainsGCPointers", "StillNoPointers");
+ Assert.False(type.ContainsGCPointers);
+
+ type = _testModule.GetType("ContainsGCPointers", "ClassNoPointers");
+ Assert.False(type.ContainsGCPointers);
+
+ type = _testModule.GetType("ContainsGCPointers", "HasPointers");
+ Assert.True(type.ContainsGCPointers);
+
+ type = _testModule.GetType("ContainsGCPointers", "FieldHasPointers");
+ Assert.True(type.ContainsGCPointers);
+
+ type = _testModule.GetType("ContainsGCPointers", "ClassHasPointers");
+ Assert.True(type.ContainsGCPointers);
+
+ type = _testModule.GetType("ContainsGCPointers", "BaseClassHasPointers");
+ Assert.True(type.ContainsGCPointers);
+
+ type = _testModule.GetType("ContainsGCPointers", "ClassHasIntArray");
+ Assert.True(type.ContainsGCPointers);
+
+ type = _testModule.GetType("ContainsGCPointers", "ClassHasArrayOfClassType");
+ Assert.True(type.ContainsGCPointers);
+ }
+
+ [Fact]
+ public void TestByRefLikeTypes()
+ {
+ {
+ DefType type = _context.GetWellKnownType(WellKnownType.TypedReference);
+ Assert.True(type.IsByRefLike);
+ }
+
+ {
+ DefType type = _context.GetWellKnownType(WellKnownType.ByReferenceOfT);
+ Assert.True(type.IsByRefLike);
+ }
+
+ {
+ DefType type = _testModule.GetType("IsByRefLike", "ByRefLikeStruct");
+ Assert.True(type.IsByRefLike);
+ }
+
+ {
+ DefType type = _testModule.GetType("IsByRefLike", "NotByRefLike");
+ Assert.False(type.IsByRefLike);
+ }
+ }
+
+ [Fact]
+ public void TestInvalidByRefLikeTypes()
+ {
+ {
+ DefType type = _ilTestModule.GetType("IsByRefLike", "InvalidClass1");
+ Assert.Throws<TypeSystemException.TypeLoadException>(() => type.ComputeInstanceLayout(InstanceLayoutKind.TypeAndFields));
+ }
+
+ {
+ DefType type = _ilTestModule.GetType("IsByRefLike", "InvalidClass2");
+ Assert.Throws<TypeSystemException.TypeLoadException>(() => type.ComputeInstanceLayout(InstanceLayoutKind.TypeAndFields));
+ }
+
+ {
+ DefType type = _ilTestModule.GetType("IsByRefLike", "InvalidStruct");
+ Assert.Throws<TypeSystemException.TypeLoadException>(() => type.ComputeInstanceLayout(InstanceLayoutKind.TypeAndFields));
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Linq;
+using Internal.TypeSystem;
+
+using Xunit;
+
+namespace TypeSystemTests
+{
+ public class InterfacesTests
+ {
+ TestTypeSystemContext _context;
+ ModuleDesc _testModule;
+
+ public InterfacesTests()
+ {
+ _context = new TestTypeSystemContext(TargetArchitecture.X64);
+ var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly");
+ _context.SetSystemModule(systemModule);
+
+ _testModule = systemModule;
+ }
+
+ [Fact]
+ public void TestMultidimensionalArrays()
+ {
+ DefType systemArrayType = _context.GetWellKnownType(WellKnownType.Array);
+ TypeDesc objectType = _context.GetWellKnownType(WellKnownType.Object);
+
+ ArrayType objectMDArray = _context.GetArrayType(objectType, 2);
+
+ // MD array should have the same set of interfaces as System.Array
+ Assert.Equal(systemArrayType.RuntimeInterfaces, objectMDArray.RuntimeInterfaces);
+ }
+
+ [Fact]
+ public void TestSingleDimensionalArrays()
+ {
+ DefType systemArrayType = _context.GetWellKnownType(WellKnownType.Array);
+ MetadataType systemIListOfTType = _testModule.GetType("System.Collections.Generic", "IList`1");
+
+ TypeDesc objectType = _context.GetWellKnownType(WellKnownType.Object);
+
+ ArrayType objectArray = _context.GetArrayType(objectType);
+
+ // The set of interfaces on an array shall start with the same set that exists on System.Array
+ for (int i = 0; i < systemArrayType.RuntimeInterfaces.Length; i++)
+ {
+ Assert.Equal(systemArrayType.RuntimeInterfaces[i], objectArray.RuntimeInterfaces[i]);
+ }
+
+ // The set of interfaces on an array of type T shall include IList<T>
+ TypeDesc ilistOfObject = systemIListOfTType.MakeInstantiatedType(objectType);
+ Assert.Contains(ilistOfObject, objectArray.RuntimeInterfaces);
+ }
+
+ [Fact]
+ public void TestNoInterface()
+ {
+ MetadataType noInterfacesType = _testModule.GetType("InterfaceArrangements", "NoInterfaces");
+ Assert.Empty(noInterfacesType.RuntimeInterfaces);
+ }
+
+
+ [Fact]
+ public void TestOneInterface()
+ {
+ MetadataType oneInterfacesType = _testModule.GetType("InterfaceArrangements", "OneInterface");
+ MetadataType i1Type = _testModule.GetType("InterfaceArrangements", "I1");
+
+ Assert.Equal(new DefType[] { i1Type }, oneInterfacesType.RuntimeInterfaces);
+ }
+
+ [Fact]
+ public void TestOverlappingInterfacesAtDerivation()
+ {
+ // This test tests that an explicit interface implementation on a type does not cause the
+ // set of runtime interfaces to get extra duplication
+ MetadataType derivedFromMidType = _testModule.GetType("InterfaceArrangements", "DerivedFromMid");
+ MetadataType igen1Type = _testModule.GetType("InterfaceArrangements", "IGen1`1");
+ TypeDesc stringType = _testModule.Context.GetWellKnownType(WellKnownType.String);
+ DefType igen1OfString = igen1Type.MakeInstantiatedType(stringType);
+ MetadataType i1Type = _testModule.GetType("InterfaceArrangements", "I1");
+
+ Assert.Equal(new DefType[] { igen1OfString, i1Type, igen1OfString }, derivedFromMidType.RuntimeInterfaces);
+ }
+
+ [Fact]
+ public void TestOverlappingGenericInterfaces()
+ {
+ // This test tests that the set of interfaces implemented on a generic type definition
+ // has the same arrangement regardless of instantiation
+ MetadataType midType = _testModule.GetType("InterfaceArrangements", "Mid`2");
+ MetadataType igen1Type = _testModule.GetType("InterfaceArrangements", "IGen1`1");
+ TypeDesc stringType = _testModule.Context.GetWellKnownType(WellKnownType.String);
+ TypeDesc objectType = _testModule.Context.GetWellKnownType(WellKnownType.Object);
+ DefType igen1OfString = igen1Type.MakeInstantiatedType(stringType);
+ DefType igen1OfObject = igen1Type.MakeInstantiatedType(objectType);
+ MetadataType i1Type = _testModule.GetType("InterfaceArrangements", "I1");
+
+ TypeDesc mid_string_string = midType.MakeInstantiatedType(stringType, stringType);
+ TypeDesc mid_string_object = midType.MakeInstantiatedType(stringType, objectType);
+ TypeDesc mid_object_string = midType.MakeInstantiatedType(objectType, stringType);
+ TypeDesc mid_object_object = midType.MakeInstantiatedType(objectType, objectType);
+
+ Assert.Equal(new DefType[] { igen1OfString, i1Type, igen1OfString }, mid_string_string.RuntimeInterfaces);
+ Assert.Equal(new DefType[] { igen1OfString, i1Type, igen1OfObject }, mid_string_object.RuntimeInterfaces);
+ Assert.Equal(new DefType[] { igen1OfObject, i1Type, igen1OfString }, mid_object_string.RuntimeInterfaces);
+ Assert.Equal(new DefType[] { igen1OfObject, i1Type, igen1OfObject }, mid_object_object.RuntimeInterfaces);
+ }
+
+ [Fact]
+ public void TestInterfaceRequiresImplmentation()
+ {
+ MetadataType i1Type = _testModule.GetType("InterfaceArrangements", "I1");
+ MetadataType i2Type = _testModule.GetType("InterfaceArrangements", "I2");
+
+ Assert.Empty(i1Type.RuntimeInterfaces);
+ Assert.Equal(i1Type.ExplicitlyImplementedInterfaces, i1Type.RuntimeInterfaces);
+
+ Assert.Equal(new DefType[] { i1Type }, i2Type.RuntimeInterfaces);
+ Assert.Equal(i2Type.ExplicitlyImplementedInterfaces, i2Type.RuntimeInterfaces);
+ }
+
+ [Fact]
+ public void TestPointerArrayInterfaces()
+ {
+ MetadataType systemArrayType = _testModule.GetType("System", "Array");
+ TypeDesc intType = _context.GetWellKnownType(WellKnownType.Int32);
+ TypeDesc intPointerType = _context.GetPointerType(intType);
+
+ ArrayType intPointerArray = _context.GetArrayType(intPointerType);
+
+ // Pointer arrays should have the same set of interfaces as System.Array
+ Assert.Equal(systemArrayType.RuntimeInterfaces, intPointerArray.RuntimeInterfaces);
+ }
+
+ [Fact]
+ public void TestInterafaceMethodResolution()
+ {
+ MetadataType fooType = _testModule.GetType("InterfaceArrangements", "Foo");
+ MetadataType derivedType = _testModule.GetType("InterfaceArrangements", "DerivedFromFoo");
+ MetadataType superDerivedType = _testModule.GetType("InterfaceArrangements", "SuperDerivedFromFoo");
+
+ MetadataType ifooOfInt = _testModule.GetType("InterfaceArrangements", "IFoo`1").MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.Int32));
+ MetadataType ifooOfString = _testModule.GetType("InterfaceArrangements", "IFoo`1").MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.String));
+
+ MethodDesc ifooOfIntMethod = ifooOfInt.GetMethods().Where(m => m.Name == "IMethod").Single();
+ MethodDesc ifooOfStringMethod = ifooOfString.GetMethods().Where(m => m.Name == "IMethod").Single();
+
+ MethodDesc result;
+
+ // Resolve on type Foo
+ {
+ result = fooType.ResolveInterfaceMethodTarget(ifooOfIntMethod);
+ Assert.NotNull(result);
+ Assert.Equal(result.OwningType, fooType);
+
+ result = fooType.ResolveInterfaceMethodTarget(ifooOfStringMethod);
+ Assert.NotNull(result);
+ Assert.Equal(result.OwningType, fooType);
+ }
+
+ // Resolve on type DerivedFromFoo
+ {
+ result = derivedType.ResolveInterfaceMethodTarget(ifooOfIntMethod);
+ Assert.NotNull(result);
+ Assert.Equal(result.OwningType, fooType);
+
+ result = derivedType.ResolveInterfaceMethodTarget(ifooOfStringMethod);
+ Assert.NotNull(result);
+ Assert.Equal(result.OwningType, derivedType);
+ }
+
+
+ // Resolve on type SuperDerivedFromFoo
+ {
+ result = superDerivedType.ResolveInterfaceMethodTarget(ifooOfIntMethod);
+ Assert.NotNull(result);
+ Assert.Equal(result.OwningType, superDerivedType);
+
+ result = superDerivedType.ResolveInterfaceMethodTarget(ifooOfStringMethod);
+ Assert.NotNull(result);
+ Assert.Equal(result.OwningType, derivedType);
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the.NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Internal.TypeSystem;
+
+using Xunit;
+
+namespace TypeSystemTests
+{
+ public class RuntimeDeterminedTypesTests
+ {
+ private TestTypeSystemContext _context;
+ private ModuleDesc _testModule;
+
+ private MetadataType _referenceType;
+ private MetadataType _otherReferenceType;
+ private MetadataType _structType;
+ private MetadataType _otherStructType;
+ private MetadataType _genericReferenceType;
+ private MetadataType _genericStructType;
+ private MetadataType _genericReferenceTypeWithThreeParams;
+ private MetadataType _genericStructTypeWithThreeParams;
+
+ public RuntimeDeterminedTypesTests()
+ {
+ _context = new TestTypeSystemContext(TargetArchitecture.Unknown);
+ var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly");
+ _context.SetSystemModule(systemModule);
+
+ _testModule = systemModule;
+
+ _referenceType = _testModule.GetType("Canonicalization", "ReferenceType");
+ _otherReferenceType = _testModule.GetType("Canonicalization", "OtherReferenceType");
+ _structType = _testModule.GetType("Canonicalization", "StructType");
+ _otherStructType = _testModule.GetType("Canonicalization", "OtherStructType");
+ _genericReferenceType = _testModule.GetType("Canonicalization", "GenericReferenceType`1");
+ _genericStructType = _testModule.GetType("Canonicalization", "GenericStructType`1");
+ _genericReferenceTypeWithThreeParams = _testModule.GetType("Canonicalization", "GenericReferenceTypeWithThreeParams`3");
+ _genericStructTypeWithThreeParams = _testModule.GetType("Canonicalization", "GenericStructTypeWithThreeParams`3");
+ }
+
+ [Fact]
+ public void TestReferenceTypeConversionToSharedForm()
+ {
+ var grtOverRt = _genericReferenceType.MakeInstantiatedType(_referenceType);
+ var grtOverOtherRt = _genericReferenceType.MakeInstantiatedType(_otherReferenceType);
+ var grtOverRtShared = grtOverRt.ConvertToSharedRuntimeDeterminedForm();
+ var grtOverOtherRtShared = grtOverOtherRt.ConvertToSharedRuntimeDeterminedForm();
+
+ // GenericReferenceType<ReferenceType> and GenericReferenceType<OtherReferenceType> have the same shared form
+ Assert.Same(grtOverRtShared, grtOverOtherRtShared);
+
+ // The instantiation argument of the shared form is a runtime determined type
+ var typeArg = grtOverRtShared.Instantiation[0];
+ Assert.IsType<RuntimeDeterminedType>(typeArg);
+
+ // The canonical type used in the shared runtime form is __Canon
+ var runtimeDeterminedType = (RuntimeDeterminedType)typeArg;
+ Assert.Same(_context.CanonType, runtimeDeterminedType.CanonicalType);
+
+ // The shared runtime form details type is the T from the generic definition
+ Assert.Same(_genericReferenceType.Instantiation[0], runtimeDeterminedType.RuntimeDeterminedDetailsType);
+
+ // Canonical form of GenericReferenceType<T__Canon> is same as canonical form of GenericReferenceType<ReferenceType>
+ Assert.Same(
+ grtOverRtShared.ConvertToCanonForm(CanonicalFormKind.Specific),
+ grtOverRt.ConvertToCanonForm(CanonicalFormKind.Specific));
+
+ // GenericReferenceType<ReferenceType> and GenericReferenceType<StructType[]> have the same shared form
+ var grtOverArray = _genericReferenceType.MakeInstantiatedType(_structType.MakeArrayType());
+ var grtOverArrayShared = grtOverArray.ConvertToSharedRuntimeDeterminedForm();
+ Assert.Same(grtOverRtShared, grtOverArrayShared);
+
+ // Converting GenericReferenceType<StructType> to shared form is a no-op
+ var grtOverSt = _genericReferenceType.MakeInstantiatedType(_structType);
+ var grtOverStShared = grtOverSt.ConvertToSharedRuntimeDeterminedForm();
+ Assert.Same(grtOverStShared, grtOverSt);
+ }
+
+ [Fact]
+ public void TestLargeReferenceTypeConversionToSharedForm()
+ {
+ var grtOverRtStRt = _genericReferenceTypeWithThreeParams.MakeInstantiatedType(
+ _referenceType, _structType, _referenceType);
+ var grtOverRtStOtherRt = _genericReferenceTypeWithThreeParams.MakeInstantiatedType(
+ _referenceType, _structType, _otherReferenceType);
+ var grtOverRtStRtShared = grtOverRtStRt.ConvertToSharedRuntimeDeterminedForm();
+ var grtOverRtStOtherRtShared = grtOverRtStOtherRt.ConvertToSharedRuntimeDeterminedForm();
+
+ // GenericReferenceTypeWithThreeParams<ReferenceType, StructType, ReferenceType>
+ // GenericReferenceTypeWithThreeParams<ReferenceType, StructType, OtherReferenceType>
+ // have the same shared runtime form.
+ Assert.Same(grtOverRtStRtShared, grtOverRtStOtherRtShared);
+
+ var grtOverStRtSt = _genericReferenceTypeWithThreeParams.MakeInstantiatedType(
+ _structType, _referenceType, _structType);
+ var grtOverStOtherRtSt = _genericReferenceTypeWithThreeParams.MakeInstantiatedType(
+ _structType, _otherReferenceType, _structType);
+ var grtOverStRtStShared = grtOverStRtSt.ConvertToSharedRuntimeDeterminedForm();
+ var grtOverStOtherRtStShared = grtOverStOtherRtSt.ConvertToSharedRuntimeDeterminedForm();
+
+ // GenericReferenceTypeWithThreeParams<StructType, ReferenceType, StructType>
+ // GenericReferenceTypeWithThreeParams<StructType, OtherReferenceType, StructType>
+ // have the same shared runtime form.
+ Assert.Same(grtOverStRtStShared, grtOverStOtherRtStShared);
+
+ // GenericReferenceTypeWithThreeParams<StructType, ReferenceType, StructType>
+ // GenericReferenceTypeWithThreeParams<StructType, ReferenceType, OtherStructType>
+ // have different shared runtime form.
+ var grtOverStRtOtherSt = _genericReferenceTypeWithThreeParams.MakeInstantiatedType(
+ _structType, _referenceType, _otherStructType);
+ var grtOverStRtOtherStShared = grtOverStRtOtherSt.ConvertToSharedRuntimeDeterminedForm();
+ Assert.NotSame(grtOverStRtStShared, grtOverStRtOtherStShared);
+ }
+
+ [Fact]
+ public void TestUniversalCanonUpgrade()
+ {
+ var gstOverUniversalCanon = _genericStructType.MakeInstantiatedType(_context.UniversalCanonType);
+ var grtOverRtRtStOverUniversal = _genericReferenceTypeWithThreeParams.MakeInstantiatedType(
+ _referenceType, _referenceType, gstOverUniversalCanon);
+ var grtOverRtRtStOverUniversalShared = grtOverRtRtStOverUniversal.ConvertToSharedRuntimeDeterminedForm();
+
+ // Shared runtime form of
+ // GenericReferenceTypeWithThreeParams<ReferenceType, ReferenceType, GenericStructType<__UniversalCanon>> is
+ // GenericReferenceTypeWithThreeParams<T__UniversalCanon, U__UniversalCanon, V__UniversalCanon>
+ var arg0 = grtOverRtRtStOverUniversalShared.Instantiation[0];
+ Assert.IsType<RuntimeDeterminedType>(arg0);
+ Assert.Same(_context.UniversalCanonType, ((RuntimeDeterminedType)arg0).CanonicalType);
+ var arg2 = grtOverRtRtStOverUniversalShared.Instantiation[2];
+ Assert.IsType<RuntimeDeterminedType>(arg2);
+ Assert.Same(_context.UniversalCanonType, ((RuntimeDeterminedType)arg2).CanonicalType);
+ }
+
+ [Fact]
+ public void TestSignatureInstantiation()
+ {
+ var grtOverRtStRt = _genericReferenceTypeWithThreeParams.MakeInstantiatedType(
+ _referenceType, _structType, _referenceType);
+ var grtOverRtStRtShared = grtOverRtStRt.ConvertToSharedRuntimeDeterminedForm();
+
+ // GenericReferenceTypeWithThreeParams<T__Canon, StructType, V__Canon> substituted over
+ // an instantiation of <ReferenceType, StructType, OtherReferenceType> is
+ // GenericReferenceTypeWithThreeParams<ReferenceType, StructType, OtherReferenceType>
+ var grtOverRtStRtSharedInstantiated = grtOverRtStRtShared.GetNonRuntimeDeterminedTypeFromRuntimeDeterminedSubtypeViaSubstitution(
+ new Instantiation(_referenceType, _structType, _otherReferenceType),
+ Instantiation.Empty);
+
+ var grtOverRtStOtherRt = _genericReferenceTypeWithThreeParams.MakeInstantiatedType(
+ _referenceType, _structType, _otherReferenceType);
+
+ Assert.Same(grtOverRtStOtherRt, grtOverRtStRtSharedInstantiated);
+ }
+
+ [Fact]
+ public void TestInstantiationOverStructOverCanon()
+ {
+ var stOverCanon = _genericStructType.MakeInstantiatedType(_context.CanonType);
+ var grtOverStOverCanon = _genericReferenceType.MakeInstantiatedType(
+ stOverCanon);
+ var grtOverStOverCanonShared = grtOverStOverCanon.ConvertToSharedRuntimeDeterminedForm();
+
+ // GenericReferenceType<GenericStructType<__Canon>> converts to
+ // GenericReferenceType<T__GenericStructType<__Canon>>
+ var typeArg = grtOverStOverCanonShared.Instantiation[0];
+ Assert.IsType<RuntimeDeterminedType>(typeArg);
+ var runtimeDeterminedType = (RuntimeDeterminedType)typeArg;
+ Assert.Same(stOverCanon, runtimeDeterminedType.CanonicalType);
+ Assert.Same(_genericReferenceType.Instantiation[0], runtimeDeterminedType.RuntimeDeterminedDetailsType);
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Linq;
+
+using Internal.TypeSystem;
+using Internal.TypeSystem.Ecma;
+
+using Xunit;
+
+namespace TypeSystemTests
+{
+ public class StaticFieldLayoutTests
+ {
+ TestTypeSystemContext _context;
+ ModuleDesc _testModule;
+
+ public StaticFieldLayoutTests()
+ {
+ _context = new TestTypeSystemContext(TargetArchitecture.X64);
+ var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly");
+ _context.SetSystemModule(systemModule);
+
+ _testModule = systemModule;
+ }
+
+ [Fact]
+ public void TestNoPointers()
+ {
+ MetadataType t = _testModule.GetType("StaticFieldLayout", "NoPointers");
+
+ foreach (var field in t.GetFields())
+ {
+ if (!field.IsStatic)
+ continue;
+
+ switch (field.Name)
+ {
+ case "int1":
+ Assert.Equal(0, field.Offset.AsInt);
+ break;
+ case "byte1":
+ Assert.Equal(4, field.Offset.AsInt);
+ break;
+ case "char1":
+ Assert.Equal(6, field.Offset.AsInt);
+ break;
+ default:
+ throw new Exception(field.Name);
+ }
+ }
+ }
+
+ [Fact]
+ public void TestStillNoPointers()
+ {
+ //
+ // Test that static offsets ignore instance fields preceeding them
+ //
+
+ MetadataType t = _testModule.GetType("StaticFieldLayout", "StillNoPointers");
+
+ foreach (var field in t.GetFields())
+ {
+ if (!field.IsStatic)
+ continue;
+
+ switch (field.Name)
+ {
+ case "bool1":
+ Assert.Equal(0, field.Offset.AsInt);
+ break;
+ default:
+ throw new Exception(field.Name);
+ }
+ }
+ }
+
+ [Fact]
+ public void TestClassNoPointers()
+ {
+ //
+ // Ensure classes behave the same as structs when containing statics
+ //
+
+ MetadataType t = _testModule.GetType("StaticFieldLayout", "ClassNoPointers");
+
+ foreach (var field in t.GetFields())
+ {
+ if (!field.IsStatic)
+ continue;
+
+ switch (field.Name)
+ {
+ case "int1":
+ Assert.Equal(0, field.Offset.AsInt);
+ break;
+ case "byte1":
+ Assert.Equal(4, field.Offset.AsInt);
+ break;
+ case "char1":
+ Assert.Equal(6, field.Offset.AsInt);
+ break;
+ default:
+ throw new Exception(field.Name);
+ }
+ }
+ }
+
+ [Fact]
+ public void TestHasPointers()
+ {
+ //
+ // Test a struct containing static types with pointers
+ //
+
+ MetadataType t = _testModule.GetType("StaticFieldLayout", "HasPointers");
+
+ foreach (var field in t.GetFields())
+ {
+ if (!field.IsStatic)
+ continue;
+
+ switch (field.Name)
+ {
+ case "string1":
+ Assert.Equal(8, field.Offset.AsInt);
+ break;
+ case "class1":
+ Assert.Equal(16, field.Offset.AsInt);
+ break;
+ default:
+ throw new Exception(field.Name);
+ }
+ }
+ }
+
+ [Fact]
+ public void TestMixPointersAndNonPointers()
+ {
+ //
+ // Test that static fields with GC pointers get separate offsets from non-GC fields
+ //
+
+ MetadataType t = _testModule.GetType("StaticFieldLayout", "MixPointersAndNonPointers");
+
+ foreach (var field in t.GetFields())
+ {
+ if (!field.IsStatic)
+ continue;
+
+ switch (field.Name)
+ {
+ case "string1":
+ Assert.Equal(8, field.Offset.AsInt);
+ break;
+ case "int1":
+ Assert.Equal(0, field.Offset.AsInt);
+ break;
+ case "class1":
+ Assert.Equal(16, field.Offset.AsInt);
+ break;
+ case "int2":
+ Assert.Equal(4, field.Offset.AsInt);
+ break;
+ case "string2":
+ Assert.Equal(24, field.Offset.AsInt);
+ break;
+ default:
+ throw new Exception(field.Name);
+ }
+ }
+ }
+
+ [Fact]
+ public void TestEnsureInheritanceResetsStaticOffsets()
+ {
+ //
+ // Test that when inheriting a class with static fields, the derived slice's static fields
+ // are again offset from 0
+ //
+
+ MetadataType t = _testModule.GetType("StaticFieldLayout", "EnsureInheritanceResetsStaticOffsets");
+
+ foreach (var field in t.GetFields())
+ {
+ if (!field.IsStatic)
+ continue;
+
+ switch (field.Name)
+ {
+ case "int3":
+ Assert.Equal(0, field.Offset.AsInt);
+ break;
+ case "string3":
+ Assert.Equal(8, field.Offset.AsInt);
+ break;
+ default:
+ throw new Exception(field.Name);
+ }
+ }
+ }
+
+ [Fact]
+ public void TestLiteralFieldsDontAffectLayout()
+ {
+ //
+ // Test that literal fields are not laid out.
+ //
+
+ MetadataType t = _testModule.GetType("StaticFieldLayout", "LiteralFieldsDontAffectLayout");
+
+ Assert.Equal(4, t.GetFields().Count());
+
+ foreach (var field in t.GetFields())
+ {
+ if (!field.IsStatic)
+ continue;
+
+ switch (field.Name)
+ {
+ case "IntConstant":
+ case "StringConstant":
+ Assert.True(field.IsStatic);
+ Assert.True(field.IsLiteral);
+ break;
+ case "Int1":
+ Assert.Equal(0, field.Offset.AsInt);
+ break;
+ case "String1":
+ Assert.Equal(8, field.Offset.AsInt);
+ break;
+ default:
+ throw new Exception(field.Name);
+ }
+ }
+ }
+
+ [Fact]
+ public void TestStaticSelfRef()
+ {
+ //
+ // Test that we can load a struct which has a static field referencing itself without
+ // going into an infinite loop
+ //
+
+ MetadataType t = _testModule.GetType("StaticFieldLayout", "StaticSelfRef");
+
+ foreach (var field in t.GetFields())
+ {
+ if (!field.IsStatic)
+ continue;
+
+ switch (field.Name)
+ {
+ case "selfRef1":
+ Assert.Equal(0, field.Offset.AsInt);
+ break;
+ default:
+ throw new Exception(field.Name);
+ }
+ }
+ }
+
+ [Fact]
+ public void TestRvaStatics()
+ {
+ //
+ // Test that an RVA mapped field has the right value for the offset.
+ //
+
+ var ilModule = _context.GetModuleForSimpleName("ILTestAssembly");
+ var t = ilModule.GetType("StaticFieldLayout", "RvaStatics");
+ var field = t.GetField("StaticInitedInt");
+
+ Assert.True(field.HasRva);
+
+ byte[] rvaData = ((EcmaField)field).GetFieldRvaData();
+
+ Assert.Equal(4, rvaData.Length);
+
+ int value = rvaData[0] |
+ rvaData[1] << 8 |
+ rvaData[2] << 16 |
+ rvaData[3] << 24;
+
+ Assert.Equal(0x78563412, value);
+ }
+
+ [Fact]
+ public void TestFunctionPointer()
+ {
+ //
+ // Test layout with a function pointer typed-field.
+ //
+
+ var ilModule = _context.GetModuleForSimpleName("ILTestAssembly");
+ var t = ilModule.GetType("StaticFieldLayout", "FunctionPointerType");
+ var field = t.GetField("StaticMethodField");
+
+ Assert.Equal(8, field.Offset.AsInt);
+ Assert.False(field.HasGCStaticBase);
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using Internal.TypeSystem;
+
+using Xunit;
+
+
+namespace TypeSystemTests
+{
+ public class SyntheticVirtualOverrideTests
+ {
+ TestTypeSystemContext _context;
+ ModuleDesc _testModule;
+
+ public SyntheticVirtualOverrideTests()
+ {
+ _context = new SyntheticVirtualOverrideTypeSystemContext();
+ var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly");
+ _context.SetSystemModule(systemModule);
+
+ _testModule = systemModule;
+ }
+
+ [Fact]
+ public void TestStructEqualsAndGetHashCode()
+ {
+ //
+ // Tests that a struct with no Equals and GetHashCode overrides
+ // receive a synthetic implementation of these courtesy of the
+ // EqualsAndGetHashCodeProvidingAlgorithm.
+ //
+
+ MetadataType t = _testModule.GetType("SyntheticVirtualOverride", "StructWithNoEqualsAndGetHashCode");
+
+ Assert.DoesNotContain(t.GetMethods(), m => m.Name == "Equals");
+ Assert.DoesNotContain(t.GetMethods(), m => m.Name == "GetHashCode");
+
+ List<MethodDesc> introducedVirtualMethods = new List<MethodDesc>(t.GetAllMethods().Where(m => m.IsVirtual));
+ Assert.Equal(2, introducedVirtualMethods.Count);
+ Assert.Contains(introducedVirtualMethods, m => m.Name == "Equals");
+ Assert.Contains(introducedVirtualMethods, m => m.Name == "GetHashCode");
+ Assert.All(introducedVirtualMethods, m => { Assert.Same(t, m.OwningType); });
+
+ List<MethodDesc> virtualSlots = new List<MethodDesc>(t.EnumAllVirtualSlots());
+ Assert.All(virtualSlots, s => { Assert.True(s.OwningType.IsObject); });
+ Assert.Equal(4, virtualSlots.Count);
+
+ List<MethodDesc> vtable = virtualSlots.Select(s => t.FindVirtualFunctionTargetMethodOnObjectType(s)).ToList();
+
+ Assert.Contains(vtable, m => m.Name == "Equals" && m.OwningType == t);
+ Assert.Contains(vtable, m => m.Name == "GetHashCode" && m.OwningType == t);
+ Assert.Contains(vtable, m => m.Name == "Finalize" && m.OwningType.IsObject);
+ Assert.Contains(vtable, m => m.Name == "ToString" && m.OwningType.IsObject);
+ }
+
+ [Fact]
+ public void TestUnoverridenSyntheticEqualsAndGetHashCode()
+ {
+ //
+ // Tests that the synthetic implementation on a base class is propagated to
+ // derived classes.
+ //
+
+ MetadataType baseType = _testModule.GetType("SyntheticVirtualOverride", "ClassWithInjectedEqualsAndGetHashCode");
+ MetadataType t = _testModule.GetType("SyntheticVirtualOverride", "ClassNotOverridingEqualsAndGetHashCode");
+
+ List<MethodDesc> virtualSlots = new List<MethodDesc>(t.EnumAllVirtualSlots());
+ Assert.All(virtualSlots, s => { Assert.True(s.OwningType.IsObject); });
+ Assert.Equal(4, virtualSlots.Count);
+
+ List<MethodDesc> vtable = virtualSlots.Select(s => t.FindVirtualFunctionTargetMethodOnObjectType(s)).ToList();
+
+ Assert.Contains(vtable, m => m.Name == "Equals" && m.OwningType == baseType);
+ Assert.Contains(vtable, m => m.Name == "GetHashCode" && m.OwningType == baseType);
+ Assert.Contains(vtable, m => m.Name == "Finalize" && m.OwningType.IsObject);
+ Assert.Contains(vtable, m => m.Name == "ToString" && m.OwningType.IsObject);
+ }
+
+ [Fact]
+ public void TestOverridenSyntheticEqualsAndGetHashCode()
+ {
+ //
+ // Tests that the synthetic implementation on a base class can be overriden by
+ // derived classes.
+ //
+
+ MetadataType baseType = _testModule.GetType("SyntheticVirtualOverride", "ClassWithInjectedEqualsAndGetHashCode");
+ MetadataType t = _testModule.GetType("SyntheticVirtualOverride", "ClassOverridingEqualsAndGetHashCode");
+
+ List<MethodDesc> virtualSlots = new List<MethodDesc>(t.EnumAllVirtualSlots());
+ Assert.All(virtualSlots, s => { Assert.True(s.OwningType.IsObject); });
+ Assert.Equal(4, virtualSlots.Count);
+
+ List<MethodDesc> vtable = virtualSlots.Select(s => t.FindVirtualFunctionTargetMethodOnObjectType(s)).ToList();
+
+ Assert.Contains(vtable, m => m.Name == "Equals" && m.OwningType == t);
+ Assert.Contains(vtable, m => m.Name == "GetHashCode" && m.OwningType == t);
+ Assert.Contains(vtable, m => m.Name == "Finalize" && m.OwningType.IsObject);
+ Assert.Contains(vtable, m => m.Name == "ToString" && m.OwningType.IsObject);
+ }
+
+ private class SyntheticVirtualOverrideTypeSystemContext : TestTypeSystemContext
+ {
+ private Dictionary<TypeDesc, MethodDesc> _getHashCodeMethods = new Dictionary<TypeDesc, MethodDesc>();
+ private Dictionary<TypeDesc, MethodDesc> _equalsMethods = new Dictionary<TypeDesc, MethodDesc>();
+
+ public SyntheticVirtualOverrideTypeSystemContext()
+ : base(TargetArchitecture.Unknown)
+ {
+ }
+
+ private MethodDesc GetGetHashCodeMethod(TypeDesc type)
+ {
+ MethodDesc result;
+ if (!_getHashCodeMethods.TryGetValue(type, out result))
+ {
+ result = new SyntheticMethod(type, "GetHashCode",
+ new MethodSignature(0, 0, type.Context.GetWellKnownType(WellKnownType.Int32), Array.Empty<TypeDesc>()));
+ _getHashCodeMethods.Add(type, result);
+ }
+ return result;
+ }
+
+ private MethodDesc GetEqualsMethod(TypeDesc type)
+ {
+ MethodDesc result;
+ if (!_equalsMethods.TryGetValue(type, out result))
+ {
+ result = new SyntheticMethod(type, "Equals",
+ new MethodSignature(0, 0, type.Context.GetWellKnownType(WellKnownType.Boolean),
+ new[] { type.Context.GetWellKnownType(WellKnownType.Object) }));
+ _equalsMethods.Add(type, result);
+ }
+ return result;
+ }
+
+ protected override IEnumerable<MethodDesc> GetAllMethods(TypeDesc type)
+ {
+ MetadataType mdType = type as MetadataType;
+
+ if (mdType.Name == "StructWithNoEqualsAndGetHashCode"
+ || mdType.Name == "ClassWithInjectedEqualsAndGetHashCode")
+ {
+ yield return GetEqualsMethod(type);
+ yield return GetGetHashCodeMethod(type);
+ }
+
+ foreach (var m in mdType.GetMethods())
+ yield return m;
+ }
+ }
+
+ private class SyntheticMethod : MethodDesc
+ {
+ private TypeDesc _owningType;
+ private MethodSignature _signature;
+ private string _name;
+
+ public SyntheticMethod(TypeDesc owningType, string name, MethodSignature signature)
+ {
+ _owningType = owningType;
+ _signature = signature;
+ _name = name;
+ }
+
+ protected override int ClassCode
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ protected override int CompareToImpl(MethodDesc other, TypeSystemComparer comparer)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override bool IsVirtual
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ public override TypeSystemContext Context
+ {
+ get
+ {
+ return _owningType.Context;
+ }
+ }
+
+ public override string Name
+ {
+ get
+ {
+ return _name;
+ }
+ }
+
+ public override string DiagnosticName
+ {
+ get
+ {
+ return _name;
+ }
+ }
+
+ public override TypeDesc OwningType
+ {
+ get
+ {
+ return _owningType;
+ }
+ }
+
+ public override MethodSignature Signature
+ {
+ get
+ {
+ return _signature;
+ }
+ }
+
+ public override bool HasCustomAttribute(string attributeNamespace, string attributeName)
+ {
+ return false;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+
+using Internal.TypeSystem;
+
+namespace TypeSystemTests
+{
+ class TestMetadataFieldLayoutAlgorithm : MetadataFieldLayoutAlgorithm
+ {
+ protected override void PrepareRuntimeSpecificStaticFieldLayout(TypeSystemContext context, ref ComputedStaticFieldLayout layout)
+ {
+ // GC statics start with a pointer to the "EEType" that signals the size and GCDesc to the GC
+ layout.GcStatics.Size = context.Target.LayoutPointerSize;
+ layout.ThreadGcStatics.Size = context.Target.LayoutPointerSize;
+ }
+
+ protected override void FinalizeRuntimeSpecificStaticFieldLayout(TypeSystemContext context, ref ComputedStaticFieldLayout layout)
+ {
+ // If the size of GCStatics is equal to the size set in PrepareRuntimeSpecificStaticFieldLayout, we
+ // don't have any GC statics
+ if (layout.GcStatics.Size == context.Target.LayoutPointerSize)
+ {
+ layout.GcStatics.Size = LayoutInt.Zero;
+ }
+ if (layout.ThreadGcStatics.Size == context.Target.LayoutPointerSize)
+ {
+ layout.ThreadGcStatics.Size = LayoutInt.Zero;
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+using Internal.TypeSystem;
+using System.Reflection;
+using System.Reflection.PortableExecutable;
+using System.IO;
+
+namespace TypeSystemTests
+{
+ public enum CanonicalizationMode
+ {
+ Standard,
+ RuntimeDetermined,
+ }
+
+ class TestTypeSystemContext : MetadataTypeSystemContext
+ {
+ Dictionary<string, ModuleDesc> _modules = new Dictionary<string, ModuleDesc>(StringComparer.OrdinalIgnoreCase);
+
+ MetadataFieldLayoutAlgorithm _metadataFieldLayout = new TestMetadataFieldLayoutAlgorithm();
+ MetadataRuntimeInterfacesAlgorithm _metadataRuntimeInterfacesAlgorithm = new MetadataRuntimeInterfacesAlgorithm();
+ ArrayOfTRuntimeInterfacesAlgorithm _arrayOfTRuntimeInterfacesAlgorithm;
+ VirtualMethodAlgorithm _virtualMethodAlgorithm = new MetadataVirtualMethodAlgorithm();
+
+ public CanonicalizationMode CanonMode { get; set; } = CanonicalizationMode.RuntimeDetermined;
+
+ public TestTypeSystemContext(TargetArchitecture arch)
+ : base(new TargetDetails(arch, TargetOS.Unknown, TargetAbi.Unknown))
+ {
+ }
+
+ public ModuleDesc GetModuleForSimpleName(string simpleName)
+ {
+ ModuleDesc existingModule;
+ if (_modules.TryGetValue(simpleName, out existingModule))
+ return existingModule;
+
+ return CreateModuleForSimpleName(simpleName);
+ }
+
+ public ModuleDesc CreateModuleForSimpleName(string simpleName)
+ {
+ string bindingDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
+ string filePath = Path.Combine(bindingDirectory, simpleName + ".dll");
+ ModuleDesc module = Internal.TypeSystem.Ecma.EcmaModule.Create(this, new PEReader(File.OpenRead(filePath)), containingAssembly: null);
+ _modules.Add(simpleName, module);
+ return module;
+ }
+
+ public override ModuleDesc ResolveAssembly(System.Reflection.AssemblyName name, bool throwIfNotFound)
+ {
+ return GetModuleForSimpleName(name.Name);
+ }
+
+ public override FieldLayoutAlgorithm GetLayoutAlgorithmForType(DefType type)
+ {
+ if (type == UniversalCanonType)
+ return UniversalCanonLayoutAlgorithm.Instance;
+
+ return _metadataFieldLayout;
+ }
+
+ protected override RuntimeInterfacesAlgorithm GetRuntimeInterfacesAlgorithmForNonPointerArrayType(ArrayType type)
+ {
+ if (_arrayOfTRuntimeInterfacesAlgorithm == null)
+ {
+ _arrayOfTRuntimeInterfacesAlgorithm = new ArrayOfTRuntimeInterfacesAlgorithm(SystemModule.GetType("System", "Array`1"));
+ }
+ return _arrayOfTRuntimeInterfacesAlgorithm;
+ }
+
+ protected override RuntimeInterfacesAlgorithm GetRuntimeInterfacesAlgorithmForDefType(DefType type)
+ {
+ return _metadataRuntimeInterfacesAlgorithm;
+ }
+
+ public override VirtualMethodAlgorithm GetVirtualMethodAlgorithmForType(TypeDesc type)
+ {
+ return _virtualMethodAlgorithm;
+ }
+
+ protected override Instantiation ConvertInstantiationToCanonForm(Instantiation instantiation, CanonicalFormKind kind, out bool changed)
+ {
+ if (CanonMode == CanonicalizationMode.Standard)
+ return StandardCanonicalizationAlgorithm.ConvertInstantiationToCanonForm(instantiation, kind, out changed);
+ else
+ return RuntimeDeterminedCanonicalizationAlgorithm.ConvertInstantiationToCanonForm(instantiation, kind, out changed);
+ }
+
+ protected override TypeDesc ConvertToCanon(TypeDesc typeToConvert, CanonicalFormKind kind)
+ {
+ if (CanonMode == CanonicalizationMode.Standard)
+ return StandardCanonicalizationAlgorithm.ConvertToCanon(typeToConvert, kind);
+ else
+ return RuntimeDeterminedCanonicalizationAlgorithm.ConvertToCanon(typeToConvert, kind);
+ }
+
+ protected override TypeDesc ConvertToCanon(TypeDesc typeToConvert, ref CanonicalFormKind kind)
+ {
+ if (CanonMode == CanonicalizationMode.Standard)
+ return StandardCanonicalizationAlgorithm.ConvertToCanon(typeToConvert, kind);
+ else
+ return RuntimeDeterminedCanonicalizationAlgorithm.ConvertToCanon(typeToConvert, ref kind);
+ }
+
+ protected override bool ComputeHasGCStaticBase(FieldDesc field)
+ {
+ Debug.Assert(field.IsStatic);
+
+ if (field.IsThreadStatic)
+ return true;
+
+ TypeDesc fieldType = field.FieldType;
+ if (fieldType.IsValueType)
+ return ((DefType)fieldType).ContainsGCPointers;
+ else
+ return fieldType.IsGCPointer;
+
+ }
+
+ public override bool SupportsUniversalCanon => true;
+ public override bool SupportsCanon => true;
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+
+using Internal.TypeSystem;
+
+using Xunit;
+
+namespace TypeSystemTests
+{
+ public class TypeNameParsingTests
+ {
+ TestTypeSystemContext _context;
+ ModuleDesc _testModule;
+
+ string _coreAssemblyQualifier;
+
+ MetadataType _simpleType;
+ MetadataType _nestedType;
+ MetadataType _nestedTwiceType;
+
+ MetadataType _genericType;
+ MetadataType _nestedNongenericType;
+ MetadataType _nestedGenericType;
+
+ MetadataType _veryGenericType;
+
+ MetadataType _structType;
+
+ public TypeNameParsingTests()
+ {
+ _context = new TestTypeSystemContext(TargetArchitecture.X64);
+
+ // TODO-NICE: split test types into a separate, non-core, module
+ _testModule = _context.CreateModuleForSimpleName("CoreTestAssembly");
+ _context.SetSystemModule(_testModule);
+
+ _simpleType = _testModule.GetType("TypeNameParsing", "Simple");
+ _nestedType = _simpleType.GetNestedType("Nested");
+ _nestedTwiceType = _nestedType.GetNestedType("NestedTwice");
+
+ _genericType = _testModule.GetType("TypeNameParsing", "Generic`1");
+ _nestedGenericType = _genericType.GetNestedType("NestedGeneric`1");
+ _nestedNongenericType = _genericType.GetNestedType("NestedNongeneric");
+
+ _veryGenericType = _testModule.GetType("TypeNameParsing", "VeryGeneric`3");
+
+ _structType = _testModule.GetType("TypeNameParsing", "Struct");
+
+ _coreAssemblyQualifier = ((IAssemblyDesc)_testModule).GetName().FullName;
+ }
+
+ [Fact]
+ public void TestSimpleNames()
+ {
+ {
+ TypeDesc result = _testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.Simple");
+ Assert.Equal(_simpleType, result);
+ }
+
+ {
+ TypeDesc result = _testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.Simple+Nested");
+ Assert.Equal(_nestedType, result);
+ }
+
+ {
+ TypeDesc result = _testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.Simple+Nested+NestedTwice");
+ Assert.Equal(_nestedTwiceType, result);
+ }
+
+ {
+ TypeDesc result = _testModule.GetTypeByCustomAttributeTypeName("System.Int32, " + _coreAssemblyQualifier);
+ Assert.Equal(_context.GetWellKnownType(WellKnownType.Int32), result);
+ }
+
+ {
+ TypeDesc result = _testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.VeryGeneric`3");
+ Assert.Equal(_veryGenericType, result);
+ }
+ }
+
+ [Fact]
+ public void TestArrayTypes()
+ {
+ {
+ TypeDesc expected = _simpleType.MakeArrayType();
+ TypeDesc result = _testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.Simple[]");
+ Assert.Equal(expected, result);
+ }
+
+ {
+ TypeDesc expected = _simpleType.MakeArrayType().MakeArrayType().MakeArrayType();
+ TypeDesc result = _testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.Simple[][][]");
+ Assert.Equal(expected, result);
+ }
+
+ {
+ TypeDesc expected = _simpleType.MakeArrayType(2).MakeArrayType(3);
+ TypeDesc result = _testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.Simple[,][,,]");
+ Assert.Equal(expected, result);
+ }
+
+ {
+ TypeDesc expected = _context.GetWellKnownType(WellKnownType.Int32).MakeArrayType();
+ TypeDesc result = _testModule.GetTypeByCustomAttributeTypeName("System.Int32[], " + _coreAssemblyQualifier);
+ Assert.Equal(expected, result);
+ }
+ }
+
+ [Fact]
+ public void TestPointerTypes()
+ {
+ {
+ TypeDesc expected = _structType.MakePointerType();
+ TypeDesc result = _testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.Struct*");
+ Assert.Equal(expected, result);
+ }
+
+ {
+ TypeDesc expected = _structType.MakePointerType().MakePointerType();
+ TypeDesc result = _testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.Struct**");
+ Assert.Equal(expected, result);
+ }
+
+ {
+ TypeDesc expected = _context.GetWellKnownType(WellKnownType.Int32).MakePointerType();
+ TypeDesc result = _testModule.GetTypeByCustomAttributeTypeName("System.Int32*, " + _coreAssemblyQualifier);
+ Assert.Equal(expected, result);
+ }
+ }
+
+ [Fact]
+ public void TestInstantiatedTypes()
+ {
+ var nullableType = (MetadataType)_context.GetWellKnownType(WellKnownType.Nullable);
+
+ {
+ TypeDesc expected = _genericType.MakeInstantiatedType(_simpleType);
+ TypeDesc result = _testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.Generic`1[TypeNameParsing.Simple]");
+ Assert.Equal(expected, result);
+ }
+
+ {
+ TypeDesc expected = _veryGenericType.MakeInstantiatedType(
+ _simpleType,
+ _genericType.MakeInstantiatedType(_simpleType),
+ _structType
+ );
+ TypeDesc result = _testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.VeryGeneric`3[TypeNameParsing.Simple,TypeNameParsing.Generic`1[TypeNameParsing.Simple],TypeNameParsing.Struct]");
+ Assert.Equal(expected, result);
+ }
+
+ {
+ TypeDesc expected = _genericType.MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.Object));
+ TypeDesc result = _testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.Generic`1[[System.Object, " + _coreAssemblyQualifier + "]]");
+ Assert.Equal(expected, result);
+ }
+
+ {
+ TypeDesc expected = _veryGenericType.MakeInstantiatedType(
+ _context.GetWellKnownType(WellKnownType.Object),
+ _simpleType,
+ _context.GetWellKnownType(WellKnownType.Int32)
+ );
+ TypeDesc result = _testModule.GetTypeByCustomAttributeTypeName(String.Format(
+ "TypeNameParsing.VeryGeneric`3[[System.Object, {0}],TypeNameParsing.Simple,[System.Int32, {0}]]", _coreAssemblyQualifier));
+ Assert.Equal(expected, result);
+ }
+
+ {
+ TypeDesc expected = nullableType.MakeInstantiatedType(_structType);
+ TypeDesc result = _testModule.GetTypeByCustomAttributeTypeName(String.Format(
+ "System.Nullable`1[TypeNameParsing.Struct], {0}", _coreAssemblyQualifier));
+ Assert.Equal(expected, result);
+ }
+
+ {
+ TypeDesc expected = nullableType.MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.Int32));
+ TypeDesc result = _testModule.GetTypeByCustomAttributeTypeName(String.Format(
+ "System.Nullable`1[[System.Int32, {0}]], {0}", _coreAssemblyQualifier));
+ Assert.Equal(expected, result);
+ }
+ }
+
+ [Fact]
+ public void TestMixed()
+ {
+ var nullableType = (MetadataType)_context.GetWellKnownType(WellKnownType.Nullable);
+
+ {
+ TypeDesc expected = _genericType.MakeInstantiatedType(_structType.MakePointerType().MakeArrayType());
+ TypeDesc result = _testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.Generic`1[TypeNameParsing.Struct*[]]");
+ Assert.Equal(expected, result);
+ }
+
+ {
+ TypeDesc expected = _genericType.MakeInstantiatedType(_structType.MakePointerType().MakePointerType().MakeArrayType().MakeArrayType(2));
+ TypeDesc result = _testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.Generic`1[TypeNameParsing.Struct**[][,]]");
+ Assert.Equal(expected, result);
+ }
+
+ {
+ TypeDesc expected = _nestedNongenericType.MakeInstantiatedType(
+ nullableType.MakeInstantiatedType(_structType)
+ );
+ TypeDesc result = _testModule.GetTypeByCustomAttributeTypeName(String.Format(
+ "TypeNameParsing.Generic`1+NestedNongeneric[[System.Nullable`1[TypeNameParsing.Struct], {0}]]", _coreAssemblyQualifier));
+ Assert.Equal(expected, result);
+ }
+
+ {
+ TypeDesc expected = _nestedGenericType.MakeInstantiatedType(
+ nullableType.MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.Int32)),
+ _nestedType.MakeArrayType()
+ );
+ TypeDesc result = _testModule.GetTypeByCustomAttributeTypeName(String.Format(
+ "TypeNameParsing.Generic`1+NestedGeneric`1[[System.Nullable`1[[System.Int32, {0}]], {0}],TypeNameParsing.Simple+Nested[]]", _coreAssemblyQualifier));
+ Assert.Equal(expected, result);
+ }
+ }
+
+ [Fact]
+ public void TestFailureWhenTypeIsMissing()
+ {
+ // Test throwing behavior
+ Assert.Throws<TypeSystemException.TypeLoadException>(() => _testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.SimpleButNotThere"));
+ Assert.Throws<TypeSystemException.TypeLoadException>(() => _testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.SimpleButNotThere+NonNamespaceQualifiedType"));
+ Assert.Throws<TypeSystemException.TypeLoadException>(() => _testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.Simple+NestedNotThere"));
+ Assert.Throws<TypeSystemException.TypeLoadException>(() => _testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.Simple+Nested+NestedTwiceNotThere"));
+ Assert.Throws<TypeSystemException.TypeLoadException>(() => _testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.Generic`1[TypeNameParsing.SimpleButNotThere]"));
+
+ // Test returning null behavior
+ Assert.Null(_testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.SimpleButNotThere", throwIfNotFound: false));
+ Assert.Null(_testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.SimpleButNotThere+NonNamespaceQualifiedType", throwIfNotFound: false));
+ Assert.Null(_testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.Simple+NestedNotThere", throwIfNotFound: false));
+ Assert.Null(_testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.Simple+NestedNotThere+NonNamespaceQualifiedType", throwIfNotFound: false));
+ Assert.Null(_testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.Simple+Nested+NestedTwiceNotThere", throwIfNotFound: false));
+ Assert.Null(_testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.Simple+Nested+NonNamespaceQualifiedType", throwIfNotFound: false));
+ Assert.Null(_testModule.GetTypeByCustomAttributeTypeName("TypeNameParsing.Generic`1[TypeNameParsing.SimpleButNotThere]", throwIfNotFound: false));
+ }
+
+ public IEnumerable<TypeDesc> GetTypesForRoundtripTest()
+ {
+ yield return _simpleType;
+ yield return _nestedType;
+ yield return _nestedTwiceType;
+ yield return _context.GetWellKnownType(WellKnownType.Int32);
+ yield return _veryGenericType;
+ yield return _simpleType.MakeArrayType();
+ yield return _simpleType.MakeArrayType().MakeArrayType();
+ yield return _simpleType.MakeArrayType(2).MakeArrayType(3);
+ yield return _context.GetWellKnownType(WellKnownType.Int32).MakeArrayType();
+ yield return _structType.MakePointerType();
+ yield return _context.GetWellKnownType(WellKnownType.Int32).MakePointerType().MakePointerType();
+ yield return _genericType.MakeInstantiatedType(_simpleType);
+ yield return _veryGenericType.MakeInstantiatedType(
+ _simpleType,
+ _genericType.MakeInstantiatedType(_simpleType),
+ _structType
+ );
+ yield return _genericType.MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.Object));
+ yield return _veryGenericType.MakeInstantiatedType(
+ _context.GetWellKnownType(WellKnownType.Object),
+ _simpleType,
+ _context.GetWellKnownType(WellKnownType.Int32)
+ );
+ yield return ((MetadataType)_context.GetWellKnownType(WellKnownType.Nullable)).MakeInstantiatedType(_structType);
+ yield return _genericType.MakeInstantiatedType(_structType.MakePointerType().MakeArrayType());
+ yield return _nestedGenericType.MakeInstantiatedType(
+ ((MetadataType)_context.GetWellKnownType(WellKnownType.Nullable)).MakeInstantiatedType(_context.GetWellKnownType(WellKnownType.Int32)),
+ _nestedType.MakeArrayType()
+ );
+ }
+
+ [Fact]
+ public void TestRoundtripping()
+ {
+ foreach (TypeDesc type in GetTypesForRoundtripTest())
+ {
+ {
+ var fmt = new CustomAttributeTypeNameFormatter((IAssemblyDesc)_testModule);
+ string formatted = fmt.FormatName(type, true);
+ TypeDesc roundTripped = _testModule.GetTypeByCustomAttributeTypeName(formatted);
+ Assert.Equal(type, roundTripped);
+ }
+
+ {
+ var fmt = new CustomAttributeTypeNameFormatter();
+ string formatted = fmt.FormatName(type, true);
+ TypeDesc roundTripped = _testModule.GetTypeByCustomAttributeTypeName(formatted);
+ Assert.Equal(type, roundTripped);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Internal.TypeSystem;
+
+using Xunit;
+
+namespace TypeSystemTests
+{
+ public class UniversalGenericFieldLayoutTests
+ {
+ TestTypeSystemContext _contextX86;
+ ModuleDesc _testModuleX86;
+ TestTypeSystemContext _contextX64;
+ ModuleDesc _testModuleX64;
+ TestTypeSystemContext _contextARM;
+ ModuleDesc _testModuleARM;
+
+ public UniversalGenericFieldLayoutTests()
+ {
+ // Architecture specific tests may use these contexts
+ _contextX64 = new TestTypeSystemContext(TargetArchitecture.X64);
+ var systemModuleX64 = _contextX64.CreateModuleForSimpleName("CoreTestAssembly");
+ _contextX64.SetSystemModule(systemModuleX64);
+
+ _testModuleX64 = systemModuleX64;
+
+ _contextARM = new TestTypeSystemContext(TargetArchitecture.ARM);
+ var systemModuleARM = _contextARM.CreateModuleForSimpleName("CoreTestAssembly");
+ _contextARM.SetSystemModule(systemModuleARM);
+
+ _testModuleARM = systemModuleARM;
+
+ _contextX86 = new TestTypeSystemContext(TargetArchitecture.X86);
+ var systemModuleX86 = _contextX86.CreateModuleForSimpleName("CoreTestAssembly");
+ _contextX86.SetSystemModule(systemModuleX86);
+
+ _testModuleX86 = systemModuleX86;
+ }
+
+ [Fact]
+ public void LayoutIntTests()
+ {
+ Assert.Throws<ArgumentException>(() => { return new LayoutInt(int.MinValue); });
+ Assert.Throws<ArgumentException>(() => { return new LayoutInt(-1); });
+
+ Assert.Equal(LayoutInt.Zero, new LayoutInt(0));
+ Assert.Equal(LayoutInt.One, new LayoutInt(1));
+
+ Assert.True(LayoutInt.Zero == new LayoutInt(0));
+ Assert.True(LayoutInt.One == new LayoutInt(1));
+ Assert.False(LayoutInt.Zero == new LayoutInt(1));
+ Assert.False(LayoutInt.One == new LayoutInt(0));
+#pragma warning disable 1718 // Allow comparison to same variable
+ Assert.True(LayoutInt.Indeterminate == LayoutInt.Indeterminate);
+#pragma warning restore 1718
+
+ Assert.False(LayoutInt.Zero != new LayoutInt(0));
+ Assert.False(LayoutInt.One != new LayoutInt(1));
+ Assert.True(LayoutInt.Zero != new LayoutInt(1));
+ Assert.True(LayoutInt.One != new LayoutInt(0));
+#pragma warning disable 1718 // Allow comparison to same variable
+ Assert.False(LayoutInt.Indeterminate != LayoutInt.Indeterminate);
+#pragma warning restore 1718
+
+ Assert.Equal(0, new LayoutInt(0).AsInt);
+ Assert.Equal(1, new LayoutInt(1).AsInt);
+ Assert.Equal(Int32.MaxValue, new LayoutInt(Int32.MaxValue).AsInt);
+ Assert.Throws<InvalidOperationException>(() => { return LayoutInt.Indeterminate.AsInt; });
+
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.Indeterminate + LayoutInt.Indeterminate);
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.One + LayoutInt.Indeterminate);
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.Indeterminate + LayoutInt.One);
+ Assert.Equal(new LayoutInt(2), LayoutInt.One + LayoutInt.One);
+ Assert.Throws<OverflowException>(() => { return new LayoutInt(int.MaxValue) + LayoutInt.One; });
+ Assert.Throws<OverflowException>(() => { return new LayoutInt(int.MaxValue) + LayoutInt.One; });
+
+ Assert.Equal(LayoutInt.One, LayoutInt.Max(LayoutInt.One, LayoutInt.Zero));
+ Assert.Equal(LayoutInt.One, LayoutInt.Max(LayoutInt.Zero, LayoutInt.One));
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.Max(LayoutInt.Indeterminate, LayoutInt.Zero));
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.Max(LayoutInt.Zero, LayoutInt.Indeterminate));
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.Max(LayoutInt.Indeterminate, LayoutInt.Indeterminate));
+
+ Assert.Equal(LayoutInt.Zero, LayoutInt.Min(LayoutInt.One, LayoutInt.Zero));
+ Assert.Equal(LayoutInt.Zero, LayoutInt.Min(LayoutInt.Zero, LayoutInt.One));
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.Min(LayoutInt.Indeterminate, LayoutInt.Zero));
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.Min(LayoutInt.Zero, LayoutInt.Indeterminate));
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.Min(LayoutInt.Indeterminate, LayoutInt.Indeterminate));
+ }
+
+ public static IEnumerable<object[]> GetTargetDetails()
+ {
+ yield return new object[] { new TargetDetails(TargetArchitecture.ARM, TargetOS.Unknown, TargetAbi.CoreRT) };
+ yield return new object[] { new TargetDetails(TargetArchitecture.ARM64, TargetOS.Unknown, TargetAbi.CoreRT) };
+ yield return new object[] { new TargetDetails(TargetArchitecture.X64, TargetOS.Unknown, TargetAbi.CoreRT) };
+ yield return new object[] { new TargetDetails(TargetArchitecture.X86, TargetOS.Unknown, TargetAbi.CoreRT) };
+ yield return new object[] { new TargetDetails(TargetArchitecture.Wasm32, TargetOS.Unknown, TargetAbi.CoreRT) };
+ }
+
+ [Theory]
+ [MemberData(nameof(GetTargetDetails))]
+ public void TestLayoutIntAlignUp(TargetDetails target)
+ {
+ // AlignUp testing
+ Assert.Equal(new LayoutInt(0), LayoutInt.AlignUp(new LayoutInt(0), new LayoutInt(1), target));
+ Assert.Equal(new LayoutInt(0), LayoutInt.AlignUp(new LayoutInt(0), new LayoutInt(2), target));
+ Assert.Equal(new LayoutInt(0), LayoutInt.AlignUp(new LayoutInt(0), new LayoutInt(4), target));
+ Assert.Equal(new LayoutInt(0), LayoutInt.AlignUp(new LayoutInt(0), new LayoutInt(8), target));
+
+ Assert.Equal(new LayoutInt(1), LayoutInt.AlignUp(new LayoutInt(1), new LayoutInt(1), target));
+ Assert.Equal(new LayoutInt(2), LayoutInt.AlignUp(new LayoutInt(2), new LayoutInt(1), target));
+ Assert.Equal(new LayoutInt(3), LayoutInt.AlignUp(new LayoutInt(3), new LayoutInt(1), target));
+ Assert.Equal(new LayoutInt(4), LayoutInt.AlignUp(new LayoutInt(4), new LayoutInt(1), target));
+ Assert.Equal(new LayoutInt(5), LayoutInt.AlignUp(new LayoutInt(5), new LayoutInt(1), target));
+ Assert.Equal(new LayoutInt(6), LayoutInt.AlignUp(new LayoutInt(6), new LayoutInt(1), target));
+ Assert.Equal(new LayoutInt(7), LayoutInt.AlignUp(new LayoutInt(7), new LayoutInt(1), target));
+ Assert.Equal(new LayoutInt(8), LayoutInt.AlignUp(new LayoutInt(8), new LayoutInt(1), target));
+ Assert.Equal(new LayoutInt(9), LayoutInt.AlignUp(new LayoutInt(9), new LayoutInt(1), target));
+ Assert.Equal(new LayoutInt(10), LayoutInt.AlignUp(new LayoutInt(10), new LayoutInt(1), target));
+ Assert.Equal(new LayoutInt(11), LayoutInt.AlignUp(new LayoutInt(11), new LayoutInt(1), target));
+ Assert.Equal(new LayoutInt(12), LayoutInt.AlignUp(new LayoutInt(12), new LayoutInt(1), target));
+ Assert.Equal(new LayoutInt(13), LayoutInt.AlignUp(new LayoutInt(13), new LayoutInt(1), target));
+ Assert.Equal(new LayoutInt(14), LayoutInt.AlignUp(new LayoutInt(14), new LayoutInt(1), target));
+ Assert.Equal(new LayoutInt(15), LayoutInt.AlignUp(new LayoutInt(15), new LayoutInt(1), target));
+ Assert.Equal(new LayoutInt(16), LayoutInt.AlignUp(new LayoutInt(16), new LayoutInt(1), target));
+
+ Assert.Equal(new LayoutInt(2), LayoutInt.AlignUp(new LayoutInt(1), new LayoutInt(2), target));
+ Assert.Equal(new LayoutInt(2), LayoutInt.AlignUp(new LayoutInt(2), new LayoutInt(2), target));
+ Assert.Equal(new LayoutInt(4), LayoutInt.AlignUp(new LayoutInt(3), new LayoutInt(2), target));
+ Assert.Equal(new LayoutInt(4), LayoutInt.AlignUp(new LayoutInt(4), new LayoutInt(2), target));
+ Assert.Equal(new LayoutInt(6), LayoutInt.AlignUp(new LayoutInt(5), new LayoutInt(2), target));
+ Assert.Equal(new LayoutInt(6), LayoutInt.AlignUp(new LayoutInt(6), new LayoutInt(2), target));
+ Assert.Equal(new LayoutInt(8), LayoutInt.AlignUp(new LayoutInt(7), new LayoutInt(2), target));
+ Assert.Equal(new LayoutInt(8), LayoutInt.AlignUp(new LayoutInt(8), new LayoutInt(2), target));
+ Assert.Equal(new LayoutInt(10), LayoutInt.AlignUp(new LayoutInt(9), new LayoutInt(2), target));
+ Assert.Equal(new LayoutInt(10), LayoutInt.AlignUp(new LayoutInt(10), new LayoutInt(2), target));
+ Assert.Equal(new LayoutInt(12), LayoutInt.AlignUp(new LayoutInt(11), new LayoutInt(2), target));
+ Assert.Equal(new LayoutInt(12), LayoutInt.AlignUp(new LayoutInt(12), new LayoutInt(2), target));
+ Assert.Equal(new LayoutInt(14), LayoutInt.AlignUp(new LayoutInt(13), new LayoutInt(2), target));
+ Assert.Equal(new LayoutInt(14), LayoutInt.AlignUp(new LayoutInt(14), new LayoutInt(2), target));
+ Assert.Equal(new LayoutInt(16), LayoutInt.AlignUp(new LayoutInt(15), new LayoutInt(2), target));
+ Assert.Equal(new LayoutInt(16), LayoutInt.AlignUp(new LayoutInt(16), new LayoutInt(2), target));
+
+ Assert.Equal(new LayoutInt(4), LayoutInt.AlignUp(new LayoutInt(1), new LayoutInt(4), target));
+ Assert.Equal(new LayoutInt(4), LayoutInt.AlignUp(new LayoutInt(2), new LayoutInt(4), target));
+ Assert.Equal(new LayoutInt(4), LayoutInt.AlignUp(new LayoutInt(3), new LayoutInt(4), target));
+ Assert.Equal(new LayoutInt(4), LayoutInt.AlignUp(new LayoutInt(4), new LayoutInt(4), target));
+ Assert.Equal(new LayoutInt(8), LayoutInt.AlignUp(new LayoutInt(5), new LayoutInt(4), target));
+ Assert.Equal(new LayoutInt(8), LayoutInt.AlignUp(new LayoutInt(6), new LayoutInt(4), target));
+ Assert.Equal(new LayoutInt(8), LayoutInt.AlignUp(new LayoutInt(7), new LayoutInt(4), target));
+ Assert.Equal(new LayoutInt(8), LayoutInt.AlignUp(new LayoutInt(8), new LayoutInt(4), target));
+ Assert.Equal(new LayoutInt(12), LayoutInt.AlignUp(new LayoutInt(9), new LayoutInt(4), target));
+ Assert.Equal(new LayoutInt(12), LayoutInt.AlignUp(new LayoutInt(10), new LayoutInt(4), target));
+ Assert.Equal(new LayoutInt(12), LayoutInt.AlignUp(new LayoutInt(11), new LayoutInt(4), target));
+ Assert.Equal(new LayoutInt(12), LayoutInt.AlignUp(new LayoutInt(12), new LayoutInt(4), target));
+ Assert.Equal(new LayoutInt(16), LayoutInt.AlignUp(new LayoutInt(13), new LayoutInt(4), target));
+ Assert.Equal(new LayoutInt(16), LayoutInt.AlignUp(new LayoutInt(14), new LayoutInt(4), target));
+ Assert.Equal(new LayoutInt(16), LayoutInt.AlignUp(new LayoutInt(15), new LayoutInt(4), target));
+ Assert.Equal(new LayoutInt(16), LayoutInt.AlignUp(new LayoutInt(16), new LayoutInt(4), target));
+
+ Assert.Equal(new LayoutInt(8), LayoutInt.AlignUp(new LayoutInt(1), new LayoutInt(8), target));
+ Assert.Equal(new LayoutInt(8), LayoutInt.AlignUp(new LayoutInt(2), new LayoutInt(8), target));
+ Assert.Equal(new LayoutInt(8), LayoutInt.AlignUp(new LayoutInt(3), new LayoutInt(8), target));
+ Assert.Equal(new LayoutInt(8), LayoutInt.AlignUp(new LayoutInt(4), new LayoutInt(8), target));
+ Assert.Equal(new LayoutInt(8), LayoutInt.AlignUp(new LayoutInt(5), new LayoutInt(8), target));
+ Assert.Equal(new LayoutInt(8), LayoutInt.AlignUp(new LayoutInt(6), new LayoutInt(8), target));
+ Assert.Equal(new LayoutInt(8), LayoutInt.AlignUp(new LayoutInt(7), new LayoutInt(8), target));
+ Assert.Equal(new LayoutInt(8), LayoutInt.AlignUp(new LayoutInt(8), new LayoutInt(8), target));
+ Assert.Equal(new LayoutInt(16), LayoutInt.AlignUp(new LayoutInt(9), new LayoutInt(8), target));
+ Assert.Equal(new LayoutInt(16), LayoutInt.AlignUp(new LayoutInt(10), new LayoutInt(8), target));
+ Assert.Equal(new LayoutInt(16), LayoutInt.AlignUp(new LayoutInt(11), new LayoutInt(8), target));
+ Assert.Equal(new LayoutInt(16), LayoutInt.AlignUp(new LayoutInt(12), new LayoutInt(8), target));
+ Assert.Equal(new LayoutInt(16), LayoutInt.AlignUp(new LayoutInt(13), new LayoutInt(8), target));
+ Assert.Equal(new LayoutInt(16), LayoutInt.AlignUp(new LayoutInt(14), new LayoutInt(8), target));
+ Assert.Equal(new LayoutInt(16), LayoutInt.AlignUp(new LayoutInt(15), new LayoutInt(8), target));
+ Assert.Equal(new LayoutInt(16), LayoutInt.AlignUp(new LayoutInt(16), new LayoutInt(8), target));
+
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.AlignUp(new LayoutInt(1), LayoutInt.Indeterminate, target));
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.AlignUp(new LayoutInt(2), LayoutInt.Indeterminate, target));
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.AlignUp(new LayoutInt(3), LayoutInt.Indeterminate, target));
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.AlignUp(new LayoutInt(4), LayoutInt.Indeterminate, target));
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.AlignUp(new LayoutInt(5), LayoutInt.Indeterminate, target));
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.AlignUp(new LayoutInt(6), LayoutInt.Indeterminate, target));
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.AlignUp(new LayoutInt(7), LayoutInt.Indeterminate, target));
+ if (target.MaximumAlignment > 8)
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.AlignUp(new LayoutInt(8), LayoutInt.Indeterminate, target));
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.AlignUp(new LayoutInt(9), LayoutInt.Indeterminate, target));
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.AlignUp(new LayoutInt(10), LayoutInt.Indeterminate, target));
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.AlignUp(new LayoutInt(11), LayoutInt.Indeterminate, target));
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.AlignUp(new LayoutInt(12), LayoutInt.Indeterminate, target));
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.AlignUp(new LayoutInt(13), LayoutInt.Indeterminate, target));
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.AlignUp(new LayoutInt(14), LayoutInt.Indeterminate, target));
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.AlignUp(new LayoutInt(15), LayoutInt.Indeterminate, target));
+ if (target.MaximumAlignment > 16)
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.AlignUp(new LayoutInt(16), LayoutInt.Indeterminate, target));
+
+ // If we the value is aligned to the maximum supported alignment, we can consider it aligned no matter
+ // the value of the alignment.
+ Assert.Equal(new LayoutInt(target.MaximumAlignment), LayoutInt.AlignUp(new LayoutInt(target.MaximumAlignment), LayoutInt.Indeterminate, target));
+ Assert.Equal(new LayoutInt(target.MaximumAlignment * 2), LayoutInt.AlignUp(new LayoutInt(target.MaximumAlignment * 2), LayoutInt.Indeterminate, target));
+
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.AlignUp(LayoutInt.Indeterminate, new LayoutInt(1), target));
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.AlignUp(LayoutInt.Indeterminate, new LayoutInt(2), target));
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.AlignUp(LayoutInt.Indeterminate, new LayoutInt(4), target));
+ Assert.Equal(LayoutInt.Indeterminate, LayoutInt.AlignUp(LayoutInt.Indeterminate, new LayoutInt(8), target));
+ }
+
+
+ private void TestLayoutOfUniversalCanonTypeOnArchitecture(TypeSystemContext context)
+ {
+ // Assert all of the various layout information about the universal canon type itself
+ Assert.Equal(LayoutInt.Indeterminate, context.UniversalCanonType.InstanceFieldAlignment);
+ Assert.Equal(LayoutInt.Indeterminate, context.UniversalCanonType.InstanceFieldSize);
+ Assert.Equal(LayoutInt.Indeterminate, context.UniversalCanonType.InstanceByteAlignment);
+ Assert.Equal(LayoutInt.Indeterminate, context.UniversalCanonType.InstanceByteCount);
+ Assert.Equal(LayoutInt.Indeterminate, context.UniversalCanonType.InstanceByteCountUnaligned);
+ Assert.Equal(LayoutInt.Zero, context.UniversalCanonType.GCStaticFieldAlignment);
+ Assert.Equal(LayoutInt.Zero, context.UniversalCanonType.GCStaticFieldSize);
+ Assert.Equal(LayoutInt.Zero, context.UniversalCanonType.NonGCStaticFieldAlignment);
+ Assert.Equal(LayoutInt.Zero, context.UniversalCanonType.NonGCStaticFieldSize);
+ Assert.Equal(LayoutInt.Zero, context.UniversalCanonType.ThreadGcStaticFieldAlignment);
+ Assert.Equal(LayoutInt.Zero, context.UniversalCanonType.ThreadGcStaticFieldSize);
+ }
+ [Fact]
+ public void TestLayoutOfUniversalCanonType()
+ {
+ // Assert all of the various layout information about the universal canon type itself, do this for all architectures
+ TestLayoutOfUniversalCanonTypeOnArchitecture(_contextX86);
+ TestLayoutOfUniversalCanonTypeOnArchitecture(_contextX64);
+ TestLayoutOfUniversalCanonTypeOnArchitecture(_contextARM);
+ }
+
+ [Fact]
+ public void TestAllFieldsStructUniversalGeneric()
+ {
+ // Given a struct with all field universal, what is the layout?
+ MetadataType tGen;
+ InstantiatedType genOfUUU;
+ ModuleDesc testModule;
+ TypeSystemContext context;
+
+ // X64 testing
+ testModule = _testModuleX64;
+ context = _contextX64;
+
+ tGen = testModule.GetType("GenericTypes", "GenStruct`3");
+ genOfUUU = tGen.MakeInstantiatedType(context.UniversalCanonType, context.UniversalCanonType, context.UniversalCanonType);
+
+ Assert.Equal(LayoutInt.Indeterminate, genOfUUU.InstanceFieldAlignment);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUUU.InstanceFieldSize);
+ Assert.Equal(new LayoutInt(8), genOfUUU.InstanceByteAlignment);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUUU.InstanceByteCount);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUUU.InstanceByteCountUnaligned);
+ Assert.Equal(0, genOfUUU.GetFields().First().Offset.AsInt);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUUU.GetFields().ElementAt(1).Offset);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUUU.GetFields().ElementAt(2).Offset);
+
+ testModule = _testModuleX86;
+ context = _contextX86;
+
+ tGen = testModule.GetType("GenericTypes", "GenStruct`3");
+ genOfUUU = tGen.MakeInstantiatedType(context.UniversalCanonType, context.UniversalCanonType, context.UniversalCanonType);
+
+ Assert.Equal(LayoutInt.Indeterminate, genOfUUU.InstanceFieldAlignment);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUUU.InstanceFieldSize);
+ Assert.Equal(new LayoutInt(4), genOfUUU.InstanceByteAlignment);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUUU.InstanceByteCount);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUUU.InstanceByteCountUnaligned);
+ Assert.Equal(0, genOfUUU.GetFields().First().Offset.AsInt);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUUU.GetFields().ElementAt(1).Offset);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUUU.GetFields().ElementAt(2).Offset);
+
+ testModule = _testModuleARM;
+ context = _contextARM;
+
+ tGen = testModule.GetType("GenericTypes", "GenStruct`3");
+ genOfUUU = tGen.MakeInstantiatedType(context.UniversalCanonType, context.UniversalCanonType, context.UniversalCanonType);
+
+ Assert.Equal(LayoutInt.Indeterminate, genOfUUU.InstanceFieldAlignment);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUUU.InstanceFieldSize);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUUU.InstanceByteAlignment);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUUU.InstanceByteCount);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUUU.InstanceByteCountUnaligned);
+ Assert.Equal(0, genOfUUU.GetFields().First().Offset.AsInt);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUUU.GetFields().ElementAt(1).Offset);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUUU.GetFields().ElementAt(2).Offset);
+ }
+
+ private void TestIndeterminatedNestedStructFieldPerContext(TypeSystemContext context, ModuleDesc testModule, out InstantiatedType genOfIntNestedInt, out InstantiatedType genOfLongNestedInt)
+ {
+ // Given a struct with all field universal, what is the layout?
+ MetadataType tGen = testModule.GetType("GenericTypes", "GenStruct`3");
+ InstantiatedType genOfUUU = tGen.MakeInstantiatedType(context.UniversalCanonType, context.UniversalCanonType, context.UniversalCanonType);
+ genOfIntNestedInt = tGen.MakeInstantiatedType(context.GetWellKnownType(WellKnownType.Int32), genOfUUU, context.GetWellKnownType(WellKnownType.Int32));
+ genOfLongNestedInt = tGen.MakeInstantiatedType(context.GetWellKnownType(WellKnownType.Int64), genOfUUU, context.GetWellKnownType(WellKnownType.Int32));
+
+ Assert.Equal(LayoutInt.Indeterminate, genOfIntNestedInt.InstanceFieldAlignment);
+ Assert.Equal(LayoutInt.Indeterminate, genOfIntNestedInt.InstanceFieldSize);
+ Assert.Equal(LayoutInt.Indeterminate, genOfIntNestedInt.InstanceByteCount);
+ Assert.Equal(LayoutInt.Indeterminate, genOfIntNestedInt.InstanceByteCountUnaligned);
+ Assert.Equal(0, genOfIntNestedInt.GetFields().First().Offset.AsInt);
+ Assert.Equal(LayoutInt.Indeterminate, genOfIntNestedInt.GetFields().ElementAt(1).Offset);
+ Assert.Equal(LayoutInt.Indeterminate, genOfIntNestedInt.GetFields().ElementAt(2).Offset);
+
+ Assert.Equal(LayoutInt.Indeterminate, genOfLongNestedInt.InstanceFieldAlignment);
+ Assert.Equal(LayoutInt.Indeterminate, genOfLongNestedInt.InstanceFieldSize);
+ Assert.Equal(LayoutInt.Indeterminate, genOfLongNestedInt.InstanceByteCount);
+ Assert.Equal(LayoutInt.Indeterminate, genOfLongNestedInt.InstanceByteCountUnaligned);
+ Assert.Equal(0, genOfLongNestedInt.GetFields().First().Offset.AsInt);
+ if (context.Target.MaximumAlignment <= 8)
+ {
+ Assert.Equal(8, genOfLongNestedInt.GetFields().ElementAt(1).Offset.AsInt);
+ }
+ else
+ {
+ Assert.Equal(LayoutInt.Indeterminate, genOfLongNestedInt.GetFields().ElementAt(1).Offset);
+ }
+ Assert.Equal(LayoutInt.Indeterminate, genOfLongNestedInt.GetFields().ElementAt(2).Offset);
+ }
+
+ [Fact]
+ public void TestIndeterminateNestedStructField()
+ {
+ InstantiatedType genOfIntNestedInt;
+ InstantiatedType genOfLongNestedInt;
+
+ TestIndeterminatedNestedStructFieldPerContext(_contextX64, _testModuleX64, out genOfIntNestedInt, out genOfLongNestedInt);
+ Assert.Equal(new LayoutInt(8), genOfLongNestedInt.InstanceByteAlignment);
+ Assert.Equal(new LayoutInt(8), genOfLongNestedInt.InstanceByteAlignment);
+ TestIndeterminatedNestedStructFieldPerContext(_contextX86, _testModuleX86, out genOfIntNestedInt, out genOfLongNestedInt);
+ Assert.Equal(new LayoutInt(4), genOfLongNestedInt.InstanceByteAlignment);
+ Assert.Equal(new LayoutInt(4), genOfLongNestedInt.InstanceByteAlignment);
+ TestIndeterminatedNestedStructFieldPerContext(_contextARM, _testModuleARM, out genOfIntNestedInt, out genOfLongNestedInt);
+ Assert.Equal(LayoutInt.Indeterminate, genOfLongNestedInt.InstanceByteAlignment);
+ Assert.Equal(LayoutInt.Indeterminate, genOfLongNestedInt.InstanceByteAlignment);
+ }
+
+ private void AssertClassIndeterminateSize(TypeSystemContext context, MetadataType type, LayoutInt expectedIndeterminateByteAlignment)
+ {
+ Assert.Equal(context.Target.LayoutPointerSize, type.InstanceFieldAlignment);
+ Assert.Equal(context.Target.LayoutPointerSize, type.InstanceFieldSize);
+ Assert.Equal(expectedIndeterminateByteAlignment, type.InstanceByteAlignment);
+ Assert.Equal(LayoutInt.Indeterminate, type.InstanceByteCount);
+ Assert.Equal(LayoutInt.Indeterminate, type.InstanceByteCountUnaligned);
+ }
+
+ private void CommonClassLayoutTestBits(ModuleDesc testModule,
+ TypeSystemContext context,
+ LayoutInt expectedIndeterminateByteAlignment,
+ out InstantiatedType genOfIU,
+ out InstantiatedType genOfLU,
+ out InstantiatedType genOfUU,
+ out InstantiatedType genOfUI,
+ out InstantiatedType genOfUL)
+ {
+ MetadataType tDerivedGen = testModule.GetType("GenericTypes", "GenDerivedClass`2");
+ genOfIU = tDerivedGen.MakeInstantiatedType(context.GetWellKnownType(WellKnownType.Int32), context.UniversalCanonType);
+ genOfLU = tDerivedGen.MakeInstantiatedType(context.GetWellKnownType(WellKnownType.Int64), context.UniversalCanonType);
+ genOfUU = tDerivedGen.MakeInstantiatedType(context.UniversalCanonType, context.UniversalCanonType);
+
+ genOfUI = tDerivedGen.MakeInstantiatedType(context.UniversalCanonType, context.GetWellKnownType(WellKnownType.Int32));
+ genOfUL = tDerivedGen.MakeInstantiatedType(context.UniversalCanonType, context.GetWellKnownType(WellKnownType.Int64));
+
+ // Assert that the class as a whole is known to be of undefined size
+ AssertClassIndeterminateSize(context, genOfIU, expectedIndeterminateByteAlignment);
+ AssertClassIndeterminateSize(context, genOfLU, expectedIndeterminateByteAlignment);
+ AssertClassIndeterminateSize(context, genOfUU, expectedIndeterminateByteAlignment);
+ AssertClassIndeterminateSize(context, genOfUI, expectedIndeterminateByteAlignment);
+ AssertClassIndeterminateSize(context, genOfUL, expectedIndeterminateByteAlignment);
+ }
+
+ [Fact]
+ public void TestClassLayout()
+ {
+ // Tests class layout behavior with universal generics
+ // Tests handling universal base types as well as non-universal base types
+
+ InstantiatedType genOfIU;
+ InstantiatedType genOfLU;
+ InstantiatedType genOfUU;
+ InstantiatedType genOfUI;
+ InstantiatedType genOfUL;
+
+ ModuleDesc testModule;
+ TypeSystemContext context;
+
+ // X64 testing
+ testModule = _testModuleX64;
+ context = _contextX64;
+
+ CommonClassLayoutTestBits(testModule,
+ context,
+ new LayoutInt(8),
+ out genOfIU,
+ out genOfLU,
+ out genOfUU,
+ out genOfUI,
+ out genOfUL);
+
+ // On x64 first field offset is well known always
+ Assert.Equal(8, genOfIU.BaseType.GetFields().First().Offset.AsInt);
+ Assert.Equal(8, genOfLU.BaseType.GetFields().First().Offset.AsInt);
+ if (context.Target.MaximumAlignment <= 8)
+ {
+ Assert.Equal(8, genOfUU.BaseType.GetFields().First().Offset.AsInt);
+ Assert.Equal(8, genOfUI.BaseType.GetFields().First().Offset.AsInt);
+ Assert.Equal(8, genOfUL.BaseType.GetFields().First().Offset.AsInt);
+ }
+ else
+ {
+
+ Assert.Equal(LayoutInt.Indeterminate, genOfUU.BaseType.GetFields().First().Offset);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUI.BaseType.GetFields().First().Offset);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUL.BaseType.GetFields().First().Offset);
+ }
+
+ Assert.Equal(LayoutInt.Indeterminate, genOfIU.GetFields().First().Offset);
+ if (context.Target.MaximumAlignment <= 16)
+ {
+ Assert.Equal(16, genOfLU.GetFields().First().Offset.AsInt);
+ }
+ else
+ {
+ Assert.Equal(LayoutInt.Indeterminate, genOfLU.GetFields().First().Offset);
+ }
+ Assert.Equal(LayoutInt.Indeterminate, genOfUU.GetFields().First().Offset);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUI.GetFields().First().Offset);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUL.GetFields().First().Offset);
+
+ // X86 testing
+ testModule = _testModuleX86;
+ context = _contextX86;
+
+ CommonClassLayoutTestBits(testModule,
+ context,
+ new LayoutInt(4),
+ out genOfIU,
+ out genOfLU,
+ out genOfUU,
+ out genOfUI,
+ out genOfUL);
+
+ Assert.Equal(4, genOfIU.BaseType.GetFields().First().Offset.AsInt);
+ Assert.Equal(8, genOfLU.BaseType.GetFields().First().Offset.AsInt);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUU.BaseType.GetFields().First().Offset);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUI.BaseType.GetFields().First().Offset);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUL.BaseType.GetFields().First().Offset);
+
+ if (context.Target.MaximumAlignment <= 8)
+ {
+ Assert.Equal(8, genOfIU.GetFields().First().Offset.AsInt);
+ }
+ else
+ {
+ Assert.Equal(LayoutInt.Indeterminate, genOfIU.GetFields().First().Offset);
+ }
+ if (context.Target.MaximumAlignment <= 16)
+ {
+ Assert.Equal(16, genOfLU.GetFields().First().Offset.AsInt);
+ }
+ else
+ {
+ Assert.Equal(LayoutInt.Indeterminate, genOfLU.GetFields().First().Offset);
+ }
+ Assert.Equal(LayoutInt.Indeterminate, genOfUU.GetFields().First().Offset);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUI.GetFields().First().Offset);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUL.GetFields().First().Offset);
+
+ // ARM testing
+ testModule = _testModuleARM;
+ context = _contextARM;
+
+ CommonClassLayoutTestBits(testModule,
+ context,
+ LayoutInt.Indeterminate,
+ out genOfIU,
+ out genOfLU,
+ out genOfUU,
+ out genOfUI,
+ out genOfUL);
+
+ Assert.Equal(4, genOfIU.BaseType.GetFields().First().Offset.AsInt);
+ Assert.Equal(8, genOfLU.BaseType.GetFields().First().Offset.AsInt);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUU.BaseType.GetFields().First().Offset);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUI.BaseType.GetFields().First().Offset);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUL.BaseType.GetFields().First().Offset);
+
+ if (context.Target.MaximumAlignment <= 8)
+ {
+ Assert.Equal(8, genOfIU.GetFields().First().Offset.AsInt);
+ }
+ else
+ {
+ Assert.Equal(LayoutInt.Indeterminate, genOfIU.GetFields().First().Offset);
+ }
+ if (context.Target.MaximumAlignment <= 16)
+ {
+ Assert.Equal(16, genOfLU.GetFields().First().Offset.AsInt);
+ }
+ else
+ {
+ Assert.Equal(LayoutInt.Indeterminate, genOfLU.GetFields().First().Offset);
+ }
+ Assert.Equal(LayoutInt.Indeterminate, genOfUU.GetFields().First().Offset);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUI.GetFields().First().Offset);
+ Assert.Equal(LayoutInt.Indeterminate, genOfUL.GetFields().First().Offset);
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Internal.TypeSystem;
+
+using Xunit;
+
+namespace TypeSystemTests
+{
+ public class ValueTypeShapeCharacteristicsTests
+ {
+ const ValueTypeShapeCharacteristics Float32Aggregate = ValueTypeShapeCharacteristics.Float32Aggregate;
+ const ValueTypeShapeCharacteristics Float64Aggregate = ValueTypeShapeCharacteristics.Float64Aggregate;
+
+ TestTypeSystemContext _context;
+ ModuleDesc _testModule;
+
+ public ValueTypeShapeCharacteristicsTests()
+ {
+ _context = new TestTypeSystemContext(TargetArchitecture.ARM);
+ var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly");
+ _context.SetSystemModule(systemModule);
+
+ _testModule = systemModule;
+ }
+
+ [Fact]
+ public void TestHfaPrimitives()
+ {
+ DefType singleType = _context.GetWellKnownType(WellKnownType.Single);
+ DefType doubleType = _context.GetWellKnownType(WellKnownType.Double);
+
+ Assert.True(singleType.IsHomogeneousAggregate);
+ Assert.Equal(Float32Aggregate, singleType.ValueTypeShapeCharacteristics);
+
+ Assert.True(doubleType.IsHomogeneousAggregate);
+ Assert.Equal(Float64Aggregate, doubleType.ValueTypeShapeCharacteristics);
+ }
+
+ [Fact]
+ public void TestSimpleHfa()
+ {
+ var simpleHfaFloatStruct = _testModule.GetType("ValueTypeShapeCharacteristics", "SimpleHfaFloatStruct");
+ Assert.True(simpleHfaFloatStruct.IsHomogeneousAggregate);
+ Assert.Equal(Float32Aggregate, simpleHfaFloatStruct.ValueTypeShapeCharacteristics);
+
+ var simpleHfaFloatStructWithManyFields = _testModule.GetType("ValueTypeShapeCharacteristics", "SimpleHfaFloatStructWithManyFields");
+ Assert.True(simpleHfaFloatStructWithManyFields.IsHomogeneousAggregate);
+ Assert.Equal(Float32Aggregate, simpleHfaFloatStructWithManyFields.ValueTypeShapeCharacteristics);
+
+ var simpleHfaDoubleStruct = _testModule.GetType("ValueTypeShapeCharacteristics", "SimpleHfaDoubleStruct");
+ Assert.True(simpleHfaDoubleStruct.IsHomogeneousAggregate);
+ Assert.Equal(Float64Aggregate, simpleHfaDoubleStruct.ValueTypeShapeCharacteristics);
+ }
+
+ [Fact]
+ public void TestCompositeHfa()
+ {
+ var compositeHfaFloatStruct = _testModule.GetType("ValueTypeShapeCharacteristics", "CompositeHfaFloatStruct");
+ Assert.True(compositeHfaFloatStruct.IsHomogeneousAggregate);
+ Assert.Equal(Float32Aggregate, compositeHfaFloatStruct.ValueTypeShapeCharacteristics);
+
+ var compositeHfaDoubleStruct = _testModule.GetType("ValueTypeShapeCharacteristics", "CompositeHfaDoubleStruct");
+ Assert.True(compositeHfaDoubleStruct.IsHomogeneousAggregate);
+ Assert.Equal(Float64Aggregate, compositeHfaDoubleStruct.ValueTypeShapeCharacteristics);
+ }
+
+ [Fact]
+ public void TestHfaNegative()
+ {
+ var nonHAEmptyStruct = _testModule.GetType("ValueTypeShapeCharacteristics", "NonHAEmptyStruct");
+ Assert.False(nonHAEmptyStruct.IsHomogeneousAggregate);
+
+ var nonHAStruct = _testModule.GetType("ValueTypeShapeCharacteristics", "NonHAStruct");
+ Assert.False(nonHAStruct.IsHomogeneousAggregate);
+
+ var nonHAMixedStruct = _testModule.GetType("ValueTypeShapeCharacteristics", "NonHAMixedStruct");
+ Assert.False(nonHAMixedStruct.IsHomogeneousAggregate);
+
+ var nonHACompositeStruct = _testModule.GetType("ValueTypeShapeCharacteristics", "NonHACompositeStruct");
+ Assert.False(nonHACompositeStruct.IsHomogeneousAggregate);
+
+ var nonHAStructWithManyFields = _testModule.GetType("ValueTypeShapeCharacteristics", "NonHAStructWithManyFields");
+ Assert.False(nonHAStructWithManyFields.IsHomogeneousAggregate);
+
+ var objectType = _context.GetWellKnownType(WellKnownType.Object);
+ Assert.False(objectType.IsHomogeneousAggregate);
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+using Internal.TypeSystem;
+
+using Xunit;
+
+
+namespace TypeSystemTests
+{
+ public class VirtualFunctionOverrideTests
+ {
+ TestTypeSystemContext _context;
+ ModuleDesc _testModule;
+ DefType _stringType;
+ DefType _voidType;
+
+ public VirtualFunctionOverrideTests()
+ {
+ _context = new TestTypeSystemContext(TargetArchitecture.X64);
+ var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly");
+ _context.SetSystemModule(systemModule);
+
+ _testModule = systemModule;
+
+ _stringType = _context.GetWellKnownType(WellKnownType.String);
+ _voidType = _context.GetWellKnownType(WellKnownType.Void);
+ }
+
+ [Fact]
+ public void TestGenericMethodInterfaceMethodImplOverride()
+ {
+ //
+ // Ensure MethodImpl based overriding works for MethodSpecs
+ //
+
+ MetadataType interfaceType = _testModule.GetType("VirtualFunctionOverride", "IIFaceWithGenericMethod");
+ MethodDesc interfaceMethod = null;
+
+ foreach(MethodDesc m in interfaceType.GetMethods())
+ {
+ if (m.Name == "GenMethod")
+ {
+ interfaceMethod = m;
+ break;
+ }
+ }
+ Assert.NotNull(interfaceMethod);
+
+ MetadataType objectType = _testModule.GetType("VirtualFunctionOverride", "HasMethodInterfaceOverrideOfGenericMethod");
+ MethodDesc expectedVirtualMethod = null;
+ foreach (MethodDesc m in objectType.GetMethods())
+ {
+ if (m.Name.Contains("GenMethod"))
+ {
+ expectedVirtualMethod = m;
+ break;
+ }
+ }
+ Assert.NotNull(expectedVirtualMethod);
+
+ Assert.Equal(expectedVirtualMethod, objectType.ResolveInterfaceMethodToVirtualMethodOnType(interfaceMethod));
+ }
+
+ [Fact]
+ public void TestVirtualDispatchOnGenericType()
+ {
+ // Verifies that virtual dispatch to a non-generic method on a generic instantiation works
+ DefType objectType = _context.GetWellKnownType(WellKnownType.Object);
+ MethodSignature toStringSig = new MethodSignature(MethodSignatureFlags.None, 0, _stringType, Array.Empty<TypeDesc>());
+ MethodDesc objectToString = objectType.GetMethod("ToString", toStringSig);
+ Assert.NotNull(objectToString);
+ MetadataType openTestType = _testModule.GetType("VirtualFunctionOverride", "SimpleGeneric`1");
+ InstantiatedType testInstance = openTestType.MakeInstantiatedType(objectType);
+ MethodDesc targetOnInstance = testInstance.GetMethod("ToString", toStringSig);
+
+ MethodDesc targetMethod = testInstance.FindVirtualFunctionTargetMethodOnObjectType(objectToString);
+ Assert.Equal(targetOnInstance, targetMethod);
+ }
+
+ [Fact]
+ public void TestVirtualDispatchOnGenericTypeWithOverload()
+ {
+ MetadataType openDerived = _testModule.GetType("VirtualFunctionOverride", "DerivedGenericWithOverload`1");
+ MetadataType derivedInstance = openDerived.MakeInstantiatedType(_stringType);
+ MetadataType baseInstance = (MetadataType)derivedInstance.BaseType;
+
+ MethodDesc baseNongenericOverload = baseInstance.GetMethod("MyMethod", new MethodSignature(MethodSignatureFlags.None, 0, _voidType, new TypeDesc[] { _stringType }));
+ MethodDesc derivedNongenericOverload = derivedInstance.GetMethod("MyMethod", new MethodSignature(MethodSignatureFlags.None, 0, _voidType, new TypeDesc[] { _stringType }));
+ MethodDesc nongenericTargetOverload = derivedInstance.FindVirtualFunctionTargetMethodOnObjectType(baseNongenericOverload);
+ Assert.Equal(derivedNongenericOverload, nongenericTargetOverload);
+
+ MethodDesc baseGenericOverload = baseInstance.GetMethod("MyMethod", new MethodSignature(MethodSignatureFlags.None, 0, _voidType, new TypeDesc[] { _context.GetSignatureVariable(0, false) }));
+ MethodDesc derivedGenericOverload = derivedInstance.GetMethod("MyMethod", new MethodSignature(MethodSignatureFlags.None, 0, _voidType, new TypeDesc[] { _context.GetSignatureVariable(0, false) }));
+ MethodDesc genericTargetOverload = derivedInstance.FindVirtualFunctionTargetMethodOnObjectType(baseGenericOverload);
+ Assert.Equal(derivedGenericOverload, genericTargetOverload);
+ }
+
+ [Fact]
+ public void TestFinalizeOverrideChecking()
+ {
+ MetadataType classWithFinalizer = _testModule.GetType("VirtualFunctionOverride", "ClassWithFinalizer");
+ DefType objectType = _testModule.Context.GetWellKnownType(WellKnownType.Object);
+ MethodDesc finalizeMethod = objectType.GetMethod("Finalize", new MethodSignature(MethodSignatureFlags.None, 0, _voidType, new TypeDesc[] { }));
+
+ MethodDesc actualFinalizer = classWithFinalizer.FindVirtualFunctionTargetMethodOnObjectType(finalizeMethod);
+ Assert.NotNull(actualFinalizer);
+ Assert.NotEqual(actualFinalizer, finalizeMethod);
+ }
+
+ [Fact]
+ public void TestExplicitOverride()
+ {
+ //
+ // Test that explicit virtual method overriding works.
+ //
+
+ var ilModule = _context.GetModuleForSimpleName("ILTestAssembly");
+ var explicitOverrideClass = ilModule.GetType("VirtualFunctionOverride", "ExplicitOverride");
+
+ var myGetHashCodeMethod = explicitOverrideClass.GetMethod("MyGetHashCode", null);
+
+ var objectGetHashCodeMethod = _context.GetWellKnownType(WellKnownType.Object).GetMethod("GetHashCode", null);
+
+ var foundOverride = explicitOverrideClass.FindVirtualFunctionTargetMethodOnObjectType(objectGetHashCodeMethod);
+
+ Assert.Equal(myGetHashCodeMethod, foundOverride);
+ }
+
+ [Fact]
+ public void TestFindBaseUnificationGroup()
+ {
+ var algo = new MetadataVirtualMethodAlgorithm();
+ var ilModule = _context.GetModuleForSimpleName("ILTestAssembly");
+ MetadataType myDerived2Type = ilModule.GetType("VirtualFunctionOverride", "MyDerived2");
+ Assert.NotNull(myDerived2Type);
+ MethodDesc method = myDerived2Type.GetMethod("get_foo", null);
+ Assert.NotNull(method);
+
+ MethodDesc virtualMethod = algo.FindVirtualFunctionTargetMethodOnObjectType(method, myDerived2Type);
+ Assert.NotNull(virtualMethod);
+ Assert.Equal(method, virtualMethod);
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Internal.TypeSystem;
+
+using Xunit;
+
+namespace TypeSystemTests
+{
+ public class WellKnownTypeTests
+ {
+ private TestTypeSystemContext _context;
+ private ModuleDesc _testModule;
+
+ public WellKnownTypeTests()
+ {
+ _context = new TestTypeSystemContext(TargetArchitecture.X64);
+ var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly");
+ _context.SetSystemModule(systemModule);
+
+ _testModule = systemModule;
+ }
+
+ [Fact]
+ public void TestIsValueType()
+ {
+ Assert.True(_context.GetWellKnownType(WellKnownType.Boolean).IsValueType);
+ Assert.True(_context.GetWellKnownType(WellKnownType.Char).IsValueType);
+ Assert.True(_context.GetWellKnownType(WellKnownType.SByte).IsValueType);
+ Assert.True(_context.GetWellKnownType(WellKnownType.Byte).IsValueType);
+ Assert.True(_context.GetWellKnownType(WellKnownType.Int16).IsValueType);
+ Assert.True(_context.GetWellKnownType(WellKnownType.UInt16).IsValueType);
+ Assert.True(_context.GetWellKnownType(WellKnownType.Int32).IsValueType);
+ Assert.True(_context.GetWellKnownType(WellKnownType.UInt32).IsValueType);
+ Assert.True(_context.GetWellKnownType(WellKnownType.Int64).IsValueType);
+ Assert.True(_context.GetWellKnownType(WellKnownType.UInt64).IsValueType);
+ Assert.True(_context.GetWellKnownType(WellKnownType.IntPtr).IsValueType);
+ Assert.True(_context.GetWellKnownType(WellKnownType.UIntPtr).IsValueType);
+ Assert.True(_context.GetWellKnownType(WellKnownType.Single).IsValueType);
+ Assert.True(_context.GetWellKnownType(WellKnownType.Double).IsValueType);
+ Assert.False(_context.GetWellKnownType(WellKnownType.ValueType).IsValueType);
+ Assert.False(_context.GetWellKnownType(WellKnownType.Enum).IsValueType);
+ Assert.True(_context.GetWellKnownType(WellKnownType.Nullable).IsValueType);
+ Assert.False(_context.GetWellKnownType(WellKnownType.Object).IsValueType);
+ Assert.False(_context.GetWellKnownType(WellKnownType.String).IsValueType);
+ Assert.False(_context.GetWellKnownType(WellKnownType.Array).IsValueType);
+ Assert.False(_context.GetWellKnownType(WellKnownType.MulticastDelegate).IsValueType);
+ Assert.True(_context.GetWellKnownType(WellKnownType.RuntimeTypeHandle).IsValueType);
+ Assert.True(_context.GetWellKnownType(WellKnownType.RuntimeMethodHandle).IsValueType);
+ Assert.True(_context.GetWellKnownType(WellKnownType.RuntimeFieldHandle).IsValueType);
+ Assert.False(_context.GetWellKnownType(WellKnownType.Exception).IsValueType);
+ }
+
+ [Fact]
+ public void TestIsPrimitive()
+ {
+ Assert.True(_context.GetWellKnownType(WellKnownType.Boolean).IsPrimitive);
+ Assert.True(_context.GetWellKnownType(WellKnownType.Char).IsPrimitive);
+ Assert.True(_context.GetWellKnownType(WellKnownType.SByte).IsPrimitive);
+ Assert.True(_context.GetWellKnownType(WellKnownType.Byte).IsPrimitive);
+ Assert.True(_context.GetWellKnownType(WellKnownType.Int16).IsPrimitive);
+ Assert.True(_context.GetWellKnownType(WellKnownType.UInt16).IsPrimitive);
+ Assert.True(_context.GetWellKnownType(WellKnownType.Int32).IsPrimitive);
+ Assert.True(_context.GetWellKnownType(WellKnownType.UInt32).IsPrimitive);
+ Assert.True(_context.GetWellKnownType(WellKnownType.Int64).IsPrimitive);
+ Assert.True(_context.GetWellKnownType(WellKnownType.UInt64).IsPrimitive);
+ Assert.True(_context.GetWellKnownType(WellKnownType.IntPtr).IsPrimitive);
+ Assert.True(_context.GetWellKnownType(WellKnownType.UIntPtr).IsPrimitive);
+ Assert.True(_context.GetWellKnownType(WellKnownType.Single).IsPrimitive);
+ Assert.True(_context.GetWellKnownType(WellKnownType.Double).IsPrimitive);
+ Assert.False(_context.GetWellKnownType(WellKnownType.ValueType).IsPrimitive);
+ Assert.False(_context.GetWellKnownType(WellKnownType.Enum).IsPrimitive);
+ Assert.False(_context.GetWellKnownType(WellKnownType.Nullable).IsPrimitive);
+ Assert.False(_context.GetWellKnownType(WellKnownType.Object).IsPrimitive);
+ Assert.False(_context.GetWellKnownType(WellKnownType.String).IsPrimitive);
+ Assert.False(_context.GetWellKnownType(WellKnownType.Array).IsPrimitive);
+ Assert.False(_context.GetWellKnownType(WellKnownType.MulticastDelegate).IsPrimitive);
+ Assert.False(_context.GetWellKnownType(WellKnownType.RuntimeTypeHandle).IsPrimitive);
+ Assert.False(_context.GetWellKnownType(WellKnownType.RuntimeMethodHandle).IsPrimitive);
+ Assert.False(_context.GetWellKnownType(WellKnownType.RuntimeFieldHandle).IsPrimitive);
+ Assert.False(_context.GetWellKnownType(WellKnownType.Exception).IsPrimitive);
+ }
+
+ [Fact]
+ public void TestPrimitiveSizes()
+ {
+ Assert.Equal(1, _context.GetWellKnownType(WellKnownType.Boolean).InstanceFieldSize.AsInt);
+ Assert.Equal(2, _context.GetWellKnownType(WellKnownType.Char).InstanceFieldSize.AsInt);
+ Assert.Equal(1, _context.GetWellKnownType(WellKnownType.SByte).InstanceFieldSize.AsInt);
+ Assert.Equal(1, _context.GetWellKnownType(WellKnownType.Byte).InstanceFieldSize.AsInt);
+ Assert.Equal(2, _context.GetWellKnownType(WellKnownType.Int16).InstanceFieldSize.AsInt);
+ Assert.Equal(2, _context.GetWellKnownType(WellKnownType.UInt16).InstanceFieldSize.AsInt);
+ Assert.Equal(4, _context.GetWellKnownType(WellKnownType.Int32).InstanceFieldSize.AsInt);
+ Assert.Equal(4, _context.GetWellKnownType(WellKnownType.UInt32).InstanceFieldSize.AsInt);
+ Assert.Equal(8, _context.GetWellKnownType(WellKnownType.Int64).InstanceFieldSize.AsInt);
+ Assert.Equal(8, _context.GetWellKnownType(WellKnownType.UInt64).InstanceFieldSize.AsInt);
+ Assert.Equal(_context.Target.PointerSize, _context.GetWellKnownType(WellKnownType.IntPtr).InstanceFieldSize.AsInt);
+ Assert.Equal(_context.Target.PointerSize, _context.GetWellKnownType(WellKnownType.UIntPtr).InstanceFieldSize.AsInt);
+ Assert.Equal(4, _context.GetWellKnownType(WellKnownType.Single).InstanceFieldSize.AsInt);
+ Assert.Equal(8, _context.GetWellKnownType(WellKnownType.Double).InstanceFieldSize.AsInt);
+ }
+
+ [Fact]
+ public void TestModuleType()
+ {
+ Assert.True(_testModule.GetGlobalModuleType().IsModuleType);
+ }
+ }
+}
<Compile Include="..\..\Common\TypeSystem\Common\AlignmentHelper.cs">
<Link>Utilities\AlignmentHelper.cs</Link>
</Compile>
+ <Compile Include="..\..\Common\TypeSystem\Common\ArrayOfTRuntimeInterfacesAlgorithm.cs">
+ <Link>Utilities\ArrayOfTRuntimeInterfacesAlgorithm.cs</Link>
+ </Compile>
<Compile Include="..\..\Common\TypeSystem\Common\CastingHelper.cs">
<Link>TypeSystem\Common\CastingHelper.cs</Link>
</Compile>
+ <Compile Include="..\..\Common\TypeSystem\Common\ConstructedTypeRewritingHelpers.cs">
+ <Link>TypeSystem\Common\ConstructedTypeRewritingHelpers.cs</Link>
+ </Compile>
<Compile Include="..\..\Common\TypeSystem\Common\ExplicitLayoutValidator.cs">
<Link>TypeSystem\Common\ExplicitLayoutValidator.cs</Link>
</Compile>
<Compile Include="..\..\Common\TypeSystem\Common\ThrowHelper.Common.cs">
<Link>TypeSystem\Common\ThrowHelper.Common.cs</Link>
</Compile>
+ <Compile Include="..\..\Common\TypeSystem\Common\UniversalCanonLayoutAlgorithm.cs">
+ <Link>TypeSystem\Common\UniversalCanonLayoutAlgorithm.cs</Link>
+ </Compile>
<Compile Include="..\..\Common\TypeSystem\Common\Utilities\CustomAttributeTypeNameFormatter.cs">
<Link>Utilities\CustomAttributeTypeNameFormatter.cs</Link>
</Compile>
<Compile Include="..\..\Common\TypeSystem\Common\TypeHashingAlgorithms.cs">
<Link>TypeSystem\Common\TypeHashingAlgorithms.cs</Link>
</Compile>
+ <Compile Include="..\..\Common\TypeSystem\Common\TypeSystemConstraintsHelpers.cs">
+ <Link>TypeSystem\Common\TypeSystemConstraintsHelpers.cs</Link>
+ </Compile>
<Compile Include="..\..\Common\TypeSystem\Common\TypeSystemContext.cs">
<Link>TypeSystem\Common\TypeSystemContext.cs</Link>
</Compile>