|
// 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 Internal.Text;
using Internal.TypeSystem;
using Internal.ReadyToRunConstants;
namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
/// <summary>
/// This class represents a single indirection cell used to call delay load helpers.
/// </summary>
public class DelayLoadHelperImport : Import
{
private readonly ReadyToRunHelper _helper;
private readonly bool _useVirtualCall;
private readonly bool _useJumpableStub;
private readonly ISymbolNode _delayLoadHelper;
public bool UseVirtualCall => _useVirtualCall;
public bool UseJumpableStub => _useJumpableStub;
public ReadyToRunHelper HelperId => _helper;
public DelayLoadHelperImport(
NodeFactory factory,
ImportSectionNode importSectionNode,
ReadyToRunHelper helper,
Signature instanceSignature,
bool useVirtualCall = false,
bool useJumpableStub = false,
MethodDesc callingMethod = null)
: base(importSectionNode, instanceSignature, callingMethod)
{
_helper = helper;
_useVirtualCall = useVirtualCall;
_useJumpableStub = useJumpableStub;
if (factory.Target.Architecture == TargetArchitecture.Wasm32)
{
if (instanceSignature is GenericLookupSignature)
{
// Generic lookups are resolved via eager fixups and don't need import thunks
_delayLoadHelper = null;
}
else
{
_delayLoadHelper = factory.WasmImportThunkPortableEntrypoint(this);
}
}
else
{
_delayLoadHelper = factory.ImportThunk(helper, importSectionNode, useVirtualCall, useJumpableStub);
}
}
public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append("DelayLoadHelperImport("u8);
if (_useVirtualCall)
{
sb.Append("[VSD] "u8);
}
if (_useJumpableStub)
{
sb.Append("[JMP] "u8);
}
sb.Append(_helper.ToString());
sb.Append(") -> "u8);
ImportSignature.AppendMangledName(nameMangler, sb);
if (CallingMethod != null)
{
sb.Append(" @ "u8);
sb.Append(nameMangler.GetMangledMethodName(CallingMethod));
}
}
public override int ClassCode => 667823013;
public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly)
{
if (_delayLoadHelper is not null)
{
// This needs to be an empty target pointer since it will be filled in with Module*
// when loaded by CoreCLR
dataBuilder.EmitReloc(_delayLoadHelper,
factory.Target.PointerSize == 4 ? RelocType.IMAGE_REL_BASED_HIGHLOW : RelocType.IMAGE_REL_BASED_DIR64);
}
else
{
// Eager fixups don't need a delay load helper thunk — emit a zero pointer
dataBuilder.EmitNaturalInt(0);
}
if (Table.EntrySize == (factory.Target.PointerSize * 2))
{
dataBuilder.EmitNaturalInt(0);
}
else
{
Debug.Assert(Table.EntrySize == factory.Target.PointerSize);
}
}
public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
{
if (_delayLoadHelper is not null)
{
return new DependencyListEntry[]
{
new DependencyListEntry(_delayLoadHelper, "Delay load helper thunk for ready-to-run fixup import"),
new DependencyListEntry(ImportSignature, "Signature for ready-to-run fixup import"),
};
}
return new DependencyListEntry[]
{
new DependencyListEntry(ImportSignature, "Signature for ready-to-run fixup import"),
};
}
public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
DelayLoadHelperImport otherNode = (DelayLoadHelperImport)other;
int result = _useJumpableStub.CompareTo(otherNode._useJumpableStub);
if (result != 0)
return result;
result = _useVirtualCall.CompareTo(otherNode._useVirtualCall);
if (result != 0)
return result;
result = _helper.CompareTo(otherNode._helper);
if (result != 0)
return result;
return base.CompareToImpl(other, comparer);
}
}
}
|