diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ExternSymbolNode.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ExternSymbolNode.cs index 3076da18905fbe..5321b9f48b3004 100644 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ExternSymbolNode.cs +++ b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ExternSymbolNode.cs @@ -2,12 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; -using System.Diagnostics; using ILCompiler.DependencyAnalysisFramework; -using ILCompiler.DependencyAnalysis.Wasm; -using Internal.JitInterface; using Internal.Text; using Internal.TypeSystem; @@ -63,72 +60,30 @@ public override string ToString() } } - /// - /// Signature information for an extern function, used to type its import on Wasm. - /// - public readonly record struct ExternalTypeSignature( - MethodSignature Signature, - bool IsUnmanagedCallersOnly, - bool IsAsyncCall, - bool HasGenericContextArg) - { - /// - /// Signature for a native target, such as a direct P/Invoke or a native runtime helper. - /// - public static ExternalTypeSignature Unmanaged(MethodSignature signature) - => new ExternalTypeSignature(signature, IsUnmanagedCallersOnly: true, IsAsyncCall: false, HasGenericContextArg: false); - - /// - /// Signature for managed code that is referenced by name. - /// - // Keep aligned with IMethodCodeNodeWithTypeSignature - public static ExternalTypeSignature FromMethod(MethodDesc method) - => new ExternalTypeSignature( - method.Signature, - method.IsUnmanagedCallersOnly, - method.IsAsyncCall(), - method.RequiresInstMethodDescArg() || method.RequiresInstMethodTableArg() || method.IsArrayAddressMethod()); - } - /// /// Represents a function symbol that is defined externally and statically linked to the output obj file. /// public class ExternFunctionSymbolNode : ExternSymbolNode, INodeWithTypeSignature { - private readonly ExternalTypeSignature? _typeSignature; + private readonly MethodSignature _signature; + private readonly bool _isUnmanagedCallersOnly; + private readonly bool _isAsyncCall; + private readonly bool _hasGenericContextArg; + + public ExternFunctionSymbolNode(Utf8String name, MethodDesc method, bool isIndirection = false) + : this(name, method.Signature, method.IsUnmanagedCallersOnly, method.IsAsyncCall(), method.RequiresInstArg() || method.IsArrayAddressMethod(), isIndirection) + { } - public ExternFunctionSymbolNode(Utf8String name, ExternalTypeSignature? typeSignature, bool isIndirection = false) + public ExternFunctionSymbolNode(Utf8String name, MethodSignature signature, bool isUnmanagedCallersOnly, bool isAsyncCall, bool hasGenericContextArg, bool isIndirection = false) : base(name, isIndirection) - { - _typeSignature = typeSignature; - } + => (_signature, _isUnmanagedCallersOnly, _isAsyncCall, _hasGenericContextArg) = (signature, isUnmanagedCallersOnly, isAsyncCall, hasGenericContextArg); public override int ClassCode => 1452455506; - /// - /// The signature of the function, or null if it has no standard-ABI signature. - /// - public ExternalTypeSignature? TypeSignature => _typeSignature; - - MethodSignature INodeWithTypeSignature.Signature => _typeSignature.Value.Signature; - bool INodeWithTypeSignature.IsUnmanagedCallersOnly => _typeSignature.Value.IsUnmanagedCallersOnly; - bool INodeWithTypeSignature.IsAsyncCall => _typeSignature.Value.IsAsyncCall; - bool INodeWithTypeSignature.HasGenericContextArg => _typeSignature.Value.HasGenericContextArg; - - public override IEnumerable GetStaticDependencies(NodeFactory factory) - { - // Indirection cells are data, not functions, so they are not imported as functions - if (!factory.Target.IsWasm || RepresentsIndirectionCell) - return null; - - Debug.Assert(_typeSignature is not null, $"Extern function '{this}' has no known signature and cannot be imported on Wasm"); - return [new DependencyListEntry(factory.WasmFunctionImport(this), "Wasm extern functions are imported")]; - } - } - - public class AddressTakenExternFunctionSymbolNode(Utf8String name) : ExternFunctionSymbolNode(name, typeSignature: null) - { - public override int ClassCode => -45645737; + MethodSignature INodeWithTypeSignature.Signature => _signature; + bool INodeWithTypeSignature.IsUnmanagedCallersOnly => _isUnmanagedCallersOnly; + bool INodeWithTypeSignature.IsAsyncCall => _isAsyncCall; + bool INodeWithTypeSignature.HasGenericContextArg => _hasGenericContextArg; } /// diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/INodeWithTypeSignature.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/INodeWithTypeSignature.cs index 11273e1d389e73..33c41b052e3a78 100644 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/INodeWithTypeSignature.cs +++ b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/INodeWithTypeSignature.cs @@ -4,7 +4,7 @@ namespace ILCompiler.DependencyAnalysis { - public interface INodeWithTypeSignature : ISymbolDefinitionNode + public interface INodeWithTypeSignature : ISymbolNode { MethodSignature Signature { get; } bool IsUnmanagedCallersOnly { get; } @@ -12,7 +12,7 @@ public interface INodeWithTypeSignature : ISymbolDefinitionNode bool HasGenericContextArg { get; } } - public interface IMethodCodeNodeWithTypeSignature : IMethodNode, INodeWithTypeSignature + public interface IMethodCodeNodeWithTypeSignature : IMethodNode, INodeWithTypeSignature, ISymbolDefinitionNode { // Keep methods aligned with WasmLowering.GetSignature(MethodDesc) MethodSignature INodeWithTypeSignature.Signature => Method.Signature; diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/WasmFunctionImportNode.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/WasmFunctionImportNode.cs deleted file mode 100644 index 2bc2564e94e527..00000000000000 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/WasmFunctionImportNode.cs +++ /dev/null @@ -1,80 +0,0 @@ -// 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 ILCompiler.DependencyAnalysis.Wasm; -using ILCompiler.ObjectWriter; - -using Internal.Text; - -namespace ILCompiler.DependencyAnalysis -{ - // - // Represents an entry in the Wasm import section that imports an extern function. The node defines the - // extern function's symbol name, so relocations against the extern function resolve to this import. - // - public class WasmFunctionImportNode : ObjectNode, ISymbolDefinitionNode - { - private static readonly Utf8String s_moduleName = new Utf8String("env"u8); - - private readonly Utf8String _name; - private readonly INodeWithTypeSignature _signatureSource; - - /// The symbol name of the imported function. - /// The node that provides the signature of the imported function. - public WasmFunctionImportNode(Utf8String name, INodeWithTypeSignature signatureSource) - { - _name = name; - _signatureSource = signatureSource; - } - - public override bool IsShareable => true; - - public override int ClassCode => -683661982; - - public override bool StaticDependenciesAreComputed => true; - - public override ObjectNodeSection GetSection(NodeFactory factory) => WasmObjectNodeSection.ImportSection; - - protected override string GetName(NodeFactory factory) => $"Wasm Function Import: {_name}"; - - public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) - { - ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); - builder.RequireInitialAlignment(1); - builder.AddSymbol(this); - - // import ::= module:name name:name desc:importdesc - // where importdesc for a function is 0x00 typeidx - // and name is a length-prefixed UTF-8 string - EmitName(ref builder, s_moduleName); - EmitName(ref builder, _name); - builder.EmitByte((byte)WasmExternalKind.Function); - builder.EmitReloc(factory.WasmTypeNode(_signatureSource), RelocType.WASM_TYPE_INDEX_LEB); - - return builder.ToObjectData(); - } - - private static void EmitName(ref ObjectDataBuilder builder, Utf8String name) - { - // name is a length-prefixed UTF-8 string - byte[] encodedName = new byte[DwarfHelper.SizeOfULEB128((ulong)name.Length) + name.Length]; - int lengthSize = DwarfHelper.WriteULEB128(encodedName, (ulong)name.Length); - name.AsSpan().CopyTo(encodedName.AsSpan(lengthSize)); - builder.EmitBytes(encodedName); - } - - public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) - { - return _name.CompareTo(((WasmFunctionImportNode)other)._name); - } - - public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) - { - sb.Append(_name); - } - - public int Offset => 0; - } -} diff --git a/src/coreclr/tools/Common/Compiler/ObjectWriter/ObjectWriter.cs b/src/coreclr/tools/Common/Compiler/ObjectWriter/ObjectWriter.cs index 555c443a8521c6..180e170182d7b2 100644 --- a/src/coreclr/tools/Common/Compiler/ObjectWriter/ObjectWriter.cs +++ b/src/coreclr/tools/Common/Compiler/ObjectWriter/ObjectWriter.cs @@ -297,6 +297,10 @@ private protected Utf8String GetMangledName(ISymbolNode symbolNode) return symbolName; } + private protected virtual void PrepareImportsForUndefinedSymbols() + { + } + private protected virtual void EmitSectionsAndLayout() { } @@ -305,7 +309,7 @@ private protected virtual void EmitSectionsAndLayout() partial void EmitDebugInfo(IReadOnlyCollection nodes, Logger logger); - private SortedSet GetUndefinedSymbols() + private protected SortedSet GetUndefinedSymbols() { SortedSet undefinedSymbolSet = new SortedSet(); foreach (var relocationList in _sectionIndexToRelocations) @@ -358,6 +362,11 @@ public virtual void EmitObject(Stream outputFileStream, IReadOnlyCollection checksumRelocations = []; foreach (DependencyNode depNode in nodes) { + if (_nodeFactory.Target.IsWasm && depNode is INodeWithTypeSignature methodDeclaration) + { + RecordMethodDeclaration(methodDeclaration); + } + // TODO-WASM: emit symbol ranges properly when code and data are separated // Right now we still need to determine placements for some traditionally text-placed nodes, // such as DebugDirectoryEntryNode and AssemblyStubNode @@ -416,19 +425,11 @@ public virtual void EmitObject(Stream outputFileStream, IReadOnlyCollection - /// Counts an import entry that was written directly to the section by an object node. - /// - public void CompleteExternallyWrittenEntry() => CompleteEntry(); - protected override void WriteEntryCore(SectionWriter writer, WasmImport entry) { writer.EmitSymbolDefinition(new Utf8String(entry.Name)); diff --git a/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmNative.cs b/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmNative.cs index 9bc77de3a9f201..496d4139749bd2 100644 --- a/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmNative.cs +++ b/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmNative.cs @@ -83,6 +83,21 @@ internal enum WasmExportKind : byte Global = 0x03, } + internal sealed class WasmFunctionImportType : WasmImportType + { + private readonly int _typeIndex; + + public WasmFunctionImportType(int typeIndex) : base(WasmExternalKind.Function) + { + _typeIndex = typeIndex; + } + + public override int Encode(Span buffer) => DwarfHelper.WriteULEB128(buffer, (ulong)_typeIndex); + public override int EncodeSize() => (int)DwarfHelper.SizeOfULEB128((ulong)_typeIndex); + public override int EncodeRelocationCount() => 0; + public override int EncodeRelocations(Span buffer) => 0; + } + public class WasmGlobalImportType : WasmImportType { private readonly WasmValueType _valueType; diff --git a/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmObjectWriter.cs b/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmObjectWriter.cs index 570921a48552f3..7f960eddb86e20 100644 --- a/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmObjectWriter.cs +++ b/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmObjectWriter.cs @@ -8,7 +8,6 @@ using System.Linq; using ILCompiler.DependencyAnalysis; using ILCompiler.DependencyAnalysis.Wasm; -using ILCompiler.DependencyAnalysisFramework; using ILCompiler.ObjectWriter.WasmInstructions; using Internal.JitInterface; using Internal.Text; @@ -63,6 +62,7 @@ internal abstract partial class WasmObjectWriter : ObjectWriter /// logical WebAssembly indices and must not be used to resolve index relocations. /// private protected Dictionary _definedSymbols; + private readonly Dictionary _externalFunctions = new(); private int[] _sectionEmitOrder; /// @@ -88,6 +88,25 @@ protected WasmObjectWriter(NodeFactory factory, ObjectWritingOptions options, Ou { } + private protected override void PrepareImportsForUndefinedSymbols() + { + // Imports must be registered before layout consumes function indices. Only actual unresolved + // references require imports; a marked extern can also resolve to a definition in this object. + foreach (Utf8String name in GetUndefinedSymbols()) + { + if (_externalFunctions.TryGetValue(name, out INodeWithTypeSignature function)) + { + if (function.Signature is null) + { + throw new InvalidOperationException($"Extern function '{name}' has no known signature and cannot be imported on Wasm"); + } + + int typeIndex = RegisterSignature(WasmLowering.GetSignature(function).FuncType); + WriteImport(new WasmImport("env", name.ToString(), new WasmFunctionImportType(typeIndex))); + } + } + } + private protected static void EmitWasmHeader(Stream outputFileStream) { outputFileStream.Write("\0asm"u8); @@ -142,6 +161,14 @@ private protected override void RecordMethodSignature(WasmTypeNode signature) } private protected override void RecordMethodDeclaration(INodeWithTypeSignature node) + { + if (node is not ISymbolDefinitionNode && !node.RepresentsIndirectionCell) + { + _externalFunctions.TryAdd(GetMangledName(node), node); + } + } + + private protected override void RecordMethodDefinition(INodeWithTypeSignature node) { WriteSignatureIndexForFunction(node); Utf8String methodName = new(node.GetMangledName(_nodeFactory.NameMangler)); @@ -159,14 +186,6 @@ private protected override void RecordMethodDeclaration(INodeWithTypeSignature n } } - private protected override void RecordFunctionImport(WasmFunctionImportNode import) - { - // Assign the import's index in the function index space. The import entry itself is emitted - // by the node's own data. - _wasmSymbolManager.AddImport(new Utf8String(import.GetMangledName(_nodeFactory.NameMangler)), WasmIndexSpace.Function); - GetOrCreateSection(WasmObjectNodeSection.ImportSection, out _).CompleteExternallyWrittenEntry(); - } - private void RecordFunclets(INodeWithFunclets nodeWithFunclets) { FuncletKind[] funcletKinds = nodeWithFunclets.GetFuncletKinds(); @@ -329,7 +348,7 @@ private protected void WriteGlobal( private protected void RegisterFunctionSymbol(Utf8String name) => _wasmSymbolManager.AddDefinition(name, WasmIndexSpace.Function); - // This effectively recreates the logic of RecordMethodBody/RecordMethodDeclaration, but for manually inserted stubs that are not + // This effectively recreates the logic of RecordMethodDefinition, but for manually inserted stubs that are not // represented by nodes in the dependency graph. // TODO-Wasm: for maintability, we should try and push some of this into the dependency graph when we do more stub generation. private protected void RegisterStubIndexAndSignature(WasmFuncType signature) diff --git a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs index 4c9d12a4714e2e..2da01e22f707c0 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs @@ -426,7 +426,6 @@ public enum ReadyToRunHelper ResolveInterfaceMethodFast, ResolveInterfaceMethod, - NyiLdVirtFtn, TlsGetAddr, } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 615f5c91ccf897..ace489f8250afa 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -760,6 +760,7 @@ private void CompileMethodCleanup() private const int handleMultiplier = 8; private const int handleBase = 0x420000; + private void* InvalidHandle => (void*)(handleBase - handleMultiplier); private IntPtr ObjectToHandle(object obj) { @@ -785,6 +786,7 @@ private IntPtr ObjectToHandleUnchecked(object obj) private object HandleToObject(void* handle) { Debug.Assert(handle != null); + Debug.Assert(handle != InvalidHandle); int index = ((int)handle - handleBase) / handleMultiplier; return _handleToObject[index]; } diff --git a/src/coreclr/tools/Common/JitInterface/WasmLowering.cs b/src/coreclr/tools/Common/JitInterface/WasmLowering.cs index cedf930dba1e7a..dab10296c1c529 100644 --- a/src/coreclr/tools/Common/JitInterface/WasmLowering.cs +++ b/src/coreclr/tools/Common/JitInterface/WasmLowering.cs @@ -613,29 +613,6 @@ public static unsafe WasmSignature GetSignature(MethodSignature signature, CORIN return GetSignature(signature, GetLoweringFlags(callSig)); } - public static WasmSignature GetSignature(MethodSignature signature, bool hasGenericContextArg, bool isAsyncCall, bool isUnmanagedCallersOnly) - { - return GetSignature(signature, GetLoweringFlags(hasGenericContextArg, isAsyncCall, isUnmanagedCallersOnly)); - } - - public static LoweringFlags GetLoweringFlags(bool hasGenericContextArg, bool isAsyncCall, bool isUnmanagedCallersOnly) - { - LoweringFlags flags = 0; - if (hasGenericContextArg) - { - flags |= LoweringFlags.HasGenericContextArg; - } - if (isAsyncCall) - { - flags |= LoweringFlags.IsAsyncCall; - } - if (isUnmanagedCallersOnly) - { - flags |= LoweringFlags.IsUnmanagedCallersOnly; - } - return flags; - } - public static LoweringFlags GetLoweringFlags(MethodDesc method) { LoweringFlags flags = 0; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs index c32b79fe1636fd..cad0906405c123 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs @@ -368,7 +368,7 @@ public ISymbolNode ComputeConstantLookup(ReadyToRunHelperId lookupKind, object t case ReadyToRunHelperId.ObjectAllocator: { var type = (TypeDesc)targetOfLookup; - return NodeFactory.KnownExternFunction(JitHelper.GetNewObjectHelperForType(type)); + return NodeFactory.ReadyToRunHelper(JitHelper.GetNewObjectHelperForType(type)); } default: diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilerGeneratedInteropStubManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilerGeneratedInteropStubManager.cs index 16cb8dcc6e8bb8..5074b26c6cbbc5 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilerGeneratedInteropStubManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilerGeneratedInteropStubManager.cs @@ -15,18 +15,17 @@ namespace ILCompiler /// public abstract class CompilerGeneratedInteropStubManager : InteropStubManager { - private readonly PInvokeILEmitterConfiguration _pInvokeILEmitterConfiguration; internal readonly InteropStateManager _interopStateManager; public CompilerGeneratedInteropStubManager(InteropStateManager interopStateManager, PInvokeILEmitterConfiguration pInvokeILEmitterConfiguration) + : base(pInvokeILEmitterConfiguration) { _interopStateManager = interopStateManager; - _pInvokeILEmitterConfiguration = pInvokeILEmitterConfiguration; } public sealed override PInvokeILProvider CreatePInvokeILProvider() { - return new PInvokeILProvider(_pInvokeILEmitterConfiguration, _interopStateManager); + return new PInvokeILProvider(_configuration, _interopStateManager); } public sealed override void AddToReadyToRunHeader(ReadyToRunHeaderNode header, NodeFactory nodeFactory, ExternalReferencesTableNode commonFixupsTableNode) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExternMethodSymbolNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExternMethodSymbolNode.cs index 35b96088a3bf71..973e1574a90525 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExternMethodSymbolNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExternMethodSymbolNode.cs @@ -17,7 +17,7 @@ public sealed class ExternMethodSymbolNode : ExternFunctionSymbolNode, IMethodNo public ExternMethodSymbolNode(NodeFactory factory, MethodDesc method, bool isUnboxing = false) : base(isUnboxing ? UnboxingStubNode.GetMangledName(factory.NameMangler, method) : factory.NameMangler.GetMangledMethodName(method), - ExternalTypeSignature.FromMethod(method)) + method) { _method = method; } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericLookupResult.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericLookupResult.cs index 2a9b9fb2346a88..6aafd57815e65f 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericLookupResult.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericLookupResult.cs @@ -962,7 +962,7 @@ public override ISymbolNode GetTarget(NodeFactory factory, GenericLookupResultCo return null; } Debug.Assert(!instantiatedType.IsCanonicalSubtype(CanonicalFormKind.Any)); - return factory.KnownExternFunction(JitHelper.GetNewObjectHelperForType(instantiatedType)); + return factory.ReadyToRunHelper(JitHelper.GetNewObjectHelperForType(instantiatedType)); } public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/KnownExternFunctions.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/KnownExternFunctions.cs index c4d8c7bac0f787..150636eb0bfd88 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/KnownExternFunctions.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/KnownExternFunctions.cs @@ -88,7 +88,6 @@ public static Utf8String GetName(ReadyToRunHelper function, TargetDetails target ReadyToRunHelper.StackProbe => "RhpStackProbe", ReadyToRunHelper.GCPoll => "RhpGcPoll", - ReadyToRunHelper.NyiLdVirtFtn => "NYI_LDVIRTFTN", ReadyToRunHelper.TlsGetAddr => "__tls_get_addr", _ => throw new NotImplementedException(function.ToString()) @@ -104,7 +103,7 @@ public static Utf8String GetName(ReadyToRunHelper function, TargetDetails target /// Extern function nodes are shared by name, so when a function is also reachable through a direct /// P/Invoke (e.g. CoreLib's memset), its signature must exactly match that P/Invoke's signature. /// - public static ExternalTypeSignature? GetTypeSignature(ReadyToRunHelper function, TypeSystemContext context) + public static MethodSignature GetSignature(ReadyToRunHelper function, TypeSystemContext context) { TypeDesc voidType = context.GetWellKnownType(WellKnownType.Void); TypeDesc voidPointerType = voidType.MakePointerType(); @@ -117,23 +116,22 @@ public static Utf8String GetName(ReadyToRunHelper function, TargetDetails target TypeDesc singleType = context.GetWellKnownType(WellKnownType.Single); TypeDesc doubleType = context.GetWellKnownType(WellKnownType.Double); - // All of these use the unmanaged calling convention, like the native FCIMPLs that implement most of them. - ExternalTypeSignature UnmanagedSignature(TypeDesc returnType, params TypeDesc[] parameters) => - ExternalTypeSignature.Unmanaged(new MethodSignature(MethodSignatureFlags.Static, 0, returnType, parameters)); + MethodSignature MakeSignature(TypeDesc returnType, params TypeDesc[] parameters) => + new MethodSignature(MethodSignatureFlags.Static, 0, returnType, parameters); return function switch { - ReadyToRunHelper.Throw => UnmanagedSignature(voidType, objectType), - ReadyToRunHelper.ThrowExact => UnmanagedSignature(voidType, objectType), + ReadyToRunHelper.Throw => MakeSignature(voidType, objectType), + ReadyToRunHelper.ThrowExact => MakeSignature(voidType, objectType), - ReadyToRunHelper.Rethrow => UnmanagedSignature(voidType), + ReadyToRunHelper.Rethrow => MakeSignature(voidType), - ReadyToRunHelper.FailFast => UnmanagedSignature(voidType), + ReadyToRunHelper.FailFast => MakeSignature(voidType), - ReadyToRunHelper.DebugBreak => UnmanagedSignature(voidType), + ReadyToRunHelper.DebugBreak => MakeSignature(voidType), - ReadyToRunHelper.WriteBarrier => UnmanagedSignature(voidType, nativeIntType, objectType), - ReadyToRunHelper.CheckedWriteBarrier => UnmanagedSignature(voidType, nativeIntType, objectType), + ReadyToRunHelper.WriteBarrier => MakeSignature(voidType, nativeIntType, objectType), + ReadyToRunHelper.CheckedWriteBarrier => MakeSignature(voidType, nativeIntType, objectType), ReadyToRunHelper.WriteBarrier_EAX or ReadyToRunHelper.WriteBarrier_EBX or @@ -148,46 +146,46 @@ ReadyToRunHelper.CheckedWriteBarrier_EDI or ReadyToRunHelper.CheckedWriteBarrier_ESI or ReadyToRunHelper.CheckedWriteBarrier_EBP => null, - ReadyToRunHelper.BulkWriteBarrierSmall => UnmanagedSignature(voidType, nativeIntType, nativeIntType, nativeUIntType), + ReadyToRunHelper.BulkWriteBarrierSmall => MakeSignature(voidType, nativeIntType, nativeIntType, nativeUIntType), - ReadyToRunHelper.NewArray => UnmanagedSignature(objectType, nativeIntType, nativeIntType), - ReadyToRunHelper.NewObject => UnmanagedSignature(objectType, nativeIntType), + ReadyToRunHelper.NewArray => MakeSignature(objectType, nativeIntType, nativeIntType), + ReadyToRunHelper.NewObject => MakeSignature(objectType, nativeIntType), - ReadyToRunHelper.NewFast => UnmanagedSignature(objectType, nativeIntType), - ReadyToRunHelper.NewFinalizable => UnmanagedSignature(objectType, nativeIntType), - ReadyToRunHelper.NewFastAlign8 => UnmanagedSignature(objectType, nativeIntType), - ReadyToRunHelper.NewFinalizableAlign8 => UnmanagedSignature(objectType, nativeIntType), - ReadyToRunHelper.NewFastMisalign => UnmanagedSignature(objectType, nativeIntType), + ReadyToRunHelper.NewFast => MakeSignature(objectType, nativeIntType), + ReadyToRunHelper.NewFinalizable => MakeSignature(objectType, nativeIntType), + ReadyToRunHelper.NewFastAlign8 => MakeSignature(objectType, nativeIntType), + ReadyToRunHelper.NewFinalizableAlign8 => MakeSignature(objectType, nativeIntType), + ReadyToRunHelper.NewFastMisalign => MakeSignature(objectType, nativeIntType), - ReadyToRunHelper.NewPtrArrayFast => UnmanagedSignature(objectType, nativeIntType, nativeIntType), - ReadyToRunHelper.NewArrayFastAlign8 => UnmanagedSignature(objectType, nativeIntType, nativeIntType), - ReadyToRunHelper.NewArrayFast => UnmanagedSignature(objectType, nativeIntType, nativeIntType), + ReadyToRunHelper.NewPtrArrayFast => MakeSignature(objectType, nativeIntType, nativeIntType), + ReadyToRunHelper.NewArrayFastAlign8 => MakeSignature(objectType, nativeIntType, nativeIntType), + ReadyToRunHelper.NewArrayFast => MakeSignature(objectType, nativeIntType, nativeIntType), - ReadyToRunHelper.NativeMemSet => UnmanagedSignature(voidPointerType, voidPointerType, int32Type, nativeUIntType), - ReadyToRunHelper.DblRem => UnmanagedSignature(doubleType, doubleType, doubleType), - ReadyToRunHelper.FltRem => UnmanagedSignature(singleType, singleType, singleType), + ReadyToRunHelper.NativeMemSet => MakeSignature(voidPointerType, voidPointerType, int32Type, nativeUIntType), + ReadyToRunHelper.DblRem => MakeSignature(doubleType, doubleType, doubleType), + ReadyToRunHelper.FltRem => MakeSignature(singleType, singleType, singleType), - ReadyToRunHelper.Lng2Dbl => UnmanagedSignature(doubleType, int64Type), - ReadyToRunHelper.ULng2Dbl => UnmanagedSignature(doubleType, uint64Type), - ReadyToRunHelper.Lng2Flt => UnmanagedSignature(singleType, int64Type), - ReadyToRunHelper.ULng2Flt => UnmanagedSignature(singleType, uint64Type), - ReadyToRunHelper.Dbl2Lng => UnmanagedSignature(int64Type, doubleType), - ReadyToRunHelper.Dbl2ULng => UnmanagedSignature(uint64Type, doubleType), + ReadyToRunHelper.Lng2Dbl => MakeSignature(doubleType, int64Type), + ReadyToRunHelper.ULng2Dbl => MakeSignature(doubleType, uint64Type), + ReadyToRunHelper.Lng2Flt => MakeSignature(singleType, int64Type), + ReadyToRunHelper.ULng2Flt => MakeSignature(singleType, uint64Type), + ReadyToRunHelper.Dbl2Lng => MakeSignature(int64Type, doubleType), + ReadyToRunHelper.Dbl2ULng => MakeSignature(uint64Type, doubleType), - ReadyToRunHelper.LMul => UnmanagedSignature(int64Type, int64Type, int64Type), - ReadyToRunHelper.LRsz => UnmanagedSignature(uint64Type, uint64Type, int32Type), - ReadyToRunHelper.LRsh => UnmanagedSignature(int64Type, int64Type, int32Type), - ReadyToRunHelper.LLsh => UnmanagedSignature(int64Type, int64Type, int32Type), + ReadyToRunHelper.LMul => MakeSignature(int64Type, int64Type, int64Type), + ReadyToRunHelper.LRsz => MakeSignature(uint64Type, uint64Type, int32Type), + ReadyToRunHelper.LRsh => MakeSignature(int64Type, int64Type, int32Type), + ReadyToRunHelper.LLsh => MakeSignature(int64Type, int64Type, int32Type), - ReadyToRunHelper.PInvokeBegin => UnmanagedSignature(voidType, nativeIntType), - ReadyToRunHelper.PInvokeEnd => UnmanagedSignature(voidType, nativeIntType), - ReadyToRunHelper.ReversePInvokeEnter => UnmanagedSignature(voidType, nativeIntType), - ReadyToRunHelper.ReversePInvokeExit => UnmanagedSignature(voidType, nativeIntType), + ReadyToRunHelper.PInvokeBegin => MakeSignature(voidType, nativeIntType), + ReadyToRunHelper.PInvokeEnd => MakeSignature(voidType, nativeIntType), + ReadyToRunHelper.ReversePInvokeEnter => MakeSignature(voidType, nativeIntType), + ReadyToRunHelper.ReversePInvokeExit => MakeSignature(voidType, nativeIntType), - ReadyToRunHelper.GCPoll => UnmanagedSignature(voidType), + ReadyToRunHelper.GCPoll => MakeSignature(voidType), - ReadyToRunHelper.GVMLookupForSlot => UnmanagedSignature(nativeIntType, objectType, nativeIntType), - ReadyToRunHelper.ResolveInterfaceMethod => UnmanagedSignature(nativeIntType, objectType, nativeIntType), + ReadyToRunHelper.GVMLookupForSlot => MakeSignature(nativeIntType, objectType, nativeIntType), + ReadyToRunHelper.ResolveInterfaceMethod => MakeSignature(nativeIntType, objectType, nativeIntType), ReadyToRunHelper.ResolveInterfaceMethodFast => throw new NotImplementedException( $"{nameof(ReadyToRunHelper.ResolveInterfaceMethodFast)} is not implemented by the runtime."), @@ -196,8 +194,6 @@ ReadyToRunHelper.InterfaceDispatch or ReadyToRunHelper.StackProbe => null, - ReadyToRunHelper.NyiLdVirtFtn => null, - ReadyToRunHelper.TlsGetAddr => null, _ => throw new NotImplementedException(function.ToString()) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs index fc23ef4f4f01f5..22e2fe649d7f52 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs @@ -272,13 +272,17 @@ private void CreateNodeCaches() return new FieldRvaDataNode(key); }); - _externFunctionSymbols = new NodeCache(static (ExternFunctionKey key) => + _directPInvokes = new NodeCache((MethodDesc key) => { - return new ExternFunctionSymbolNode(key.Name, key.TypeSignature); + Utf8String externName = new Utf8String(InteropStubManager.GetDirectCallExternName(key)); + externName = NameMangler.NodeMangler.ExternMethod(externName, key); + + return new ExternFunctionSymbolNode(externName, key.Signature, isUnmanagedCallersOnly: true, isAsyncCall: false, hasGenericContextArg: false); }); + _externIndirectFunctionSymbols = new NodeCache((Utf8String name) => { - return new ExternFunctionSymbolNode(name, typeSignature: null, isIndirection: true); + return new ExternFunctionSymbolNode(name, signature: null, false, false, false, isIndirection: true); }); _externDataSymbols = new NodeCache((Utf8String name) => { @@ -432,6 +436,14 @@ private void CreateNodeCaches() return new InterfaceUseNode(type); }); + _r2rHelpers = new NodeCache((ReadyToRunHelper id) => + { + return new ExternFunctionSymbolNode( + KnownExternFunctions.GetName(id, TypeSystemContext.Target), + KnownExternFunctions.GetSignature(id, TypeSystemContext), + isUnmanagedCallersOnly: true, isAsyncCall: false, hasGenericContextArg: false); + }); + _readyToRunHelpers = new NodeCache(CreateReadyToRunHelperNode); _genericReadyToRunHelpersFromDict = new NodeCache(CreateGenericLookupFromDictionaryNode); @@ -627,9 +639,6 @@ private void CreateNodeCaches() return new AnalysisCharacteristicNode(c); }); - _wasmFunctionImports = new NodeCache((Utf8String name) => - throw new InvalidOperationException($"Wasm function import '{name}' must be created from an extern function")); - _wasmTypeNodes = new NodeCache(key => { return new WasmTypeNode(key); @@ -998,31 +1007,6 @@ internal ISymbolNode GenericVariance(GenericVarianceDetails details) return _genericVariances.GetOrAdd(details); } - private NodeCache _externFunctionSymbols; - - /// - /// Gets the node for an extern function. Nodes are keyed by name alone, so every reference to the - /// same symbol (e.g. a JIT helper and a direct P/Invoke to the same native function) shares one node, - /// and on Wasm all references must agree on its lowered function type. - /// - private ExternFunctionSymbolNode ExternFunctionSymbol(Utf8String name, ExternalTypeSignature? typeSignature) - { - ExternFunctionSymbolNode node = _externFunctionSymbols.GetOrAdd(new ExternFunctionKey(name, typeSignature)); - // Distinct managed types can describe the same native ABI. In the a case like shared pinvoke source with - // different managed enum types, fall back to checking the lowered ABI is at least the same. - Debug.Assert(!Target.IsWasm || node.TypeSignature == typeSignature || - Equals( - WasmLowering.GetSignature(node), - typeSignature.HasValue ? - WasmLowering.GetSignature(typeSignature.Value.Signature, - typeSignature.Value.HasGenericContextArg, - typeSignature.Value.IsAsyncCall, - typeSignature.Value.IsUnmanagedCallersOnly) - : null), - $"Conflicting signatures for extern function '{name}'"); - return node; - } - private NodeCache _externIndirectFunctionSymbols; public ISortableSymbolNode ExternIndirectFunctionSymbol(Utf8String name) @@ -1030,9 +1014,10 @@ public ISortableSymbolNode ExternIndirectFunctionSymbol(Utf8String name) return _externIndirectFunctionSymbols.GetOrAdd(name); } - public ExternFunctionSymbolNode DirectPInvokeTarget(Utf8String externName, MethodDesc pInvoke) + private NodeCache _directPInvokes; + public ExternFunctionSymbolNode DirectPInvokeTarget(MethodDesc method) { - return ExternFunctionSymbol(externName, ExternalTypeSignature.Unmanaged(pInvoke.Signature)); + return _directPInvokes.GetOrAdd(method); } private NodeCache _externDataSymbols; @@ -1042,13 +1027,6 @@ public ISortableSymbolNode ExternDataSymbol(Utf8String name) return _externDataSymbols.GetOrAdd(name); } - public ExternFunctionSymbolNode KnownExternFunction(ReadyToRunHelper function) - { - return ExternFunctionSymbol( - KnownExternFunctions.GetName(function, TypeSystemContext.Target), - KnownExternFunctions.GetTypeSignature(function, TypeSystemContext)); - } - public ISortableSymbolNode ExternVariable(Utf8String name) { Utf8String mangledName = NameMangler.NodeMangler.ExternVariable(name); @@ -1458,6 +1436,13 @@ public DependencyNodeCore InterfaceUse(TypeDesc type) return _interfaceUses.GetOrAdd(type); } + private NodeCache _r2rHelpers; + + public ISymbolNode ReadyToRunHelper(ReadyToRunHelper id) + { + return _r2rHelpers.GetOrAdd(id); + } + private NodeCache _readyToRunHelpers; public ISymbolNode ReadyToRunHelper(ReadyToRunHelperId id, object target) @@ -1657,13 +1642,6 @@ public AnalysisCharacteristicNode AnalysisCharacteristic(string ch) private NodeCache _wasmTypeNodes; - private NodeCache _wasmFunctionImports; - - public WasmFunctionImportNode WasmFunctionImport(ExternFunctionSymbolNode node) - { - return _wasmFunctionImports.GetOrAdd(node.Name, name => new WasmFunctionImportNode(name, node)); - } - // TODO-Wasm: Do not use WasmFuncType directly as the key for better // memory efficiency on lookup public WasmTypeNode WasmTypeNode(MethodDesc desc) @@ -1889,24 +1867,6 @@ public SerializedFrozenObjectKey(MetadataType ownerType, int allocationSiteId, T public override int GetHashCode() => HashCode.Combine(OwnerType.GetHashCode(), AllocationSiteId); } - private struct ExternFunctionKey : IEquatable - { - public readonly Utf8String Name; - - // Used to create the node, but not part of the key's identity - public readonly ExternalTypeSignature? TypeSignature; - - public ExternFunctionKey(Utf8String name, ExternalTypeSignature? typeSignature) - { - Name = name; - TypeSignature = typeSignature; - } - - public bool Equals(ExternFunctionKey other) => Name.Equals(other.Name); - public override bool Equals(object obj) => obj is ExternFunctionKey other && Equals(other); - public override int GetHashCode() => Name.GetHashCode(); - } - private struct MethodILKey : IEquatable { public readonly MethodIL MethodIL; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeImportMethodNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeImportMethodNode.cs index 37ab15a2d7d188..a7169798eb15b4 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeImportMethodNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeImportMethodNode.cs @@ -10,13 +10,13 @@ namespace ILCompiler.DependencyAnalysis /// /// Represents a method that is imported from the runtime library. /// - public class RuntimeImportMethodNode : ExternFunctionSymbolNode, IMethodNode, ISymbolDefinitionNode + public class RuntimeImportMethodNode : ExternFunctionSymbolNode, IMethodNode { private MethodDesc _method; public RuntimeImportMethodNode(MethodDesc method, NameMangler nameMangler) : base(nameMangler.NodeMangler.ExternMethod(new Utf8String(((EcmaMethod)method).GetRuntimeImportName()), method), - ExternalTypeSignature.FromMethod(method)) + method) { _method = method; } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs index 523e4a1e29ecef..99a7c4eaae0e84 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs @@ -132,7 +132,7 @@ protected override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bo if (targetMethod.OwningType.IsInterface) { encoder.EmitMOV(encoder.TargetRegister.Arg1, factory.DispatchCell(targetMethod)); - encoder.EmitJMP(factory.KnownExternFunction(ReadyToRunHelper.ResolveInterfaceMethod)); + encoder.EmitJMP(factory.ReadyToRunHelper(ReadyToRunHelper.ResolveInterfaceMethod)); } else { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunHelperNode.cs index 0510734bb7d575..05db57041dd5db 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunHelperNode.cs @@ -147,7 +147,7 @@ protected override void EmitCode(NodeFactory factory, ref ARM64Emitter encoder, if (targetMethod.OwningType.IsInterface) { encoder.EmitMOV(encoder.TargetRegister.Arg1, factory.DispatchCell(targetMethod)); - encoder.EmitJMP(factory.KnownExternFunction(ReadyToRunHelper.ResolveInterfaceMethod)); + encoder.EmitJMP(factory.ReadyToRunHelper(ReadyToRunHelper.ResolveInterfaceMethod)); } else { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_LoongArch64/LoongArch64ReadyToRunHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_LoongArch64/LoongArch64ReadyToRunHelperNode.cs index 52ed3590c522d6..026f6f44b5deaf 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_LoongArch64/LoongArch64ReadyToRunHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_LoongArch64/LoongArch64ReadyToRunHelperNode.cs @@ -139,7 +139,7 @@ protected override void EmitCode(NodeFactory factory, ref LoongArch64Emitter enc if (targetMethod.OwningType.IsInterface) { encoder.EmitMOV(encoder.TargetRegister.Arg1, factory.DispatchCell(targetMethod)); - encoder.EmitJMP(factory.KnownExternFunction(ReadyToRunHelper.ResolveInterfaceMethod)); + encoder.EmitJMP(factory.ReadyToRunHelper(ReadyToRunHelper.ResolveInterfaceMethod)); } else { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_RiscV64/RiscV64ReadyToRunHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_RiscV64/RiscV64ReadyToRunHelperNode.cs index 4e928be256d8d3..7f4fb096c8575c 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_RiscV64/RiscV64ReadyToRunHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_RiscV64/RiscV64ReadyToRunHelperNode.cs @@ -137,7 +137,7 @@ protected override void EmitCode(NodeFactory factory, ref RiscV64Emitter encoder if (targetMethod.OwningType.IsInterface) { encoder.EmitMOV(encoder.TargetRegister.Arg1, factory.DispatchCell(targetMethod)); - encoder.EmitJMP(factory.KnownExternFunction(ReadyToRunHelper.ResolveInterfaceMethod)); + encoder.EmitJMP(factory.ReadyToRunHelper(ReadyToRunHelper.ResolveInterfaceMethod)); } else { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_Wasm/WasmReadyToRunHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_Wasm/WasmReadyToRunHelperNode.cs index cbdabcdc3b881f..5a263202b44612 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_Wasm/WasmReadyToRunHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_Wasm/WasmReadyToRunHelperNode.cs @@ -179,7 +179,7 @@ protected override void EmitCode(NodeFactory factory, ref WasmEmitter encoder, b MethodDesc targetMethod = (MethodDesc)Target; if (targetMethod.OwningType.IsInterface) { - ISymbolNode helper = factory.KnownExternFunction(ReadyToRunHelper.ResolveInterfaceMethod); + ISymbolNode helper = factory.ReadyToRunHelper(ReadyToRunHelper.ResolveInterfaceMethod); expressions.Add(Local.Get(1)); expressions.Add(I32.ConstRVA(factory.DispatchCell(targetMethod))); expressions.Add(ControlFlow.ReturnCall(helper)); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs index 8557152e5fe943..d87e3c902d507b 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs @@ -152,7 +152,7 @@ protected override void EmitCode(NodeFactory factory, ref X64Emitter encoder, bo if (targetMethod.OwningType.IsInterface) { encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.DispatchCell(targetMethod)); - encoder.EmitJMP(factory.KnownExternFunction(ReadyToRunHelper.ResolveInterfaceMethod)); + encoder.EmitJMP(factory.ReadyToRunHelper(ReadyToRunHelper.ResolveInterfaceMethod)); } else { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X86/X86ReadyToRunHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X86/X86ReadyToRunHelperNode.cs index a809bc0f4c52da..c4bec4b48661b9 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X86/X86ReadyToRunHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X86/X86ReadyToRunHelperNode.cs @@ -161,7 +161,7 @@ protected override void EmitCode(NodeFactory factory, ref X86Emitter encoder, bo if (targetMethod.OwningType.IsInterface) { encoder.EmitMOV(encoder.TargetRegister.Arg1, factory.DispatchCell(targetMethod)); - encoder.EmitJMP(factory.KnownExternFunction(ReadyToRunHelper.ResolveInterfaceMethod)); + encoder.EmitJMP(factory.ReadyToRunHelper(ReadyToRunHelper.ResolveInterfaceMethod)); } else { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/EmptyInteropStubManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/EmptyInteropStubManager.cs index 53dc3e7143a53d..67f7213a7dfa74 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/EmptyInteropStubManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/EmptyInteropStubManager.cs @@ -14,6 +14,19 @@ namespace ILCompiler /// public sealed class EmptyInteropStubManager : InteropStubManager { + private class DummyConfiguration : PInvokeILEmitterConfiguration + { + public override bool GenerateDirectCall(MethodDesc method, out string externName) + { + externName = method.GetPInvokeMethodMetadata().Name; + return true; + } + } + + public EmptyInteropStubManager() + : base(new DummyConfiguration()) + { } + public override PInvokeILProvider CreatePInvokeILProvider() { return null; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILScanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILScanner.cs index ed0a36ccbb5f9f..214994a58b0dea 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILScanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILScanner.cs @@ -194,7 +194,7 @@ protected override Helper CreateValueFromKey(ReadyToRunHelper key) { MethodDesc methodDesc = JitHelper.GetEntryPoint(_compilation.TypeSystemContext, key); ISymbolNode entryPoint = methodDesc is null - ? _compilation.NodeFactory.KnownExternFunction(key) + ? _compilation.NodeFactory.ReadyToRunHelper(key) : _compilation.NodeFactory.MethodEntrypoint(methodDesc); return new Helper(key, entryPoint); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/InteropStubManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/InteropStubManager.cs index 3ea2357cda46cf..5b7290272113ec 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/InteropStubManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/InteropStubManager.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; + using Internal.IL; using Internal.TypeSystem; using ILCompiler.DependencyAnalysis; @@ -14,6 +16,13 @@ namespace ILCompiler /// public abstract class InteropStubManager : ICompilationRootProvider { + protected readonly PInvokeILEmitterConfiguration _configuration; + + public InteropStubManager(PInvokeILEmitterConfiguration configuration) + { + _configuration = configuration; + } + public abstract void AddDependenciesDueToMethodCodePresence(ref DependencyList dependencies, NodeFactory factory, MethodDesc method); public abstract void AddInterestingInteropConstructedTypeDependencies(ref DependencyList dependencies, NodeFactory factory, TypeDesc type); @@ -33,5 +42,13 @@ public virtual void AddToReadyToRunHeader(ReadyToRunHeaderNode header, NodeFacto public virtual void AddCompilationRoots(IRootingServiceProvider rootProvider) { } + + public string GetDirectCallExternName(MethodDesc method) + { + bool directCall = _configuration.GenerateDirectCall(method, out string externName); + Debug.Assert(directCall); + Debug.Assert(externName != null); + return externName; + } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/ObjectWriter.Aot.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/ObjectWriter.Aot.cs index aff785577bb8d9..4be2bc2740591e 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/ObjectWriter.Aot.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/ObjectWriter.Aot.cs @@ -158,7 +158,7 @@ partial void EmitUnwindInfoForNode(ObjectNode node, Utf8String currentSymbolName partial void HandleControlFlowForRelocation(ISymbolNode relocTarget, Utf8String relocSymbolName) { - if (relocTarget is IMethodNode or AssemblyStubNode or AddressTakenExternFunctionSymbolNode) + if (relocTarget is IMethodNode or AssemblyStubNode) { // For now consider all method symbols address taken. // We could restrict this in the future to those that are referenced from diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/Stubs/PInvokeILProvider.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/Stubs/PInvokeILProvider.cs index 3b6c61264f1302..30c6f3d2434b5d 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/Stubs/PInvokeILProvider.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/Stubs/PInvokeILProvider.cs @@ -36,13 +36,5 @@ public MethodDesc GetCalliStub(MethodSignature signature, ModuleDesc moduleConte { return _interopStateManager.GetPInvokeCalliStub(signature, moduleContext); } - - public string GetDirectCallExternName(MethodDesc method) - { - bool directCall = _pInvokeILEmitterConfiguration.GenerateDirectCall(method, out string externName); - Debug.Assert(directCall); - Debug.Assert(externName != null); - return externName; - } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj index 55e76266df2f5b..55003585495e5f 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj @@ -330,7 +330,6 @@ - diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs index 58d17ff74d511e..c36307dd5c3cce 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs @@ -1500,12 +1500,6 @@ public Utf8String GetSymbolAlternateName(ISymbolNode node, out bool isHidden) private NodeCache _wasmTypeNodes; - public WasmFunctionImportNode WasmFunctionImport(ExternFunctionSymbolNode node) - { - // ReadyToRun does not reference extern functions - throw new NotSupportedException(); - } - private NodeCache _wasmMethodRelativeVirtualIPs; private readonly struct WasmUnboxingStubKey : IEquatable diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj index 47bf7c3876eebd..b0dd89c86f575d 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj @@ -111,7 +111,6 @@ - diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 4a5510c5f9cf1b..61fbdf35a206f4 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -631,30 +631,30 @@ private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum) id = ReadyToRunHelper.NewObject; break; case CorInfoHelpFunc.CORINFO_HELP_NEWSFAST: - return _compilation.NodeFactory.KnownExternFunction(ReadyToRunHelper.NewFast); + return _compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelper.NewFast); case CorInfoHelpFunc.CORINFO_HELP_NEWSFAST_FINALIZE: - return _compilation.NodeFactory.KnownExternFunction(ReadyToRunHelper.NewFinalizable); + return _compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelper.NewFinalizable); case CorInfoHelpFunc.CORINFO_HELP_NEWSFAST_ALIGN8: - return _compilation.NodeFactory.KnownExternFunction(ReadyToRunHelper.NewFastAlign8); + return _compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelper.NewFastAlign8); case CorInfoHelpFunc.CORINFO_HELP_NEWSFAST_ALIGN8_FINALIZE: - return _compilation.NodeFactory.KnownExternFunction(ReadyToRunHelper.NewFinalizableAlign8); + return _compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelper.NewFinalizableAlign8); case CorInfoHelpFunc.CORINFO_HELP_NEWSFAST_ALIGN8_VC: - return _compilation.NodeFactory.KnownExternFunction(ReadyToRunHelper.NewFastMisalign); + return _compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelper.NewFastMisalign); case CorInfoHelpFunc.CORINFO_HELP_NEWARR_1_DIRECT: id = ReadyToRunHelper.NewArray; break; case CorInfoHelpFunc.CORINFO_HELP_NEWARR_1_PTR: - return _compilation.NodeFactory.KnownExternFunction(ReadyToRunHelper.NewPtrArrayFast); + return _compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelper.NewPtrArrayFast); case CorInfoHelpFunc.CORINFO_HELP_NEWARR_1_ALIGN8: - return _compilation.NodeFactory.KnownExternFunction(ReadyToRunHelper.NewArrayFastAlign8); + return _compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelper.NewArrayFastAlign8); case CorInfoHelpFunc.CORINFO_HELP_NEWARR_1_VC: - return _compilation.NodeFactory.KnownExternFunction(ReadyToRunHelper.NewArrayFast); + return _compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelper.NewArrayFast); case CorInfoHelpFunc.CORINFO_HELP_STACK_PROBE: - return _compilation.NodeFactory.KnownExternFunction(ReadyToRunHelper.StackProbe); + return _compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelper.StackProbe); case CorInfoHelpFunc.CORINFO_HELP_POLL_GC: - return _compilation.NodeFactory.KnownExternFunction(ReadyToRunHelper.GCPoll); + return _compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelper.GCPoll); case CorInfoHelpFunc.CORINFO_HELP_LMUL: id = ReadyToRunHelper.LMul; @@ -800,10 +800,10 @@ private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum) if ((_compilation._compilationOptions & RyuJitCompilationOptions.ControlFlowGuardAnnotations) != 0 // Not implemented on x86: https://github.com/dotnet/runtime/issues/99516 && _compilation.NodeFactory.TypeSystemContext.Target.Architecture != TargetArchitecture.X86) - return _compilation.NodeFactory.KnownExternFunction(ReadyToRunHelper.InterfaceDispatchGuarded); - return _compilation.NodeFactory.KnownExternFunction(ReadyToRunHelper.InterfaceDispatch); + return _compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelper.InterfaceDispatchGuarded); + return _compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelper.InterfaceDispatch); case CorInfoHelpFunc.CORINFO_HELP_INTERFACELOOKUP_FOR_SLOT: - return _compilation.NodeFactory.KnownExternFunction(ReadyToRunHelper.ResolveInterfaceMethodFast); + return _compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelper.ResolveInterfaceMethodFast); case CorInfoHelpFunc.CORINFO_HELP_GETREFANY: id = ReadyToRunHelper.GetRefAny; @@ -825,7 +825,7 @@ private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum) MethodDesc methodDesc = JitHelper.GetEntryPoint(_compilation.TypeSystemContext, id); return methodDesc is null - ? _compilation.NodeFactory.KnownExternFunction(id) + ? _compilation.NodeFactory.ReadyToRunHelper(id) : _compilation.NodeFactory.MethodEntrypoint(methodDesc); } @@ -1674,7 +1674,8 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO // If this is LDVIRTFTN of an interface method that is part of a verifiable delegate creation sequence, // RyuJIT is not going to use this value. pResult->exactContextNeedsRuntimeLookup = false; - pResult->codePointerOrStubLookup.constLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.KnownExternFunction(ReadyToRunHelper.NyiLdVirtFtn)); + pResult->codePointerOrStubLookup.constLookup.addr = InvalidHandle; + pResult->codePointerOrStubLookup.constLookup.accessType = InfoAccessType.IAT_VALUE; } else { @@ -1940,11 +1941,7 @@ private unsafe HRESULT allocPgoInstrumentationBySchema(CORINFO_METHOD_STRUCT_* f private void getAddressOfPInvokeTarget(CORINFO_METHOD_STRUCT_* method, ref CORINFO_CONST_LOOKUP pLookup) { MethodDesc md = HandleToObject(method); - - Utf8String externName = new Utf8String(_compilation.PInvokeILProvider.GetDirectCallExternName(md)); - externName = _compilation.NodeFactory.NameMangler.NodeMangler.ExternMethod(externName, md); - - pLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.DirectPInvokeTarget(externName, md)); + pLookup = CreateConstLookupToSymbol(_compilation.NodeFactory.DirectPInvokeTarget(md)); } private void getGSCookie(IntPtr* pCookieVal, IntPtr** ppCookieVal) @@ -2495,7 +2492,7 @@ private void getThreadLocalStaticInfo_NativeAOT(CORINFO_THREAD_STATIC_INFO_NATIV pInfo->tlsIndexObject = CreateConstLookupToSymbol(_compilation.NodeFactory.ExternDataSymbol(new Utf8String("_tls_index"u8))); pInfo->tlsRootObject = CreateConstLookupToSymbol(_compilation.NodeFactory.TlsRoot); pInfo->threadStaticBaseSlow = CreateConstLookupToSymbol(_compilation.NodeFactory.HelperEntrypoint(HelperEntrypoint.GetInlinedThreadStaticBaseSlow)); - pInfo->tlsGetAddrFtnPtr = CreateConstLookupToSymbol(_compilation.NodeFactory.KnownExternFunction(ReadyToRunHelper.TlsGetAddr)); + pInfo->tlsGetAddrFtnPtr = CreateConstLookupToSymbol(_compilation.NodeFactory.ReadyToRunHelper(ReadyToRunHelper.TlsGetAddr)); } #pragma warning disable CA1822 // Mark members as static