public MethodSignature ParseMethodSignature() { MethodSignatureFlags flags = 0; byte callingConvention = _reader.ReadByte(); if ((callingConvention & (byte)SignatureAttributes.Instance) == 0) { flags |= MethodSignatureFlags.Static; } int arity = ((callingConvention & (byte)SignatureAttributes.Generic) != 0) ? _reader.ReadCompressedInteger() : 0; int count = _reader.ReadCompressedInteger(); TypeDesc returnType = ParseType(); TypeDesc[] parameters; if (count > 0) { // Get all of the parameters. parameters = new TypeDesc[count]; for (int i = 0; i < count; i++) { parameters[i] = ParseType(); } } else { parameters = TypeDesc.EmptyTypes; } return(new MethodSignature(flags, arity, returnType, parameters)); }
public MethodSignature ParseMethodSignature() { MethodSignatureFlags flags = 0; SignatureHeader header = _reader.ReadSignatureHeader(); if (!header.IsInstance) { flags |= MethodSignatureFlags.Static; } int arity = header.IsGeneric ? _reader.ReadCompressedInteger() : 0; int count = _reader.ReadCompressedInteger(); TypeDesc returnType = ParseType(); TypeDesc[] parameters; if (count > 0) { // Get all of the parameters. parameters = new TypeDesc[count]; for (int i = 0; i < count; i++) { parameters[i] = ParseType(); } } else { parameters = TypeDesc.EmptyTypes; } return(new MethodSignature(flags, arity, returnType, parameters)); }
private MethodSignature ParseMethodSignatureImpl(bool skipEmbeddedSignatureData) { SignatureHeader header = _reader.ReadSignatureHeader(); MethodSignatureFlags flags = 0; SignatureCallingConvention signatureCallConv = header.CallingConvention; if (signatureCallConv != SignatureCallingConvention.Default) { // Verify that it is safe to convert CallingConvention to MethodSignatureFlags via a simple cast Debug.Assert((int)MethodSignatureFlags.UnmanagedCallingConventionCdecl == (int)SignatureCallingConvention.CDecl); Debug.Assert((int)MethodSignatureFlags.UnmanagedCallingConventionStdCall == (int)SignatureCallingConvention.StdCall); Debug.Assert((int)MethodSignatureFlags.UnmanagedCallingConventionThisCall == (int)SignatureCallingConvention.ThisCall); Debug.Assert((int)MethodSignatureFlags.CallingConventionVarargs == (int)SignatureCallingConvention.VarArgs); Debug.Assert((int)MethodSignatureFlags.UnmanagedCallingConvention == (int)SignatureCallingConvention.Unmanaged); flags = (MethodSignatureFlags)signatureCallConv; } if (!header.IsInstance) { flags |= MethodSignatureFlags.Static; } int arity = header.IsGeneric ? _reader.ReadCompressedInteger() : 0; int count = _reader.ReadCompressedInteger(); TypeDesc returnType = ParseType(); TypeDesc[] parameters; if (count > 0) { // Get all of the parameters. parameters = new TypeDesc[count]; for (int i = 0; i < count; i++) { parameters[i] = ParseType(); } } else { parameters = TypeDesc.EmptyTypes; } EmbeddedSignatureData[] embeddedSignatureDataArray = (_embeddedSignatureDataList == null || _embeddedSignatureDataList.Count == 0 || skipEmbeddedSignatureData) ? null : _embeddedSignatureDataList.ToArray(); if (_resolutionFailure == null) { return(new MethodSignature(flags, arity, returnType, parameters, embeddedSignatureDataArray)); } else { return(null); } }
public MethodSignatureBuilder(MethodSignature template) { _template = template; _flags = template._flags; _genericParameterCount = template._genericParameterCount; _returnType = template._returnType; _parameters = template._parameters; }
public MethodSignature(MethodSignatureFlags flags, int genericParameterCount, TypeDesc returnType, TypeDesc[] parameters) { _flags = flags; _genericParameterCount = genericParameterCount; _returnType = returnType; _parameters = parameters; Debug.Assert(parameters != null, "Parameters must not be null"); }
public MethodSignatureBuilder(MethodSignature template) { _template = template; _flags = template._flags; _genericParameterCount = template._genericParameterCount; _returnType = template._returnType; _parameters = template._parameters; _customModifiers = template._embeddedSignatureData; }
public MethodSignature ParseMethodSignature() { SignatureHeader header = _reader.ReadSignatureHeader(); MethodSignatureFlags flags = 0; SignatureCallingConvention signatureCallConv = header.CallingConvention; if (signatureCallConv != SignatureCallingConvention.Default) { // Verify that it is safe to convert CallingConvention to MethodSignatureFlags via a simple cast Debug.Assert((int)MethodSignatureFlags.UnmanagedCallingConventionCdecl == (int)SignatureCallingConvention.CDecl); Debug.Assert((int)MethodSignatureFlags.UnmanagedCallingConventionStdCall == (int)SignatureCallingConvention.StdCall); Debug.Assert((int)MethodSignatureFlags.UnmanagedCallingConventionThisCall == (int)SignatureCallingConvention.ThisCall); // Vararg methods are not supported in .NET Core if (signatureCallConv == SignatureCallingConvention.VarArgs) { throw new TypeSystemException.BadImageFormatException(); } flags = (MethodSignatureFlags)signatureCallConv; } if (!header.IsInstance) { flags |= MethodSignatureFlags.Static; } int arity = header.IsGeneric ? _reader.ReadCompressedInteger() : 0; int count = _reader.ReadCompressedInteger(); TypeDesc returnType = ParseType(); TypeDesc[] parameters; if (count > 0) { // Get all of the parameters. parameters = new TypeDesc[count]; for (int i = 0; i < count; i++) { parameters[i] = ParseType(); } } else { parameters = TypeDesc.EmptyTypes; } return(new MethodSignature(flags, arity, returnType, parameters)); }
/// <summary> /// Gets calling conventions for a standalone ('calli') method signature. /// </summary> public static UnmanagedCallingConventions GetStandaloneMethodSignatureCallingConventions(this MethodSignature signature) { // If calling convention is anything but 'unmanaged', or there's no modifiers, we can bitcast to our enum and we're done. MethodSignatureFlags unmanagedCallconv = signature.Flags & MethodSignatureFlags.UnmanagedCallingConventionMask; if (unmanagedCallconv != MethodSignatureFlags.UnmanagedCallingConvention) { Debug.Assert((int)MethodSignatureFlags.UnmanagedCallingConventionCdecl == (int)UnmanagedCallingConventions.Cdecl && (int)MethodSignatureFlags.UnmanagedCallingConventionStdCall == (int)UnmanagedCallingConventions.Stdcall && (int)MethodSignatureFlags.UnmanagedCallingConventionThisCall == (int)UnmanagedCallingConventions.Thiscall); Debug.Assert(unmanagedCallconv != 0); return((UnmanagedCallingConventions)unmanagedCallconv); } // If calling convention is 'unmanaged', there might be more metadata in the custom modifiers. UnmanagedCallingConventions result = 0; if (signature.HasEmbeddedSignatureData) { foreach (EmbeddedSignatureData data in signature.GetEmbeddedSignatureData()) { if (data.kind != EmbeddedSignatureDataKind.OptionalCustomModifier) { continue; } // We only care about the modifiers for the return type. These will be at the start of // the signature, so will be first in the array of embedded signature data. if (data.index != MethodSignature.IndexOfCustomModifiersOnReturnType) { break; } if (data.type is not MetadataType mdType) { continue; } result = AccumulateCallingConventions(result, mdType); } } // If we haven't found a calling convention in the modifiers, the calling convention is 'unmanaged'. if ((result & UnmanagedCallingConventions.CallingConventionMask) == 0) { result |= GetPlatformDefaultUnmanagedCallingConvention(signature.Context); } return(result); }
private void EmitPInvokeCall(PInvokeILCodeStreams ilCodeStreams) { ILEmitter emitter = ilCodeStreams.Emitter; ILCodeStream callsiteSetupCodeStream = ilCodeStreams.CallsiteSetupCodeStream; TypeSystemContext context = _targetMethod.Context; TypeDesc nativeReturnType = _marshallers[0].NativeParameterType; TypeDesc[] nativeParameterTypes = new TypeDesc[_marshallers.Length - 1]; MetadataType stubHelpersType = InteropTypes.GetStubHelpers(context); // if the SetLastError flag is set in DllImport, clear the error code before doing P/Invoke if (_importMetadata.Flags.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( stubHelpersType.GetKnownMethod("ClearLastError", null))); } for (int i = 1; i < _marshallers.Length; i++) { 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, nativeParameterTypes); callsiteSetupCodeStream.Emit(ILOpcode.calli, emitter.NewToken(nativeSig)); // if the SetLastError flag is set in DllImport, call the PInvokeMarshal. // SaveLastWin32Error so that last error can be used later by calling // PInvokeMarshal.GetLastWin32Error if (_importMetadata.Flags.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( stubHelpersType.GetKnownMethod("SetLastError", null))); } }
public static MethodIL EmitIL(MethodDesc target) { Debug.Assert(target.Name == "Call" || target.Name == "StdCall"); Debug.Assert(target.Signature.Length > 0 && target.Signature[0] == target.Context.GetWellKnownType(WellKnownType.IntPtr)); ILEmitter emitter = new ILEmitter(); var codeStream = emitter.NewCodeStream(); // Load all the arguments except the first one (IntPtr address) for (int i = 1; i < target.Signature.Length; i++) { codeStream.EmitLdArg(i); } // now load IntPtr address codeStream.EmitLdArg(0); // Create a signature for the calli by copying the signature of the containing method // while skipping the first argument MethodSignature template = target.Signature; TypeDesc returnType = template.ReturnType; TypeDesc[] parameters = new TypeDesc[template.Length - 1]; for (int i = 1; i < template.Length; i++) { parameters[i - 1] = template[i]; } MethodSignatureFlags flags = template.Flags; if (target.Name == "StdCall") { flags |= MethodSignatureFlags.UnmanagedCallingConventionStdCall; } var signature = new MethodSignature(flags, 0, returnType, parameters); codeStream.Emit(ILOpcode.calli, emitter.NewToken(signature)); codeStream.Emit(ILOpcode.ret); return(emitter.Link(target)); }
public static UnmanagedCallingConventions GetPInvokeMethodCallingConventions(this MethodDesc method) { Debug.Assert(method.IsPInvoke); UnmanagedCallingConventions result; if (method is Internal.IL.Stubs.PInvokeTargetNativeMethod pinvokeTarget) { method = pinvokeTarget.Target; } MethodSignatureFlags unmanagedCallConv = method.GetPInvokeMethodMetadata().Flags.UnmanagedCallingConvention; if (unmanagedCallConv != MethodSignatureFlags.None) { Debug.Assert((int)MethodSignatureFlags.UnmanagedCallingConventionCdecl == (int)UnmanagedCallingConventions.Cdecl && (int)MethodSignatureFlags.UnmanagedCallingConventionStdCall == (int)UnmanagedCallingConventions.Stdcall && (int)MethodSignatureFlags.UnmanagedCallingConventionThisCall == (int)UnmanagedCallingConventions.Thiscall); result = (UnmanagedCallingConventions)unmanagedCallConv; } else { CustomAttributeValue <TypeDesc>?unmanagedCallConvAttribute = ((EcmaMethod)method).GetDecodedCustomAttribute("System.Runtime.InteropServices", "UnmanagedCallConvAttribute"); if (unmanagedCallConvAttribute != null) { result = GetUnmanagedCallingConventionFromAttribute(unmanagedCallConvAttribute.Value, method.Context); } else { result = GetPlatformDefaultUnmanagedCallingConvention(method.Context); } } if (method.HasCustomAttribute("System.Runtime.InteropServices", "SuppressGCTransitionAttribute")) { result |= UnmanagedCallingConventions.IsSuppressGcTransition; } return(result); }
public MethodSignature ParseMethodSignature() { var methodSignature = _metadataReader.GetMethodSignature(_signatureHandle.ToMethodSignatureHandle(_metadataReader)); MethodSignatureFlags flags = 0; if ((methodSignature.CallingConvention & System.Reflection.CallingConventions.HasThis) == 0) { flags |= MethodSignatureFlags.Static; } int arity = methodSignature.GenericParameterCount; var parameterSignatureArray = methodSignature.Parameters; int count = parameterSignatureArray.Count; TypeDesc returnType = _metadataUnit.GetType(methodSignature.ReturnType); TypeDesc[] parameters; if (count > 0) { // Get all of the parameters. parameters = new TypeDesc[count]; int i = 0; foreach (Handle parameterHandle in parameterSignatureArray) { parameters[i] = _metadataUnit.GetType(parameterHandle); i++; } } else { parameters = TypeDesc.EmptyTypes; } return(new MethodSignature(flags, arity, returnType, parameters)); }
/// <summary> /// Gets a value indicating whether GC transition should be suppressed on the given p/invoke. /// </summary> public static bool IsSuppressGCTransition(this MethodDesc method) { Debug.Assert(method.IsPInvoke); // Check SuppressGCTransition attribute if (method.HasSuppressGCTransitionAttribute()) { return(true); } MethodSignatureFlags unmanagedCallConv = method.GetPInvokeMethodMetadata().Flags.UnmanagedCallingConvention; if (unmanagedCallConv != MethodSignatureFlags.None) { return(false); } if (!(method is Internal.TypeSystem.Ecma.EcmaMethod ecmaMethod)) { return(false); } // Check UnmanagedCallConv attribute System.Reflection.Metadata.CustomAttributeValue <TypeDesc>?unmanagedCallConvAttribute = ecmaMethod.GetDecodedCustomAttribute("System.Runtime.InteropServices", "UnmanagedCallConvAttribute"); if (unmanagedCallConvAttribute == null) { return(false); } foreach (DefType defType in Internal.JitInterface.CallConvHelper.EnumerateCallConvsFromAttribute(unmanagedCallConvAttribute.Value)) { if (defType.Name == "CallConvSuppressGCTransition") { return(true); } } return(false); }
public static MethodSignature NormalizeSignature(MethodSignature sig, bool valueTypeInstanceMethod) { MethodSignatureFlags flags = 0; if (sig.IsStatic) { flags |= MethodSignatureFlags.Static; } // TODO: Reflection invoke assumes unboxing stubs. It means that the "this" pointer is always a regular boxed object reference and // that the dynamic invoke thunks cannot be used to invoke instance methods on unboxed value types currently. This will need // to be addressed for the eventual allocation-free reflection invoke. // else if (valueTypeInstanceMethod) // { // flags |= MethodSignatureFlags_ValueTypeInstanceMethod; // } TypeDesc[] parameters = new TypeDesc[sig.Length]; for (int i = 0; i < sig.Length; i++) { parameters[i] = NormalizeType(sig[i]); } return(new MethodSignature(flags, 0, NormalizeType(sig.ReturnType), parameters));
private MethodIL EmitIL() { PInvokeILCodeStreams pInvokeILCodeStreams = new PInvokeILCodeStreams(); ILEmitter emitter = pInvokeILCodeStreams.Emitter; ILCodeStream fnptrLoadStream = pInvokeILCodeStreams.FunctionPointerLoadStream; ILCodeStream callsiteSetupCodeStream = pInvokeILCodeStreams.CallsiteSetupCodeStream; ILCodeStream unmarshallingCodestream = pInvokeILCodeStreams.UnmarshallingCodestream; TypeSystemContext context = _targetMethod.Context; // Marshal the arguments for (int i = 0; i < _marshallers.Length; i++) { _marshallers[i].EmitMarshallingIL(pInvokeILCodeStreams); } // if the SetLastError flag is set in DllImport, clear the error code before doing P/Invoke if (_importMetadata.Flags.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( InteropTypes.GetPInvokeMarshal(context).GetKnownMethod("ClearLastWin32Error", null))); } // make the call DelegateMarshallingMethodThunk delegateMethod = _targetMethod as DelegateMarshallingMethodThunk; if (delegateMethod != null) { EmitDelegateCall(delegateMethod, pInvokeILCodeStreams); } else { 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; } if (MarshalHelpers.UseLazyResolution(_targetMethod, _importMetadata.Module, _pInvokeILEmitterConfiguration)) { MetadataType lazyHelperType = _targetMethod.Context.GetHelperType("InteropHelpers"); FieldDesc lazyDispatchCell = new PInvokeLazyFixupField(_targetMethod); fnptrLoadStream.Emit(ILOpcode.ldsflda, emitter.NewToken(lazyDispatchCell)); fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(lazyHelperType .GetKnownMethod("ResolvePInvoke", null))); MethodSignatureFlags unmanagedCallConv = _importMetadata.Flags.UnmanagedCallingConvention; MethodSignature nativeSig = new MethodSignature( _targetMethod.Signature.Flags | unmanagedCallConv, 0, nativeReturnType, nativeParameterTypes); ILLocalVariable vNativeFunctionPointer = emitter.NewLocal(_targetMethod.Context .GetWellKnownType(WellKnownType.IntPtr)); fnptrLoadStream.EmitStLoc(vNativeFunctionPointer); callsiteSetupCodeStream.EmitLdLoc(vNativeFunctionPointer); callsiteSetupCodeStream.Emit(ILOpcode.calli, emitter.NewToken(nativeSig)); } else { // Eager call MethodSignature nativeSig = new MethodSignature( _targetMethod.Signature.Flags, 0, nativeReturnType, nativeParameterTypes); MethodDesc nativeMethod = new PInvokeTargetNativeMethod(_targetMethod, nativeSig); callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken(nativeMethod)); } } // if the SetLastError flag is set in DllImport, call the PInvokeMarshal. // SaveLastWin32Error so that last error can be used later by calling // PInvokeMarshal.GetLastWin32Error if (_importMetadata.Flags.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( InteropTypes.GetPInvokeMarshal(context) .GetKnownMethod("SaveLastWin32Error", null))); } unmarshallingCodestream.Emit(ILOpcode.ret); return(new PInvokeILStubMethodIL((ILStubMethodIL)emitter.Link(_targetMethod), IsStubRequired())); }
private void EmitPInvokeCall(PInvokeILCodeStreams ilCodeStreams) { ILEmitter emitter = ilCodeStreams.Emitter; ILCodeStream fnptrLoadStream = ilCodeStreams.FunctionPointerLoadStream; ILCodeStream callsiteSetupCodeStream = ilCodeStreams.CallsiteSetupCodeStream; TypeSystemContext context = _targetMethod.Context; TypeDesc nativeReturnType = _marshallers[0].NativeParameterType; TypeDesc[] nativeParameterTypes = new TypeDesc[_marshallers.Length - 1]; // if the SetLastError flag is set in DllImport, clear the error code before doing P/Invoke if (_flags.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( InteropTypes.GetPInvokeMarshal(context).GetKnownMethod("ClearLastWin32Error", null))); } for (int i = 1; i < _marshallers.Length; i++) { nativeParameterTypes[i - 1] = _marshallers[i].NativeParameterType; } if (MarshalHelpers.UseLazyResolution(_targetMethod, _importMetadata.Module, _pInvokeILEmitterConfiguration)) { MetadataType lazyHelperType = context.GetHelperType("InteropHelpers"); FieldDesc lazyDispatchCell = _interopStateManager.GetPInvokeLazyFixupField(_targetMethod); fnptrLoadStream.Emit(ILOpcode.ldsflda, emitter.NewToken(lazyDispatchCell)); fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(lazyHelperType .GetKnownMethod("ResolvePInvoke", null))); MethodSignatureFlags unmanagedCallConv = _flags.UnmanagedCallingConvention; MethodSignature nativeSig = new MethodSignature( _targetMethod.Signature.Flags | unmanagedCallConv, 0, nativeReturnType, nativeParameterTypes); ILLocalVariable vNativeFunctionPointer = emitter.NewLocal(context .GetWellKnownType(WellKnownType.IntPtr)); fnptrLoadStream.EmitStLoc(vNativeFunctionPointer); callsiteSetupCodeStream.EmitLdLoc(vNativeFunctionPointer); callsiteSetupCodeStream.Emit(ILOpcode.calli, emitter.NewToken(nativeSig)); } else { // Eager call MethodSignature nativeSig = new MethodSignature( _targetMethod.Signature.Flags, 0, nativeReturnType, nativeParameterTypes); MethodDesc nativeMethod = new PInvokeTargetNativeMethod(_targetMethod, nativeSig); callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken(nativeMethod)); } // if the SetLastError flag is set in DllImport, call the PInvokeMarshal. // SaveLastWin32Error so that last error can be used later by calling // PInvokeMarshal.GetLastWin32Error if (_flags.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( InteropTypes.GetPInvokeMarshal(context) .GetKnownMethod("SaveLastWin32Error", null))); } }
private MethodIL EmitIL() { // We have 4 code streams: // - _marshallingCodeStream is used to convert each argument into a native type and // store that into the local // - callsiteSetupCodeStream is used to used to load each previously generated local // and call the actual target native method. // - _returnValueMarshallingCodeStream is used to convert the native return value // to managed one. // - _unmarshallingCodestream is used to propagate [out] native arguments values to // managed ones. ILEmitter emitter = new ILEmitter(); ILCodeStream fnptrLoadStream = emitter.NewCodeStream(); ILCodeStream marshallingCodeStream = emitter.NewCodeStream(); ILCodeStream callsiteSetupCodeStream = emitter.NewCodeStream(); ILCodeStream returnValueMarshallingCodeStream = emitter.NewCodeStream(); ILCodeStream unmarshallingCodestream = emitter.NewCodeStream(); // Marshal the arguments for (int i = 0; i < _marshallers.Length; i++) { Marshaller marshaller = _marshallers[i]; marshaller.EmitMarshallingIL(emitter, marshallingCodeStream, callsiteSetupCodeStream, unmarshallingCodestream, returnValueMarshallingCodeStream); } // make the call TypeDesc nativeReturnType = _marshallers[0].NativeType; TypeDesc[] nativeParameterTypes = new TypeDesc[_marshallers.Length - 1]; for (int i = 1; i < _marshallers.Length; i++) { nativeParameterTypes[i - 1] = _marshallers[i].NativeType; } MethodDesc targetMethod = _methodData.TargetMethod; PInvokeMetadata importMetadata = _methodData.ImportMetadata; PInvokeILEmitterConfiguration pinvokeILEmitterConfiguration = _methodData.PInvokeILEmitterConfiguration; // if the SetLastError flag is set in DllImport, clear the error code before doing P/Invoke if ((importMetadata.Attributes & PInvokeAttributes.SetLastError) == PInvokeAttributes.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( _methodData.PInvokeMarshal.GetKnownMethod("ClearLastWin32Error", null))); } if (MarshalHelpers.UseLazyResolution(targetMethod, importMetadata.Module, pinvokeILEmitterConfiguration)) { MetadataType lazyHelperType = targetMethod.Context.GetHelperType("InteropHelpers"); FieldDesc lazyDispatchCell = new PInvokeLazyFixupField((DefType)targetMethod.OwningType, importMetadata); fnptrLoadStream.Emit(ILOpcode.ldsflda, emitter.NewToken(lazyDispatchCell)); fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(lazyHelperType.GetKnownMethod("ResolvePInvoke", null))); MethodSignatureFlags unmanagedCallConv = PInvokeMetadata.GetUnmanagedCallingConvention(importMetadata.Attributes); MethodSignature nativeCalliSig = new MethodSignature( targetMethod.Signature.Flags | unmanagedCallConv, 0, nativeReturnType, nativeParameterTypes); ILLocalVariable vNativeFunctionPointer = emitter.NewLocal(targetMethod.Context.GetWellKnownType(WellKnownType.IntPtr)); fnptrLoadStream.EmitStLoc(vNativeFunctionPointer); callsiteSetupCodeStream.EmitLdLoc(vNativeFunctionPointer); callsiteSetupCodeStream.Emit(ILOpcode.calli, emitter.NewToken(nativeCalliSig)); } else { // Eager call PInvokeMetadata nativeImportMetadata = new PInvokeMetadata(importMetadata.Module, importMetadata.Name ?? targetMethod.Name, importMetadata.Attributes); MethodSignature nativeSig = new MethodSignature( targetMethod.Signature.Flags, 0, nativeReturnType, nativeParameterTypes); MethodDesc nativeMethod = new PInvokeTargetNativeMethod(targetMethod.OwningType, nativeSig, nativeImportMetadata, pinvokeILEmitterConfiguration.GetNextNativeMethodId()); callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken(nativeMethod)); } // if the SetLastError flag is set in DllImport, call the PInvokeMarshal.SaveLastWin32Error so that last error can be used later // by calling PInvokeMarshal.GetLastWin32Error if ((importMetadata.Attributes & PInvokeAttributes.SetLastError) == PInvokeAttributes.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( _methodData.PInvokeMarshal.GetKnownMethod("SaveLastWin32Error", null))); } unmarshallingCodestream.Emit(ILOpcode.ret); return(emitter.Link(targetMethod)); }
private void EmitDelegateCall(DelegateMarshallingMethodThunk delegateMethod, PInvokeILCodeStreams ilCodeStreams) { ILEmitter emitter = ilCodeStreams.Emitter; ILCodeStream fnptrLoadStream = ilCodeStreams.FunctionPointerLoadStream; ILCodeStream callsiteSetupCodeStream = ilCodeStreams.CallsiteSetupCodeStream; TypeSystemContext context = _targetMethod.Context; Debug.Assert(delegateMethod != null); if (delegateMethod.Kind == DelegateMarshallingMethodThunkKind.ReverseOpenStatic) { // // For Open static delegates call // InteropHelpers.GetCurrentCalleeOpenStaticDelegateFunctionPointer() // which returns a function pointer. Just call the function pointer and we are done. // TypeDesc[] parameters = new TypeDesc[_marshallers.Length - 1]; for (int i = 1; i < _marshallers.Length; i++) { parameters[i - 1] = _marshallers[i].ManagedParameterType; } MethodSignature managedSignature = new MethodSignature( MethodSignatureFlags.Static, 0, _marshallers[0].ManagedParameterType, parameters); fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken( delegateMethod.Context.GetHelperType("InteropHelpers").GetKnownMethod( "GetCurrentCalleeOpenStaticDelegateFunctionPointer", null))); ILLocalVariable vDelegateStub = emitter.NewLocal( delegateMethod.Context.GetWellKnownType(WellKnownType.IntPtr)); fnptrLoadStream.EmitStLoc(vDelegateStub); callsiteSetupCodeStream.EmitLdLoc(vDelegateStub); callsiteSetupCodeStream.Emit(ILOpcode.calli, emitter.NewToken(managedSignature)); } else if (delegateMethod.Kind == DelegateMarshallingMethodThunkKind.ReverseClosed) { // // For closed delegates call // InteropHelpers.GetCurrentCalleeDelegate<Delegate> // which returns the delegate. Do a CallVirt on the invoke method. // MethodDesc instantiatedHelper = delegateMethod.Context.GetInstantiatedMethod( delegateMethod.Context.GetHelperType("InteropHelpers") .GetKnownMethod("GetCurrentCalleeDelegate", null), new Instantiation((delegateMethod.DelegateType))); fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(instantiatedHelper)); ILLocalVariable vDelegateStub = emitter.NewLocal(delegateMethod.DelegateType); fnptrLoadStream.EmitStLoc(vDelegateStub); fnptrLoadStream.EmitLdLoc(vDelegateStub); MethodDesc invokeMethod = delegateMethod.DelegateType.GetKnownMethod("Invoke", null); callsiteSetupCodeStream.Emit(ILOpcode.callvirt, emitter.NewToken(invokeMethod)); } else if (delegateMethod.Kind == DelegateMarshallingMethodThunkKind .ForwardNativeFunctionWrapper) { // // For NativeFunctionWrapper we need to load the native function and call it // fnptrLoadStream.EmitLdArg(0); fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(InteropTypes .GetNativeFunctionPointerWrapper(context) .GetMethod("get_NativeFunctionPointer", null))); var fnPtr = emitter.NewLocal( context.GetWellKnownType(WellKnownType.IntPtr)); fnptrLoadStream.EmitStLoc(fnPtr); callsiteSetupCodeStream.EmitLdLoc(fnPtr); 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; } MethodSignatureFlags flags = MethodSignatureFlags.Static; var delegateType = ((DelegateMarshallingMethodThunk)_targetMethod).DelegateType as EcmaType; if (delegateType != null) { flags |= delegateType.GetDelegatePInvokeFlags().UnmanagedCallingConvention; } MethodSignature nativeSig = new MethodSignature( flags, 0, nativeReturnType, nativeParameterTypes); callsiteSetupCodeStream.Emit(ILOpcode.calli, emitter.NewToken(nativeSig)); } else { Debug.Assert(false, "Unexpected DelegateMarshallingMethodThunkKind"); } }
private MethodIL EmitIL() { PInvokeILCodeStreams pInvokeILCodeStreams = new PInvokeILCodeStreams(); ILEmitter emitter = pInvokeILCodeStreams.Emitter; ILCodeStream fnptrLoadStream = pInvokeILCodeStreams.FunctionPointerLoadStream; ILCodeStream callsiteSetupCodeStream = pInvokeILCodeStreams.CallsiteSetupCodeStream; ILCodeStream unmarshallingCodestream = pInvokeILCodeStreams.UnmarshallingCodestream; TypeSystemContext context = _targetMethod.Context; // Marshal the arguments for (int i = 0; i < _marshallers.Length; i++) { _marshallers[i].EmitMarshallingIL(pInvokeILCodeStreams); } // make the call 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; // if the SetLastError flag is set in DllImport, clear the error code before doing P/Invoke if (_importMetadata.Flags.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( InteropTypes.GetPInvokeMarshal(context).GetKnownMethod("ClearLastWin32Error", null))); } DelegateMarshallingMethodThunk delegateMethod = _targetMethod as DelegateMarshallingMethodThunk; if (delegateMethod != null) { if (delegateMethod.IsOpenStaticDelegate) { // // For Open static delegates call // InteropHelpers.GetCurrentCalleeOpenStaticDelegateFunctionPointer() // which returns a function pointer. Just call the function pointer and we are done. // TypeDesc[] parameters = new TypeDesc[_marshallers.Length - 1]; for (int i = 1; i < _marshallers.Length; i++) { parameters[i - 1] = _marshallers[i].ManagedParameterType; } MethodSignature managedSignature = new MethodSignature(MethodSignatureFlags.Static, 0, _marshallers[0].ManagedParameterType, parameters); fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(delegateMethod.Context.GetHelperType("InteropHelpers").GetKnownMethod("GetCurrentCalleeOpenStaticDelegateFunctionPointer", null))); ILLocalVariable vDelegateStub = emitter.NewLocal(delegateMethod.Context.GetWellKnownType(WellKnownType.IntPtr)); fnptrLoadStream.EmitStLoc(vDelegateStub); callsiteSetupCodeStream.EmitLdLoc(vDelegateStub); callsiteSetupCodeStream.Emit(ILOpcode.calli, emitter.NewToken(managedSignature)); } else { // // For closed delegates call // InteropHelpers.GetCurrentCalleeDelegate<Delegate> // which returns the delegate. Do a CallVirt on the invoke method. // MethodDesc instantiatedHelper = delegateMethod.Context.GetInstantiatedMethod( delegateMethod.Context.GetHelperType("InteropHelpers").GetKnownMethod("GetCurrentCalleeDelegate", null), new Instantiation((delegateMethod.DelegateType))); fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(instantiatedHelper)); ILLocalVariable vDelegateStub = emitter.NewLocal(delegateMethod.DelegateType); fnptrLoadStream.EmitStLoc(vDelegateStub); fnptrLoadStream.EmitLdLoc(vDelegateStub); MethodDesc invokeMethod = delegateMethod.DelegateType.GetKnownMethod("Invoke", null); callsiteSetupCodeStream.Emit(ILOpcode.callvirt, emitter.NewToken(invokeMethod)); } } else if (MarshalHelpers.UseLazyResolution(_targetMethod, _importMetadata.Module, _pInvokeILEmitterConfiguration)) { MetadataType lazyHelperType = _targetMethod.Context.GetHelperType("InteropHelpers"); FieldDesc lazyDispatchCell = new PInvokeLazyFixupField((DefType)_targetMethod.OwningType, _importMetadata); fnptrLoadStream.Emit(ILOpcode.ldsflda, emitter.NewToken(lazyDispatchCell)); fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(lazyHelperType.GetKnownMethod("ResolvePInvoke", null))); MethodSignatureFlags unmanagedCallConv = _importMetadata.Flags.UnmanagedCallingConvention; nativeSig = new MethodSignature( _targetMethod.Signature.Flags | unmanagedCallConv, 0, nativeReturnType, nativeParameterTypes); ILLocalVariable vNativeFunctionPointer = emitter.NewLocal(_targetMethod.Context.GetWellKnownType(WellKnownType.IntPtr)); fnptrLoadStream.EmitStLoc(vNativeFunctionPointer); callsiteSetupCodeStream.EmitLdLoc(vNativeFunctionPointer); callsiteSetupCodeStream.Emit(ILOpcode.calli, emitter.NewToken(nativeSig)); } else { // Eager call PInvokeMetadata nativeImportMetadata = new PInvokeMetadata(_importMetadata.Module, _importMetadata.Name ?? _targetMethod.Name, _importMetadata.Flags); nativeSig = new MethodSignature( _targetMethod.Signature.Flags, 0, nativeReturnType, nativeParameterTypes); MethodDesc nativeMethod = new PInvokeTargetNativeMethod(_targetMethod.OwningType, nativeSig, nativeImportMetadata, _pInvokeILEmitterConfiguration.GetNextNativeMethodId()); callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken(nativeMethod)); } // if the SetLastError flag is set in DllImport, call the PInvokeMarshal.SaveLastWin32Error so that last error can be used later // by calling PInvokeMarshal.GetLastWin32Error if (_importMetadata.Flags.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( InteropTypes.GetPInvokeMarshal(context).GetKnownMethod("SaveLastWin32Error", null))); } unmarshallingCodestream.Emit(ILOpcode.ret); return(new PInvokeILStubMethodIL((ILStubMethodIL)emitter.Link(_targetMethod), IsStubRequired())); }
private void EmitPInvokeCall(PInvokeILCodeStreams ilCodeStreams) { ILEmitter emitter = ilCodeStreams.Emitter; ILCodeStream fnptrLoadStream = ilCodeStreams.FunctionPointerLoadStream; ILCodeStream callsiteSetupCodeStream = ilCodeStreams.CallsiteSetupCodeStream; TypeSystemContext context = _targetMethod.Context; bool isHRSwappedRetVal = !_flags.PreserveSig && !_targetMethod.Signature.ReturnType.IsVoid; TypeDesc nativeReturnType = _flags.PreserveSig ? _marshallers[0].NativeParameterType : context.GetWellKnownType(WellKnownType.Int32); TypeDesc[] nativeParameterTypes = new TypeDesc[isHRSwappedRetVal ? _marshallers.Length : _marshallers.Length - 1]; // if the SetLastError flag is set in DllImport, clear the error code before doing P/Invoke if (_flags.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( InteropTypes.GetPInvokeMarshal(context).GetKnownMethod("ClearLastError", null))); } for (int i = 1; i < _marshallers.Length; i++) { nativeParameterTypes[i - 1] = _marshallers[i].NativeParameterType; } if (isHRSwappedRetVal) { nativeParameterTypes[_marshallers.Length - 1] = _marshallers[0].NativeParameterType; } if (!_pInvokeILEmitterConfiguration.GenerateDirectCall(_targetMethod, out _)) { MetadataType lazyHelperType = context.GetHelperType("InteropHelpers"); FieldDesc lazyDispatchCell = _interopStateManager.GetPInvokeLazyFixupField(_targetMethod); fnptrLoadStream.Emit(ILOpcode.ldsflda, emitter.NewToken(lazyDispatchCell)); fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(lazyHelperType .GetKnownMethod("ResolvePInvoke", null))); MethodSignatureFlags unmanagedCallingConvention = _flags.UnmanagedCallingConvention; if (unmanagedCallingConvention == MethodSignatureFlags.None) { unmanagedCallingConvention = MethodSignatureFlags.UnmanagedCallingConvention; } EmbeddedSignatureData[] embeddedSignatureData = null; if (_targetMethod.HasCustomAttribute("System.Runtime.InteropServices", "SuppressGCTransitionAttribute")) { embeddedSignatureData = new EmbeddedSignatureData[] { new EmbeddedSignatureData() { index = MethodSignature.IndexOfCustomModifiersOnReturnType, kind = EmbeddedSignatureDataKind.OptionalCustomModifier, type = context.SystemModule.GetKnownType("System.Runtime.CompilerServices", "CallConvSuppressGCTransition") } }; } MethodSignature nativeSig = new MethodSignature( _targetMethod.Signature.Flags | unmanagedCallingConvention, 0, nativeReturnType, nativeParameterTypes, embeddedSignatureData); ILLocalVariable vNativeFunctionPointer = emitter.NewLocal(context .GetWellKnownType(WellKnownType.IntPtr)); fnptrLoadStream.EmitStLoc(vNativeFunctionPointer); callsiteSetupCodeStream.EmitLdLoc(vNativeFunctionPointer); callsiteSetupCodeStream.Emit(ILOpcode.calli, emitter.NewToken(nativeSig)); } else { // Eager call MethodSignature nativeSig = new MethodSignature( _targetMethod.Signature.Flags, 0, nativeReturnType, nativeParameterTypes); MethodDesc nativeMethod = new PInvokeTargetNativeMethod(_targetMethod, nativeSig); callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken(nativeMethod)); } if (!_flags.PreserveSig) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( InteropTypes.GetMarshal(context) .GetKnownMethod("ThrowExceptionForHR", null))); } // if the SetLastError flag is set in DllImport, call the PInvokeMarshal.SaveLastError // so that last error can be used later by calling Marshal.GetLastPInvokeError if (_flags.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( InteropTypes.GetPInvokeMarshal(context) .GetKnownMethod("SaveLastError", null))); } }
private MethodIL EmitIL() { PInvokeILCodeStreams pInvokeILCodeStreams = new PInvokeILCodeStreams(); ILEmitter emitter = pInvokeILCodeStreams.Emitter; ILCodeStream fnptrLoadStream = pInvokeILCodeStreams.FunctionPointerLoadStream; ILCodeStream callsiteSetupCodeStream = pInvokeILCodeStreams.CallsiteSetupCodeStream; ILCodeStream unmarshallingCodestream = pInvokeILCodeStreams.UnmarshallingCodestream; // Marshal the arguments for (int i = 0; i < _marshallers.Length; i++) { _marshallers[i].EmitMarshallingIL(pInvokeILCodeStreams); } // make the call 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; } MethodDesc targetMethod = _methodData.TargetMethod; PInvokeMetadata importMetadata = _methodData.ImportMetadata; PInvokeILEmitterConfiguration pinvokeILEmitterConfiguration = _methodData.PInvokeILEmitterConfiguration; MethodSignature nativeSig; // if the SetLastError flag is set in DllImport, clear the error code before doing P/Invoke if ((importMetadata.Attributes & PInvokeAttributes.SetLastError) == PInvokeAttributes.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( _methodData.PInvokeMarshal.GetKnownMethod("ClearLastWin32Error", null))); } if (targetMethod is DelegateMarshallingMethodThunk) { nativeSig = new MethodSignature(MethodSignatureFlags.Static, 0, nativeReturnType, nativeParameterTypes); TypeDesc[] parameters = new TypeDesc[_marshallers.Length - 1]; for (int i = 1; i < _marshallers.Length; i++) { parameters[i - 1] = _marshallers[i].ManagedParameterType; } MethodSignature managedSignature = new MethodSignature(MethodSignatureFlags.Static, 0, _marshallers[0].ManagedParameterType, parameters); fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(targetMethod.Context.GetHelperType("InteropHelpers").GetKnownMethod("GetDelegateFunctionPointer", null))); ILLocalVariable vDelegateStub = emitter.NewLocal(targetMethod.Context.GetWellKnownType(WellKnownType.IntPtr)); fnptrLoadStream.EmitStLoc(vDelegateStub); callsiteSetupCodeStream.EmitLdLoc(vDelegateStub); callsiteSetupCodeStream.Emit(ILOpcode.calli, emitter.NewToken(managedSignature)); } else if (MarshalHelpers.UseLazyResolution(targetMethod, importMetadata.Module, pinvokeILEmitterConfiguration)) { MetadataType lazyHelperType = targetMethod.Context.GetHelperType("InteropHelpers"); FieldDesc lazyDispatchCell = new PInvokeLazyFixupField((DefType)targetMethod.OwningType, importMetadata); fnptrLoadStream.Emit(ILOpcode.ldsflda, emitter.NewToken(lazyDispatchCell)); fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(lazyHelperType.GetKnownMethod("ResolvePInvoke", null))); MethodSignatureFlags unmanagedCallConv = PInvokeMetadata.GetUnmanagedCallingConvention(importMetadata.Attributes); nativeSig = new MethodSignature( targetMethod.Signature.Flags | unmanagedCallConv, 0, nativeReturnType, nativeParameterTypes); ILLocalVariable vNativeFunctionPointer = emitter.NewLocal(targetMethod.Context.GetWellKnownType(WellKnownType.IntPtr)); fnptrLoadStream.EmitStLoc(vNativeFunctionPointer); callsiteSetupCodeStream.EmitLdLoc(vNativeFunctionPointer); callsiteSetupCodeStream.Emit(ILOpcode.calli, emitter.NewToken(nativeSig)); } else { // Eager call PInvokeMetadata nativeImportMetadata = new PInvokeMetadata(importMetadata.Module, importMetadata.Name ?? targetMethod.Name, importMetadata.Attributes); nativeSig = new MethodSignature( targetMethod.Signature.Flags, 0, nativeReturnType, nativeParameterTypes); MethodDesc nativeMethod = new PInvokeTargetNativeMethod(targetMethod.OwningType, nativeSig, nativeImportMetadata, pinvokeILEmitterConfiguration.GetNextNativeMethodId()); callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken(nativeMethod)); } // if the SetLastError flag is set in DllImport, call the PInvokeMarshal.SaveLastWin32Error so that last error can be used later // by calling PInvokeMarshal.GetLastWin32Error if ((importMetadata.Attributes & PInvokeAttributes.SetLastError) == PInvokeAttributes.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( _methodData.PInvokeMarshal.GetKnownMethod("SaveLastWin32Error", null))); } unmarshallingCodestream.Emit(ILOpcode.ret); return(new PInvokeILStubMethodIL((ILStubMethodIL)emitter.Link(targetMethod), IsStubRequired(), nativeSig)); }
public MethodIL EmitIL() { MethodSignature targetMethodSignature = _targetMethod.Signature; // We have 4 code streams: // - _marshallingCodeStream is used to convert each argument into a native type and // store that into the local // - callsiteSetupCodeStream is used to used to load each previously generated local // and call the actual target native method. // - _returnValueMarshallingCodeStream is used to convert the native return value // to managed one. // - _unmarshallingCodestream is used to propagate [out] native arguments values to // managed ones. _emitter = new ILEmitter(); ILCodeStream fnptrLoadStream = _emitter.NewCodeStream(); _marshallingCodeStream = _emitter.NewCodeStream(); ILCodeStream callsiteSetupCodeStream = _emitter.NewCodeStream(); _returnValueMarshallingCodeStream = _emitter.NewCodeStream(); _unmarshallingCodestream = _emitter.NewCodeStream(); TypeDesc[] nativeParameterTypes = new TypeDesc[targetMethodSignature.Length]; // // Parameter marshalling // // // Convert each argument to something we can pass to native and store it in a local. // Then load the local in the second code stream. // for (int i = 0; i < targetMethodSignature.Length; i++) { // TODO: throw if there's custom marshalling _marshallingCodeStream.EmitLdArg(i); TypeDesc nativeType = MarshalArgument(targetMethodSignature[i]); nativeParameterTypes[i] = nativeType; ILLocalVariable vMarshalledTypeTemp = _emitter.NewLocal(nativeType); _marshallingCodeStream.EmitStLoc(vMarshalledTypeTemp); callsiteSetupCodeStream.EmitLdLoc(vMarshalledTypeTemp); } // // Return value marshalling // // TODO: throw if SetLastError is true // TODO: throw if there's custom marshalling TypeDesc nativeReturnType = MarshalReturnValue(targetMethodSignature.ReturnType); if (UseLazyResolution(_targetMethod, _importMetadata.Module)) { MetadataType lazyHelperType = _targetMethod.Context.GetHelperType("InteropHelpers"); FieldDesc lazyDispatchCell = new PInvokeLazyFixupField((DefType)_targetMethod.OwningType, _importMetadata); fnptrLoadStream.Emit(ILOpcode.ldsflda, _emitter.NewToken(lazyDispatchCell)); fnptrLoadStream.Emit(ILOpcode.call, _emitter.NewToken(lazyHelperType.GetKnownMethod("ResolvePInvoke", null))); MethodSignatureFlags unmanagedCallConv = PInvokeMetadata.GetUnmanagedCallingConvention(_importMetadata.Attributes); MethodSignature nativeCalliSig = new MethodSignature( targetMethodSignature.Flags | unmanagedCallConv, 0, nativeReturnType, nativeParameterTypes); ILLocalVariable vNativeFunctionPointer = _emitter.NewLocal(_targetMethod.Context.GetWellKnownType(WellKnownType.IntPtr)); fnptrLoadStream.EmitStLoc(vNativeFunctionPointer); callsiteSetupCodeStream.EmitLdLoc(vNativeFunctionPointer); callsiteSetupCodeStream.Emit(ILOpcode.calli, _emitter.NewToken(nativeCalliSig)); } else { // Eager call PInvokeMetadata nativeImportMetadata = new PInvokeMetadata(_importMetadata.Module, _importMetadata.Name ?? _targetMethod.Name, _importMetadata.Attributes); MethodSignature nativeSig = new MethodSignature( targetMethodSignature.Flags, 0, nativeReturnType, nativeParameterTypes); MethodDesc nativeMethod = new PInvokeTargetNativeMethod(_targetMethod.OwningType, nativeSig, nativeImportMetadata); callsiteSetupCodeStream.Emit(ILOpcode.call, _emitter.NewToken(nativeMethod)); } _unmarshallingCodestream.Emit(ILOpcode.ret); return(_emitter.Link(_targetMethod)); }