本文整理汇总了C#中ILCompiler.DependencyAnalysis.NodeFactory.MethodEntrypoint方法的典型用法代码示例。如果您正苦于以下问题:C# NodeFactory.MethodEntrypoint方法的具体用法?C# NodeFactory.MethodEntrypoint怎么用?C# NodeFactory.MethodEntrypoint使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类ILCompiler.DependencyAnalysis.NodeFactory
的用法示例。
在下文中一共展示了NodeFactory.MethodEntrypoint方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: GetData
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
var builder = new ObjectDataBuilder(factory);
// These need to be aligned the same as methods because they show up in same contexts
builder.RequireAlignment(factory.Target.MinimumFunctionAlignment);
builder.DefinedSymbols.Add(this);
MethodDesc canonMethod = Method.GetCanonMethodTarget(CanonicalFormKind.Specific);
// Pointer to the canonical body of the method
builder.EmitPointerReloc(factory.MethodEntrypoint(canonMethod));
// Find out what's the context to use
ISymbolNode contextParameter;
if (canonMethod.RequiresInstMethodDescArg())
{
contextParameter = factory.MethodGenericDictionary(Method);
}
else
{
Debug.Assert(canonMethod.RequiresInstMethodTableArg());
// Ask for a constructed type symbol because we need the vtable to get to the dictionary
contextParameter = factory.ConstructedTypeSymbol(Method.OwningType);
}
// The next entry is a pointer to the pointer to the context to be used for the canonical method
// TODO: in multi-module, this points to the import cell, and is no longer this weird pointer
builder.EmitPointerReloc(factory.Indirection(contextParameter));
return builder.ToObjectData();
}
示例2: EmitCode
protected override void EmitCode(NodeFactory factory, ref X64Emitter encoder, bool relocsOnly)
{
AddrMode thisPtr = new AddrMode(
Register.RegDirect | encoder.TargetRegister.Arg0, null, 0, 0, AddrModeSize.Int64);
encoder.EmitADD(ref thisPtr, (sbyte)factory.Target.PointerSize);
encoder.EmitJMP(factory.MethodEntrypoint(_target));
}
示例3: EmitCode
//.........这里部分代码省略.........
TypeDesc target = (TypeDesc)Target;
encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.NecessaryTypeSymbol(target));
encoder.EmitJMP(factory.ExternSymbol(JitHelper.GetCastingHelperNameForType(target, false)));
}
break;
case ReadyToRunHelperId.CastClass:
{
TypeDesc target = (TypeDesc)Target;
encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.NecessaryTypeSymbol(target));
encoder.EmitJMP(factory.ExternSymbol(JitHelper.GetCastingHelperNameForType(target, true)));
}
break;
case ReadyToRunHelperId.NewArr1:
{
TypeDesc target = (TypeDesc)Target;
// TODO: Swap argument order instead
// mov arg1, arg0
encoder.Builder.EmitByte(0x48);
encoder.Builder.EmitShort((short)((encoder.TargetRegister.Arg0 == Register.RCX) ? 0xD18B : 0xF78B));
encoder.EmitLEAQ(encoder.TargetRegister.Arg0, factory.NecessaryTypeSymbol(target));
encoder.EmitJMP(factory.ExternSymbol(JitHelper.GetNewArrayHelperForType(target)));
}
break;
case ReadyToRunHelperId.GetNonGCStaticBase:
{
MetadataType target = (MetadataType)Target;
if (!target.HasStaticConstructor)
{
Debug.Assert(Id == ReadyToRunHelperId.GetNonGCStaticBase);
encoder.EmitLEAQ(encoder.TargetRegister.Result, factory.TypeNonGCStaticsSymbol(target));
encoder.EmitRET();
}
else
{
// We need to trigger the cctor before returning the base
encoder.EmitLEAQ(encoder.TargetRegister.Arg0, factory.TypeCctorContextSymbol(target));
encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.TypeNonGCStaticsSymbol(target));
encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnNonGCStaticBase));
}
}
break;
case ReadyToRunHelperId.GetThreadStaticBase:
encoder.EmitINT3();
break;
case ReadyToRunHelperId.GetGCStaticBase:
{
MetadataType target = (MetadataType)Target;
if (!target.HasStaticConstructor)
{
encoder.EmitLEAQ(encoder.TargetRegister.Result, factory.TypeGCStaticsSymbol(target));
AddrMode loadFromRax = new AddrMode(encoder.TargetRegister.Result, null, 0, 0, AddrModeSize.Int64);
encoder.EmitMOV(encoder.TargetRegister.Result, ref loadFromRax);
encoder.EmitMOV(encoder.TargetRegister.Result, ref loadFromRax);
encoder.EmitRET();
}
else
{
// We need to trigger the cctor before returning the base
encoder.EmitLEAQ(encoder.TargetRegister.Arg0, factory.TypeCctorContextSymbol(target));
encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.TypeGCStaticsSymbol(target));
AddrMode loadFromRdx = new AddrMode(encoder.TargetRegister.Arg1, null, 0, 0, AddrModeSize.Int64);
encoder.EmitMOV(encoder.TargetRegister.Arg1, ref loadFromRdx);
encoder.EmitMOV(encoder.TargetRegister.Arg1, ref loadFromRdx);
encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnGCStaticBase));
}
}
break;
case ReadyToRunHelperId.DelegateCtor:
{
DelegateInfo target = (DelegateInfo)Target;
encoder.EmitLEAQ(encoder.TargetRegister.Arg2, factory.MethodEntrypoint(target.Target));
if (target.ShuffleThunk != null)
encoder.EmitLEAQ(encoder.TargetRegister.Arg3, factory.MethodEntrypoint(target.ShuffleThunk));
encoder.EmitJMP(factory.MethodEntrypoint(target.Ctor));
}
break;
case ReadyToRunHelperId.InterfaceDispatch:
{
encoder.EmitLEAQ(Register.R10, factory.InterfaceDispatchCell((MethodDesc)Target));
AddrMode jmpAddrMode = new AddrMode(Register.R10, null, 0, 0, AddrModeSize.Int64);
encoder.EmitJmpToAddrMode(ref jmpAddrMode);
}
break;
default:
throw new NotImplementedException();
}
}
示例4: OutputFinalizerMethod
private void OutputFinalizerMethod(NodeFactory factory, ref ObjectDataBuilder objData)
{
MethodDesc finalizerMethod = _type.GetFinalizer();
if (finalizerMethod != null)
{
objData.EmitPointerReloc(factory.MethodEntrypoint(finalizerMethod));
}
}
示例5: OutputVirtualSlots
private void OutputVirtualSlots(NodeFactory factory, ref ObjectDataBuilder objData, TypeDesc implType, TypeDesc declType)
{
var baseType = declType.BaseType;
if (baseType != null)
OutputVirtualSlots(factory, ref objData, implType, baseType);
List<MethodDesc> virtualSlots;
factory.VirtualSlots.TryGetValue(declType, out virtualSlots);
if (virtualSlots != null)
{
for (int i = 0; i < virtualSlots.Count; i++)
{
MethodDesc declMethod = virtualSlots[i];
MethodDesc implMethod = VirtualFunctionResolution.FindVirtualFunctionTargetMethodOnObjectType(declMethod, implType.GetClosestMetadataType());
if (!implMethod.IsAbstract)
objData.EmitPointerReloc(factory.MethodEntrypoint(implMethod));
else
objData.EmitZeroPointer();
}
}
}
示例6: GetConditionalStaticDependencies
public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory)
{
if (_type is MetadataType)
{
foreach (MethodDesc decl in VirtualFunctionResolution.EnumAllVirtualSlots((MetadataType)_type))
{
MethodDesc impl = VirtualFunctionResolution.FindVirtualFunctionTargetMethodOnObjectType(decl, (MetadataType)_type);
if (impl.OwningType == _type && !impl.IsAbstract)
{
yield return new DependencyNodeCore<NodeFactory>.CombinedDependencyListEntry(factory.MethodEntrypoint(impl), factory.VirtualMethodUse(decl), "Virtual method");
}
}
// Add conditional dependencies for interface methods the type implements. For example, if the type T implements
// interface IFoo which has a method M1, add a dependency on T.M1 dependent on IFoo.M1 being called, since it's
// possible for any IFoo object to actually be an instance of T.
foreach (DefType interfaceType in _type.RuntimeInterfaces)
{
Debug.Assert(interfaceType.IsInterface);
foreach (MethodDesc interfaceMethod in interfaceType.GetMethods())
{
Debug.Assert(interfaceMethod.IsVirtual);
MethodDesc implMethod = VirtualFunctionResolution.ResolveInterfaceMethodToVirtualMethodOnType(interfaceMethod, _type.GetClosestMetadataType());
if (implMethod != null)
{
yield return new DependencyNodeCore<NodeFactory>.CombinedDependencyListEntry(factory.VirtualMethodUse(implMethod), factory.ReadyToRunHelper(ReadyToRunHelperId.InterfaceDispatch, interfaceMethod), "Interface method");
}
}
}
}
}
示例7: GetConditionalStaticDependencies
public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory)
{
// The generic dictionary layout is shared between all the canonically equivalent
// instantiations. We need to track the dependencies of all canonical method bodies
// that use the same dictionary layout.
foreach (var method in _owningType.GetAllMethods())
{
// Static and generic methods have their own generic dictionaries
if (method.Signature.IsStatic || method.HasInstantiation)
continue;
// Abstract methods don't have a body
if (method.IsAbstract)
continue;
// If a canonical method body was compiled, we need to track the dictionary
// dependencies in the context of the concrete type that owns this dictionary.
yield return new CombinedDependencyListEntry(
factory.ShadowConcreteMethod(method),
factory.MethodEntrypoint(method.GetCanonMethodTarget(CanonicalFormKind.Specific)),
"Generic dictionary dependency");
}
}
示例8: Create
/// <summary>
/// Constructs a new instance of <see cref="DelegateCreationInfo"/> set up to construct a delegate of type
/// '<paramref name="delegateType"/>' pointing to '<paramref name="targetMethod"/>'.
/// </summary>
public static DelegateCreationInfo Create(TypeDesc delegateType, MethodDesc targetMethod, NodeFactory factory)
{
var context = (CompilerTypeSystemContext)delegateType.Context;
var systemDelegate = targetMethod.Context.GetWellKnownType(WellKnownType.MulticastDelegate).BaseType;
int paramCountTargetMethod = targetMethod.Signature.Length;
if (!targetMethod.Signature.IsStatic)
{
paramCountTargetMethod++;
}
DelegateInfo delegateInfo = context.GetDelegateInfo(delegateType.GetTypeDefinition());
int paramCountDelegateClosed = delegateInfo.Signature.Length + 1;
bool closed = false;
if (paramCountDelegateClosed == paramCountTargetMethod)
{
closed = true;
}
else
{
Debug.Assert(paramCountDelegateClosed == paramCountTargetMethod + 1);
}
if (targetMethod.Signature.IsStatic)
{
MethodDesc invokeThunk;
MethodDesc initMethod;
if (!closed)
{
// Open delegate to a static method
invokeThunk = delegateInfo.Thunks[DelegateThunkKind.OpenStaticThunk];
initMethod = systemDelegate.GetKnownMethod("InitializeOpenStaticThunk", null);
}
else
{
// Closed delegate to a static method (i.e. delegate to an extension method that locks the first parameter)
invokeThunk = delegateInfo.Thunks[DelegateThunkKind.ClosedStaticThunk];
initMethod = systemDelegate.GetKnownMethod("InitializeClosedStaticThunk", null);
}
var instantiatedDelegateType = delegateType as InstantiatedType;
if (instantiatedDelegateType != null)
invokeThunk = context.GetMethodForInstantiatedType(invokeThunk, instantiatedDelegateType);
return new DelegateCreationInfo(
factory.MethodEntrypoint(initMethod),
factory.MethodEntrypoint(targetMethod),
factory.MethodEntrypoint(invokeThunk));
}
else
{
if (!closed)
throw new NotImplementedException("Open instance delegates");
bool useUnboxingStub = targetMethod.OwningType.IsValueType;
return new DelegateCreationInfo(
factory.MethodEntrypoint(systemDelegate.GetKnownMethod("InitializeClosedInstance", null)),
factory.MethodEntrypoint(targetMethod, useUnboxingStub));
}
}
示例9: OutputFinalizerMethod
private void OutputFinalizerMethod(NodeFactory factory, ref ObjectDataBuilder objData)
{
MethodDesc finalizerMethod = _type.GetFinalizer();
if (finalizerMethod != null)
{
MethodDesc canonFinalizerMethod = finalizerMethod.GetCanonMethodTarget(CanonicalFormKind.Specific);
objData.EmitPointerReloc(factory.MethodEntrypoint(canonFinalizerMethod));
}
}
示例10: GetData
public override ObjectData GetData(NodeFactory factory, bool relocsOnly)
{
ObjectDataBuilder builder = new ObjectDataBuilder(factory);
// If the type has a class constructor, it's non-GC statics section is prefixed
// by System.Runtime.CompilerServices.StaticClassConstructionContext struct.
if (HasClassConstructorContext)
{
int alignmentRequired = Math.Max(_type.NonGCStaticFieldAlignment, ClassConstructorContextAlignment);
builder.RequireAlignment(alignmentRequired);
Debug.Assert(((ISymbolNode)this).Offset >= ClassConstructorContextSize);
// Add padding before the context if alignment forces us to do so
builder.EmitZeros(((ISymbolNode)this).Offset - ClassConstructorContextSize);
// Emit the actual StaticClassConstructionContext
var cctorMethod = _type.GetStaticConstructor();
builder.EmitPointerReloc(factory.MethodEntrypoint(cctorMethod));
builder.EmitZeroPointer();
builder.DefinedSymbols.Add(_classConstructorContext);
}
else
{
builder.RequireAlignment(_type.NonGCStaticFieldAlignment);
}
builder.EmitZeros(_type.NonGCStaticFieldSize);
builder.DefinedSymbols.Add(this);
return builder.ToObjectData();
}
示例11: ComputeNonRelocationBasedDependencies
protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
{
DependencyList dependencies = null;
TypeDesc owningType = _method.OwningType;
if (factory.TypeSystemContext.HasEagerStaticConstructor(owningType))
{
if (dependencies == null)
dependencies = new DependencyList();
dependencies.Add(factory.EagerCctorIndirection(owningType.GetStaticConstructor()), "Eager .cctor");
}
if (_ehInfo != null && _ehInfo.Relocs != null)
{
if (dependencies == null)
dependencies = new DependencyList();
foreach (Relocation reloc in _ehInfo.Relocs)
{
dependencies.Add(reloc.Target, "reloc");
}
}
// Reflection invoke stub handling is here because in the current reflection model we reflection-enable
// all methods that are compiled. Ideally the list of reflection enabled methods should be known before
// we even start the compilation process (with the invocation stubs being compilation roots like any other).
// The existing model has it's problems: e.g. the invocability of the method depends on inliner decisions.
if (factory.MetadataManager.HasReflectionInvokeStub(_method)
&& !_method.IsCanonicalMethod(CanonicalFormKind.Any) /* Shared generics handled in the shadow concrete method node */)
{
if (dependencies == null)
dependencies = new DependencyList();
MethodDesc invokeStub = factory.MetadataManager.GetReflectionInvokeStub(Method);
MethodDesc canonInvokeStub = invokeStub.GetCanonMethodTarget(CanonicalFormKind.Specific);
if (invokeStub != canonInvokeStub)
dependencies.Add(new DependencyListEntry(factory.FatFunctionPointer(invokeStub), "Reflection invoke"));
else
dependencies.Add(new DependencyListEntry(factory.MethodEntrypoint(invokeStub), "Reflection invoke"));
}
return dependencies;
}
示例12: GetConditionalStaticDependencies
public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory)
{
if (_type is MetadataType)
{
foreach (MethodDesc decl in VirtualFunctionResolution.EnumAllVirtualSlots((MetadataType)_type))
{
MethodDesc impl = VirtualFunctionResolution.FindVirtualFunctionTargetMethodOnObjectType(decl, (MetadataType)_type);
if (impl.OwningType == _type && !impl.IsAbstract)
{
yield return new DependencyNodeCore<NodeFactory>.CombinedDependencyListEntry(factory.MethodEntrypoint(impl), factory.VirtualMethodUse(decl), "Virtual method");
}
}
}
}
示例13: EmitCode
protected override void EmitCode(NodeFactory factory, ref X64Emitter encoder, bool relocsOnly)
{
switch (Id)
{
case ReadyToRunHelperId.NewHelper:
encoder.EmitLEAQ(encoder.TargetRegister.Arg0, factory.ConstructedTypeSymbol((TypeDesc)Target));
encoder.EmitJMP(factory.ExternSymbol("__allocate_object"));
break;
case ReadyToRunHelperId.VirtualCall:
if (relocsOnly)
break;
AddrMode loadFromThisPtr = new AddrMode(encoder.TargetRegister.Arg0, null, 0, 0, AddrModeSize.Int64);
encoder.EmitMOV(encoder.TargetRegister.Result, ref loadFromThisPtr);
{
int slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, (MethodDesc)Target);
Debug.Assert(slot != -1);
AddrMode jmpAddrMode = new AddrMode(encoder.TargetRegister.Result, null, EETypeNode.GetVTableOffset(factory.Target.PointerSize) + (slot * factory.Target.PointerSize), 0, AddrModeSize.Int64);
encoder.EmitJmpToAddrMode(ref jmpAddrMode);
}
break;
case ReadyToRunHelperId.IsInstanceOf:
encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.NecessaryTypeSymbol((TypeDesc)Target));
encoder.EmitJMP(factory.ExternSymbol("__isinst_class"));
break;
case ReadyToRunHelperId.CastClass:
encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.NecessaryTypeSymbol((TypeDesc)Target));
encoder.EmitJMP(factory.ExternSymbol("__castclass_class"));
break;
case ReadyToRunHelperId.NewArr1:
encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.NecessaryTypeSymbol((TypeDesc)Target));
encoder.EmitJMP(factory.ExternSymbol("__allocate_array"));
break;
case ReadyToRunHelperId.GetNonGCStaticBase:
if (!((MetadataType)Target).HasStaticConstructor)
{
Debug.Assert(Id == ReadyToRunHelperId.GetNonGCStaticBase);
encoder.EmitLEAQ(encoder.TargetRegister.Result, factory.TypeNonGCStaticsSymbol((MetadataType)Target));
encoder.EmitRET();
}
else
{
// We need to trigger the cctor before returning the base
encoder.EmitLEAQ(encoder.TargetRegister.Arg0, factory.TypeCctorContextSymbol((MetadataType)Target));
encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.TypeNonGCStaticsSymbol((MetadataType)Target));
encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnNonGCStaticBase));
}
break;
case ReadyToRunHelperId.GetThreadStaticBase:
encoder.EmitINT3();
break;
case ReadyToRunHelperId.GetGCStaticBase:
if (!((MetadataType)Target).HasStaticConstructor)
{
encoder.EmitLEAQ(encoder.TargetRegister.Result, factory.TypeGCStaticsSymbol((MetadataType)Target));
AddrMode loadFromRax = new AddrMode(encoder.TargetRegister.Result, null, 0, 0, AddrModeSize.Int64);
encoder.EmitMOV(encoder.TargetRegister.Result, ref loadFromRax);
encoder.EmitMOV(encoder.TargetRegister.Result, ref loadFromRax);
encoder.EmitRET();
}
else
{
// We need to trigger the cctor before returning the base
encoder.EmitLEAQ(encoder.TargetRegister.Arg0, factory.TypeCctorContextSymbol((MetadataType)Target));
encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.TypeGCStaticsSymbol((MetadataType)Target));
AddrMode loadFromRdx = new AddrMode(encoder.TargetRegister.Arg1, null, 0, 0, AddrModeSize.Int64);
encoder.EmitMOV(encoder.TargetRegister.Arg1, ref loadFromRdx);
encoder.EmitMOV(encoder.TargetRegister.Arg1, ref loadFromRdx);
encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnGCStaticBase));
}
break;
case ReadyToRunHelperId.DelegateCtor:
{
DelegateInfo target = (DelegateInfo)Target;
encoder.EmitLEAQ(encoder.TargetRegister.Arg2, factory.MethodEntrypoint(target.Target));
if (target.ShuffleThunk != null)
encoder.EmitLEAQ(encoder.TargetRegister.Arg3, factory.MethodEntrypoint(target.ShuffleThunk));
encoder.EmitJMP(factory.MethodEntrypoint(target.Ctor));
}
break;
default:
throw new NotImplementedException();
}
}
示例14: GetConditionalStaticDependencies
public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory)
{
DefType defType = _type.GetClosestDefType();
foreach (MethodDesc decl in defType.EnumAllVirtualSlots())
{
MethodDesc impl = defType.FindVirtualFunctionTargetMethodOnObjectType(decl);
if (impl.OwningType == defType && !impl.IsAbstract)
{
MethodDesc canonImpl = impl.GetCanonMethodTarget(CanonicalFormKind.Specific);
yield return new CombinedDependencyListEntry(factory.MethodEntrypoint(canonImpl, _type.IsValueType), factory.VirtualMethodUse(decl), "Virtual method");
}
}
Debug.Assert(
_type == defType ||
((System.Collections.IStructuralEquatable)defType.RuntimeInterfaces).Equals(_type.RuntimeInterfaces,
EqualityComparer<DefType>.Default));
// Add conditional dependencies for interface methods the type implements. For example, if the type T implements
// interface IFoo which has a method M1, add a dependency on T.M1 dependent on IFoo.M1 being called, since it's
// possible for any IFoo object to actually be an instance of T.
foreach (DefType interfaceType in defType.RuntimeInterfaces)
{
Debug.Assert(interfaceType.IsInterface);
foreach (MethodDesc interfaceMethod in interfaceType.GetAllMethods())
{
if (interfaceMethod.Signature.IsStatic)
continue;
MethodDesc implMethod = defType.ResolveInterfaceMethodToVirtualMethodOnType(interfaceMethod);
if (implMethod != null)
{
yield return new CombinedDependencyListEntry(factory.VirtualMethodUse(implMethod), factory.ReadyToRunHelper(ReadyToRunHelperId.VirtualCall, interfaceMethod), "Interface method");
yield return new CombinedDependencyListEntry(factory.VirtualMethodUse(implMethod), factory.ReadyToRunHelper(ReadyToRunHelperId.ResolveVirtualFunction, interfaceMethod), "Interface method address");
}
}
}
}
示例15: OutputVirtualSlots
protected override void OutputVirtualSlots(NodeFactory factory, ref ObjectDataBuilder objData, TypeDesc implType, TypeDesc declType)
{
declType = declType.GetClosestDefType();
var baseType = declType.BaseType;
if (baseType != null)
OutputVirtualSlots(factory, ref objData, implType, baseType);
IReadOnlyList<MethodDesc> virtualSlots = factory.VTable(declType).Slots;
for (int i = 0; i < virtualSlots.Count; i++)
{
MethodDesc declMethod = virtualSlots[i];
MethodDesc implMethod = implType.GetClosestDefType().FindVirtualFunctionTargetMethodOnObjectType(declMethod);
if (declMethod.HasInstantiation)
{
// Generic virtual methods will "compile", but will fail to link. Check for it here.
throw new NotImplementedException("VTable for " + _type + " has generic virtual methods.");
}
if (!implMethod.IsAbstract)
objData.EmitPointerReloc(factory.MethodEntrypoint(implMethod, implMethod.OwningType.IsValueType));
else
objData.EmitZeroPointer();
}
}