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