File: parent\ILCompiler.Compiler\Compiler\JitHelper.cs
Web Access
Project: ILCompiler.RyuJit.csproj (ILCompiler.RyuJit)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;

using Internal.TypeSystem;
using Internal.IL;
using Internal.ReadyToRunConstants;

namespace ILCompiler
{
    internal static class JitHelper
    {
        /// <summary>
        /// Returns the managed JIT helper entrypoint, or null if the helper is implemented by a native extern function.
        /// </summary>
        public static MethodDesc GetEntryPoint(TypeSystemContext context, ReadyToRunHelper id)
        {
            switch (id)
            {
                case ReadyToRunHelper.Throw:
                case ReadyToRunHelper.Rethrow:
                case ReadyToRunHelper.ThrowExact:
                case ReadyToRunHelper.FailFast: // TODO: Report stack buffer overrun
                case ReadyToRunHelper.DebugBreak:
                case ReadyToRunHelper.WriteBarrier:
                case ReadyToRunHelper.CheckedWriteBarrier:
                case ReadyToRunHelper.BulkWriteBarrierSmall:
                case ReadyToRunHelper.WriteBarrier_EAX:
                case ReadyToRunHelper.WriteBarrier_EBX:
                case ReadyToRunHelper.WriteBarrier_ECX:
                case ReadyToRunHelper.WriteBarrier_EDI:
                case ReadyToRunHelper.WriteBarrier_ESI:
                case ReadyToRunHelper.WriteBarrier_EBP:
                case ReadyToRunHelper.CheckedWriteBarrier_EAX:
                case ReadyToRunHelper.CheckedWriteBarrier_EBX:
                case ReadyToRunHelper.CheckedWriteBarrier_ECX:
                case ReadyToRunHelper.CheckedWriteBarrier_EDI:
                case ReadyToRunHelper.CheckedWriteBarrier_ESI:
                case ReadyToRunHelper.CheckedWriteBarrier_EBP:
                case ReadyToRunHelper.NewArray:
                case ReadyToRunHelper.NewObject:
                case ReadyToRunHelper.NativeMemSet:
                case ReadyToRunHelper.Lng2Dbl:
                case ReadyToRunHelper.ULng2Dbl:
                case ReadyToRunHelper.Lng2Flt:
                case ReadyToRunHelper.ULng2Flt:
                case ReadyToRunHelper.Dbl2Lng:
                case ReadyToRunHelper.Dbl2ULng:
                case ReadyToRunHelper.DblRem:
                case ReadyToRunHelper.FltRem:
                case ReadyToRunHelper.LMul:
                case ReadyToRunHelper.LRsz:
                case ReadyToRunHelper.LRsh:
                case ReadyToRunHelper.LLsh:
                case ReadyToRunHelper.PInvokeBegin:
                case ReadyToRunHelper.PInvokeEnd:
                case ReadyToRunHelper.ReversePInvokeEnter:
                case ReadyToRunHelper.ReversePInvokeExit:
                case ReadyToRunHelper.GVMLookupForSlot:
                    return null;

                case ReadyToRunHelper.Overflow:
                    return context.GetHelperEntryPoint("ThrowHelpers"u8, "ThrowOverflowException"u8);
                case ReadyToRunHelper.RngChkFail:
                    return context.GetHelperEntryPoint("ThrowHelpers"u8, "ThrowIndexOutOfRangeException"u8);
                case ReadyToRunHelper.ThrowNullRef:
                    return context.GetHelperEntryPoint("ThrowHelpers"u8, "ThrowNullReferenceException"u8);
                case ReadyToRunHelper.ThrowDivZero:
                    return context.GetHelperEntryPoint("ThrowHelpers"u8, "ThrowDivideByZeroException"u8);
                case ReadyToRunHelper.ThrowArgumentOutOfRange:
                    return context.GetHelperEntryPoint("ThrowHelpers"u8, "ThrowArgumentOutOfRangeException"u8);
                case ReadyToRunHelper.ThrowArgument:
                    return context.GetHelperEntryPoint("ThrowHelpers"u8, "ThrowArgumentException"u8);
                case ReadyToRunHelper.ThrowPlatformNotSupported:
                    return context.GetHelperEntryPoint("ThrowHelpers"u8, "ThrowPlatformNotSupportedException"u8);
                case ReadyToRunHelper.ThrowNotImplemented:
                    return context.GetHelperEntryPoint("ThrowHelpers"u8, "ThrowNotImplementedException"u8);

                case ReadyToRunHelper.BulkWriteBarrier:
                    return context.GetCoreLibEntryPoint("System"u8, "Buffer"u8, "BulkMoveWithWriteBarrier"u8, null);
                case ReadyToRunHelper.Box:
                case ReadyToRunHelper.Box_Nullable:
                    return context.GetCoreLibEntryPoint("System.Runtime"u8, "RuntimeExports"u8, "RhBox"u8, null);
                case ReadyToRunHelper.Unbox:
                    return context.GetCoreLibEntryPoint("System.Runtime"u8, "RuntimeExports"u8, "RhUnbox2"u8, null);
                case ReadyToRunHelper.Unbox_Nullable:
                    return context.GetCoreLibEntryPoint("System.Runtime"u8, "RuntimeExports"u8, "RhUnboxNullable"u8, null);
                case ReadyToRunHelper.Unbox_TypeTest:
                    return context.GetCoreLibEntryPoint("System.Runtime"u8, "RuntimeExports"u8, "RhUnboxTypeTest"u8, null);

                case ReadyToRunHelper.NewMultiDimArr:
                    return context.GetCoreLibEntryPoint("System"u8, "Array"u8, "Ctor"u8, null);
                case ReadyToRunHelper.NewMultiDimArrRare:
                    return context.GetCoreLibEntryPoint("System"u8, "Array"u8, "CtorRare"u8, null);

                case ReadyToRunHelper.Stelem_Ref:
                    return context.GetCoreLibEntryPoint("System.Runtime"u8, "TypeCast"u8, "StelemRef"u8, null);
                case ReadyToRunHelper.Ldelema_Ref:
                    return context.GetCoreLibEntryPoint("System.Runtime"u8, "TypeCast"u8, "LdelemaRef"u8, null);

                case ReadyToRunHelper.MemCpy:
                    return context.GetCoreLibEntryPoint("System"u8, "SpanHelpers"u8, "Memmove"u8, null);
                case ReadyToRunHelper.MemSet:
                    return context.GetCoreLibEntryPoint("System"u8, "SpanHelpers"u8, "Fill"u8, null);
                case ReadyToRunHelper.MemZero:
                    return context.GetCoreLibEntryPoint("System"u8, "SpanHelpers"u8, "ClearWithoutReferences"u8, null);

                case ReadyToRunHelper.GetRuntimeTypeHandle:
                    return context.GetCoreLibEntryPoint("System"u8, "RuntimeTypeHandle"u8, "GetRuntimeTypeHandleFromMethodTable"u8, null);
                case ReadyToRunHelper.GetRuntimeType:
                    return context.GetCoreLibEntryPoint("System"u8, "Type"u8, "GetTypeFromMethodTable"u8, null);
                case ReadyToRunHelper.GetRuntimeMethodHandle:
                    return context.GetHelperEntryPoint("LdTokenHelpers"u8, "GetRuntimeMethodHandle"u8);
                case ReadyToRunHelper.GetRuntimeFieldHandle:
                    return context.GetHelperEntryPoint("LdTokenHelpers"u8, "GetRuntimeFieldHandle"u8);

                case ReadyToRunHelper.Dbl2IntOvf:
                    return context.SystemModule.GetKnownType("System"u8, "Math"u8).GetKnownMethod("ConvertToInt32Checked"u8, null);
                case ReadyToRunHelper.Dbl2UIntOvf:
                    return context.SystemModule.GetKnownType("System"u8, "Math"u8).GetKnownMethod("ConvertToUInt32Checked"u8, null);
                case ReadyToRunHelper.Dbl2LngOvf:
                    return context.SystemModule.GetKnownType("System"u8, "Math"u8).GetKnownMethod("ConvertToInt64Checked"u8, null);
                case ReadyToRunHelper.Dbl2ULngOvf:
                    return context.SystemModule.GetKnownType("System"u8, "Math"u8).GetKnownMethod("ConvertToUInt64Checked"u8, null);

                case ReadyToRunHelper.LMulOfv:
                    {
                        TypeDesc t = context.GetWellKnownType(WellKnownType.Int64);
                        return context.SystemModule.GetKnownType("System"u8, "Math"u8).GetKnownMethod("MultiplyChecked"u8,
                            new MethodSignature(MethodSignatureFlags.Static, 0, t, [t, t]));
                    }
                case ReadyToRunHelper.ULMulOvf:
                    {
                        TypeDesc t = context.GetWellKnownType(WellKnownType.UInt64);
                        return context.SystemModule.GetKnownType("System"u8, "Math"u8).GetKnownMethod("MultiplyChecked"u8,
                            new MethodSignature(MethodSignatureFlags.Static, 0, t, [t, t]));
                    }

                case ReadyToRunHelper.Div:
                    return context.SystemModule.GetKnownType("System"u8, "Math"u8).GetKnownMethod("DivInt32"u8, null);
                case ReadyToRunHelper.UDiv:
                    return context.SystemModule.GetKnownType("System"u8, "Math"u8).GetKnownMethod("DivUInt32"u8, null);
                case ReadyToRunHelper.LDiv:
                    return context.SystemModule.GetKnownType("System"u8, "Math"u8).GetKnownMethod("DivInt64"u8, null);
                case ReadyToRunHelper.ULDiv:
                    return context.SystemModule.GetKnownType("System"u8, "Math"u8).GetKnownMethod("DivUInt64"u8, null);

                case ReadyToRunHelper.Mod:
                    return context.SystemModule.GetKnownType("System"u8, "Math"u8).GetKnownMethod("ModInt32"u8, null);
                case ReadyToRunHelper.UMod:
                    return context.SystemModule.GetKnownType("System"u8, "Math"u8).GetKnownMethod("ModUInt32"u8, null);
                case ReadyToRunHelper.LMod:
                    return context.SystemModule.GetKnownType("System"u8, "Math"u8).GetKnownMethod("ModInt64"u8, null);
                case ReadyToRunHelper.ULMod:
                    return context.SystemModule.GetKnownType("System"u8, "Math"u8).GetKnownMethod("ModUInt64"u8, null);

                case ReadyToRunHelper.CheckCastAny:
                    return context.GetCoreLibEntryPoint("System.Runtime"u8, "TypeCast"u8, "CheckCastAny"u8, null);
                case ReadyToRunHelper.CheckCastInterface:
                    return context.GetCoreLibEntryPoint("System.Runtime"u8, "TypeCast"u8, "CheckCastInterface"u8, null);
                case ReadyToRunHelper.CheckCastClass:
                    return context.GetCoreLibEntryPoint("System.Runtime"u8, "TypeCast"u8, "CheckCastClass"u8, null);
                case ReadyToRunHelper.CheckCastClassSpecial:
                    return context.GetCoreLibEntryPoint("System.Runtime"u8, "TypeCast"u8, "CheckCastClassSpecial"u8, null);

                case ReadyToRunHelper.CheckInstanceAny:
                    return context.GetCoreLibEntryPoint("System.Runtime"u8, "TypeCast"u8, "IsInstanceOfAny"u8, null);
                case ReadyToRunHelper.CheckInstanceInterface:
                    return context.GetCoreLibEntryPoint("System.Runtime"u8, "TypeCast"u8, "IsInstanceOfInterface"u8, null);
                case ReadyToRunHelper.CheckInstanceClass:
                    return context.GetCoreLibEntryPoint("System.Runtime"u8, "TypeCast"u8, "IsInstanceOfClass"u8, null);
                case ReadyToRunHelper.IsInstanceOfException:
                    return context.GetCoreLibEntryPoint("System.Runtime"u8, "TypeCast"u8, "IsInstanceOfException"u8, null);

                case ReadyToRunHelper.MonitorEnter:
                    return context.GetCoreLibEntryPoint("System.Threading"u8, "Monitor"u8, "SynchronizedMethodEnter"u8, null);
                case ReadyToRunHelper.MonitorExit:
                    return context.GetCoreLibEntryPoint("System.Threading"u8, "Monitor"u8, "SynchronizedMethodExit"u8, null);

                case ReadyToRunHelper.TypeHandleToRuntimeType:
                    return context.GetCoreLibEntryPoint("System"u8, "Type"u8, "GetTypeFromMethodTableMaybeNull"u8, null);
                case ReadyToRunHelper.GetRefAny:
                    return context.GetCoreLibEntryPoint("System"u8, "TypedReference"u8, "GetRefAny"u8, null);
                case ReadyToRunHelper.TypeHandleToRuntimeTypeHandle:
                    return context.GetCoreLibEntryPoint("System"u8, "RuntimeTypeHandle"u8, "GetRuntimeTypeHandleFromMethodTable"u8, null);

                case ReadyToRunHelper.GetCurrentManagedThreadId:
                    return context.SystemModule.GetKnownType("System"u8, "Environment"u8).GetKnownMethod("get_CurrentManagedThreadId"u8, null);

                case ReadyToRunHelper.AllocContinuation:
                    return context.GetCoreLibEntryPoint("System.Runtime.CompilerServices"u8, "AsyncHelpers"u8, "AllocContinuation"u8, null);

                default:
                    throw new NotImplementedException(id.ToString());
            }
        }

        //
        // These methods are static compiler equivalent of RhGetRuntimeHelperForType
        //
        public static ReadyToRunHelper GetNewObjectHelperForType(TypeDesc type)
        {
            if (type.RequiresAlign8())
            {
                if (type.HasFinalizer)
                    return ReadyToRunHelper.NewFinalizableAlign8;

                if (type.IsValueType)
                    return ReadyToRunHelper.NewFastMisalign;

                return ReadyToRunHelper.NewFastAlign8;
            }

            if (type.HasFinalizer)
                return ReadyToRunHelper.NewFinalizable;

            return ReadyToRunHelper.NewFast;
        }
    }
}