Ejemplo n.º 1
0
        private PInvokeILEmitter(MethodDesc targetMethod, PInvokeILEmitterConfiguration pinvokeILEmitterConfiguration)
        {
            Debug.Assert(targetMethod.IsPInvoke || targetMethod is DelegateMarshallingMethodThunk);

            _methodData  = new PInvokeMethodData(targetMethod, pinvokeILEmitterConfiguration);
            _marshallers = InitializeMarshallers(_methodData);
        }
Ejemplo n.º 2
0
 public PInvokeMethodData(MethodDesc method, PInvokeILEmitterConfiguration config)
 {
     TargetMethod = method;
     PInvokeILEmitterConfiguration = config;
     Context        = method.Context;
     ImportMetadata = method.GetPInvokeMethodMetadata();
 }
Ejemplo n.º 3
0
        private PInvokeILEmitter(MethodDesc targetMethod, PInvokeILEmitterConfiguration pinvokeILEmitterConfiguration, InteropStateManager interopStateManager)
        {
            Debug.Assert(targetMethod.IsPInvoke || targetMethod is DelegateMarshallingMethodThunk);
            _targetMethod = targetMethod;
            _pInvokeILEmitterConfiguration = pinvokeILEmitterConfiguration;
            _importMetadata      = targetMethod.GetPInvokeMethodMetadata();
            _interopStateManager = interopStateManager;

            PInvokeFlags flags = new PInvokeFlags();

            if (targetMethod.IsPInvoke)
            {
                flags = _importMetadata.Flags;
            }
            else
            {
                var delegateType = ((DelegateMarshallingMethodThunk)_targetMethod).DelegateType as EcmaType;
                if (delegateType != null)
                {
                    flags = delegateType.GetDelegatePInvokeFlags();
                }
            }

            _marshallers = InitializeMarshallers(targetMethod, interopStateManager, flags);
        }
Ejemplo n.º 4
0
        public static MethodIL EmitIL(MethodDesc method, PInvokeILEmitterConfiguration pinvokeILEmitterConfiguration)
        {
            try
            {
                return(new PInvokeILEmitter(method, pinvokeILEmitterConfiguration).EmitIL());
            }
            catch (NotSupportedException)
            {
                ILEmitter emitter = new ILEmitter();
                string    message = "Method '" + method.ToString() +
                                    "' requires non-trivial marshalling that is not yet supported by this compiler.";

                TypeSystemContext context       = method.Context;
                MethodSignature   ctorSignature = new MethodSignature(0, 0, context.GetWellKnownType(WellKnownType.Void),
                                                                      new TypeDesc[] { context.GetWellKnownType(WellKnownType.String) });
                MethodDesc exceptionCtor = method.Context.GetWellKnownType(WellKnownType.Exception).GetKnownMethod(".ctor", ctorSignature);

                ILCodeStream codeStream = emitter.NewCodeStream();
                codeStream.Emit(ILOpcode.ldstr, emitter.NewToken(message));
                codeStream.Emit(ILOpcode.newobj, emitter.NewToken(exceptionCtor));
                codeStream.Emit(ILOpcode.throw_);
                codeStream.Emit(ILOpcode.ret);

                return(emitter.Link(method));
            }
        }
Ejemplo n.º 5
0
        private PInvokeILEmitter(MethodDesc targetMethod, PInvokeILEmitterConfiguration pinvokeILEmitterConfiguration)
        {
            Debug.Assert(targetMethod.IsPInvoke);

            _methodData  = new PInvokeMethodData(targetMethod, pinvokeILEmitterConfiguration, MarshalDirection.Forward);
            _marshallers = InitializeMarshallers(_methodData);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Returns true if the PInvoke target should be resolved lazily.
        /// </summary>
        public static bool UseLazyResolution(MethodDesc method, string importModule, PInvokeILEmitterConfiguration configuration)
        {
            bool?forceLazyResolution = configuration.ForceLazyResolution;

            if (forceLazyResolution.HasValue)
            {
                return(forceLazyResolution.Value);
            }

            // Determine whether this call should be made through a lazy resolution or a static reference
            // Eventually, this should be controlled by a custom attribute (or an extension to the metadata format).
            if (importModule == "[MRT]" || importModule == "*")
            {
                return(false);
            }

            if (method.Context.Target.IsWindows)
            {
                return(!importModule.StartsWith("api-ms-win-"));
            }
            else
            {
                // Account for System.Private.CoreLib.Native / System.Globalization.Native / System.Native / etc
                return(!importModule.StartsWith("System."));
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Returns true if <paramref name="method"/> requires a stub to be generated.
        /// </summary>
        public static bool IsStubRequired(MethodDesc method, PInvokeILEmitterConfiguration configuration)
        {
            Debug.Assert(method.IsPInvoke);

            // TODO: true if there are any custom marshalling rules on the parameters

            TypeDesc returnType = method.Signature.ReturnType;

            if (!MarshalHelpers.IsBlittableType(returnType) && !returnType.IsVoid)
            {
                return(true);
            }

            for (int i = 0; i < method.Signature.Length; i++)
            {
                if (!MarshalHelpers.IsBlittableType(method.Signature[i]))
                {
                    return(true);
                }
            }

            PInvokeMetadata methodData = method.GetPInvokeMethodMetadata();

            if (UseLazyResolution(method, methodData.Module, configuration))
            {
                return(true);
            }
            if ((methodData.Attributes & PInvokeAttributes.SetLastError) == PInvokeAttributes.SetLastError)
            {
                return(true);
            }

            return(false);
        }
Ejemplo n.º 8
0
        private PInvokeILEmitter(MethodDesc targetMethod, PInvokeILEmitterConfiguration pinvokeILEmitterConfiguration, InteropStateManager interopStateManager)
        {
            Debug.Assert(targetMethod.IsPInvoke || targetMethod is DelegateMarshallingMethodThunk);
            _targetMethod = targetMethod;
            _pInvokeILEmitterConfiguration = pinvokeILEmitterConfiguration;
            _importMetadata      = targetMethod.GetPInvokeMethodMetadata();
            _interopStateManager = interopStateManager;

            //
            // targetMethod could be either a PInvoke or a DelegateMarshallingMethodThunk
            // ForwardNativeFunctionWrapper method thunks are marked as PInvokes, so it is
            // important to check them first here so that we get the right flags.
            //
            DelegateMarshallingMethodThunk delegateThunk = _targetMethod as DelegateMarshallingMethodThunk;

            if (delegateThunk != null)
            {
                _flags = ((EcmaType)delegateThunk.DelegateType).GetDelegatePInvokeFlags();
            }
            else
            {
                Debug.Assert(_targetMethod.IsPInvoke);
                _flags = _importMetadata.Flags;
            }
            _marshallers = InitializeMarshallers(targetMethod, interopStateManager, _flags);
        }
Ejemplo n.º 9
0
 public PInvokeMethodData(MethodDesc method, PInvokeILEmitterConfiguration config, MarshalDirection direction)
 {
     TargetMethod = method;
     PInvokeILEmitterConfiguration = config;
     Context        = method.Context;
     ImportMetadata = method.GetPInvokeMethodMetadata();
     Direction      = direction;
 }
Ejemplo n.º 10
0
 internal ILScannerBuilder(CompilerTypeSystemContext context, CompilationModuleGroup compilationGroup, NameMangler mangler, ILProvider ilProvider, PInvokeILEmitterConfiguration pinvokePolicy)
 {
     _context          = context;
     _compilationGroup = compilationGroup;
     _nameMangler      = mangler;
     _metadataManager  = new EmptyMetadataManager(context);
     _ilProvider       = ilProvider;
     _pinvokePolicy    = pinvokePolicy;
 }
Ejemplo n.º 11
0
 internal ILScanner(
     DependencyAnalyzerBase <NodeFactory> dependencyGraph,
     ILScanNodeFactory nodeFactory,
     IEnumerable <ICompilationRootProvider> roots,
     ILProvider ilProvider,
     DebugInformationProvider debugInformationProvider,
     PInvokeILEmitterConfiguration pinvokePolicy,
     Logger logger)
     : base(dependencyGraph, nodeFactory, roots, ilProvider, debugInformationProvider, null, pinvokePolicy, logger)
 {
 }
Ejemplo n.º 12
0
 internal CppCodegenCompilation(
     DependencyAnalyzerBase <NodeFactory> dependencyGraph,
     NodeFactory nodeFactory,
     IEnumerable <ICompilationRootProvider> roots,
     ILProvider ilProvider,
     DebugInformationProvider debugInformationProvider,
     PInvokeILEmitterConfiguration pinvokePolicy,
     Logger logger,
     CppCodegenConfigProvider options)
     : base(dependencyGraph, nodeFactory, GetCompilationRoots(roots, nodeFactory), ilProvider, debugInformationProvider, null, pinvokePolicy, logger)
 {
     Options = options;
 }
Ejemplo n.º 13
0
 internal RyuJitCompilation(
     DependencyAnalyzerBase <NodeFactory> dependencyGraph,
     NodeFactory nodeFactory,
     IEnumerable <ICompilationRootProvider> roots,
     ILProvider ilProvider,
     DebugInformationProvider debugInformationProvider,
     PInvokeILEmitterConfiguration pinvokePolicy,
     Logger logger,
     DevirtualizationManager devirtualizationManager,
     JitConfigProvider configProvider)
     : base(dependencyGraph, nodeFactory, roots, ilProvider, debugInformationProvider, devirtualizationManager, pinvokePolicy, logger)
 {
     _jitConfigProvider = configProvider;
 }
Ejemplo n.º 14
0
        private PInvokeILEmitter(MethodDesc targetMethod, PInvokeILEmitterConfiguration pinvokeIlEmitterConfiguration)
        {
            Debug.Assert(targetMethod.IsPInvoke);

            _targetMethod = targetMethod;
            _pinvokeILEmitterConfiguration = pinvokeIlEmitterConfiguration;
            _context        = _targetMethod.Context;
            _importMetadata = targetMethod.GetPInvokeMethodMetadata();

            _emitter = null;
            _marshallingCodeStream            = null;
            _returnValueMarshallingCodeStream = null;
            _unmarshallingCodestream          = null;
        }
Ejemplo n.º 15
0
 internal RyuJitCompilation(
     DependencyAnalyzerBase <NodeFactory> dependencyGraph,
     NodeFactory nodeFactory,
     IEnumerable <ICompilationRootProvider> roots,
     ILProvider ilProvider,
     DebugInformationProvider debugInformationProvider,
     PInvokeILEmitterConfiguration pinvokePolicy,
     Logger logger,
     DevirtualizationManager devirtualizationManager,
     JitConfigProvider configProvider,
     RyuJitCompilationOptions options)
     : base(dependencyGraph, nodeFactory, roots, ilProvider, debugInformationProvider, devirtualizationManager, pinvokePolicy, logger)
 {
     _jitConfigProvider      = configProvider;
     _compilationOptions     = options;
     _hardwareIntrinsicFlags = new ExternSymbolMappedField(nodeFactory.TypeSystemContext.GetWellKnownType(WellKnownType.Int32), "g_cpuFeatures");
 }
Ejemplo n.º 16
0
 public static MethodIL EmitIL(MethodDesc method, PInvokeILEmitterConfiguration pinvokeILEmitterConfiguration)
 {
     try
     {
         return(new PInvokeILEmitter(method, pinvokeILEmitterConfiguration).EmitIL());
     }
     catch (NotSupportedException)
     {
         string message = "Method '" + method.ToString() +
                          "' requires non-trivial marshalling that is not yet supported by this compiler.";
         return(EmitExceptionBody(message, method));
     }
     catch (InvalidProgramException ex)
     {
         Debug.Assert(!String.IsNullOrEmpty(ex.Message));
         return(EmitExceptionBody(ex.Message, method));
     }
 }
 internal WebAssemblyCodegenCompilation(
     DependencyAnalyzerBase <NodeFactory> dependencyGraph,
     WebAssemblyCodegenNodeFactory nodeFactory,
     IEnumerable <ICompilationRootProvider> roots,
     ILProvider ilProvider,
     DebugInformationProvider debugInformationProvider,
     PInvokeILEmitterConfiguration pinvokePolicy,
     Logger logger,
     WebAssemblyCodegenConfigProvider options)
     : base(dependencyGraph, nodeFactory, GetCompilationRoots(roots, nodeFactory), ilProvider, debugInformationProvider, null, pinvokePolicy, logger)
 {
     NodeFactory = nodeFactory;
     Module      = LLVM.ModuleCreateWithName("netscripten");
     LLVM.SetTarget(Module, "asmjs-unknown-emscripten");
     Options          = options;
     DIBuilder        = LLVMPInvokes.LLVMCreateDIBuilder(Module);
     DebugMetadataMap = new Dictionary <string, DebugMetadata>();
 }
Ejemplo n.º 18
0
        internal ReadyToRunCodegenCompilation(
            DependencyAnalyzerBase <NodeFactory> dependencyGraph,
            ReadyToRunCodegenNodeFactory nodeFactory,
            IEnumerable <ICompilationRootProvider> roots,
            ILProvider ilProvider,
            DebugInformationProvider debugInformationProvider,
            PInvokeILEmitterConfiguration pInvokePolicy,
            Logger logger,
            DevirtualizationManager devirtualizationManager,
            JitConfigProvider configProvider,
            string inputFilePath)
            : base(dependencyGraph, nodeFactory, roots, ilProvider, debugInformationProvider, devirtualizationManager, pInvokePolicy, logger)
        {
            NodeFactory        = nodeFactory;
            SymbolNodeFactory  = new ReadyToRunSymbolNodeFactory(nodeFactory);
            _jitConfigProvider = configProvider;

            _inputFilePath = inputFilePath;
            _corInfo       = new CorInfoImpl(this, _jitConfigProvider);
        }
Ejemplo n.º 19
0
        protected Compilation(
            DependencyAnalyzerBase <NodeFactory> dependencyGraph,
            NodeFactory nodeFactory,
            IEnumerable <ICompilationRootProvider> compilationRoots,
            ILProvider ilProvider,
            DebugInformationProvider debugInformationProvider,
            DevirtualizationManager devirtualizationManager,
            PInvokeILEmitterConfiguration pInvokeConfiguration,
            Logger logger)
        {
            _dependencyGraph          = dependencyGraph;
            _nodeFactory              = nodeFactory;
            _logger                   = logger;
            _debugInformationProvider = debugInformationProvider;
            _devirtualizationManager  = devirtualizationManager;

            _dependencyGraph.ComputeDependencyRoutine += ComputeDependencyNodeDependencies;
            NodeFactory.AttachToDependencyGraph(_dependencyGraph);

            var rootingService = new RootingServiceProvider(dependencyGraph, nodeFactory);

            foreach (var rootProvider in compilationRoots)
            {
                rootProvider.AddCompilationRoots(rootingService);
            }

            MetadataType globalModuleGeneratedType = nodeFactory.TypeSystemContext.GeneratedAssembly.GetGlobalModuleType();

            _typeGetTypeMethodThunks = new TypeGetTypeMethodThunkCache(globalModuleGeneratedType);
            _assemblyGetExecutingAssemblyMethodThunks = new AssemblyGetExecutingAssemblyMethodThunkCache(globalModuleGeneratedType);
            _methodBaseGetCurrentMethodThunks         = new MethodBaseGetCurrentMethodThunkCache();

            if (!(nodeFactory.InteropStubManager is EmptyInteropStubManager))
            {
                PInvokeILProvider = new PInvokeILProvider(pInvokeConfiguration, nodeFactory.InteropStubManager.InteropStateManager);
                ilProvider        = new CombinedILProvider(ilProvider, PInvokeILProvider);
            }

            _methodILCache = new ILCache(ilProvider);
        }
Ejemplo n.º 20
0
        /// <summary>
        /// Returns true if the PInvoke target should be resolved lazily.
        /// </summary>
        public static bool UseLazyResolution(MethodDesc method, string importModule, PInvokeILEmitterConfiguration configuration)
        {
            bool?forceLazyResolution = configuration.ForceLazyResolution;

            if (forceLazyResolution.HasValue)
            {
                return(forceLazyResolution.Value);
            }

            // In multi-module library mode, the WinRT p/invokes in System.Private.Interop cause linker failures
            // since we don't link against the OS libraries containing those APIs. Force them to be lazy.
            // See https://github.com/dotnet/corert/issues/2601
            string assemblySimpleName = ((IAssemblyDesc)((MetadataType)method.OwningType).Module).GetName().Name;

            if (assemblySimpleName == "System.Private.Interop")
            {
                return(true);
            }

            // Determine whether this call should be made through a lazy resolution or a static reference
            // Eventually, this should be controlled by a custom attribute (or an extension to the metadata format).
            if (importModule == "[MRT]" || importModule == "*")
            {
                return(false);
            }

            if (method.Context.Target.IsWindows)
            {
                return(!importModule.StartsWith("api-ms-win-"));
            }
            else
            {
                // Account for System.Private.CoreLib.Native / System.Globalization.Native / System.Native / etc
                return(!importModule.StartsWith("System."));
            }
        }
Ejemplo n.º 21
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));
        }
Ejemplo n.º 22
0
        /// <summary>
        /// Returns true if the PInvoke target should be resolved lazily.
        /// </summary>
        private static bool UseLazyResolution(MethodDesc method, string importModule, PInvokeILEmitterConfiguration configuration)
        {
            // TODO: Test and make this work on non-Windows
            if (!method.Context.Target.IsWindows)
            {
                return(false);
            }

            if (configuration.ForceLazyResolution)
            {
                return(true);
            }

            // Determine whether this call should be made through a lazy resolution or a static reference
            // Eventually, this should be controlled by a custom attribute (or an extension to the metadata format).
            if (importModule == "[MRT]" || importModule == "*")
            {
                return(false);
            }

            if (method.Context.Target.IsWindows)
            {
                return(!importModule.StartsWith("api-ms-win-"));
            }
            else
            {
                return(!importModule.StartsWith("System.Private."));
            }
        }
Ejemplo n.º 23
0
 public CompilationBuilder UsePInvokePolicy(PInvokeILEmitterConfiguration policy)
 {
     _pinvokePolicy = policy;
     return(this);
 }
 public AnalysisBasedInteropStubManager(InteropStateManager interopStateManager, PInvokeILEmitterConfiguration pInvokeILEmitterConfiguration, IEnumerable <DefType> typesWithStructMarshalling, IEnumerable <DefType> typesWithDelegateMarshalling)
     : base(interopStateManager, pInvokeILEmitterConfiguration)
 {
     _typesWithStructMarshalling   = typesWithStructMarshalling;
     _typesWithDelegateMarshalling = typesWithDelegateMarshalling;
 }
Ejemplo n.º 25
0
 public AnalysisBasedInteropStubManager GetInteropStubManager(InteropStateManager stateManager, PInvokeILEmitterConfiguration pinvokePolicy)
 {
     return(new AnalysisBasedInteropStubManager(stateManager, pinvokePolicy,
                                                _factory.MetadataManager.GetTypesWithStructMarshalling(),
                                                _factory.MetadataManager.GetTypesWithDelegateMarshalling()));
 }
Ejemplo n.º 26
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));
        }
 public CompilerGeneratedInteropStubManager(InteropStateManager interopStateManager, PInvokeILEmitterConfiguration pInvokeILEmitterConfiguration)
 {
     _interopStateManager           = interopStateManager;
     _pInvokeILEmitterConfiguration = pInvokeILEmitterConfiguration;
 }
Ejemplo n.º 28
0
 public UsageBasedInteropStubManager(InteropStateManager interopStateManager, PInvokeILEmitterConfiguration pInvokeILEmitterConfiguration)
     : base(interopStateManager, pInvokeILEmitterConfiguration)
 {
 }