-
Notifications
You must be signed in to change notification settings - Fork 199
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement handling PreserveSig = false for interfaces #1206
Changes from 4 commits
ba68a4b
f614212
15a5c68
48de7aa
0b5bb1c
dbdb239
5903921
df9bdb1
5e098f6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -97,7 +97,9 @@ private static Marshaller[] InitializeMarshallers(MethodDesc targetMethod, Inter | |
TypeDesc parameterType = (i == 0) | ||
? methodSig.ReturnType //first item is the return type | ||
: methodSig[i - 1]; | ||
marshallers[i] = Marshaller.CreateMarshaller(parameterType, | ||
bool isHRSwapping = !flags.PreserveSig && !parameterType.IsVoid | ||
&& targetMethod is not DelegateMarshallingMethodThunk; | ||
marshallers[i] = Marshaller.CreateMarshaller((i == 0 && isHRSwapping) ? methodSig.Context.GetByRefType(parameterType): parameterType, | ||
parameterIndex, | ||
methodSig.GetEmbeddedSignatureData(), | ||
MarshallerType.Argument, | ||
|
@@ -108,8 +110,8 @@ private static Marshaller[] InitializeMarshallers(MethodDesc targetMethod, Inter | |
indexOffset + parameterMetadata.Index, | ||
flags, | ||
parameterMetadata.In, | ||
parameterMetadata.Out, | ||
parameterMetadata.Return | ||
(i == 0 && isHRSwapping) ? true : parameterMetadata.Out, | ||
(i == 0 && isHRSwapping) ? false : parameterMetadata.Return | ||
); | ||
} | ||
|
||
|
@@ -231,16 +233,15 @@ private void EmitDelegateCall(DelegateMarshallingMethodThunk delegateMethod, PIn | |
|
||
private void EmitPInvokeCall(PInvokeILCodeStreams ilCodeStreams) | ||
{ | ||
if (!_flags.PreserveSig && _targetMethod.Signature.ReturnType != _targetMethod.Context.GetWellKnownType(WellKnownType.Void)) | ||
throw new NotSupportedException(); | ||
|
||
ILEmitter emitter = ilCodeStreams.Emitter; | ||
ILCodeStream fnptrLoadStream = ilCodeStreams.FunctionPointerLoadStream; | ||
ILCodeStream callsiteSetupCodeStream = ilCodeStreams.CallsiteSetupCodeStream; | ||
TypeSystemContext context = _targetMethod.Context; | ||
|
||
bool isHRSwapping = !_flags.PreserveSig && _targetMethod.Signature.ReturnType != _targetMethod.Context.GetWellKnownType(WellKnownType.Void) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
&& _targetMethod is not DelegateMarshallingMethodThunk; | ||
TypeDesc nativeReturnType = _flags.PreserveSig ? _marshallers[0].NativeParameterType : context.GetWellKnownType(WellKnownType.Int32); | ||
TypeDesc[] nativeParameterTypes = new TypeDesc[_marshallers.Length - 1]; | ||
TypeDesc[] nativeParameterTypes = new TypeDesc[isHRSwapping ? _marshallers.Length : _marshallers.Length - 1]; | ||
|
||
// if the SetLastError flag is set in DllImport, clear the error code before doing P/Invoke | ||
if (_flags.SetLastError) | ||
|
@@ -254,6 +255,11 @@ private void EmitPInvokeCall(PInvokeILCodeStreams ilCodeStreams) | |
nativeParameterTypes[i - 1] = _marshallers[i].NativeParameterType; | ||
} | ||
|
||
if (isHRSwapping) | ||
{ | ||
nativeParameterTypes[_marshallers.Length - 1] = _marshallers[0].NativeParameterType; | ||
} | ||
|
||
if (!_pInvokeILEmitterConfiguration.GenerateDirectCall(_targetMethod, out _)) | ||
{ | ||
MetadataType lazyHelperType = context.GetHelperType("InteropHelpers"); | ||
|
@@ -357,11 +363,18 @@ private MethodIL EmitIL() | |
cleanupCodestream.BeginHandler(tryFinally); | ||
|
||
// Marshal the arguments | ||
for (int i = 0; i < _marshallers.Length; i++) | ||
bool isHRSwapping = !_flags.PreserveSig && _targetMethod.Signature.ReturnType != _targetMethod.Context.GetWellKnownType(WellKnownType.Void) | ||
&& _targetMethod is not DelegateMarshallingMethodThunk; | ||
for (int i = isHRSwapping ? 1 : 0; i < _marshallers.Length; i++) | ||
{ | ||
_marshallers[i].EmitMarshallingIL(pInvokeILCodeStreams); | ||
} | ||
|
||
if (isHRSwapping) | ||
{ | ||
_marshallers[0].EmitMarshallingIL(pInvokeILCodeStreams); | ||
} | ||
|
||
// make the call | ||
switch (_targetMethod) | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -512,7 +512,7 @@ protected virtual void EmitMarshalReturnValueManagedToNative() | |
|
||
public virtual void LoadReturnValue(ILCodeStream codeStream) | ||
{ | ||
Debug.Assert(Return); | ||
Debug.Assert(Return || Index == 0); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be nice to replace all |
||
|
||
switch (MarshalDirection) | ||
{ | ||
|
@@ -653,9 +653,18 @@ protected void PropagateFromByRefArg(ILCodeStream stream, Home home) | |
/// </summary> | ||
protected void PropagateToByRefArg(ILCodeStream stream, Home home) | ||
{ | ||
stream.EmitLdArg(Index - 1); | ||
home.LoadValue(stream); | ||
stream.EmitStInd(ManagedType); | ||
// If by-ref arg has index == 0 then that argument is used for HR swapping and we just return that value. | ||
if (Index == 0) | ||
{ | ||
// Returning result would be handled by LoadReturnValue | ||
return; | ||
} | ||
else | ||
{ | ||
stream.EmitLdArg(Index - 1); | ||
home.LoadValue(stream); | ||
stream.EmitStInd(ManagedType); | ||
} | ||
kant2002 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
protected virtual void EmitMarshalArgumentManagedToNative() | ||
|
@@ -903,7 +912,7 @@ class BlittableValueMarshaller : Marshaller | |
{ | ||
protected override void EmitMarshalArgumentManagedToNative() | ||
{ | ||
if (IsNativeByRef && MarshalDirection == MarshalDirection.Forward) | ||
if (IsNativeByRef && MarshalDirection == MarshalDirection.Forward && Index > 0) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would move the special case first and then leave the rest of the method intact.
|
||
{ | ||
ILCodeStream marshallingCodeStream = _ilCodeStreams.MarshallingCodeStream; | ||
ILEmitter emitter = _ilCodeStreams.Emitter; | ||
|
@@ -917,10 +926,14 @@ protected override void EmitMarshalArgumentManagedToNative() | |
marshallingCodeStream.EmitStLoc(native); | ||
_ilCodeStreams.CallsiteSetupCodeStream.EmitLdLoc(native); | ||
} | ||
else | ||
else if (Index > 0) | ||
{ | ||
_ilCodeStreams.CallsiteSetupCodeStream.EmitLdArg(Index - 1); | ||
} | ||
else | ||
{ | ||
base.EmitMarshalArgumentManagedToNative(); | ||
} | ||
} | ||
|
||
protected override void EmitMarshalArgumentNativeToManaged() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(i == 0 && isHRSwapping)
condition is repeated multiple times here. Also, I do not think you should need the check forDelegateMarshallingMethodThunk
here. We should make sure to setPreserveSig=true
for marshalled delegates earlier (UnmanagedFunctionPointerAttribute
won't allow you to specifyPreserveSig=false
so we do not need to worry about handling it).I think it would be a bit more efficient and readable like this: