Fixes #5587
This commit is contained in:
Jan Kotas 2018-05-02 22:06:24 -07:00 коммит произвёл Michal Strehovský
Родитель 1b248ccfd7
Коммит ad22792139
4 изменённых файлов: 109 добавлений и 45 удалений

Просмотреть файл

@ -62,9 +62,9 @@ namespace Internal.IL.Stubs
// 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];
parameterTypes[i] = _targetSignature[i];
parameterTypes[parameterTypes.Length - 1] = Context.GetWellKnownType(WellKnownType.IntPtr);
_signature = new MethodSignature(MethodSignatureFlags.Static, 0, _targetSignature.ReturnType, parameterTypes);
}
@ -80,10 +80,17 @@ namespace Internal.IL.Stubs
}
}
public override bool IsPInvoke
{
get
{
return true;
}
}
public override MethodIL EmitIL()
{
// TODO
throw null;
return PInvokeILEmitter.EmitIL(this, default(PInvokeILEmitterConfiguration), _interopStateManager);
}
}
}

Просмотреть файл

@ -40,12 +40,10 @@ namespace Internal.IL.Stubs
// targetMethod could be either a PInvoke or a DelegateMarshallingMethodThunk
// ForwardNativeFunctionWrapper method thunks are marked as PInvokes, so it is
// important to check them first here so that we get the right flags.
//
DelegateMarshallingMethodThunk delegateThunk = _targetMethod as DelegateMarshallingMethodThunk;
if (delegateThunk != null)
//
if (_targetMethod is DelegateMarshallingMethodThunk delegateMethod)
{
_flags = ((EcmaType)delegateThunk.DelegateType).GetDelegatePInvokeFlags();
_flags = ((EcmaType)delegateMethod.DelegateType).GetDelegatePInvokeFlags();
}
else
{
@ -57,9 +55,21 @@ namespace Internal.IL.Stubs
private static Marshaller[] InitializeMarshallers(MethodDesc targetMethod, InteropStateManager interopStateManager, PInvokeFlags flags)
{
bool isDelegate = targetMethod is DelegateMarshallingMethodThunk;
MethodSignature methodSig = isDelegate ? ((DelegateMarshallingMethodThunk)targetMethod).DelegateSignature : targetMethod.Signature;
MarshalDirection direction = isDelegate ? ((DelegateMarshallingMethodThunk)targetMethod).Direction: MarshalDirection.Forward;
MarshalDirection direction = MarshalDirection.Forward;
MethodSignature methodSig;
switch (targetMethod)
{
case DelegateMarshallingMethodThunk delegateMethod:
methodSig = delegateMethod.DelegateSignature;
direction = delegateMethod.Direction;
break;
case CalliMarshallingMethodThunk calliMethod:
methodSig = calliMethod.TargetSignature;
break;
default:
methodSig = targetMethod.Signature;
break;
}
int indexOffset = 0;
if (!methodSig.IsStatic && direction == MarshalDirection.Forward)
{
@ -282,6 +292,27 @@ namespace Internal.IL.Stubs
}
}
private void EmitCalli(PInvokeILCodeStreams ilCodeStreams, CalliMarshallingMethodThunk calliThunk)
{
ILEmitter emitter = ilCodeStreams.Emitter;
ILCodeStream callsiteSetupCodeStream = ilCodeStreams.CallsiteSetupCodeStream;
TypeDesc nativeReturnType = _marshallers[0].NativeParameterType;
TypeDesc[] nativeParameterTypes = new TypeDesc[_marshallers.Length - 1];
for (int i = 1; i < _marshallers.Length; i++)
{
nativeParameterTypes[i - 1] = _marshallers[i].NativeParameterType;
}
MethodSignature nativeSig = new MethodSignature(
calliThunk.TargetSignature.Flags, 0, nativeReturnType,
nativeParameterTypes);
callsiteSetupCodeStream.EmitLdArg(calliThunk.TargetSignature.Length);
callsiteSetupCodeStream.Emit(ILOpcode.calli, emitter.NewToken(nativeSig));
}
private MethodIL EmitIL()
{
PInvokeILCodeStreams pInvokeILCodeStreams = new PInvokeILCodeStreams();
@ -295,20 +326,23 @@ namespace Internal.IL.Stubs
}
// make the call
DelegateMarshallingMethodThunk delegateMethod = _targetMethod as DelegateMarshallingMethodThunk;
if (delegateMethod != null)
switch (_targetMethod)
{
EmitDelegateCall(delegateMethod, pInvokeILCodeStreams);
}
else
{
EmitPInvokeCall(pInvokeILCodeStreams);
case DelegateMarshallingMethodThunk delegateMethod:
EmitDelegateCall(delegateMethod, pInvokeILCodeStreams);
break;
case CalliMarshallingMethodThunk calliMethod:
EmitCalli(pInvokeILCodeStreams, calliMethod);
break;
default:
EmitPInvokeCall(pInvokeILCodeStreams);
break;
}
_marshallers[0].LoadReturnValue(unmarshallingCodestream);
unmarshallingCodestream.Emit(ILOpcode.ret);
return new PInvokeILStubMethodIL((ILStubMethodIL)emitter.Link(_targetMethod), IsStubRequired());
return new PInvokeILStubMethodIL((ILStubMethodIL)emitter.Link(_targetMethod), IsStubRequired());
}
public static MethodIL EmitIL(MethodDesc method,
@ -342,11 +376,14 @@ namespace Internal.IL.Stubs
return true;
}
if (MarshalHelpers.UseLazyResolution(_targetMethod, _importMetadata.Module,
_pInvokeILEmitterConfiguration))
if (_pInvokeILEmitterConfiguration != null)
{
return true;
if (MarshalHelpers.UseLazyResolution(_targetMethod, _importMetadata.Module, _pInvokeILEmitterConfiguration))
{
return true;
}
}
if (_flags.SetLastError)
{
return true;

Просмотреть файл

@ -760,13 +760,8 @@ namespace Internal.JitInterface
result |= CorInfoFlag.CORINFO_FLG_SHAREDINST;
if (method.IsPInvoke)
{
result |= CorInfoFlag.CORINFO_FLG_PINVOKE;
// See comment in pInvokeMarshalingRequired
result |= CorInfoFlag.CORINFO_FLG_DONT_INLINE;
}
// TODO: Cache inlining hits
// Check for an inlining directive.
@ -1037,23 +1032,34 @@ namespace Internal.JitInterface
return (CorInfoUnmanagedCallConv)unmanagedCallConv;
}
private bool IsPInvokeStubRequired(MethodDesc method)
{
return ((Internal.IL.Stubs.PInvokeILStubMethodIL)_compilation.GetMethodIL(method)).IsStubRequired;
}
private bool pInvokeMarshalingRequired(CORINFO_METHOD_STRUCT_* handle, CORINFO_SIG_INFO* callSiteSig)
{
// TODO: Support for PInvoke calli with marshalling. For now, assume there is no marshalling required.
// calli is covered by convertPInvokeCalliToCall
if (handle == null)
{
#if DEBUG
MethodSignature methodSignature = (MethodSignature)HandleToObject((IntPtr)callSiteSig->pSig);
MethodDesc stub = _compilation.PInvokeILProvider.GetCalliStub(methodSignature);
Debug.Assert(!IsPInvokeStubRequired(stub));
#endif
return false;
}
MethodDesc method = HandleToObject(handle);
if (method.IsRawPInvoke())
return false;
// TODO: Ideally, we would just give back the PInvoke stub IL to the JIT and let it inline it, without
// checking whether it is required upfront. Unfortunatelly, RyuJIT is not able to generate PInvoke
// transitions in inlined methods today (impCheckForPInvokeCall is not called for inlinees and number of other places
// depend on it). To get a decent code with this limitation, we mirror CoreCLR behavior: Check
// whether PInvoke stub is required here, and disable inlining of PInvoke methods in getMethodAttribsInternal.
return ((Internal.IL.Stubs.PInvokeILStubMethodIL)_compilation.GetMethodIL(method)).IsStubRequired;
// We could have given back the PInvoke stub IL to the JIT and let it inline it, without
// checking whether there is any stub required. Save the JIT from doing the inlining by checking upfront.
return IsPInvokeStubRequired(method);
}
private bool satisfiesMethodConstraints(CORINFO_CLASS_STRUCT_* parent, CORINFO_METHOD_STRUCT_* method)
@ -3450,8 +3456,30 @@ namespace Internal.JitInterface
private bool convertPInvokeCalliToCall(ref CORINFO_RESOLVED_TOKEN pResolvedToken, bool mustConvert)
{
Debug.Assert(!mustConvert);
return false;
var methodIL = (MethodIL)HandleToObject((IntPtr)pResolvedToken.tokenScope);
if (methodIL.OwningMethod.IsPInvoke)
{
return false;
}
MethodSignature signature = (MethodSignature)methodIL.GetObject((int)pResolvedToken.token);
CorInfoCallConv callConv = (CorInfoCallConv)(signature.Flags & MethodSignatureFlags.UnmanagedCallingConventionMask);
if (callConv != CorInfoCallConv.CORINFO_CALLCONV_C &&
callConv != CorInfoCallConv.CORINFO_CALLCONV_STDCALL &&
callConv != CorInfoCallConv.CORINFO_CALLCONV_THISCALL &&
callConv != CorInfoCallConv.CORINFO_CALLCONV_FASTCALL)
{
return false;
}
MethodDesc stub = _compilation.PInvokeILProvider.GetCalliStub(signature);
if (!mustConvert && !IsPInvokeStubRequired(stub))
return false;
pResolvedToken.hMethod = ObjectToHandle(stub);
pResolvedToken.hClass = ObjectToHandle(stub.OwningType);
return true;
}
private void* getMemoryManager()

Просмотреть файл

@ -2,12 +2,6 @@
xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >
<ItemGroup Condition="'$(XunitTestBinBase)' != ''">
<!-- Pinvoke calli -->
<!-- https://github.com/dotnet/corert/issues/5587 -->
<ExcludeList Include="$(XunitTestBinBase)\JIT\Methodical\Invoke\SEH\_il_dbgcatchfinally_ind\_il_dbgcatchfinally_ind.*" />
<ExcludeList Include="$(XunitTestBinBase)\JIT\Methodical\Invoke\SEH\_il_relcatchfinally_ind\_il_relcatchfinally_ind.*" />
<ExcludeList Include="$(XunitTestBinBase)\JIT\Regression\CLR-x86-JIT\V2.0-RTM\b487364\b487364\b487364.*" />
<!-- Infinite generic expansion -->
<!-- https://github.com/dotnet/corert/issues/363 -->
<ExcludeList Include="$(XunitTestBinBase)\JIT\Methodical\inlining\bug505642\test\test.*" />
@ -266,8 +260,6 @@
<ExcludeList Include="$(XunitTestBinBase)\Interop\RefCharArray\RefCharArrayTest\RefCharArrayTest.*" />
<ExcludeList Include="$(XunitTestBinBase)\Interop\RefInt\RefIntTest\RefIntTest.*" />
<ExcludeList Include="$(XunitTestBinBase)\Interop\StringMarshalling\LPTSTR\LPTSTRTest\LPTSTRTest.*" />
<ExcludeList Include="$(XunitTestBinBase)\JIT\Directed\coverage\oldtests\Desktop\callipinvoke_il_d\callipinvoke_il_d.*" />
<ExcludeList Include="$(XunitTestBinBase)\JIT\Directed\coverage\oldtests\Desktop\callipinvoke_il_r\callipinvoke_il_r.*" />
<ExcludeList Include="$(XunitTestBinBase)\JIT\Directed\IL\PInvokeTail\TailWinApi\TailWinApi.*" />
<ExcludeList Include="$(XunitTestBinBase)\Interop\ICastable\Castable\Castable.*" />
<ExcludeList Include="$(XunitTestBinBase)\JIT\Generics\pinvoke\instance01\instance01.*" />