diff options
author | Jan Kotas <jkotas@microsoft.com> | 2018-06-24 03:19:20 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-06-24 03:19:20 +0300 |
commit | c9326538e74bcb8f73760cceb84b8abcddc9812f (patch) | |
tree | 97b300513b2eee7fc36691f657c482653acf4351 /src | |
parent | 6c2368b53687609f2fd8ce4389596f2a0d283e3f (diff) |
Plumbing to generate calli PInvoke stubs (#6002)
Contributes to #5587
Diffstat (limited to 'src')
13 files changed, 281 insertions, 9 deletions
diff --git a/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Mangling.cs b/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Mangling.cs new file mode 100644 index 000000000..5bb37b622 --- /dev/null +++ b/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Mangling.cs @@ -0,0 +1,28 @@ +// 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; + +namespace Internal.IL.Stubs +{ + public partial class CalliMarshallingMethodThunk : IPrefixMangledSignature + { + MethodSignature IPrefixMangledSignature.BaseSignature + { + get + { + return _targetSignature; + } + } + + string IPrefixMangledSignature.Prefix + { + get + { + return "Calli"; + } + } + } +} diff --git a/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Sorting.cs b/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Sorting.cs new file mode 100644 index 000000000..2ac126d11 --- /dev/null +++ b/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Sorting.cs @@ -0,0 +1,20 @@ +// 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; + +namespace Internal.IL.Stubs +{ + // Functionality related to deterministic ordering of methods + partial class CalliMarshallingMethodThunk + { + protected internal override int ClassCode => 1594107963; + + protected internal override int CompareToImpl(MethodDesc other, TypeSystemComparer comparer) + { + var otherMethod = (CalliMarshallingMethodThunk)other; + return comparer.Compare(_targetSignature, otherMethod._targetSignature); + } + } +} diff --git a/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.cs b/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.cs new file mode 100644 index 000000000..a70ceb5fe --- /dev/null +++ b/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.cs @@ -0,0 +1,89 @@ +// 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.TypeSystem.Interop; +using Debug = System.Diagnostics.Debug; +using Internal.TypeSystem.Ecma; + +namespace Internal.IL.Stubs +{ + /// <summary> + /// Thunk to marshal calli PInvoke parameters and invoke the appropriate function pointer + /// </summary> + public partial class CalliMarshallingMethodThunk : ILStubMethod + { + private readonly MethodSignature _targetSignature; + private readonly InteropStateManager _interopStateManager; + private readonly TypeDesc _owningType; + + private MethodSignature _signature; + + public CalliMarshallingMethodThunk(MethodSignature targetSignature, TypeDesc owningType, + InteropStateManager interopStateManager) + { + _targetSignature = targetSignature; + _owningType = owningType; + _interopStateManager = interopStateManager; + } + + public MethodSignature TargetSignature + { + get + { + return _targetSignature; + } + } + + public override TypeSystemContext Context + { + get + { + return _owningType.Context; + } + } + + public override TypeDesc OwningType + { + get + { + return _owningType; + } + } + + public override MethodSignature Signature + { + get + { + if (_signature == null) + { + // Prepend fnptr argument to the signature + TypeDesc[] parameterTypes = new TypeDesc[_targetSignature.Length + 1]; + + parameterTypes[0] = Context.GetWellKnownType(WellKnownType.IntPtr); + for (int i = 0; i < _targetSignature.Length; i++) + parameterTypes[i + 1] = _targetSignature[i]; + + _signature = new MethodSignature(MethodSignatureFlags.Static, 0, _targetSignature.ReturnType, parameterTypes); + } + return _signature; + } + } + + public override string Name + { + get + { + return "CalliMarshallingMethodThunk"; + } + } + + public override MethodIL EmitIL() + { + // TODO + throw null; + } + } +} diff --git a/src/Common/src/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.Mangling.cs b/src/Common/src/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.Mangling.cs index 7813d0318..bd140239c 100644 --- a/src/Common/src/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.Mangling.cs +++ b/src/Common/src/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.Mangling.cs @@ -7,9 +7,6 @@ using Internal.TypeSystem; namespace Internal.IL.Stubs { - /// <summary> - /// contains functionality related to name mangling - /// </summary> public partial class DelegateMarshallingMethodThunk : IPrefixMangledType { TypeDesc IPrefixMangledType.BaseType diff --git a/src/Common/src/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs b/src/Common/src/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs index 650b244c1..dd4f182de 100644 --- a/src/Common/src/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs +++ b/src/Common/src/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs @@ -109,5 +109,13 @@ namespace Internal.IL.Stubs { return false; } + + public override string Name + { + get + { + return _targetMethod.Name; + } + } } } diff --git a/src/Common/src/TypeSystem/IL/Stubs/PInvokeTargetNativeMethod.cs b/src/Common/src/TypeSystem/IL/Stubs/PInvokeTargetNativeMethod.cs index 2a2cae4e8..5aab575a2 100644 --- a/src/Common/src/TypeSystem/IL/Stubs/PInvokeTargetNativeMethod.cs +++ b/src/Common/src/TypeSystem/IL/Stubs/PInvokeTargetNativeMethod.cs @@ -72,6 +72,15 @@ namespace Internal.IL.Stubs } } + public override bool IsNoInlining + { + get + { + // This method does not have real IL body. NoInlining stops the JIT asking for it. + return true; + } + } + public override PInvokeMetadata GetPInvokeMethodMetadata() { return _declMethod.GetPInvokeMethodMetadata(); diff --git a/src/Common/src/TypeSystem/Interop/InteropStateManager.cs b/src/Common/src/TypeSystem/Interop/InteropStateManager.cs index c28ca119d..3e71c1382 100644 --- a/src/Common/src/TypeSystem/Interop/InteropStateManager.cs +++ b/src/Common/src/TypeSystem/Interop/InteropStateManager.cs @@ -22,6 +22,7 @@ namespace Internal.TypeSystem private readonly PInvokeDelegateWrapperHashtable _pInvokeDelegateWrapperHashtable; private readonly InlineArrayHashTable _inlineArrayHashtable; private readonly PInvokeLazyFixupFieldHashtable _pInvokeLazyFixupFieldHashtable; + private readonly PInvokeCalliHashtable _pInvokeCalliHashtable; public InteropStateManager(ModuleDesc generatedAssembly) { @@ -33,6 +34,7 @@ namespace Internal.TypeSystem _pInvokeDelegateWrapperHashtable = new PInvokeDelegateWrapperHashtable(this, _generatedAssembly); _inlineArrayHashtable = new InlineArrayHashTable(this, _generatedAssembly); _pInvokeLazyFixupFieldHashtable = new PInvokeLazyFixupFieldHashtable(_generatedAssembly.GetGlobalModuleType()); + _pInvokeCalliHashtable = new PInvokeCalliHashtable(this, _generatedAssembly.GetGlobalModuleType()); } // // Delegate Marshalling Stubs @@ -185,6 +187,11 @@ namespace Internal.TypeSystem return _pInvokeLazyFixupFieldHashtable.GetOrCreateValue(method); } + public MethodDesc GetPInvokeCalliStub(MethodSignature signature) + { + return _pInvokeCalliHashtable.GetOrCreateValue(signature); + } + private class NativeStructTypeHashtable : LockFreeReaderHashtable<MetadataType, NativeStructType> { protected override int GetKeyHashCode(MetadataType key) @@ -471,5 +478,42 @@ namespace Internal.TypeSystem _owningType = owningType; } } + + private class PInvokeCalliHashtable : LockFreeReaderHashtable<MethodSignature, CalliMarshallingMethodThunk> + { + private readonly InteropStateManager _interopStateManager; + private readonly TypeDesc _owningType; + + protected override int GetKeyHashCode(MethodSignature key) + { + return key.GetHashCode(); + } + + protected override int GetValueHashCode(CalliMarshallingMethodThunk value) + { + return value.TargetSignature.GetHashCode(); + } + + protected override bool CompareKeyToValue(MethodSignature key, CalliMarshallingMethodThunk value) + { + return key.Equals(value.TargetSignature); + } + + protected override bool CompareValueToValue(CalliMarshallingMethodThunk value1, CalliMarshallingMethodThunk value2) + { + return value1.TargetSignature.Equals(value2.TargetSignature); + } + + protected override CalliMarshallingMethodThunk CreateValueFromKey(MethodSignature key) + { + return new CalliMarshallingMethodThunk(key, _owningType, _interopStateManager); + } + + public PInvokeCalliHashtable(InteropStateManager interopStateManager, TypeDesc owningType) + { + _interopStateManager = interopStateManager; + _owningType = owningType; + } + } } } diff --git a/src/Common/src/TypeSystem/Mangling/IPrefixMangledSignature.cs b/src/Common/src/TypeSystem/Mangling/IPrefixMangledSignature.cs new file mode 100644 index 000000000..3dabbc53a --- /dev/null +++ b/src/Common/src/TypeSystem/Mangling/IPrefixMangledSignature.cs @@ -0,0 +1,23 @@ +// 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 Internal.TypeSystem +{ + /// <summary> + /// When implemented by a <see cref="MethodDesc"/>, instructs a name mangler to use the same mangled name + /// as another entity while prepending a specific prefix to that mangled name. + /// </summary> + public interface IPrefixMangledSignature + { + /// <summary> + /// Signature whose mangled name to use. + /// </summary> + MethodSignature BaseSignature { get; } + + /// <summary> + /// Prefix to apply when mangling. + /// </summary> + string Prefix { get; } + } +} diff --git a/src/ILCompiler.Compiler/src/Compiler/CoreRTNameMangler.cs b/src/ILCompiler.Compiler/src/Compiler/CoreRTNameMangler.cs index 5c292f87f..8c5636c21 100644 --- a/src/ILCompiler.Compiler/src/Compiler/CoreRTNameMangler.cs +++ b/src/ILCompiler.Compiler/src/Compiler/CoreRTNameMangler.cs @@ -410,6 +410,35 @@ namespace ILCompiler return sb.ToUtf8String(); } + private Utf8String GetPrefixMangledSignatureName(IPrefixMangledSignature prefixMangledSignature) + { + Utf8StringBuilder sb = new Utf8StringBuilder(); + sb.Append(EnterNameScopeSequence).Append(prefixMangledSignature.Prefix).Append(ExitNameScopeSequence); + + var signature = prefixMangledSignature.BaseSignature; + sb.Append(signature.Flags.ToStringInvariant()); + + sb.Append(EnterNameScopeSequence); + + string sigRetTypeName = GetMangledTypeName(signature.ReturnType); + if (_mangleForCplusPlus) + sigRetTypeName = sigRetTypeName.Replace("::", "_"); + sb.Append(sigRetTypeName); + + for (int i = 0; i < signature.Length; i++) + { + sb.Append("__"); + string sigArgName = GetMangledTypeName(signature[i]); + if (_mangleForCplusPlus) + sigArgName = sigArgName.Replace("::", "_"); + sb.Append(sigArgName); + } + + sb.Append(ExitNameScopeSequence); + + return sb.ToUtf8String(); + } + private Utf8String GetPrefixMangledMethodName(IPrefixMangledMethod prefixMangledMetod) { Utf8StringBuilder sb = new Utf8StringBuilder(); @@ -497,6 +526,10 @@ namespace ILCompiler { utf8MangledName = GetPrefixMangledTypeName((IPrefixMangledType)method); } + else if (method is IPrefixMangledSignature) + { + utf8MangledName = GetPrefixMangledSignatureName((IPrefixMangledSignature)method); + } else { // Assume that Name is unique for all other methods diff --git a/src/ILCompiler.Compiler/src/IL/Stubs/PInvokeILProvider.cs b/src/ILCompiler.Compiler/src/IL/Stubs/PInvokeILProvider.cs index 4aec04036..7ae483dbc 100644 --- a/src/ILCompiler.Compiler/src/IL/Stubs/PInvokeILProvider.cs +++ b/src/ILCompiler.Compiler/src/IL/Stubs/PInvokeILProvider.cs @@ -29,5 +29,10 @@ namespace Internal.IL { return PInvokeILEmitter.EmitIL(method, _pInvokeILEmitterConfiguration, _interopStateManager); } + + public MethodDesc GetCalliStub(MethodSignature signature) + { + return _interopStateManager.GetPInvokeCalliStub(signature); + } } } diff --git a/src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj b/src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj index aab6301a4..ec7b134e6 100644 --- a/src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj +++ b/src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj @@ -358,9 +358,6 @@ <Compile Include="..\..\Common\src\TypeSystem\IL\DelegateInfo.cs"> <Link>IL\DelegateInfo.cs</Link> </Compile> - <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DelegateMarshallingMethodThunk.Sorting.cs"> - <Link>IL\Stubs\DelegateMarshallingMethodThunk.Sorting.cs</Link> - </Compile> <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DelegateThunks.Sorting.cs"> <Link>IL\Stubs\DelegateThunks.Sorting.cs</Link> </Compile> @@ -475,12 +472,24 @@ <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DebuggerSteppingHelpers.cs"> <Link>IL\Stubs\DebuggerSteppingHelpers.cs</Link> </Compile> + <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\CalliMarshallingMethodThunk.cs"> + <Link>IL\Stubs\CalliMarshallingMethodThunk.cs</Link> + </Compile> + <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\CalliMarshallingMethodThunk.Mangling.cs"> + <Link>IL\Stubs\CalliMarshallingMethodThunk.Mangling.cs</Link> + </Compile> + <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\CalliMarshallingMethodThunk.Sorting.cs"> + <Link>IL\Stubs\CalliMarshallingMethodThunk.Sorting.cs</Link> + </Compile> <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DelegateMarshallingMethodThunk.cs"> <Link>IL\Stubs\DelegateMarshallingMethodThunk.cs</Link> </Compile> <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DelegateMarshallingMethodThunk.Mangling.cs"> <Link>IL\Stubs\DelegateMarshallingMethodThunk.Mangling.cs</Link> </Compile> + <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DelegateMarshallingMethodThunk.Sorting.cs"> + <Link>IL\Stubs\DelegateMarshallingMethodThunk.Sorting.cs</Link> + </Compile> <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\ForwardDelegateCreationThunk.cs"> <Link>IL\Stubs\ForwardDelegateCreationThunk.cs</Link> </Compile> @@ -562,6 +571,9 @@ <Compile Include="..\..\Common\src\TypeSystem\Mangling\IPrefixMangledType.cs"> <Link>TypeSystem\Mangling\IPrefixMangledType.cs</Link> </Compile> + <Compile Include="..\..\Common\src\TypeSystem\Mangling\IPrefixMangledSignature.cs"> + <Link>TypeSystem\Mangling\IPrefixMangledSignature.cs</Link> + </Compile> <Compile Include="..\..\Common\src\System\Collections\Generic\ArrayBuilder.cs"> <Link>Utilities\ArrayBuilder.cs</Link> </Compile> diff --git a/src/System.Private.Jit/src/Internal/Runtime/JitSupport/JitCompilation.cs b/src/System.Private.Jit/src/Internal/Runtime/JitSupport/JitCompilation.cs index e628978b9..2c5f06f72 100644 --- a/src/System.Private.Jit/src/Internal/Runtime/JitSupport/JitCompilation.cs +++ b/src/System.Private.Jit/src/Internal/Runtime/JitSupport/JitCompilation.cs @@ -21,7 +21,8 @@ namespace ILCompiler { _typeSystemContext = context; _typeGetTypeMethodThunks = new TypeGetTypeMethodThunkCache(context.GetWellKnownType(WellKnownType.Object)); - _methodILCache = new ILProvider(new PInvokeILProvider(new PInvokeILEmitterConfiguration(forceLazyResolution: true), null)); + _pInvokeILProvider = new PInvokeILProvider(new PInvokeILEmitterConfiguration(forceLazyResolution: true), null); + _methodILCache = new ILProvider(_pInvokeILProvider); _nodeFactory = new NodeFactory(context); _devirtualizationManager = new DevirtualizationManager(); } @@ -31,9 +32,11 @@ namespace ILCompiler protected readonly Logger _logger = Logger.Null; private readonly TypeGetTypeMethodThunkCache _typeGetTypeMethodThunks; private ILProvider _methodILCache; + private PInvokeILProvider _pInvokeILProvider; private readonly DevirtualizationManager _devirtualizationManager; internal Logger Logger => _logger; + internal PInvokeILProvider PInvokeILProvider => _pInvokeILProvider; public TypeSystemContext TypeSystemContext { get { return _typeSystemContext; } } public NodeFactory NodeFactory { get { return _nodeFactory; } } @@ -51,7 +54,7 @@ namespace ILCompiler { // Flush the cache when it grows too big if (_methodILCache.Count > 1000) - _methodILCache = new ILProvider(new PInvokeILProvider(new PInvokeILEmitterConfiguration(forceLazyResolution: true), null)); + _methodILCache = new ILProvider(_pInvokeILProvider); return _methodILCache.GetMethodIL(method); } @@ -142,4 +145,4 @@ namespace ILCompiler return DelegateCreationInfo.Create(delegateType, target, NodeFactory, followVirtualDispatch); } } -}
\ No newline at end of file +} diff --git a/src/System.Private.Jit/src/System.Private.Jit.csproj b/src/System.Private.Jit/src/System.Private.Jit.csproj index 662339fa5..39cb058cc 100644 --- a/src/System.Private.Jit/src/System.Private.Jit.csproj +++ b/src/System.Private.Jit/src/System.Private.Jit.csproj @@ -69,6 +69,7 @@ <Compile Include="$(TypeSystemBasePath)\IL\Stubs\ArrayMethodILEmitter.cs" /> <Compile Include="$(TypeSystemBasePath)\IL\Stubs\CalliIntrinsic.cs" /> <Compile Include="$(TypeSystemBasePath)\IL\Stubs\ComparerIntrinsics.cs" /> + <Compile Include="$(TypeSystemBasePath)\IL\Stubs\CalliMarshallingMethodThunk.cs" /> <Compile Include="$(TypeSystemBasePath)\IL\Stubs\DelegateMarshallingMethodThunk.cs" /> <Compile Include="$(TypeSystemBasePath)\IL\Stubs\ForwardDelegateCreationThunk.cs" /> <Compile Include="$(TypeSystemBasePath)\IL\Stubs\EETypePtrOfIntrinsic.cs" /> |