Пример #1
0
        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));
        }
Пример #2
0
        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));
        }
Пример #3
0
        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);
            }
        }
Пример #4
0
        public MethodSignatureBuilder(MethodSignature template)
        {
            _template = template;

            _flags = template._flags;
            _genericParameterCount = template._genericParameterCount;
            _returnType            = template._returnType;
            _parameters            = template._parameters;
        }
Пример #5
0
        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");
        }
Пример #6
0
        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");
        }
Пример #7
0
        public MethodSignatureBuilder(MethodSignature template)
        {
            _template = template;

            _flags = template._flags;
            _genericParameterCount = template._genericParameterCount;
            _returnType            = template._returnType;
            _parameters            = template._parameters;
            _customModifiers       = template._embeddedSignatureData;
        }
Пример #8
0
        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);
        }
Пример #10
0
        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)));
            }
        }
Пример #11
0
        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));
        }
Пример #14
0
        /// <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);
        }
Пример #15
0
        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));
Пример #16
0
        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()));
        }
Пример #17
0
        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)));
            }
        }
Пример #18
0
        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));
        }
Пример #19
0
        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");
            }
        }
Пример #20
0
        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()));
        }
Пример #21
0
        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)));
            }
        }
Пример #22
0
        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));
        }
Пример #23
0
        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));
        }
Пример #24
0
        public MethodSignatureBuilder(MethodSignature template)
        {
            _template = template;

            _flags = template._flags;
            _genericParameterCount = template._genericParameterCount;
            _returnType = template._returnType;
            _parameters = template._parameters;
        }