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); // The generic dictionary pointer occupies the first slot of each type vtable slice if (declType.HasGenericDictionarySlot()) { objData.EmitPointerReloc(factory.TypeGenericDictionary(declType)); } // Actual vtable slots follow 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) { MethodDesc canonImplMethod = implMethod.GetCanonMethodTarget(CanonicalFormKind.Specific); objData.EmitPointerReloc(factory.MethodEntrypoint(canonImplMethod, implMethod.OwningType.IsValueType)); } else { objData.EmitZeroPointer(); } } }
/// <summary> /// Gets the vtable slot that holds the generic dictionary of this type. /// </summary> public static int GetGenericDictionarySlot(NodeFactory factory, TypeDesc type) { Debug.Assert(type.HasGenericDictionarySlot()); return GetNumberOfBaseSlots(factory, type); }