File: src\runtime\src\libraries\System.Private.CoreLib\src\System\Reflection\ModifiedFunctionPointerType.cs
Web Access
Project: src\runtime\src\coreclr\nativeaot\System.Private.CoreLib\src\System.Private.CoreLib.csproj (System.Private.CoreLib)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Threading;

namespace System.Reflection
{
    internal sealed partial class ModifiedFunctionPointerType : ModifiedType
    {
        private Type[]? _parameterTypes;
        private Type? _returnType;

        internal ModifiedFunctionPointerType(Type unmodifiedType, TypeSignature typeSignature)
            : base(unmodifiedType, typeSignature)
        {
            Debug.Assert(unmodifiedType.IsFunctionPointer);
        }

        public override Type GetFunctionPointerReturnType()
        {
            return _returnType ?? Initialize();

            Type Initialize()
            {
                Interlocked.CompareExchange(ref _returnType, GetTypeParameter(UnmodifiedType.GetFunctionPointerReturnType(), 0), null);
                return _returnType;
            }
        }

        public override Type[] GetFunctionPointerParameterTypes()
        {
            return (Type[])(_parameterTypes ?? Initialize()).Clone();

            Type[] Initialize()
            {
                Type[] parameterTypes = UnmodifiedType.GetFunctionPointerParameterTypes();
                for (int i = 0; i < parameterTypes.Length; i++)
                {
                    parameterTypes[i] = GetTypeParameter(parameterTypes[i], i + 1);
                }
                Interlocked.CompareExchange(ref _parameterTypes, parameterTypes, null);
                return _parameterTypes!;
            }
        }

        public override Type[] GetFunctionPointerCallingConventions()
        {
            ArrayBuilder<Type> builder = default;

            // Normalize the calling conventions by manufacturing a type.
            switch (GetCallingConventionFromFunctionPointer())
            {
                case SignatureCallingConvention.Cdecl:
                    builder.Add(typeof(CallConvCdecl));
                    break;
                case SignatureCallingConvention.StdCall:
                    builder.Add(typeof(CallConvStdcall));
                    break;
                case SignatureCallingConvention.ThisCall:
                    builder.Add(typeof(CallConvThiscall));
                    break;
                case SignatureCallingConvention.FastCall:
                    builder.Add(typeof(CallConvFastcall));
                    break;
                case SignatureCallingConvention.Unmanaged:
                    // For the above cases, there will be no other custom calling convention modifiers.
                    foreach (Type type in GetFunctionPointerReturnType().GetOptionalCustomModifiers())
                    {
                        if (type.FullName!.StartsWith(Type.CallingConventionTypePrefix, StringComparison.Ordinal))
                        {
                            builder.Add(type);
                        }
                    }
                    break;
            }

            return builder.ToArray();
        }
    }
}