From 8c39b7ec3781af3b3f1b36ce3eeccbb15b3dfb32 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Michal=20Strehovsk=C3=BD?= Date: Mon, 27 Apr 2020 16:23:43 +0200 Subject: [PATCH] Sync shared crossgen2 files (#35504) --- .../Common/Compiler/HardwareIntrinsicHelpers.cs | 151 --------------------- .../src/tools/Common/JitInterface/CorInfoImpl.cs | 4 +- .../Common/JitInterface/CorInfoInstructionSet.cs | 90 ++++++------ .../ThunkGenerator/InstructionSetGenerator.cs | 7 +- .../Common/JitInterface/UnboxingMethodDesc.cs | 20 --- .../ILCompiler.ReadyToRun.csproj | 1 + .../JitInterface/CorInfoImpl.ReadyToRun.cs | 9 +- .../JitInterface/UnboxingMethodDescFactory.cs | 31 +++++ 8 files changed, 92 insertions(+), 221 deletions(-) create mode 100644 src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/JitInterface/UnboxingMethodDescFactory.cs diff --git a/src/coreclr/src/tools/Common/Compiler/HardwareIntrinsicHelpers.cs b/src/coreclr/src/tools/Common/Compiler/HardwareIntrinsicHelpers.cs index 8ec5a77..fbf7b61 100644 --- a/src/coreclr/src/tools/Common/Compiler/HardwareIntrinsicHelpers.cs +++ b/src/coreclr/src/tools/Common/Compiler/HardwareIntrinsicHelpers.cs @@ -20,156 +20,5 @@ namespace ILCompiler { return !string.IsNullOrEmpty(InstructionSetSupport.GetHardwareIntrinsicId(method.Context.Target.Architecture, method.OwningType)); } - -#if !READYTORUN - public static bool IsIsSupportedMethod(MethodDesc method) - { - return method.Name == "get_IsSupported"; - } - - public static MethodIL GetUnsupportedImplementationIL(MethodDesc method) - { - // The implementation of IsSupported for codegen backends that don't support hardware intrinsics - // at all is to return 0. - if (IsIsSupportedMethod(method)) - { - return new ILStubMethodIL(method, - new byte[] { - (byte)ILOpcode.ldc_i4_0, - (byte)ILOpcode.ret - }, - Array.Empty(), null); - } - - // Other methods throw PlatformNotSupportedException - MethodDesc throwPnse = method.Context.GetHelperEntryPoint("ThrowHelpers", "ThrowPlatformNotSupportedException"); - - return new ILStubMethodIL(method, - new byte[] { - (byte)ILOpcode.call, 1, 0, 0, 0, - (byte)ILOpcode.br_s, unchecked((byte)-7), - }, - Array.Empty(), - new object[] { throwPnse }); - } - - /// - /// Generates IL for the IsSupported property that reads this information from a field initialized by the runtime - /// at startup. Returns null for hardware intrinsics whose support level is known at compile time - /// (i.e. they're known to be always supported or always unsupported). - /// - public static MethodIL EmitIsSupportedIL(MethodDesc method, FieldDesc isSupportedField) - { - Debug.Assert(IsIsSupportedMethod(method)); - Debug.Assert(isSupportedField.IsStatic && isSupportedField.FieldType.IsWellKnownType(WellKnownType.Int32)); - - TargetDetails target = method.Context.Target; - MetadataType owningType = (MetadataType)method.OwningType; - - // Check for case of nested "X64" types - if (owningType.Name == "X64") - { - if (target.Architecture != TargetArchitecture.X64) - return null; - - // Un-nest the type so that we can do a name match - owningType = (MetadataType)owningType.ContainingType; - } - - int flag; - if ((target.Architecture == TargetArchitecture.X64 || target.Architecture == TargetArchitecture.X86) - && owningType.Namespace == "System.Runtime.Intrinsics.X86") - { - switch (owningType.Name) - { - case "Aes": - flag = XArchIntrinsicConstants.Aes; - break; - case "Pclmulqdq": - flag = XArchIntrinsicConstants.Pclmulqdq; - break; - case "Sse3": - flag = XArchIntrinsicConstants.Sse3; - break; - case "Ssse3": - flag = XArchIntrinsicConstants.Ssse3; - break; - case "Lzcnt": - flag = XArchIntrinsicConstants.Lzcnt; - break; - // NOTE: this switch is complemented by IsKnownSupportedIntrinsicAtCompileTime - // in the method below. - default: - return null; - } - } - else - { - return null; - } - - var emit = new ILEmitter(); - ILCodeStream codeStream = emit.NewCodeStream(); - - codeStream.Emit(ILOpcode.ldsfld, emit.NewToken(isSupportedField)); - codeStream.EmitLdc(flag); - codeStream.Emit(ILOpcode.and); - codeStream.EmitLdc(0); - codeStream.Emit(ILOpcode.cgt_un); - codeStream.Emit(ILOpcode.ret); - - return emit.Link(method); - } - - /// - /// Gets a value indicating whether the support for a given intrinsic is known at compile time. - /// - public static bool IsKnownSupportedIntrinsicAtCompileTime(MethodDesc method) - { - TargetDetails target = method.Context.Target; - - if (target.Architecture == TargetArchitecture.X64 - || target.Architecture == TargetArchitecture.X86) - { - var owningType = (MetadataType)method.OwningType; - if (owningType.Name == "X64") - { - if (target.Architecture != TargetArchitecture.X64) - return true; - owningType = (MetadataType)owningType.ContainingType; - } - - if (owningType.Namespace != "System.Runtime.Intrinsics.X86") - return true; - - // Sse and Sse2 are baseline required intrinsics. - // RyuJIT also uses Sse41/Sse42 with the general purpose Vector APIs. - // RyuJIT only respects Popcnt if Sse41/Sse42 is also enabled. - // Avx/Avx2/Bmi1/Bmi2 require VEX encoding and RyuJIT currently can't enable them - // without enabling VEX encoding everywhere. We don't support them. - // This list complements EmitIsSupportedIL above. - return owningType.Name == "Sse" || owningType.Name == "Sse2" - || owningType.Name == "Sse41" || owningType.Name == "Sse42" - || owningType.Name == "Popcnt" - || owningType.Name == "Bmi1" || owningType.Name == "Bmi2" - || owningType.Name == "Avx" || owningType.Name == "Avx2"; - } - - return false; - } - - // Keep this enumeration in sync with startup.cpp in the native runtime. - private static class XArchIntrinsicConstants - { - public const int Aes = 0x0001; - public const int Pclmulqdq = 0x0002; - public const int Sse3 = 0x0004; - public const int Ssse3 = 0x0008; - public const int Sse41 = 0x0010; - public const int Sse42 = 0x0020; - public const int Popcnt = 0x0040; - public const int Lzcnt = 0x0080; - } -#endif // !READYTORUN } } diff --git a/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs index 3901cd3..292f42d 100644 --- a/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs @@ -109,8 +109,6 @@ namespace Internal.JitInterface [DllImport(JitSupportLibrary)] private extern static char* GetExceptionMessage(IntPtr obj); - private static readonly UnboxingMethodDescFactory _unboxingThunkFactory = new UnboxingMethodDescFactory(); - public static void Startup() { jitStartup(GetJitHost(JitConfigProvider.Instance.UnmanagedInstance)); @@ -874,7 +872,7 @@ namespace Internal.JitInterface { if (impl.OwningType.IsValueType) { - impl = _unboxingThunkFactory.GetUnboxingMethod(impl); + impl = getUnboxingThunk(impl); } return ObjectToHandle(impl); diff --git a/src/coreclr/src/tools/Common/JitInterface/CorInfoInstructionSet.cs b/src/coreclr/src/tools/Common/JitInterface/CorInfoInstructionSet.cs index 92e987f..256fd8d 100644 --- a/src/coreclr/src/tools/Common/JitInterface/CorInfoInstructionSet.cs +++ b/src/coreclr/src/tools/Common/JitInterface/CorInfoInstructionSet.cs @@ -396,12 +396,14 @@ namespace Internal.JitInterface public struct InstructionSetInfo { public readonly string Name; + public readonly string ManagedName; public readonly InstructionSet InstructionSet; public readonly bool Specifiable; - public InstructionSetInfo(string name, InstructionSet instructionSet, bool specifiable) + public InstructionSetInfo(string name, string managedName, InstructionSet instructionSet, bool specifiable) { Name = name; + ManagedName = managedName; InstructionSet = instructionSet; Specifiable = specifiable; } @@ -413,55 +415,55 @@ namespace Internal.JitInterface { case TargetArchitecture.ARM64: - yield return new InstructionSetInfo("base", InstructionSet.ARM64_ArmBase, true); - yield return new InstructionSetInfo("neon", InstructionSet.ARM64_AdvSimd, true); - yield return new InstructionSetInfo("aes", InstructionSet.ARM64_Aes, true); - yield return new InstructionSetInfo("crc", InstructionSet.ARM64_Crc32, true); - yield return new InstructionSetInfo("sha1", InstructionSet.ARM64_Sha1, true); - yield return new InstructionSetInfo("sha2", InstructionSet.ARM64_Sha256, true); - yield return new InstructionSetInfo("lse", InstructionSet.ARM64_Atomics, true); - yield return new InstructionSetInfo("Vector64", InstructionSet.ARM64_Vector64, false); - yield return new InstructionSetInfo("Vector128", InstructionSet.ARM64_Vector128, false); + yield return new InstructionSetInfo("base", "ArmBase", InstructionSet.ARM64_ArmBase, true); + yield return new InstructionSetInfo("neon", "AdvSimd", InstructionSet.ARM64_AdvSimd, true); + yield return new InstructionSetInfo("aes", "Aes", InstructionSet.ARM64_Aes, true); + yield return new InstructionSetInfo("crc", "Crc32", InstructionSet.ARM64_Crc32, true); + yield return new InstructionSetInfo("sha1", "Sha1", InstructionSet.ARM64_Sha1, true); + yield return new InstructionSetInfo("sha2", "Sha256", InstructionSet.ARM64_Sha256, true); + yield return new InstructionSetInfo("lse", "", InstructionSet.ARM64_Atomics, true); + yield return new InstructionSetInfo("Vector64", "", InstructionSet.ARM64_Vector64, false); + yield return new InstructionSetInfo("Vector128", "", InstructionSet.ARM64_Vector128, false); break; case TargetArchitecture.X64: - yield return new InstructionSetInfo("sse", InstructionSet.X64_SSE, true); - yield return new InstructionSetInfo("sse2", InstructionSet.X64_SSE2, true); - yield return new InstructionSetInfo("sse3", InstructionSet.X64_SSE3, true); - yield return new InstructionSetInfo("ssse3", InstructionSet.X64_SSSE3, true); - yield return new InstructionSetInfo("sse4.1", InstructionSet.X64_SSE41, true); - yield return new InstructionSetInfo("sse4.2", InstructionSet.X64_SSE42, true); - yield return new InstructionSetInfo("avx", InstructionSet.X64_AVX, true); - yield return new InstructionSetInfo("avx2", InstructionSet.X64_AVX2, true); - yield return new InstructionSetInfo("aes", InstructionSet.X64_AES, true); - yield return new InstructionSetInfo("bmi", InstructionSet.X64_BMI1, true); - yield return new InstructionSetInfo("bmi2", InstructionSet.X64_BMI2, true); - yield return new InstructionSetInfo("fma", InstructionSet.X64_FMA, true); - yield return new InstructionSetInfo("lzcnt", InstructionSet.X64_LZCNT, true); - yield return new InstructionSetInfo("pclmul", InstructionSet.X64_PCLMULQDQ, true); - yield return new InstructionSetInfo("popcnt", InstructionSet.X64_POPCNT, true); - yield return new InstructionSetInfo("Vector128", InstructionSet.X64_Vector128, false); - yield return new InstructionSetInfo("Vector256", InstructionSet.X64_Vector256, false); + yield return new InstructionSetInfo("sse", "Sse", InstructionSet.X64_SSE, true); + yield return new InstructionSetInfo("sse2", "Sse2", InstructionSet.X64_SSE2, true); + yield return new InstructionSetInfo("sse3", "Sse3", InstructionSet.X64_SSE3, true); + yield return new InstructionSetInfo("ssse3", "Ssse3", InstructionSet.X64_SSSE3, true); + yield return new InstructionSetInfo("sse4.1", "Sse41", InstructionSet.X64_SSE41, true); + yield return new InstructionSetInfo("sse4.2", "Sse42", InstructionSet.X64_SSE42, true); + yield return new InstructionSetInfo("avx", "Avx", InstructionSet.X64_AVX, true); + yield return new InstructionSetInfo("avx2", "Avx2", InstructionSet.X64_AVX2, true); + yield return new InstructionSetInfo("aes", "Aes", InstructionSet.X64_AES, true); + yield return new InstructionSetInfo("bmi", "Bmi1", InstructionSet.X64_BMI1, true); + yield return new InstructionSetInfo("bmi2", "Bmi2", InstructionSet.X64_BMI2, true); + yield return new InstructionSetInfo("fma", "Fma", InstructionSet.X64_FMA, true); + yield return new InstructionSetInfo("lzcnt", "Lzcnt", InstructionSet.X64_LZCNT, true); + yield return new InstructionSetInfo("pclmul", "Pclmulqdq", InstructionSet.X64_PCLMULQDQ, true); + yield return new InstructionSetInfo("popcnt", "Popcnt", InstructionSet.X64_POPCNT, true); + yield return new InstructionSetInfo("Vector128", "", InstructionSet.X64_Vector128, false); + yield return new InstructionSetInfo("Vector256", "", InstructionSet.X64_Vector256, false); break; case TargetArchitecture.X86: - yield return new InstructionSetInfo("sse", InstructionSet.X86_SSE, true); - yield return new InstructionSetInfo("sse2", InstructionSet.X86_SSE2, true); - yield return new InstructionSetInfo("sse3", InstructionSet.X86_SSE3, true); - yield return new InstructionSetInfo("ssse3", InstructionSet.X86_SSSE3, true); - yield return new InstructionSetInfo("sse4.1", InstructionSet.X86_SSE41, true); - yield return new InstructionSetInfo("sse4.2", InstructionSet.X86_SSE42, true); - yield return new InstructionSetInfo("avx", InstructionSet.X86_AVX, true); - yield return new InstructionSetInfo("avx2", InstructionSet.X86_AVX2, true); - yield return new InstructionSetInfo("aes", InstructionSet.X86_AES, true); - yield return new InstructionSetInfo("bmi", InstructionSet.X86_BMI1, true); - yield return new InstructionSetInfo("bmi2", InstructionSet.X86_BMI2, true); - yield return new InstructionSetInfo("fma", InstructionSet.X86_FMA, true); - yield return new InstructionSetInfo("lzcnt", InstructionSet.X86_LZCNT, true); - yield return new InstructionSetInfo("pclmul", InstructionSet.X86_PCLMULQDQ, true); - yield return new InstructionSetInfo("popcnt", InstructionSet.X86_POPCNT, true); - yield return new InstructionSetInfo("Vector128", InstructionSet.X86_Vector128, false); - yield return new InstructionSetInfo("Vector256", InstructionSet.X86_Vector256, false); + yield return new InstructionSetInfo("sse", "Sse", InstructionSet.X86_SSE, true); + yield return new InstructionSetInfo("sse2", "Sse2", InstructionSet.X86_SSE2, true); + yield return new InstructionSetInfo("sse3", "Sse3", InstructionSet.X86_SSE3, true); + yield return new InstructionSetInfo("ssse3", "Ssse3", InstructionSet.X86_SSSE3, true); + yield return new InstructionSetInfo("sse4.1", "Sse41", InstructionSet.X86_SSE41, true); + yield return new InstructionSetInfo("sse4.2", "Sse42", InstructionSet.X86_SSE42, true); + yield return new InstructionSetInfo("avx", "Avx", InstructionSet.X86_AVX, true); + yield return new InstructionSetInfo("avx2", "Avx2", InstructionSet.X86_AVX2, true); + yield return new InstructionSetInfo("aes", "Aes", InstructionSet.X86_AES, true); + yield return new InstructionSetInfo("bmi", "Bmi1", InstructionSet.X86_BMI1, true); + yield return new InstructionSetInfo("bmi2", "Bmi2", InstructionSet.X86_BMI2, true); + yield return new InstructionSetInfo("fma", "Fma", InstructionSet.X86_FMA, true); + yield return new InstructionSetInfo("lzcnt", "Lzcnt", InstructionSet.X86_LZCNT, true); + yield return new InstructionSetInfo("pclmul", "Pclmulqdq", InstructionSet.X86_PCLMULQDQ, true); + yield return new InstructionSetInfo("popcnt", "Popcnt", InstructionSet.X86_POPCNT, true); + yield return new InstructionSetInfo("Vector128", "", InstructionSet.X86_Vector128, false); + yield return new InstructionSetInfo("Vector256", "", InstructionSet.X86_Vector256, false); break; } diff --git a/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/InstructionSetGenerator.cs b/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/InstructionSetGenerator.cs index ea4268f..ad5a210 100644 --- a/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/InstructionSetGenerator.cs +++ b/src/coreclr/src/tools/Common/JitInterface/ThunkGenerator/InstructionSetGenerator.cs @@ -522,12 +522,14 @@ namespace Internal.JitInterface public struct InstructionSetInfo { public readonly string Name; + public readonly string ManagedName; public readonly InstructionSet InstructionSet; public readonly bool Specifiable; - public InstructionSetInfo(string name, InstructionSet instructionSet, bool specifiable) + public InstructionSetInfo(string name, string managedName, InstructionSet instructionSet, bool specifiable) { Name = name; + ManagedName = managedName; InstructionSet = instructionSet; Specifiable = specifiable; } @@ -548,9 +550,10 @@ namespace Internal.JitInterface if (instructionSet.Architecture != architecture) continue; bool instructionSetIsSpecifiable = !String.IsNullOrEmpty(instructionSet.CommandLineName); string name = instructionSet.PublicName; + string managedName = instructionSet.ManagedName; string specifiable = instructionSetIsSpecifiable ? "true" : "false"; string instructionSetString = $"InstructionSet.{architecture}_{instructionSet.JitName}"; - tr.WriteLine($" yield return new InstructionSetInfo(\"{name}\", {instructionSetString}, {specifiable});"); + tr.WriteLine($" yield return new InstructionSetInfo(\"{name}\", \"{managedName}\", {instructionSetString}, {specifiable});"); } tr.WriteLine(" break;"); } diff --git a/src/coreclr/src/tools/Common/JitInterface/UnboxingMethodDesc.cs b/src/coreclr/src/tools/Common/JitInterface/UnboxingMethodDesc.cs index b21a721..817e6f3 100644 --- a/src/coreclr/src/tools/Common/JitInterface/UnboxingMethodDesc.cs +++ b/src/coreclr/src/tools/Common/JitInterface/UnboxingMethodDesc.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using Internal.TypeSystem; @@ -80,25 +79,6 @@ namespace Internal.JitInterface #endif } - internal class UnboxingMethodDescFactory : ConcurrentDictionary - { - private Func _factoryDelegate; - private UnboxingMethodDesc CreateUnboxingMethod(MethodDesc method) - { - return new UnboxingMethodDesc(method, this); - } - - public UnboxingMethodDescFactory() - { - _factoryDelegate = CreateUnboxingMethod; - } - - public UnboxingMethodDesc GetUnboxingMethod(MethodDesc method) - { - return GetOrAdd(method, _factoryDelegate); - } - } - internal static class UnboxingMethodDescExtensions { public static bool IsUnboxingThunk(this MethodDesc method) diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj index f36eb5f..2374f68 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj @@ -201,6 +201,7 @@ + diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs index 433b69a..5c59632 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -141,6 +141,8 @@ namespace Internal.JitInterface private NativeVarInfo[] _debugVarInfos; private ArrayBuilder _inlinedMethods; + private static readonly UnboxingMethodDescFactory s_unboxingThunkFactory = new UnboxingMethodDescFactory(); + public CorInfoImpl(ReadyToRunCodegenCompilation compilation) : this() { @@ -1884,7 +1886,7 @@ namespace Internal.JitInterface if ((td.IsValueType) && !md.Signature.IsStatic) { - md = _unboxingThunkFactory.GetUnboxingMethod(md); + md = getUnboxingThunk(md); } symbolNode = _compilation.SymbolNodeFactory.CreateReadyToRunHelper( @@ -1907,6 +1909,11 @@ namespace Internal.JitInterface } } + private MethodDesc getUnboxingThunk(MethodDesc method) + { + return s_unboxingThunkFactory.GetUnboxingMethod(method); + } + private CORINFO_METHOD_STRUCT_* embedMethodHandle(CORINFO_METHOD_STRUCT_* handle, ref void* ppIndirection) { // TODO: READYTORUN FUTURE: Handle this case correctly diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/JitInterface/UnboxingMethodDescFactory.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/JitInterface/UnboxingMethodDescFactory.cs new file mode 100644 index 0000000..9763e88 --- /dev/null +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/JitInterface/UnboxingMethodDescFactory.cs @@ -0,0 +1,31 @@ +// 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.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using Internal.TypeSystem; + +namespace Internal.JitInterface +{ + internal class UnboxingMethodDescFactory : ConcurrentDictionary + { + private Func _factoryDelegate; + private UnboxingMethodDesc CreateUnboxingMethod(MethodDesc method) + { + return new UnboxingMethodDesc(method, this); + } + + public UnboxingMethodDescFactory() + { + _factoryDelegate = CreateUnboxingMethod; + } + + public UnboxingMethodDesc GetUnboxingMethod(MethodDesc method) + { + return GetOrAdd(method, _factoryDelegate); + } + } +} \ No newline at end of file -- 2.7.4