Skip to content

Commit

Permalink
Wip
Browse files Browse the repository at this point in the history
  • Loading branch information
MichalStrehovsky committed Oct 31, 2019
1 parent 24cdf66 commit ffc8fff
Show file tree
Hide file tree
Showing 11 changed files with 222 additions and 27 deletions.
5 changes: 2 additions & 3 deletions src/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6460,9 +6460,8 @@ void Compiler::impCheckForPInvokeCall(
return;
}

// Legal PInvoke CALL in PInvoke IL stubs must be inlined to avoid infinite recursive
// inlining in CoreRT. Skip the ambient conditions checks and profitability checks.
if (!IsTargetAbi(CORINFO_CORERT_ABI) || (info.compFlags & CORINFO_FLG_PINVOKE) == 0)
// Skip the ambient conditions checks and profitability checks if forced inlining was requested.
if ((mflags & CORINFO_FLG_FORCEINLINE) == 0)
{
if (!impCanPInvokeInline())
{
Expand Down
17 changes: 5 additions & 12 deletions src/tools/crossgen2/Common/JitInterface/CorInfoImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,11 @@ private uint getMethodAttribsInternal(MethodDesc method)
if (method.IsPInvoke)
{
result |= CorInfoFlag.CORINFO_FLG_PINVOKE;

if (method.IsRawPInvoke())
{
result |= CorInfoFlag.CORINFO_FLG_FORCEINLINE;
}
}

#if READYTORUN
Expand Down Expand Up @@ -759,14 +764,6 @@ private CorInfoInline canInline(CORINFO_METHOD_STRUCT_* callerHnd, CORINFO_METHO
MethodDesc callerMethod = HandleToObject(callerHnd);
MethodDesc calleeMethod = HandleToObject(calleeHnd);

#if READYTORUN
// IL stubs don't inline well
if (calleeMethod.IsPInvoke)
{
return CorInfoInline.INLINE_NEVER;
}
#endif

if (_compilation.CanInline(callerMethod, calleeMethod))
{
// No restrictions on inlining
Expand Down Expand Up @@ -3055,10 +3052,6 @@ private uint getJitFlags(ref CORJIT_FLAGS flags, uint sizeInBytes)
if (this.MethodBeingCompiled.IsPInvoke)
{
flags.Set(CorJitFlag.CORJIT_FLAG_IL_STUB);

#if READYTORUN
flags.Set(CorJitFlag.CORJIT_FLAG_PUBLISH_SECRET_PARAM);
#endif
}

if (this.MethodBeingCompiled.IsNoOptimization)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// 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
{
partial class PInvokeTargetNativeMethod
{
public override string DiagnosticName
{
get
{
return _declMethod.DiagnosticName;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// 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
{
partial class PInvokeTargetNativeMethod : IPrefixMangledMethod
{
MethodDesc IPrefixMangledMethod.BaseMethod
{
get
{
return _declMethod;
}
}

string IPrefixMangledMethod.Prefix
{
get
{
return "rawpinvoke";
}
}
}
}
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 types
partial class PInvokeTargetNativeMethod
{
protected internal override int ClassCode => -1626939381;

protected internal override int CompareToImpl(MethodDesc other, TypeSystemComparer comparer)
{
var otherMethod = (PInvokeTargetNativeMethod)other;
return comparer.Compare(_declMethod, otherMethod._declMethod);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// 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
{
/// <summary>
/// Synthetic method that represents the actual PInvoke target method.
/// All parameters are simple types. There will be no code
/// generated for this method. Instead, a static reference to a symbol will be emitted.
/// </summary>
public sealed partial class PInvokeTargetNativeMethod : MethodDesc
{
private readonly MethodDesc _declMethod;
private readonly MethodSignature _signature;

public MethodDesc Target
{
get
{
return _declMethod;
}
}

public PInvokeTargetNativeMethod(MethodDesc declMethod, MethodSignature signature)
{
_declMethod = declMethod;
_signature = signature;
}

public override TypeSystemContext Context
{
get
{
return _declMethod.Context;
}
}

public override TypeDesc OwningType
{
get
{
return _declMethod.OwningType;
}
}

public override MethodSignature Signature
{
get
{
return _signature;
}
}

public override string Name
{
get
{
return _declMethod.Name;
}
}

public override bool HasCustomAttribute(string attributeNamespace, string attributeName)
{
return false;
}

public override bool IsPInvoke
{
get
{
return true;
}
}

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();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// 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 ILCompiler
{
static class MethodExtensions
{
/// <summary>
/// Returns true if <paramref name="method"/> is an actual native entrypoint.
/// There's a distinction between when a method reports it's a PInvoke in the metadata
/// versus how it's treated in the compiler. For many PInvoke methods the compiler will generate
/// an IL body. The methods with an IL method body shouldn't be treated as PInvoke within the compiler.
/// </summary>
public static bool IsRawPInvoke(this MethodDesc method)
{
return method.IsPInvoke && (method is Internal.IL.Stubs.PInvokeTargetNativeMethod);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,18 +93,13 @@ private void EmitPInvokeCall(PInvokeILCodeStreams ilCodeStreams)
nativeParameterTypes[i - 1] = _marshallers[i].NativeParameterType;
}

callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken(
stubHelpersType.GetKnownMethod("GetStubContext", null)));
callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken(
stubHelpersType.GetKnownMethod("GetNDirectTarget", null)));

MethodSignatureFlags unmanagedCallConv = _importMetadata.Flags.UnmanagedCallingConvention;

MethodSignature nativeSig = new MethodSignature(
_targetMethod.Signature.Flags | unmanagedCallConv, 0, nativeReturnType,
_targetMethod.Signature.Flags, 0, nativeReturnType,
nativeParameterTypes);

callsiteSetupCodeStream.Emit(ILOpcode.calli, emitter.NewToken(nativeSig));
var rawTargetMethod = new PInvokeTargetNativeMethod(_targetMethod, nativeSig);

callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken(rawTargetMethod));

// if the SetLastError flag is set in DllImport, call the PInvokeMarshal.
// SaveLastWin32Error so that last error can be used later by calling
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@
<Compile Include="Compiler\DependencyAnalysis\ReadyToRunSymbolNodeFactory.cs" />
<Compile Include="Compiler\DependencyAnalysis\TypeAndMethod.cs" />
<Compile Include="Compiler\IRootingServiceProvider.cs" />
<Compile Include="Compiler\MethodExtensions.cs" />
<Compile Include="IBC\IBCDataModel.cs" />
<Compile Include="IBC\IBCDataReader.cs" />
<Compile Include="IBC\ReaderExtensions.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,9 @@ private ModuleToken HandleToModuleToken(ref CORINFO_RESOLVED_TOKEN pResolvedToke

if (resultDef is MethodDesc)
{
if (resultDef is IL.Stubs.PInvokeTargetNativeMethod rawPinvoke)
resultDef = rawPinvoke.Target;

Debug.Assert(resultDef is EcmaMethod);
Debug.Assert(_compilation.NodeFactory.CompilationModuleGroup.VersionsWithType(((EcmaMethod)resultDef).OwningType));
token = (mdToken)MetadataTokens.GetToken(((EcmaMethod)resultDef).Handle);
Expand Down Expand Up @@ -1375,6 +1378,10 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO
{
nonUnboxingMethod = methodToCall.GetUnboxedMethod();
}
if (nonUnboxingMethod is IL.Stubs.PInvokeTargetNativeMethod rawPinvoke)
{
nonUnboxingMethod = rawPinvoke.Target;
}

// READYTORUN: FUTURE: Direct calls if possible
pResult->codePointerOrStubLookup.constLookup = CreateConstLookupToSymbol(
Expand Down Expand Up @@ -1910,7 +1917,10 @@ private HRESULT getMethodBlockCounts(CORINFO_METHOD_STRUCT_* ftnHnd, ref uint pC

private void getAddressOfPInvokeTarget(CORINFO_METHOD_STRUCT_* method, ref CORINFO_CONST_LOOKUP pLookup)
{
EcmaMethod ecmaMethod = (EcmaMethod)HandleToObject(method);
MethodDesc methodDesc = HandleToObject(method);
if (methodDesc is IL.Stubs.PInvokeTargetNativeMethod rawPInvoke)
methodDesc = rawPInvoke.Target;
EcmaMethod ecmaMethod = (EcmaMethod)methodDesc;
ModuleToken moduleToken = new ModuleToken(ecmaMethod.Module, ecmaMethod.Handle);
MethodWithToken methodWithToken = new MethodWithToken(ecmaMethod, moduleToken, constrainedType: null);

Expand All @@ -1928,8 +1938,13 @@ private bool pInvokeMarshalingRequired(CORINFO_METHOD_STRUCT_* handle, CORINFO_S

if (handle != null)
{
EcmaMethod method = (EcmaMethod)HandleToObject(handle);
return MethodRequiresMarshaling(method);
var method = HandleToObject(handle);
if (method.IsRawPInvoke())
{
return false;
}

return ((IL.Stubs.PInvokeILStubMethodIL)_compilation.GetMethodIL(method))?.IsStubRequired ?? false;
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,18 @@
<Compile Include="..\Common\TypeSystem\IL\Stubs\ILEmitter.cs">
<Link>IL\Stubs\ILEmitter.cs</Link>
</Compile>
<Compile Include="..\Common\TypeSystem\IL\Stubs\PInvokeTargetNativeMethod.cs">
<Link>IL\Stubs\PInvokeTargetNativeMethod.cs</Link>
</Compile>
<Compile Include="..\Common\TypeSystem\IL\Stubs\PInvokeTargetNativeMethod.Diagnostic.cs">
<Link>IL\Stubs\PInvokeTargetNativeMethod.Diagnostic.cs</Link>
</Compile>
<Compile Include="..\Common\TypeSystem\IL\Stubs\PInvokeTargetNativeMethod.Mangling.cs">
<Link>IL\Stubs\PInvokeTargetNativeMethod.Mangling.cs</Link>
</Compile>
<Compile Include="..\Common\TypeSystem\IL\Stubs\PInvokeTargetNativeMethod.Sorting.cs">
<Link>IL\Stubs\PInvokeTargetNativeMethod.Sorting.cs</Link>
</Compile>
<Compile Include="..\Common\TypeSystem\Serialization\FieldDesc.Serialization.cs">
<Link>TypeSystem\CodeGen\FieldDesc.Serialization.cs</Link>
</Compile>
Expand Down

0 comments on commit ffc8fff

Please sign in to comment.