示例#1
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)
            {
                if (!MarshalHelpers.IsRuntimeMarshallingEnabled(((MetadataType)_targetMethod.OwningType).Module))
                {
                    // When runtime marshalling is disabled, we don't support generating the stub IL
                    // in Ready-to-Run so we can correctly throw an exception at runtime when the user tries to
                    // use SetLastError=true when marshalling is disabled.
                    throw new NotSupportedException();
                }
                callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken(
                                                 stubHelpersType.GetKnownMethod("ClearLastError", null)));
            }

            for (int i = 1; i < _marshallers.Length; i++)
            {
                nativeParameterTypes[i - 1] = _marshallers[i].NativeParameterType;
            }

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

            var rawTargetMethod = new PInvokeTargetNativeMethod(_targetMethod, nativeSig);

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

            // 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 (_importMetadata.Flags.SetLastError)
            {
                callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken(
                                                 stubHelpersType.GetKnownMethod("SetLastError", null)));
            }
        }
示例#2
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)));
            }
        }
示例#3
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)));
            }
        }
示例#4
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)
            {
                // if the SetLastError flag is set in UnmanagedFunctionPointerAttribute, clear the error code before doing P/Invoke
                if (_flags.SetLastError)
                {
                    callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken(
                                                     InteropTypes.GetPInvokeMarshal(context).GetKnownMethod("ClearLastWin32Error", null)));
                }

                //
                // 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;
                }

                MethodSignature nativeSig = new MethodSignature(
                    MethodSignatureFlags.Static | _flags.UnmanagedCallingConvention, 0, nativeReturnType, nativeParameterTypes);

                callsiteSetupCodeStream.Emit(ILOpcode.calli, emitter.NewToken(nativeSig));

                // if the SetLastError flag is set in UnmanagedFunctionPointerAttribute, 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)));
                }
            }
            else
            {
                Debug.Fail("Unexpected DelegateMarshallingMethodThunkKind");
            }
        }
示例#5
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()));
        }
示例#6
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)));
            }
        }
示例#7
0
        public void Setup(AssemblyNode mscorlib, AssemblyNode jsTypes, AssemblyNode rewriteAssembly)
        {
            NumWarnings = 0;
            NumErrors = 0;

            MsCorLib = mscorlib;

            AssemblyDelaySignAttributeType = GetType(mscorlib, "System.Reflection", "AssemblyDelaySignAttribute");

            VoidType = GetType(mscorlib, "System", "Void");
            ObjectType = GetType(mscorlib, "System", "Object");
            StringType = GetType(mscorlib, "System", "String");
            IntType = GetType(mscorlib, "System", "Int32");
            BooleanType = GetType(mscorlib, "System", "Boolean");
            MethodBaseType = GetType(mscorlib, "System.Reflection", "MethodBase");
            RuntimeTypeHandleType = GetType(mscorlib, "System", "RuntimeTypeHandle");
            NullableTypeConstructor = GetType(mscorlib, "System", "Nullable`1");
            CompilerGeneratedAttributeType = GetType
                (mscorlib, "System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
            DllImportAttributeType = GetType(mscorlib, "System.Runtime.InteropServices", "DllImportAttribute");

            TypeType = GetType(mscorlib, "System", "Type");
            Type_GetMethodMethod = GetMethod(TypeType, "GetMethod", StringType, TypeType.GetArrayType(1));
            Type_GetMemberMethod = GetMethod(TypeType, "GetMember", StringType);
            Type_GetConstructorMethod = GetMethod(TypeType, "GetConstructor", TypeType.GetArrayType(1));
            Type_GetTypeFromHandleMethod = GetMethod(TypeType, "GetTypeFromHandle", RuntimeTypeHandleType);
            Type_GetGenericArgumentsMethod = GetMethod(TypeType, "GetGenericArguments");
            Type_MakeArrayTypeMethod = GetMethod(TypeType, "MakeArrayType");
            Type_MakeGenericTypeMethod = GetMethod(TypeType, "MakeGenericType", TypeType.GetArrayType(1));

            InteropTypes = new InteropTypes(this);
            InteropManager = new InteropManager(this);

            IgnoreAttributeType = GetType(jsTypes, Constants.JSTypesIL2JSNS, "IgnoreAttribute");
            InteropAttributeType = GetType(jsTypes, Constants.JSTypesInteropNS, "InteropAttribute");
            NamingAttributeType = GetType(jsTypes, Constants.JSTypesInteropNS, "NamingAttribute");
            ImportAttributeType = GetType(jsTypes, Constants.JSTypesInteropNS, "ImportAttribute");
            ImportKeyAttributeType = GetType(jsTypes, Constants.JSTypesInteropNS, "ImportKeyAttribute");
            ExportAttributeType = GetType(jsTypes, Constants.JSTypesInteropNS, "ExportAttribute");
            NotExportedAttributeType = GetType(jsTypes, Constants.JSTypesInteropNS, "NotExportedAttribute");
            InteropGeneratedAttributeType = GetType(jsTypes, Constants.JSTypesIL2JSNS, "InteropGeneratedAttribute");

            JSTypes = jsTypes;

            JSContextType = GetType(jsTypes, Constants.JSTypesInteropNS, "JSContext");

            InteropContextManagerType = GetType(jsTypes, Constants.JSTypesManagedInteropNS, "InteropContextManager");
            InteropContextManager_GetDatabaseMethod = GetMethod(InteropContextManagerType, "get_Database");
            InteropContextManager_GetCurrentRuntimeMethod = GetMethod(InteropContextManagerType, "get_CurrentRuntime");
            InteropContextManager_GetRuntimeForObjectMethod = GetMethod
                (InteropContextManagerType, "GetRuntimeForObject", ObjectType);

            InteropDatabaseType = GetType(jsTypes, Constants.JSTypesManagedInteropNS, "InteropDatabase");
            InteropDatabase_RegisterRootExpression = GetMethod(InteropDatabaseType, "RegisterRootExpression", StringType);
            InteropDatabase_RegisterDelegateShimMethod = GetMethod
                (InteropDatabaseType, "RegisterDelegateShim", TypeType);
            InteropDatabase_RegisterTypeMethod = GetMethod
                (InteropDatabaseType,
                 "RegisterType",
                 TypeType,
                 IntType,
                 StringType,
                 StringType,
                 IntType,
                 BooleanType,
                 BooleanType,
                 BooleanType);
            InteropDatabase_RegisterExportMethod = GetMethod
                (InteropDatabaseType, "RegisterExport", MethodBaseType, BooleanType, StringType);

            SimpleMethodBaseType = GetType(jsTypes, Constants.JSTypesManagedInteropNS, "SimpleMethodBase");

            SimpleMethodInfoType = GetType(jsTypes, Constants.JSTypesManagedInteropNS, "SimpleMethodInfo");
            SimpleMethodInfo_Ctor = GetConstructor
                (SimpleMethodInfoType, BooleanType, StringType, TypeType, TypeType.GetArrayType(1), TypeType);

            SimpleConstructorInfoType = GetType(jsTypes, Constants.JSTypesManagedInteropNS, "SimpleConstructorInfo");
            SimpleConstructorInfo_Ctor = GetConstructor(SimpleConstructorInfoType, TypeType, TypeType.GetArrayType(1));

            RuntimeType = GetType(jsTypes, Constants.JSTypesManagedInteropNS, "Runtime");
            Runtime_CompleteConstructionMethod = GetMethod
                (RuntimeType, "CompleteConstruction", SimpleMethodBaseType, ObjectType, JSContextType);
            Runtime_CallImportedMethodMethod = GetMethod
                (RuntimeType, "CallImportedMethod", SimpleMethodBaseType, StringType, ObjectType.GetArrayType(1));

            UniversalDelegateType = GetType(jsTypes, Constants.JSTypesManagedInteropNS, "UniversalDelegate");
            UniversalDelegate_InvokeMethod = GetUniqueMethod(UniversalDelegateType, "Invoke");

            MethodBase_GetGenericArgumentsMethod = GetMethod(MethodBaseType, "GetGenericArguments");

            ModuleType = GetType(rewriteAssembly, "", "<Module>");
            foreach (var member in ModuleType.Members)
            {
                var cctor = member as StaticInitializer;
                if (cctor != null)
                    ModuleCCtorMethod = cctor;
            }
        }
示例#8
0
 public InteropManager(RewriterEnvironment env)
 {
     this.env = env;
     interopTypes = env.InteropTypes;
     typeDefnToStyleCache = new Map<CCI.TypeNode, Nullable<InteropStyle>>();
 }
示例#9
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()));
        }
示例#10
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];

            bool runtimeMarshallingEnabled = MarshalHelpers.IsRuntimeMarshallingEnabled(((MetadataType)_targetMethod.OwningType).Module);

            // if the SetLastError flag is set in DllImport, clear the error code before doing P/Invoke
            if (_flags.SetLastError)
            {
                if (!runtimeMarshallingEnabled)
                {
                    // When runtime marshalling is disabled, we don't support SetLastError
                    throw new NotSupportedException();
                }
                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)
            {
                if (!runtimeMarshallingEnabled)
                {
                    // When runtime marshalling is disabled, we don't support HResult-return-swapping
                    throw new NotSupportedException();
                }
                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)));

                MethodSignature nativeSig = new MethodSignature(
                    MethodSignatureFlags.Static | MethodSignatureFlags.UnmanagedCallingConvention, 0, nativeReturnType, nativeParameterTypes,
                    _targetMethod.GetPInvokeMethodCallingConventions().EncodeAsEmbeddedSignatureData(context));

                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)));
            }
        }