// 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.Text; using Internal.TypeSystem; using ILCompiler.DependencyAnalysis.X64; 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 { protected override void EmitCode(NodeFactory factory, ref X64Emitter instructionEncoder, bool relocsOnly) { switch (_thunkKind) { case ImportThunkKind.Eager: break; case ImportThunkKind.DelayLoadHelper: // xor eax, eax instructionEncoder.EmitZeroReg(Register.RAX); if (!relocsOnly) { // push table index instructionEncoder.EmitPUSH((sbyte)_containingImportSection.IndexFromBeginningOfArray); } // push [module] instructionEncoder.EmitPUSH(factory.ModuleImport); break; case ImportThunkKind.DelayLoadHelperWithExistingIndirectionCell: // Indirection cell is already in rax which will be first arg. Used for fast tailcalls. if (!relocsOnly) { // push table index instructionEncoder.EmitPUSH((sbyte)_containingImportSection.IndexFromBeginningOfArray); } // push [module] instructionEncoder.EmitPUSH(factory.ModuleImport); break; case ImportThunkKind.VirtualStubDispatch: // mov rax, r11 - this is the most general case as the value of R11 also propagates // to the new method after the indirection cell has been updated so the cell content // can be repeatedly modified as needed during virtual / interface dispatch. instructionEncoder.EmitMOV(Register.RAX, Register.R11); if (!relocsOnly) { // push table index instructionEncoder.EmitPUSH((sbyte)_containingImportSection.IndexFromBeginningOfArray); } // push [module] instructionEncoder.EmitPUSH(factory.ModuleImport); break; case ImportThunkKind.Lazy: instructionEncoder.EmitMOV(factory.Target.OperatingSystem == TargetOS.Windows ? Register.RDX : Register.RSI, factory.ModuleImport); break; default: throw new NotImplementedException(); } instructionEncoder.EmitJMP(_helperCell); } } } |