diff --git a/src/ILCompiler/src/Program.cs b/src/ILCompiler/src/Program.cs index 5efabc2d5ad..5d1ddae6fd4 100644 --- a/src/ILCompiler/src/Program.cs +++ b/src/ILCompiler/src/Program.cs @@ -493,6 +493,8 @@ private int Run(string[] args) removedFeatures |= RemovedFeature.FrameworkResources; else if (feature == "Globalization") removedFeatures |= RemovedFeature.Globalization; + else if (feature == "Comparers") + removedFeatures |= RemovedFeature.Comparers; } ILProvider ilProvider = _isReadyToRunCodeGen ? (ILProvider)new ReadyToRunILProvider() : new CoreRTILProvider(); diff --git a/src/ILCompiler/src/RemovingILProvider.cs b/src/ILCompiler/src/RemovingILProvider.cs index 9beb2cf4d19..3d0b4c23adc 100644 --- a/src/ILCompiler/src/RemovingILProvider.cs +++ b/src/ILCompiler/src/RemovingILProvider.cs @@ -23,7 +23,8 @@ public RemovingILProvider(ILProvider baseILProvider, RemovedFeature feature) public override MethodIL GetMethodIL(MethodDesc method) { - switch (GetAction(method)) + RemoveAction action = GetAction(method); + switch (action) { case RemoveAction.Nothing: return _baseILProvider.GetMethodIL(method); @@ -48,6 +49,26 @@ public override MethodIL GetMethodIL(MethodDesc method) case RemoveAction.ConvertToThrow: return new ILStubMethodIL(method, new byte[] { (byte)ILOpcode.ldnull, (byte)ILOpcode.throw_ }, Array.Empty(), null); + case RemoveAction.ConvertToGetKnownObjectComparer: + case RemoveAction.ConvertToGetKnownObjectEqualityComparer: + { + TypeSystemContext context = method.Context; + MetadataType comparerType = + action == RemoveAction.ConvertToGetKnownObjectComparer ? + context.SystemModule.GetType("System.Collections.Generic", "ObjectComparer`1") : + context.SystemModule.GetType("System.Collections.Generic", "ObjectEqualityComparer`1"); + + MethodDesc methodDef = method.GetTypicalMethodDefinition(); + + ILEmitter emitter = new ILEmitter(); + ILCodeStream codeStream = emitter.NewCodeStream(); + codeStream.Emit(ILOpcode.newobj, emitter.NewToken(comparerType.MakeInstantiatedType(context.GetSignatureVariable(0, method: false)).GetDefaultConstructor())); + codeStream.Emit(ILOpcode.dup); + codeStream.Emit(ILOpcode.stsfld, emitter.NewToken(methodDef.OwningType.InstantiateAsOpen().GetField("_default"))); + codeStream.Emit(ILOpcode.ret); + return new InstantiatedMethodIL(method, emitter.Link(methodDef)); + } + default: throw new NotImplementedException(); } @@ -131,6 +152,20 @@ owningType is Internal.TypeSystem.Ecma.EcmaType mdType && } } + if ((_removedFeature & RemovedFeature.Comparers) != 0) + { + if (owningType.GetTypeDefinition() is Internal.TypeSystem.Ecma.EcmaType mdType + && mdType.Module == method.Context.SystemModule + && method.Name == "Create" + && mdType.Namespace == "System.Collections.Generic") + { + if (mdType.Name == "EqualityComparer`1") + return RemoveAction.ConvertToGetKnownObjectEqualityComparer; + else if (mdType.Name == "Comparer`1") + return RemoveAction.ConvertToGetKnownObjectComparer; + } + } + return RemoveAction.Nothing; } @@ -170,6 +205,8 @@ private enum RemoveAction ConvertToTrueStub, ConvertToGetResourceStringStub, + ConvertToGetKnownObjectComparer, + ConvertToGetKnownObjectEqualityComparer, } } @@ -179,5 +216,6 @@ public enum RemovedFeature Etw = 0x1, FrameworkResources = 0x2, Globalization = 0x4, + Comparers = 0x8, } }