diff options
author | David Wrighton <davidwr@microsoft.com> | 2021-05-31 10:36:24 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-31 10:36:24 +0300 |
commit | fea7ff2cce79da2df9cf1c50ce215287750f055e (patch) | |
tree | 5b233aa1de06132180c823ff3f29d7c240428cf0 /src/coreclr/tools | |
parent | 8538a754f4fcbe190d9299d6f153db2cea39748e (diff) |
Fix issues with virtuals and mdarrays (#53400)
- Change up the definition of an MDArray which doesn't need a special descriptor in the embedded signature data to match the type of mdarray thay everyone always uses. This fixes the virtual function handling behavior for all reasonable cases. (All cases where the MDArray is used for a base type in the expected fashion.)
- Add a devirtualization test for this specific scenario
Fixes #52444
Diffstat (limited to 'src/coreclr/tools')
4 files changed, 51 insertions, 5 deletions
diff --git a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaSignatureParser.cs b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaSignatureParser.cs index 9705ccdd179..48ca23cf1ea 100644 --- a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaSignatureParser.cs +++ b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaSignatureParser.cs @@ -169,10 +169,16 @@ namespace Internal.TypeSystem.Ecma var lowerBoundsCount = _reader.ReadCompressedInteger(); int []lowerBounds = lowerBoundsCount > 0 ? new int[lowerBoundsCount] : Array.Empty<int>(); + bool nonZeroLowerBounds = false; for (int j = 0; j < lowerBoundsCount; j++) - lowerBounds[j] = _reader.ReadCompressedSignedInteger(); + { + int loBound = _reader.ReadCompressedSignedInteger(); + if (loBound != 0) + nonZeroLowerBounds = true; + lowerBounds[j] = loBound; + } - if (boundsCount != 0 || lowerBoundsCount != 0) + if (boundsCount != 0 || lowerBoundsCount != rank || nonZeroLowerBounds) { StringBuilder arrayShapeString = new StringBuilder(); arrayShapeString.Append(string.Join(",", bounds)); diff --git a/src/coreclr/tools/Common/TypeSystem/MetadataEmitter/TypeSystemMetadataEmitter.cs b/src/coreclr/tools/Common/TypeSystem/MetadataEmitter/TypeSystemMetadataEmitter.cs index 0d05bb92e09..5a47094605c 100644 --- a/src/coreclr/tools/Common/TypeSystem/MetadataEmitter/TypeSystemMetadataEmitter.cs +++ b/src/coreclr/tools/Common/TypeSystem/MetadataEmitter/TypeSystemMetadataEmitter.cs @@ -424,10 +424,29 @@ namespace Internal.TypeSystem if (!emittedWithShape) { - shapeEncoder.Shape(rank, ImmutableArray<int>.Empty, ImmutableArray<int>.Empty); + shapeEncoder.Shape(rank, ImmutableArray<int>.Empty, GetZeroedImmutableArrayOfSize(rank)); } } + private static ImmutableArray<int>[] ImmutableArraysFilledWithZeroes = CreateStaticArrayOfImmutableArraysFilledWithZeroes(33); // The max rank of an array is 32 + + private static ImmutableArray<int> GetZeroedImmutableArrayOfSize(int rank) + { + if (rank < ImmutableArraysFilledWithZeroes.Length) + return ImmutableArraysFilledWithZeroes[rank]; + + return new int[rank].ToImmutableArray(); + } + private static ImmutableArray<int>[] CreateStaticArrayOfImmutableArraysFilledWithZeroes(int count) + { + ImmutableArray<int>[] result = new ImmutableArray<int>[count]; + for (int i = 0; i < result.Length; i++) + { + result[i] = new int[i].ToImmutableArray(); + } + return result; + } + public void EmitAtCurrentIndexStack(BlobBuilder signatureBuilder) { if (!Complete) diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/ILTestAssembly/Signature.il b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/ILTestAssembly/Signature.il index 0b9a489f4b8..32e307b7036 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/ILTestAssembly/Signature.il +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/ILTestAssembly/Signature.il @@ -34,6 +34,11 @@ { ret } + + .method public hidebysig instance int32 [0...,0...] Method5(int32 [0...,], int32 [,]) cil managed + { + ret + } } .class private auto ansi beforefieldinit Atom diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/SignatureTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/SignatureTests.cs index 0ea96171119..41362ee5856 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/SignatureTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/SignatureTests.cs @@ -95,11 +95,27 @@ namespace TypeSystemTests MetadataType modOptTester = _testModule.GetType("", "ModOptTester"); MethodSignature methodWithModOpt = modOptTester.GetMethods().Single(m => string.Equals(m.Name, "Method4")).Signature; - Assert.Equal(6, methodWithModOpt.GetEmbeddedSignatureData().Length); + _output.WriteLine($"Found ModOptData '{GetModOptMethodSignatureInfo(methodWithModOpt)}'"); + Assert.Equal(7, methodWithModOpt.GetEmbeddedSignatureData().Length); Assert.Equal(MethodSignature.GetIndexOfCustomModifierOnPointedAtTypeByParameterIndex(0), methodWithModOpt.GetEmbeddedSignatureData()[0].index); Assert.Equal(MethodSignature.GetIndexOfCustomModifierOnPointedAtTypeByParameterIndex(1), methodWithModOpt.GetEmbeddedSignatureData()[2].index); Assert.Equal(MethodSignature.GetIndexOfCustomModifierOnPointedAtTypeByParameterIndex(2), methodWithModOpt.GetEmbeddedSignatureData()[4].index); - Assert.Equal("OptionalCustomModifier0.1.1.2.1.1VoidArrayShape1.2.1.1|3,4|0,1<null>OptionalCustomModifier0.1.1.2.2.1FooModifierArrayShape1.2.2.1|0,9|2,0<null>OptionalCustomModifier0.1.1.2.3.1FooModifierArrayShape1.2.3.1||0<null>", GetModOptMethodSignatureInfo(methodWithModOpt)); + Assert.Equal("OptionalCustomModifier0.1.1.2.1.1VoidArrayShape1.2.1.1|3,4|0,1<null>OptionalCustomModifier0.1.1.2.2.1FooModifierArrayShape1.2.2.1|0,9|2,0<null>OptionalCustomModifier0.1.1.2.3.1FooModifierArrayShape1.2.3.1||0<null>ArrayShape1.2.4.1||<null>", GetModOptMethodSignatureInfo(methodWithModOpt)); + } + + [Fact] + public void TestSignatureMatchesForArrayShapeDetails_HandlingOfCasesWhichDoNotNeedEmbeddeSignatureData() + { + // Test that ensure the typical case (where the loBounds is 0, and the hibounds is unspecified) doesn't produce an + // EmbeddedSignatureData, but that other cases do. This isn't a complete test as ilasm won't actually properly generate the metadata for many of these cases + MetadataType modOptTester = _testModule.GetType("", "ModOptTester"); + MethodSignature methodWithModOpt = modOptTester.GetMethods().Single(m => string.Equals(m.Name, "Method5")).Signature; + + _output.WriteLine($"Found ModOptData '{GetModOptMethodSignatureInfo(methodWithModOpt)}'"); + Assert.Equal(2, methodWithModOpt.GetEmbeddedSignatureData().Length); + Assert.EndsWith(methodWithModOpt.GetEmbeddedSignatureData()[0].index.Split('|')[0], MethodSignature.GetIndexOfCustomModifierOnPointedAtTypeByParameterIndex(1)); + Assert.EndsWith(methodWithModOpt.GetEmbeddedSignatureData()[1].index.Split('|')[0], MethodSignature.GetIndexOfCustomModifierOnPointedAtTypeByParameterIndex(2)); + Assert.Equal("ArrayShape1.2.2.1||0<null>ArrayShape1.2.3.1||<null>", GetModOptMethodSignatureInfo(methodWithModOpt)); } [Fact] |