Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,14 @@ public sealed override IEnumerable<DependencyListEntry> GetStaticDependencies(No
}
}

if (factory.Target.IsWasm && this is IMethodCodeNodeWithTypeSignature wasmMethodCodeNode)
if (factory.Target.IsWasm && this is INodeWithTypeSignature wasmCodeNode)
{
dependencies ??= new DependencyList();

WasmTypeNode wasmTypeNode = factory.WasmTypeNode(wasmMethodCodeNode.Method);
dependencies.Add(wasmTypeNode, "Wasm Method Code Nodes Require Signature");
WasmTypeNode wasmTypeNode = wasmCodeNode is IMethodCodeNodeWithTypeSignature methodCodeNode

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look right. #133739 (comment) pointed out a bug in IMethodCodeNodeWithTypeSignature.HasGenericContextArg saying it doesn't match what LoweringFlags GetLoweringFlags(MethodDesc method).

Shouldn't the fix be in IMethodCodeNodeWithTypeSignature?

? factory.WasmTypeNode(methodCodeNode.Method)
: factory.WasmTypeNode(wasmCodeNode);
dependencies.Add(wasmTypeNode, "Wasm Code Nodes Require Signature");
}

if (dependencies == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1630,6 +1630,11 @@ public WasmTypeNode WasmTypeNode(MethodDesc desc)
return _wasmTypeNodes.GetOrAdd(WasmLowering.GetSignature(desc).FuncType);
}

public WasmTypeNode WasmTypeNode(INodeWithTypeSignature node)
{
return _wasmTypeNodes.GetOrAdd(WasmLowering.GetSignature(node).FuncType);
}

public WasmTypeNode WasmTypeNode(CorInfoWasmType[] types)
{
return _wasmTypeNodes.GetOrAdd(WasmFuncType.FromCorInfoSignature(types));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,206 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Diagnostics;

using ILCompiler.DependencyAnalysis.Wasm;
using ILCompiler.ObjectWriter.WasmInstructions;

using Internal.JitInterface;
using Internal.TypeSystem;

namespace ILCompiler.DependencyAnalysis
{
public partial class ReadyToRunHelperNode
public partial class ReadyToRunHelperNode : INodeWithTypeSignature
{
private MethodSignature _signature;

public MethodSignature Signature => _signature ??= InitializeWasmSignature();
public bool IsUnmanagedCallersOnly => false;
public bool IsAsyncCall => false;
public bool HasGenericContextArg => false;

private MethodSignature InitializeWasmSignature()
{
TypeSystemContext context = Id switch
{
ReadyToRunHelperId.DelegateCtor => ((DelegateCreationInfo)Target).DelegateType.Context,
_ => ((TypeSystemEntity)Target).Context,
};

TypeDesc nativeIntType = context.GetWellKnownType(WellKnownType.IntPtr);
TypeDesc[] parameters = Id switch
{
ReadyToRunHelperId.DelegateCtor => [nativeIntType, nativeIntType],
ReadyToRunHelperId.ResolveVirtualFunction => [nativeIntType],
_ => [],
};
TypeDesc returnType = Id == ReadyToRunHelperId.DelegateCtor ?
context.GetWellKnownType(WellKnownType.Void) : nativeIntType;

return new MethodSignature(MethodSignatureFlags.Static, genericParameterCount: 0, returnType, parameters);
}

protected override void EmitCode(NodeFactory factory, ref WasmEmitter encoder, bool relocsOnly)
{
throw new NotImplementedException();
Debug.Assert(!encoder.Is64Bit);

List<WasmExpr> expressions = new List<WasmExpr>();

switch (Id)
{
case ReadyToRunHelperId.GetNonGCStaticBase:
{
MetadataType target = (MetadataType)Target;
ISymbolNode staticBase = factory.TypeNonGCStaticsSymbol(target);

if (!factory.PreinitializationManager.HasLazyStaticConstructor(target))
{
expressions.Add(I32.ConstRVA(staticBase));
}
else
{
ISymbolNode helper = factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnNonGCStaticBase);
expressions.Add(Local.Get(0));
expressions.Add(I32.ConstRVA(staticBase));
expressions.Add(I32.Const(NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)));
expressions.Add(I32.Sub);
expressions.Add(I32.ConstRVA(staticBase));
expressions.Add(ControlFlow.ReturnCall(helper));
Comment thread
jtschuster marked this conversation as resolved.
}
}
break;

case ReadyToRunHelperId.GetThreadStaticBase:
{
MetadataType target = (MetadataType)Target;
ISortableSymbolNode index = factory.TypeThreadStaticIndex(target);
if (index is TypeThreadStaticIndexNode ti && ti.IsInlined)
{
throw new NotImplementedException();
}

expressions.Add(Local.Get(0));
expressions.Add(I32.ConstRVA(index));
expressions.Add(I32.Load(0));
expressions.Add(I32.ConstRVA(index));
expressions.Add(I32.Load((ulong)factory.Target.PointerSize));

ISymbolNode helper;
if (!factory.PreinitializationManager.HasLazyStaticConstructor(target))
{
helper = factory.HelperEntrypoint(HelperEntrypoint.GetThreadStaticBaseForType);
}
else
{
ISymbolNode staticBase = factory.TypeNonGCStaticsSymbol(target);
expressions.Add(I32.ConstRVA(staticBase));
expressions.Add(I32.Const(NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)));
expressions.Add(I32.Sub);
helper = factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnThreadStaticBase);
}

expressions.Add(ControlFlow.ReturnCall(helper));
}
break;

case ReadyToRunHelperId.GetGCStaticBase:
{
MetadataType target = (MetadataType)Target;
ISymbolNode gcStaticBase = factory.TypeGCStaticsSymbol(target);

if (!factory.PreinitializationManager.HasLazyStaticConstructor(target))
{
expressions.Add(I32.ConstRVA(gcStaticBase));
expressions.Add(I32.Load(0));
}
else
{
ISymbolNode nonGCStaticBase = factory.TypeNonGCStaticsSymbol(target);
ISymbolNode helper = factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnGCStaticBase);
expressions.Add(Local.Get(0));
expressions.Add(I32.ConstRVA(nonGCStaticBase));
expressions.Add(I32.Const(NonGCStaticsNode.GetClassConstructorContextSize(factory.Target)));
expressions.Add(I32.Sub);
expressions.Add(I32.ConstRVA(gcStaticBase));
expressions.Add(I32.Load(0));
expressions.Add(ControlFlow.ReturnCall(helper));
}
}
break;

case ReadyToRunHelperId.DelegateCtor:
{
DelegateCreationInfo target = (DelegateCreationInfo)Target;

expressions.Add(Local.Get(0));
expressions.Add(Local.Get(1));
expressions.Add(Local.Get(2));

if (target.TargetNeedsVTableLookup)
{
Debug.Assert(!target.TargetMethod.CanMethodBeInSealedVTable(factory));
expressions.Add(Local.Get(2));
expressions.Add(I32.Load(0));

int slot = 0;
if (!relocsOnly)
{
slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, target.TargetMethod, target.TargetMethod.OwningType);
}

Debug.Assert(slot != -1);
expressions.Add(I32.Load((ulong)(EETypeNode.GetVTableOffset(factory.Target.PointerSize) + (slot * factory.Target.PointerSize))));
}
else
{
expressions.Add(I32.ConstRVA(target.GetTargetNode(factory)));
}

if (target.Thunk is not null)
{
Debug.Assert(target.Constructor.Method.Signature.Length == 3);
expressions.Add(I32.ConstRVA(target.Thunk));
}
else
{
Debug.Assert(target.Constructor.Method.Signature.Length == 2);
}

expressions.Add(ControlFlow.ReturnCall(target.Constructor));
}
break;

case ReadyToRunHelperId.ResolveVirtualFunction:
{
MethodDesc targetMethod = (MethodDesc)Target;
if (targetMethod.OwningType.IsInterface)
{
ISymbolNode helper = factory.ExternFunctionSymbol(s_RhpResolveInterfaceMethod);
expressions.Add(Local.Get(0));
expressions.Add(Local.Get(1));
expressions.Add(I32.ConstRVA(factory.DispatchCell(targetMethod)));
expressions.Add(ControlFlow.ReturnCall(helper));
Comment on lines +182 to +185
}
else if (!relocsOnly)
{
expressions.Add(Local.Get(1));
expressions.Add(I32.Load(0));

Debug.Assert(!targetMethod.CanMethodBeInSealedVTable(factory));
int slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, targetMethod, targetMethod.OwningType);
Debug.Assert(slot != -1);
expressions.Add(I32.Load((ulong)(EETypeNode.GetVTableOffset(factory.Target.PointerSize) + (slot * factory.Target.PointerSize))));
}
}
break;

default:
throw new NotImplementedException();
Comment thread
MichalStrehovsky marked this conversation as resolved.
}

encoder.FunctionBody = new WasmFunctionBody(WasmLowering.GetSignature(this).FuncType, expressions.ToArray());
Comment thread
jtschuster marked this conversation as resolved.
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1518,6 +1518,11 @@ public WasmTypeNode WasmTypeNode(MethodDesc method)
return _wasmTypeNodes.GetOrAdd(funcType);
}

public WasmTypeNode WasmTypeNode(INodeWithTypeSignature node)
{
return _wasmTypeNodes.GetOrAdd(WasmLowering.GetSignature(node).FuncType);
}

internal WasmMethodRelativeVirtualIPNode WasmMethodRelativeVirtualIP(MethodWithGCInfo method)
{
return _wasmMethodRelativeVirtualIPs.GetOrAdd(method);
Expand Down