diff options
author | Jan Kotas <jkotas@microsoft.com> | 2015-12-29 00:05:54 +0300 |
---|---|---|
committer | Jan Kotas <jkotas@microsoft.com> | 2015-12-30 16:54:24 +0300 |
commit | 1bc1dfa2a8470ec9508e04b11d7504e7df907206 (patch) | |
tree | 7d8de2269e8647662494a4162096f5ddd14c7ce7 /src/Common | |
parent | 5a6227d2a5645cc429905654685f36b2c516e2ba (diff) |
Implement most RyuJIT intrinsics
- Add lookup of all RyuJIT intrinsics
- Update manage implementations of the intrinsics to fit with what RyuJIT is capable of
- Make intrinsic expansions by the codegen to be optional by providing fallback paths
- Fix USE_PORTABLE_HELPERS to be defined for portable runtime only
These changes are under CORERT ifdefs as necessary to be reconciled with .NET Native for UWP later.
Diffstat (limited to 'src/Common')
6 files changed, 168 insertions, 74 deletions
diff --git a/src/Common/src/TypeSystem/CodeGen/InstantiatedMethod.CodeGen.cs b/src/Common/src/TypeSystem/CodeGen/InstantiatedMethod.CodeGen.cs deleted file mode 100644 index f62af3023..000000000 --- a/src/Common/src/TypeSystem/CodeGen/InstantiatedMethod.CodeGen.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; -using System.Runtime.CompilerServices; - -namespace Internal.TypeSystem -{ - // Additional members of InstantiatedMethod related to code generation. - public partial class InstantiatedMethod - { - public override bool IsIntrinsic - { - get - { - return _methodDef.IsIntrinsic; - } - } - - public override bool IsNoInlining - { - get - { - return _methodDef.IsNoInlining; - } - } - - public override bool IsAggressiveInlining - { - get - { - return _methodDef.IsAggressiveInlining; - } - } - } -} diff --git a/src/Common/src/TypeSystem/CodeGen/MethodDesc.CodeGen.cs b/src/Common/src/TypeSystem/CodeGen/MethodDesc.CodeGen.cs index e45484f30..9f6784726 100644 --- a/src/Common/src/TypeSystem/CodeGen/MethodDesc.CodeGen.cs +++ b/src/Common/src/TypeSystem/CodeGen/MethodDesc.CodeGen.cs @@ -47,4 +47,72 @@ namespace Internal.TypeSystem } } } + + // Additional members of InstantiatedMethod related to code generation. + public partial class InstantiatedMethod + { + public override bool IsIntrinsic + { + get + { + return _methodDef.IsIntrinsic; + } + } + + public override bool IsNoInlining + { + get + { + return _methodDef.IsNoInlining; + } + } + + public override bool IsAggressiveInlining + { + get + { + return _methodDef.IsAggressiveInlining; + } + } + } + + // Additional members of MethodForInstantiatedType related to code generation. + public partial class MethodForInstantiatedType + { + public override bool IsIntrinsic + { + get + { + return _typicalMethodDef.IsIntrinsic; + } + } + + public override bool IsNoInlining + { + get + { + return _typicalMethodDef.IsNoInlining; + } + } + + public override bool IsAggressiveInlining + { + get + { + return _typicalMethodDef.IsAggressiveInlining; + } + } + } + + // Additional members of ArrayMethod related to code generation. + public partial class ArrayMethod + { + public override bool IsIntrinsic + { + get + { + return true; + } + } + } } diff --git a/src/Common/src/TypeSystem/CodeGen/MethodForInstantiatedType.CodeGen.cs b/src/Common/src/TypeSystem/CodeGen/MethodForInstantiatedType.CodeGen.cs deleted file mode 100644 index a701afe84..000000000 --- a/src/Common/src/TypeSystem/CodeGen/MethodForInstantiatedType.CodeGen.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; -using System.Runtime.CompilerServices; - -namespace Internal.TypeSystem -{ - // Additional members of MethodForInstantiatedType related to code generation. - public partial class MethodForInstantiatedType - { - public override bool IsIntrinsic - { - get - { - return _typicalMethodDef.IsIntrinsic; - } - } - - public override bool IsNoInlining - { - get - { - return _typicalMethodDef.IsNoInlining; - } - } - - public override bool IsAggressiveInlining - { - get - { - return _typicalMethodDef.IsAggressiveInlining; - } - } - } -} diff --git a/src/Common/src/TypeSystem/IL/HelperExtensions.cs b/src/Common/src/TypeSystem/IL/HelperExtensions.cs index 6c494e4fb..ee46558bc 100644 --- a/src/Common/src/TypeSystem/IL/HelperExtensions.cs +++ b/src/Common/src/TypeSystem/IL/HelperExtensions.cs @@ -3,7 +3,6 @@ using System; -using ILCompiler; using Internal.TypeSystem; using Internal.IL.Stubs; @@ -13,6 +12,36 @@ namespace Internal.IL { internal static class HelperExtensions { + /// <summary> + /// NEWOBJ operation on String type is actually a call to a static method that returns a String + /// instance (i.e. there's an explicit call to the runtime allocator from the static method body). + /// This method returns the alloc+init helper corresponding to a given string constructor. + /// </summary> + public static MethodDesc GetStringInitializer(this MethodDesc constructorMethod) + { + Debug.Assert(constructorMethod.IsConstructor); + Debug.Assert(constructorMethod.OwningType.IsString); + + var constructorSignature = constructorMethod.Signature; + + // There's an extra (useless) Object as the first arg to match RyuJIT expectations. + var parameters = new TypeDesc[constructorSignature.Length + 1]; + parameters[0] = constructorMethod.Context.GetWellKnownType(WellKnownType.Object); + for (int i = 0; i < constructorSignature.Length; i++) + parameters[i + 1] = constructorSignature[i]; + + MethodSignature sig = new MethodSignature( + MethodSignatureFlags.Static, 0, constructorMethod.OwningType, parameters); + + MethodDesc result = constructorMethod.OwningType.GetMethod("Ctor", sig); + + // TODO: Better exception type. Should be: "CoreLib doesn't have a required thing in it". + if (result == null) + throw new NotImplementedException(); + + return result; + } + public static MetadataType GetHelperType(this TypeSystemContext context, string name) { MetadataType helperType = context.SystemModule.GetType("Internal.Runtime.CompilerHelpers", name, false); diff --git a/src/Common/src/TypeSystem/IL/ILProvider.cs b/src/Common/src/TypeSystem/IL/ILProvider.cs index 4d8cf5246..9b24cdfe4 100644 --- a/src/Common/src/TypeSystem/IL/ILProvider.cs +++ b/src/Common/src/TypeSystem/IL/ILProvider.cs @@ -31,10 +31,18 @@ namespace Internal.IL if (owningType == null) return null; - if (method.Name == "UncheckedCast" && owningType.Name == "RuntimeHelpers" && owningType.Namespace == "System.Runtime.CompilerServices") + string methodName = method.Name; + + if (methodName == "UncheckedCast" && owningType.Name == "RuntimeHelpers" && owningType.Namespace == "System.Runtime.CompilerServices") { return new ILStubMethodIL(new byte[] { (byte)ILOpcode.ldarg_0, (byte)ILOpcode.ret }, Array.Empty<LocalVariableDefinition>(), null); } + else + if ((methodName == "CompareExchange" || methodName == "Exchange") && method.HasInstantiation && owningType.Name == "Interlocked" && owningType.Namespace == "System.Threading") + { + // TODO: Replace with regular implementation once ref locals are available in C# (https://github.com/dotnet/roslyn/issues/118) + return InterlockedIntrinsic.EmitIL(method); + } return null; } diff --git a/src/Common/src/TypeSystem/IL/Stubs/InterlockedIntrinsic.cs b/src/Common/src/TypeSystem/IL/Stubs/InterlockedIntrinsic.cs new file mode 100644 index 000000000..d2d56018b --- /dev/null +++ b/src/Common/src/TypeSystem/IL/Stubs/InterlockedIntrinsic.cs @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; + +using Internal.TypeSystem; + +using Debug = System.Diagnostics.Debug; + +namespace Internal.IL.Stubs +{ + /// <summary> + /// Provides method bodies for generic Interlocked intrinsics. These intrinsics work around the lack of byref locals + /// return values in C#. The intrinsic method forwards the call to the non-generic version. + /// </summary> + public static class InterlockedIntrinsic + { + public static MethodIL EmitIL(MethodDesc target) + { + Debug.Assert(target.Name == "CompareExchange" || target.Name == "Exchange"); + + // + // Find non-generic method to forward the generic method to. + // + + int parameterCount = target.Signature.Length; + Debug.Assert(parameterCount == 3 || parameterCount == 2); + + var objectType = target.Context.GetWellKnownType(WellKnownType.Object); + + var parameters = new TypeDesc[parameterCount]; + parameters[0] = objectType.MakeByRefType(); + for (int i = 1; i < parameters.Length; i++) + parameters[i] = objectType; + + MethodSignature nonGenericSignature = new MethodSignature(MethodSignatureFlags.Static, 0, objectType, parameters); + + MethodDesc nonGenericMethod = target.OwningType.GetMethod(target.Name, nonGenericSignature); + + // TODO: Better exception type. Should be: "CoreLib doesn't have a required thing in it". + if (nonGenericMethod == null) + throw new NotImplementedException(); + + // + // Emit the forwarder + // + + ILEmitter emitter = new ILEmitter(); + var codeStream = emitter.NewCodeStream(); + + // Reload all arguments + for (int i = 0; i < parameterCount; i++) + codeStream.EmitLdArg(i); + + codeStream.Emit(ILOpcode.call, emitter.NewToken(nonGenericMethod)); + codeStream.Emit(ILOpcode.ret); + + return emitter.Link(); + } + } +} |