File: Compiler\DependencyAnalysis\ReadyToRun\Target_ARM64\ImportThunk.cs
Web Access
Project: src\src\runtime\src\coreclr\tools\aot\ILCompiler.ReadyToRun\ILCompiler.ReadyToRun.csproj (ILCompiler.ReadyToRun)
// 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 System.Diagnostics;
using ILCompiler.DependencyAnalysis.ARM64;

namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
    /// <summary>
    /// This node emits a thunk calling DelayLoad_Helper with a given instance signature
    /// to populate its indirection cell.
    /// </summary>
    public partial class ImportThunk : ISymbolNode
    {
        protected override void EmitCode(NodeFactory factory, ref ARM64Emitter instructionEncoder, bool relocsOnly)
        {
            if (_thunkKind == ImportThunkKind.Eager)
            {
                instructionEncoder.EmitJMP(_helperCell);
                return;
            }
            if (relocsOnly)
            {
                // When doing relocs only, we don't need to generate the actual instructions
                // as they will be ignored. Just emit the module import load and jump so we record the dependencies.
                instructionEncoder.EmitADRP(Register.X1, factory.ModuleImport);
                instructionEncoder.EmitLDR(Register.X1, Register.X1, factory.ModuleImport);
                instructionEncoder.EmitJMP(_helperCell);
                return;
            }

            switch (_thunkKind)
            {
                case ImportThunkKind.DelayLoadHelper:
                case ImportThunkKind.DelayLoadHelperWithExistingIndirectionCell:
                case ImportThunkKind.VirtualStubDispatch:

                    // x11 contains indirection cell
                    // Do nothing x11 contains our first param

                    // movz x9, #index
                    int index = _containingImportSection.IndexFromBeginningOfArray;
                    instructionEncoder.EmitMOV(Register.X9, checked((ushort)index));

                    // Move Module* -> x10
                    // adrp x10, ModuleImport
                    instructionEncoder.EmitADRP(Register.X10, factory.ModuleImport);

                    // ldr x10, [x10, ModuleImport page offset]
                    instructionEncoder.EmitLDR(Register.X10, Register.X10, factory.ModuleImport);
                    break;

                case ImportThunkKind.Lazy:

                    // Move Module* -> x1
                    // adrp x1, ModuleImport
                    instructionEncoder.EmitADRP(Register.X1, factory.ModuleImport);

                    // ldr x1, [x1, ModuleImport page offset]
                    instructionEncoder.EmitLDR(Register.X1, Register.X1, factory.ModuleImport);
                    break;

                default:
                    throw new NotImplementedException();
            }

            // branch to helper
            instructionEncoder.EmitJMP(_helperCell);
        }
    }
}