public static EmbeddedSignatureData[] EncodeAsEmbeddedSignatureData(this UnmanagedCallingConventions callingConventions, TypeSystemContext context) { UnmanagedCallingConventions convention = (callingConventions & UnmanagedCallingConventions.CallingConventionMask); UnmanagedCallingConventions modifiers = (callingConventions & UnmanagedCallingConventions.ModifiersMask); UnmanagedCallingConventions platformDefault = GetPlatformDefaultUnmanagedCallingConvention(context); int count = ((convention != platformDefault) ? 1 : 0) + BitOperations.PopCount((uint)modifiers); if (count == 0) { return(null); } EmbeddedSignatureData[] ret = new EmbeddedSignatureData[count]; int index = 0; if (convention != platformDefault) { ret[index++] = CreateCallConvEmbeddedSignatureData(context, convention switch { UnmanagedCallingConventions.Cdecl => "CallConvCdecl", UnmanagedCallingConventions.Stdcall => "CallConvStdcall", UnmanagedCallingConventions.Fastcall => "CallConvFastcall", UnmanagedCallingConventions.Thiscall => "CallConvThiscall", _ => throw new InvalidProgramException() });
private static UnmanagedCallingConventions AccumulateCallingConventions(UnmanagedCallingConventions existing, MetadataType newConvention) { if (newConvention.Namespace != "System.Runtime.CompilerServices") { return(existing); } UnmanagedCallingConventions?addedCallConv = newConvention.Name switch { "CallConvCdecl" => UnmanagedCallingConventions.Cdecl, "CallConvStdcall" => UnmanagedCallingConventions.Stdcall, "CallConvFastcall" => UnmanagedCallingConventions.Fastcall, "CallConvThiscall" => UnmanagedCallingConventions.Thiscall, "CallConvSuppressGCTransition" => UnmanagedCallingConventions.IsSuppressGcTransition, "CallConvMemberFunction" => UnmanagedCallingConventions.IsMemberFunction, _ => null }; if (addedCallConv == null) { return(existing); } // Do not allow accumulating additional calling conventions - only modifiers are allowed if ((addedCallConv.Value & UnmanagedCallingConventions.CallingConventionMask) != 0 && (existing & UnmanagedCallingConventions.CallingConventionMask) != 0) { ThrowHelper.ThrowInvalidProgramException(ExceptionStringID.InvalidProgramMultipleCallConv); } return(existing | addedCallConv.Value); }
private static UnmanagedCallingConventions GetUnmanagedCallingConventionFromAttribute(CustomAttributeValue <TypeDesc> attributeWithCallConvsArray, TypeSystemContext context) { ImmutableArray <CustomAttributeTypedArgument <TypeDesc> > callConvArray = default; foreach (var arg in attributeWithCallConvsArray.NamedArguments) { if (arg.Name == "CallConvs") { callConvArray = (ImmutableArray <CustomAttributeTypedArgument <TypeDesc> >)arg.Value; } } UnmanagedCallingConventions result = 0; if (!callConvArray.IsDefault) { foreach (CustomAttributeTypedArgument <TypeDesc> type in callConvArray) { if (type.Value is not MetadataType mdType) { continue; } result = AccumulateCallingConventions(result, mdType); } } // If we haven't found a calling convention in the attribute, the calling convention is 'unmanaged'. if ((result & UnmanagedCallingConventions.CallingConventionMask) == 0) { result |= GetPlatformDefaultUnmanagedCallingConvention(context); } return(result); }
/// <summary> /// Gets calling conventions for a standalone ('calli') method signature. /// </summary> public static UnmanagedCallingConventions GetStandaloneMethodSignatureCallingConventions(this MethodSignature signature) { // If calling convention is anything but 'unmanaged', or there's no modifiers, we can bitcast to our enum and we're done. MethodSignatureFlags unmanagedCallconv = signature.Flags & MethodSignatureFlags.UnmanagedCallingConventionMask; if (unmanagedCallconv != MethodSignatureFlags.UnmanagedCallingConvention) { Debug.Assert((int)MethodSignatureFlags.UnmanagedCallingConventionCdecl == (int)UnmanagedCallingConventions.Cdecl && (int)MethodSignatureFlags.UnmanagedCallingConventionStdCall == (int)UnmanagedCallingConventions.Stdcall && (int)MethodSignatureFlags.UnmanagedCallingConventionThisCall == (int)UnmanagedCallingConventions.Thiscall); Debug.Assert(unmanagedCallconv != 0); return((UnmanagedCallingConventions)unmanagedCallconv); } // If calling convention is 'unmanaged', there might be more metadata in the custom modifiers. UnmanagedCallingConventions result = 0; if (signature.HasEmbeddedSignatureData) { foreach (EmbeddedSignatureData data in signature.GetEmbeddedSignatureData()) { if (data.kind != EmbeddedSignatureDataKind.OptionalCustomModifier) { continue; } // We only care about the modifiers for the return type. These will be at the start of // the signature, so will be first in the array of embedded signature data. if (data.index != MethodSignature.IndexOfCustomModifiersOnReturnType) { break; } if (data.type is not MetadataType mdType) { continue; } result = AccumulateCallingConventions(result, mdType); } } // If we haven't found a calling convention in the modifiers, the calling convention is 'unmanaged'. if ((result & UnmanagedCallingConventions.CallingConventionMask) == 0) { result |= GetPlatformDefaultUnmanagedCallingConvention(signature.Context); } return(result); }
/// <summary> /// Creates a new <see cref="CILMethodSignature"/> which has all its information specified from the parameters of this method. /// </summary> /// <param name="ctx">The current <see cref="CILReflectionContext"/>.</param> /// <param name="currentModule">The current <see cref="CILModule"/>.</param> /// <param name="callingConventions">The <see cref="UnmanagedCallingConventions"/> for the method signature.</param> /// <param name="returnType">The return type for the method signature.</param> /// <param name="returnParamMods">The <see cref="CILCustomModifier"/>s for the method signature. May be <c>null</c> if no modifiers should be used.</param> /// <param name="parameters">The parameter information for the method signature. Each element is a tuple containing <see cref="CILCustomModifier"/>s and type for the parameter. Custom modifiers array may be <c>null</c> if no modifiers should be used.</param> /// <returns>A new <see cref="CILMethodSignature"/>.</returns> /// <exception cref="NullReferenceException">If <paramref name="ctx"/> is <c>null</c>.</exception> /// <exception cref="ArgumentNullException">If <paramref name="currentModule"/>, <paramref name="returnType"/> or any of the types within <paramref name="parameters"/> is <c>null</c>.</exception> /// <seealso cref="CILMethodSignature"/> public static CILMethodSignature NewMethodSignature(this CILReflectionContext ctx, CILModule currentModule, UnmanagedCallingConventions callingConventions, CILTypeBase returnType, CILCustomModifier[] returnParamMods, params Tuple <CILCustomModifier[], CILTypeBase>[] parameters) { if (ctx == null) { // Throw nullref explicitly for consistency (since it is 'this' parameter) // Because CILMethodSignatureImpl ctor throws ArgumentNullException throw new NullReferenceException(); } var cctx = (CILReflectionContextImpl)ctx; return(new CILMethodSignatureImpl(ctx, currentModule, callingConventions, returnParamMods == null ? null : cctx.CollectionsFactory.NewListProxyFromParams(returnParamMods), returnType, parameters.Select(t => Tuple.Create(t.Item1 == null ? null : cctx.CollectionsFactory.NewListProxyFromParams(t.Item1), t.Item2)).ToList(), null)); }
/// <summary> /// Creates a new <see cref="CILMethodSignature"/> which has all its information specified from the parameters of this method. /// </summary> /// <param name="ctx">The current <see cref="CILReflectionContext"/>.</param> /// <param name="currentModule">The current <see cref="CILModule"/>.</param> /// <param name="callingConventions">The <see cref="UnmanagedCallingConventions"/> for the method signature.</param> /// <param name="returnType">The return type for the method signature.</param> /// <param name="paramTypes">The types of the parameters.</param> /// <returns>A new <see cref="CILMethodSignature"/>.</returns> /// <exception cref="NullReferenceException">If <paramref name="ctx"/> is <c>null</c>.</exception> /// <exception cref="ArgumentNullException">If <paramref name="currentModule"/>, <paramref name="returnType"/> or any of the types within <paramref name="paramTypes"/> is <c>null</c>.</exception> /// <seealso cref="CILMethodSignature"/> public static CILMethodSignature NewMethodSignature(this CILReflectionContext ctx, CILModule currentModule, UnmanagedCallingConventions callingConventions, CILTypeBase returnType, params CILTypeBase[] paramTypes) { return(NewMethodSignature(ctx, currentModule, callingConventions, returnType, null, paramTypes.Select(pt => Tuple.Create((CILCustomModifier[])null, pt)).ToArray())); }
/// <summary> /// Creates a new <see cref="CILMethodSignature"/> that captures the signature of the current method. /// </summary> /// <param name="method">The <see cref="CILMethodBase"/>.</param> /// <param name="callConventions">The <see cref="UnmanagedCallingConventions"/> for the resulting <see cref="CILMethodSignature"/>.</param> /// <returns>The new <see cref="CILMethodSignature"/> that captures the signature of the <paramref name="method"/>.</returns> /// <exception cref="NullReferenceException">If <paramref name="method"/> is <c>null</c>.</exception> /// <exception cref="ArgumentNullException">If any type of parameters is <c>null</c>.</exception> public static CILMethodSignature CreateMethodSignature(this CILMethodBase method, UnmanagedCallingConventions callConventions = UnmanagedCallingConventions.C) { return(new CILMethodSignatureImpl( method.ReflectionContext, method.DeclaringType.Module, callConventions | (UnmanagedCallingConventions)(method.CallingConvention & CallingConventions.HasThis & CallingConventions.ExplicitThis), MethodKind.Method == method.MethodKind ? ((CILReflectionContextImpl)method.ReflectionContext).CollectionsFactory.NewListProxyFromParams(((CILMethod)method).ReturnParameter.CustomModifiers.ToArray()) : null, MethodKind.Method == method.MethodKind ? ((CILMethod)method).ReturnParameter.ParameterType : method.DeclaringType.Module.AssociatedMSCorLibModule.GetTypeByName("System.Void"), method.Parameters.Select(param => Tuple.Create(((CILReflectionContextImpl)method.ReflectionContext).CollectionsFactory.NewListProxyFromParams(param.CustomModifiers.ToArray()), param.ParameterType)).ToList(), method )); }