Skip to content
This repository has been archived by the owner on Nov 1, 2020. It is now read-only.

Commit

Permalink
Plumbing to generate calli PInvoke stubs (#6002)
Browse files Browse the repository at this point in the history
Contributes to #5587
  • Loading branch information
jkotas authored Jun 24, 2018
1 parent 6c2368b commit c932653
Show file tree
Hide file tree
Showing 13 changed files with 281 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -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";
}
}
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
89 changes: 89 additions & 0 deletions src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.cs
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@

namespace Internal.IL.Stubs
{
/// <summary>
/// contains functionality related to name mangling
/// </summary>
public partial class DelegateMarshallingMethodThunk : IPrefixMangledType
{
TypeDesc IPrefixMangledType.BaseType
Expand Down
8 changes: 8 additions & 0 deletions src/Common/src/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,5 +109,13 @@ public override bool HasCustomAttribute(string attributeNamespace, string attrib
{
return false;
}

public override string Name
{
get
{
return _targetMethod.Name;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,15 @@ public override bool IsPInvoke
}
}

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();
Expand Down
44 changes: 44 additions & 0 deletions src/Common/src/TypeSystem/Interop/InteropStateManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public sealed class InteropStateManager
private readonly PInvokeDelegateWrapperHashtable _pInvokeDelegateWrapperHashtable;
private readonly InlineArrayHashTable _inlineArrayHashtable;
private readonly PInvokeLazyFixupFieldHashtable _pInvokeLazyFixupFieldHashtable;
private readonly PInvokeCalliHashtable _pInvokeCalliHashtable;

public InteropStateManager(ModuleDesc generatedAssembly)
{
Expand All @@ -33,6 +34,7 @@ public InteropStateManager(ModuleDesc generatedAssembly)
_pInvokeDelegateWrapperHashtable = new PInvokeDelegateWrapperHashtable(this, _generatedAssembly);
_inlineArrayHashtable = new InlineArrayHashTable(this, _generatedAssembly);
_pInvokeLazyFixupFieldHashtable = new PInvokeLazyFixupFieldHashtable(_generatedAssembly.GetGlobalModuleType());
_pInvokeCalliHashtable = new PInvokeCalliHashtable(this, _generatedAssembly.GetGlobalModuleType());
}
//
// Delegate Marshalling Stubs
Expand Down Expand Up @@ -185,6 +187,11 @@ public FieldDesc GetPInvokeLazyFixupField(MethodDesc method)
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)
Expand Down Expand Up @@ -471,5 +478,42 @@ public PInvokeLazyFixupFieldHashtable(DefType owningType)
_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;
}
}
}
}
23 changes: 23 additions & 0 deletions src/Common/src/TypeSystem/Mangling/IPrefixMangledSignature.cs
Original file line number Diff line number Diff line change
@@ -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; }
}
}
33 changes: 33 additions & 0 deletions src/ILCompiler.Compiler/src/Compiler/CoreRTNameMangler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,35 @@ private Utf8String GetPrefixMangledTypeName(IPrefixMangledType prefixMangledType
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();
Expand Down Expand Up @@ -497,6 +526,10 @@ private Utf8String ComputeUnqualifiedMangledMethodName(MethodDesc method)
{
utf8MangledName = GetPrefixMangledTypeName((IPrefixMangledType)method);
}
else if (method is IPrefixMangledSignature)
{
utf8MangledName = GetPrefixMangledSignatureName((IPrefixMangledSignature)method);
}
else
{
// Assume that Name is unique for all other methods
Expand Down
5 changes: 5 additions & 0 deletions src/ILCompiler.Compiler/src/IL/Stubs/PInvokeILProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,10 @@ public MethodIL EmitIL(MethodDesc method)
{
return PInvokeILEmitter.EmitIL(method, _pInvokeILEmitterConfiguration, _interopStateManager);
}

public MethodDesc GetCalliStub(MethodSignature signature)
{
return _interopStateManager.GetPInvokeCalliStub(signature);
}
}
}
18 changes: 15 additions & 3 deletions src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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>
Expand Down Expand Up @@ -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>
Expand Down
Loading

0 comments on commit c932653

Please sign in to comment.