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))); } }
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))); } }
private void EmitPInvokeCall(PInvokeILCodeStreams ilCodeStreams) { ILEmitter emitter = ilCodeStreams.Emitter; ILCodeStream fnptrLoadStream = ilCodeStreams.FunctionPointerLoadStream; ILCodeStream callsiteSetupCodeStream = ilCodeStreams.CallsiteSetupCodeStream; TypeSystemContext context = _targetMethod.Context; TypeDesc nativeReturnType = _marshallers[0].NativeParameterType; TypeDesc[] nativeParameterTypes = new TypeDesc[_marshallers.Length - 1]; // if the SetLastError flag is set in DllImport, clear the error code before doing P/Invoke if (_flags.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( InteropTypes.GetPInvokeMarshal(context).GetKnownMethod("ClearLastWin32Error", null))); } for (int i = 1; i < _marshallers.Length; i++) { nativeParameterTypes[i - 1] = _marshallers[i].NativeParameterType; } if (MarshalHelpers.UseLazyResolution(_targetMethod, _importMetadata.Module, _pInvokeILEmitterConfiguration)) { MetadataType lazyHelperType = context.GetHelperType("InteropHelpers"); FieldDesc lazyDispatchCell = _interopStateManager.GetPInvokeLazyFixupField(_targetMethod); fnptrLoadStream.Emit(ILOpcode.ldsflda, emitter.NewToken(lazyDispatchCell)); fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(lazyHelperType .GetKnownMethod("ResolvePInvoke", null))); MethodSignatureFlags unmanagedCallConv = _flags.UnmanagedCallingConvention; MethodSignature nativeSig = new MethodSignature( _targetMethod.Signature.Flags | unmanagedCallConv, 0, nativeReturnType, nativeParameterTypes); ILLocalVariable vNativeFunctionPointer = emitter.NewLocal(context .GetWellKnownType(WellKnownType.IntPtr)); fnptrLoadStream.EmitStLoc(vNativeFunctionPointer); callsiteSetupCodeStream.EmitLdLoc(vNativeFunctionPointer); callsiteSetupCodeStream.Emit(ILOpcode.calli, emitter.NewToken(nativeSig)); } else { // Eager call MethodSignature nativeSig = new MethodSignature( _targetMethod.Signature.Flags, 0, nativeReturnType, nativeParameterTypes); MethodDesc nativeMethod = new PInvokeTargetNativeMethod(_targetMethod, nativeSig); callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken(nativeMethod)); } // if the SetLastError flag is set in DllImport, call the PInvokeMarshal. // SaveLastWin32Error so that last error can be used later by calling // PInvokeMarshal.GetLastWin32Error if (_flags.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( InteropTypes.GetPInvokeMarshal(context) .GetKnownMethod("SaveLastWin32Error", null))); } }
private 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"); } }
private MethodIL EmitIL() { PInvokeILCodeStreams pInvokeILCodeStreams = new PInvokeILCodeStreams(); ILEmitter emitter = pInvokeILCodeStreams.Emitter; ILCodeStream fnptrLoadStream = pInvokeILCodeStreams.FunctionPointerLoadStream; ILCodeStream callsiteSetupCodeStream = pInvokeILCodeStreams.CallsiteSetupCodeStream; ILCodeStream unmarshallingCodestream = pInvokeILCodeStreams.UnmarshallingCodestream; TypeSystemContext context = _targetMethod.Context; // Marshal the arguments for (int i = 0; i < _marshallers.Length; i++) { _marshallers[i].EmitMarshallingIL(pInvokeILCodeStreams); } // if the SetLastError flag is set in DllImport, clear the error code before doing P/Invoke if (_importMetadata.Flags.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( InteropTypes.GetPInvokeMarshal(context).GetKnownMethod("ClearLastWin32Error", null))); } // make the call DelegateMarshallingMethodThunk delegateMethod = _targetMethod as DelegateMarshallingMethodThunk; if (delegateMethod != null) { EmitDelegateCall(delegateMethod, pInvokeILCodeStreams); } else { TypeDesc nativeReturnType = _marshallers[0].NativeParameterType; TypeDesc[] nativeParameterTypes = new TypeDesc[_marshallers.Length - 1]; for (int i = 1; i < _marshallers.Length; i++) { nativeParameterTypes[i - 1] = _marshallers[i].NativeParameterType; } if (MarshalHelpers.UseLazyResolution(_targetMethod, _importMetadata.Module, _pInvokeILEmitterConfiguration)) { MetadataType lazyHelperType = _targetMethod.Context.GetHelperType("InteropHelpers"); FieldDesc lazyDispatchCell = new PInvokeLazyFixupField(_targetMethod); fnptrLoadStream.Emit(ILOpcode.ldsflda, emitter.NewToken(lazyDispatchCell)); fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(lazyHelperType .GetKnownMethod("ResolvePInvoke", null))); MethodSignatureFlags unmanagedCallConv = _importMetadata.Flags.UnmanagedCallingConvention; MethodSignature nativeSig = new MethodSignature( _targetMethod.Signature.Flags | unmanagedCallConv, 0, nativeReturnType, nativeParameterTypes); ILLocalVariable vNativeFunctionPointer = emitter.NewLocal(_targetMethod.Context .GetWellKnownType(WellKnownType.IntPtr)); fnptrLoadStream.EmitStLoc(vNativeFunctionPointer); callsiteSetupCodeStream.EmitLdLoc(vNativeFunctionPointer); callsiteSetupCodeStream.Emit(ILOpcode.calli, emitter.NewToken(nativeSig)); } else { // Eager call MethodSignature nativeSig = new MethodSignature( _targetMethod.Signature.Flags, 0, nativeReturnType, nativeParameterTypes); MethodDesc nativeMethod = new PInvokeTargetNativeMethod(_targetMethod, nativeSig); callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken(nativeMethod)); } } // if the SetLastError flag is set in DllImport, call the PInvokeMarshal. // SaveLastWin32Error so that last error can be used later by calling // PInvokeMarshal.GetLastWin32Error if (_importMetadata.Flags.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( InteropTypes.GetPInvokeMarshal(context) .GetKnownMethod("SaveLastWin32Error", null))); } unmarshallingCodestream.Emit(ILOpcode.ret); return(new PInvokeILStubMethodIL((ILStubMethodIL)emitter.Link(_targetMethod), IsStubRequired())); }
private void EmitPInvokeCall(PInvokeILCodeStreams ilCodeStreams) { ILEmitter emitter = ilCodeStreams.Emitter; ILCodeStream fnptrLoadStream = ilCodeStreams.FunctionPointerLoadStream; ILCodeStream callsiteSetupCodeStream = ilCodeStreams.CallsiteSetupCodeStream; TypeSystemContext context = _targetMethod.Context; 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))); } }
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; } }
public InteropManager(RewriterEnvironment env) { this.env = env; interopTypes = env.InteropTypes; typeDefnToStyleCache = new Map<CCI.TypeNode, Nullable<InteropStyle>>(); }
private MethodIL EmitIL() { PInvokeILCodeStreams pInvokeILCodeStreams = new PInvokeILCodeStreams(); ILEmitter emitter = pInvokeILCodeStreams.Emitter; ILCodeStream fnptrLoadStream = pInvokeILCodeStreams.FunctionPointerLoadStream; ILCodeStream callsiteSetupCodeStream = pInvokeILCodeStreams.CallsiteSetupCodeStream; ILCodeStream unmarshallingCodestream = pInvokeILCodeStreams.UnmarshallingCodestream; TypeSystemContext context = _targetMethod.Context; // Marshal the arguments for (int i = 0; i < _marshallers.Length; i++) { _marshallers[i].EmitMarshallingIL(pInvokeILCodeStreams); } // make the call TypeDesc nativeReturnType = _marshallers[0].NativeParameterType; TypeDesc[] nativeParameterTypes = new TypeDesc[_marshallers.Length - 1]; for (int i = 1; i < _marshallers.Length; i++) { nativeParameterTypes[i - 1] = _marshallers[i].NativeParameterType; } MethodSignature nativeSig; // if the SetLastError flag is set in DllImport, clear the error code before doing P/Invoke if (_importMetadata.Flags.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( InteropTypes.GetPInvokeMarshal(context).GetKnownMethod("ClearLastWin32Error", null))); } DelegateMarshallingMethodThunk delegateMethod = _targetMethod as DelegateMarshallingMethodThunk; if (delegateMethod != null) { if (delegateMethod.IsOpenStaticDelegate) { // // For Open static delegates call // InteropHelpers.GetCurrentCalleeOpenStaticDelegateFunctionPointer() // which returns a function pointer. Just call the function pointer and we are done. // TypeDesc[] parameters = new TypeDesc[_marshallers.Length - 1]; for (int i = 1; i < _marshallers.Length; i++) { parameters[i - 1] = _marshallers[i].ManagedParameterType; } MethodSignature managedSignature = new MethodSignature(MethodSignatureFlags.Static, 0, _marshallers[0].ManagedParameterType, parameters); fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(delegateMethod.Context.GetHelperType("InteropHelpers").GetKnownMethod("GetCurrentCalleeOpenStaticDelegateFunctionPointer", null))); ILLocalVariable vDelegateStub = emitter.NewLocal(delegateMethod.Context.GetWellKnownType(WellKnownType.IntPtr)); fnptrLoadStream.EmitStLoc(vDelegateStub); callsiteSetupCodeStream.EmitLdLoc(vDelegateStub); callsiteSetupCodeStream.Emit(ILOpcode.calli, emitter.NewToken(managedSignature)); } else { // // For closed delegates call // InteropHelpers.GetCurrentCalleeDelegate<Delegate> // which returns the delegate. Do a CallVirt on the invoke method. // MethodDesc instantiatedHelper = delegateMethod.Context.GetInstantiatedMethod( delegateMethod.Context.GetHelperType("InteropHelpers").GetKnownMethod("GetCurrentCalleeDelegate", null), new Instantiation((delegateMethod.DelegateType))); fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(instantiatedHelper)); ILLocalVariable vDelegateStub = emitter.NewLocal(delegateMethod.DelegateType); fnptrLoadStream.EmitStLoc(vDelegateStub); fnptrLoadStream.EmitLdLoc(vDelegateStub); MethodDesc invokeMethod = delegateMethod.DelegateType.GetKnownMethod("Invoke", null); callsiteSetupCodeStream.Emit(ILOpcode.callvirt, emitter.NewToken(invokeMethod)); } } else if (MarshalHelpers.UseLazyResolution(_targetMethod, _importMetadata.Module, _pInvokeILEmitterConfiguration)) { MetadataType lazyHelperType = _targetMethod.Context.GetHelperType("InteropHelpers"); FieldDesc lazyDispatchCell = new PInvokeLazyFixupField((DefType)_targetMethod.OwningType, _importMetadata); fnptrLoadStream.Emit(ILOpcode.ldsflda, emitter.NewToken(lazyDispatchCell)); fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(lazyHelperType.GetKnownMethod("ResolvePInvoke", null))); MethodSignatureFlags unmanagedCallConv = _importMetadata.Flags.UnmanagedCallingConvention; nativeSig = new MethodSignature( _targetMethod.Signature.Flags | unmanagedCallConv, 0, nativeReturnType, nativeParameterTypes); ILLocalVariable vNativeFunctionPointer = emitter.NewLocal(_targetMethod.Context.GetWellKnownType(WellKnownType.IntPtr)); fnptrLoadStream.EmitStLoc(vNativeFunctionPointer); callsiteSetupCodeStream.EmitLdLoc(vNativeFunctionPointer); callsiteSetupCodeStream.Emit(ILOpcode.calli, emitter.NewToken(nativeSig)); } else { // Eager call PInvokeMetadata nativeImportMetadata = new PInvokeMetadata(_importMetadata.Module, _importMetadata.Name ?? _targetMethod.Name, _importMetadata.Flags); nativeSig = new MethodSignature( _targetMethod.Signature.Flags, 0, nativeReturnType, nativeParameterTypes); MethodDesc nativeMethod = new PInvokeTargetNativeMethod(_targetMethod.OwningType, nativeSig, nativeImportMetadata, _pInvokeILEmitterConfiguration.GetNextNativeMethodId()); callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken(nativeMethod)); } // if the SetLastError flag is set in DllImport, call the PInvokeMarshal.SaveLastWin32Error so that last error can be used later // by calling PInvokeMarshal.GetLastWin32Error if (_importMetadata.Flags.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( InteropTypes.GetPInvokeMarshal(context).GetKnownMethod("SaveLastWin32Error", null))); } unmarshallingCodestream.Emit(ILOpcode.ret); return(new PInvokeILStubMethodIL((ILStubMethodIL)emitter.Link(_targetMethod), IsStubRequired())); }
private void EmitPInvokeCall(PInvokeILCodeStreams ilCodeStreams) { ILEmitter emitter = ilCodeStreams.Emitter; ILCodeStream fnptrLoadStream = ilCodeStreams.FunctionPointerLoadStream; ILCodeStream callsiteSetupCodeStream = ilCodeStreams.CallsiteSetupCodeStream; TypeSystemContext context = _targetMethod.Context; bool isHRSwappedRetVal = !_flags.PreserveSig && !_targetMethod.Signature.ReturnType.IsVoid; TypeDesc nativeReturnType = _flags.PreserveSig ? _marshallers[0].NativeParameterType : context.GetWellKnownType(WellKnownType.Int32); TypeDesc[] nativeParameterTypes = new TypeDesc[isHRSwappedRetVal ? _marshallers.Length : _marshallers.Length - 1]; 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))); } }