Esempio n. 1
0
        /// <summary>
        /// Returns true if <paramref name="method"/> requires a stub to be generated.
        /// </summary>
        public static bool IsStubRequired(MethodDesc method)
        {
            Debug.Assert(method.IsPInvoke);

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

            TypeDesc returnType = method.Signature.ReturnType;
            if (!IsBlittableType(returnType) && !returnType.IsVoid)
                return true;

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

            if (UseLazyResolution(method, method.GetPInvokeMethodMetadata().Module))
            {
                return true;
            }

            return false;
        }
        private PInvokeMarshallingILEmitter(MethodDesc targetMethod)
        {
            Debug.Assert(targetMethod.IsPInvoke);
            Debug.Assert(RequiresMarshalling(targetMethod));

            _targetMethod = targetMethod;
            _importMetadata = targetMethod.GetPInvokeMethodMetadata();

            _emitter = null;
            _marshallingCodeStream = null;
        }
Esempio n. 3
0
        private PInvokeILEmitter(MethodDesc targetMethod)
        {
            Debug.Assert(targetMethod.IsPInvoke);

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

            _emitter = null;
            _marshallingCodeStream = null;
            _returnValueMarshallingCodeStream = null;
            _unmarshallingCodestream = null;
        }
        public static UnmanagedCallingConventions GetPInvokeMethodCallingConventions(this MethodDesc method)
        {
            Debug.Assert(method.IsPInvoke);

            UnmanagedCallingConventions result;

            if (method is Internal.IL.Stubs.PInvokeTargetNativeMethod pinvokeTarget)
            {
                method = pinvokeTarget.Target;
            }

            MethodSignatureFlags unmanagedCallConv = method.GetPInvokeMethodMetadata().Flags.UnmanagedCallingConvention;

            if (unmanagedCallConv != MethodSignatureFlags.None)
            {
                Debug.Assert((int)MethodSignatureFlags.UnmanagedCallingConventionCdecl == (int)UnmanagedCallingConventions.Cdecl &&
                             (int)MethodSignatureFlags.UnmanagedCallingConventionStdCall == (int)UnmanagedCallingConventions.Stdcall &&
                             (int)MethodSignatureFlags.UnmanagedCallingConventionThisCall == (int)UnmanagedCallingConventions.Thiscall);
                result = (UnmanagedCallingConventions)unmanagedCallConv;
            }
            else
            {
                CustomAttributeValue <TypeDesc>?unmanagedCallConvAttribute = ((EcmaMethod)method).GetDecodedCustomAttribute("System.Runtime.InteropServices", "UnmanagedCallConvAttribute");
                if (unmanagedCallConvAttribute != null)
                {
                    result = GetUnmanagedCallingConventionFromAttribute(unmanagedCallConvAttribute.Value, method.Context);
                }
                else
                {
                    result = GetPlatformDefaultUnmanagedCallingConvention(method.Context);
                }
            }

            if (method.HasCustomAttribute("System.Runtime.InteropServices", "SuppressGCTransitionAttribute"))
            {
                result |= UnmanagedCallingConventions.IsSuppressGcTransition;
            }

            return(result);
        }
Esempio n. 5
0
        /// <summary>
        /// Gets a value indicating whether GC transition should be suppressed on the given p/invoke.
        /// </summary>
        public static bool IsSuppressGCTransition(this MethodDesc method)
        {
            Debug.Assert(method.IsPInvoke);

            // Check SuppressGCTransition attribute
            if (method.HasSuppressGCTransitionAttribute())
            {
                return(true);
            }

            MethodSignatureFlags unmanagedCallConv = method.GetPInvokeMethodMetadata().Flags.UnmanagedCallingConvention;

            if (unmanagedCallConv != MethodSignatureFlags.None)
            {
                return(false);
            }

            if (!(method is Internal.TypeSystem.Ecma.EcmaMethod ecmaMethod))
            {
                return(false);
            }

            // Check UnmanagedCallConv attribute
            System.Reflection.Metadata.CustomAttributeValue <TypeDesc>?unmanagedCallConvAttribute = ecmaMethod.GetDecodedCustomAttribute("System.Runtime.InteropServices", "UnmanagedCallConvAttribute");
            if (unmanagedCallConvAttribute == null)
            {
                return(false);
            }

            foreach (DefType defType in unmanagedCallConvAttribute.Value.EnumerateCallConvsFromAttribute())
            {
                if (defType.Name == "CallConvSuppressGCTransition")
                {
                    return(true);
                }
            }

            return(false);
        }
Esempio n. 6
0
        private string CompileSpecialMethod(MethodDesc method, SpecialMethodKind kind)
        {
            StringBuilder builder = new StringBuilder();
            switch (kind)
            {
                case SpecialMethodKind.PInvoke:
                case SpecialMethodKind.RuntimeImport:
                    {
                        EcmaMethod ecmaMethod = method as EcmaMethod;

                        string importName = kind == SpecialMethodKind.PInvoke ?
                            method.GetPInvokeMethodMetadata().Name : ecmaMethod.GetAttributeStringValue("System.Runtime", "RuntimeImportAttribute");

                        if (importName == null)
                            importName = method.Name;

                        MethodSignature methodSignature = method.Signature;
                        bool slotCastRequired = false;

                        MethodSignature externCSignature;
                        if (_externCSignatureMap.TryGetValue(importName, out externCSignature))
                        {
                            slotCastRequired = !externCSignature.Equals(method.Signature);
                        }
                        else
                        {
                            _externCSignatureMap.Add(importName, methodSignature);
                            externCSignature = methodSignature;
                        }

                        builder.AppendLine(GetCppMethodDeclaration(method, true));
                        builder.AppendLine("{");

                        if (slotCastRequired)
                        {
                            AppendSlotTypeDef(builder, method);
                        }

                        if (!method.Signature.ReturnType.IsVoid)
                        {
                            builder.Append("return ");
                        }

                        if (slotCastRequired)
                            builder.Append("((__slot__" + GetCppMethodName(method) + ")");
                        builder.Append("::");
                        builder.Append(importName);
                        if (slotCastRequired)
                            builder.Append(")");

                        builder.Append("(");
                        builder.Append(GetCppMethodCallParamList(method));
                        builder.AppendLine(");");
                        builder.AppendLine("}");

                        return builder.ToString();
                    }

                default:
                    return GetCppMethodDeclaration(method, true) + " { throw 0xC000C000; }" + Environment.NewLine;
            }
        }
Esempio n. 7
0
        private string CompileSpecialMethod(MethodDesc method, SpecialMethodKind kind)
        {
            StringBuilder builder = new StringBuilder();
            switch (kind)
            {
                case SpecialMethodKind.PInvoke:
                case SpecialMethodKind.RuntimeImport:
                    {
                        EcmaMethod ecmaMethod = method as EcmaMethod;

                        string importName = kind == SpecialMethodKind.PInvoke ?
                            method.GetPInvokeMethodMetadata().Name : ecmaMethod.GetAttributeStringValue("System.Runtime", "RuntimeImportAttribute");

                        if (importName == null)
                            importName = method.Name;

                        // TODO: hacky special-case
                        if (importName != "memmove" && importName != "malloc") // some methods are already declared by the CRT headers
                        {
                            builder.AppendLine(GetCppMethodDeclaration(method, false, importName));
                        }
                        builder.AppendLine(GetCppMethodDeclaration(method, true));
                        builder.AppendLine("{");
                        builder.Append("    ");
                        if (GetCppSignatureTypeName(method.Signature.ReturnType) != "void")
                        {
                            builder.Append("return ");
                        }

                        builder.AppendLine("::" + importName + "(" + GetCppMethodCallParamList(method) + ");");
                        builder.AppendLine("}");

                        return builder.ToString();
                    }

                default:
                    // TODO: hacky special-case
                    if (method.Name == "BlockCopy")
                        return null;

                    return GetCppMethodDeclaration(method, true) + " { throw 0xC000C000; }" + Environment.NewLine;
            }
        }