protected virtual void OutputVirtualSlots(NodeFactory factory, ref ObjectDataBuilder objData, TypeDesc implType, TypeDesc declType, bool relocsOnly) { Debug.Assert(EmitVirtualSlotsAndInterfaces); declType = declType.GetClosestDefType(); var baseType = declType.BaseType; if (baseType != null) { OutputVirtualSlots(factory, ref objData, implType, baseType, relocsOnly); } // The generic dictionary pointer occupies the first slot of each type vtable slice if (declType.HasGenericDictionarySlot()) { // Note: Canonical type instantiations always have a generic dictionary vtable slot, but it's empty // TODO: emit the correction dictionary slot for interfaces (needed when we start supporting static methods on interfaces) if (declType.IsInterface || declType.IsCanonicalSubtype(CanonicalFormKind.Any)) { objData.EmitZeroPointer(); } else { objData.EmitPointerReloc(factory.TypeGenericDictionary(declType)); } } // It's only okay to touch the actual list of slots if we're in the final emission phase // or the vtable is not built lazily. if (relocsOnly && !factory.CompilationModuleGroup.ShouldProduceFullVTable(declType)) { return; } // Actual vtable slots follow IReadOnlyList <MethodDesc> virtualSlots = factory.VTable(declType).Slots; for (int i = 0; i < virtualSlots.Count; i++) { MethodDesc declMethod = virtualSlots[i]; // No generic virtual methods can appear in the vtable! Debug.Assert(!declMethod.HasInstantiation); MethodDesc implMethod = implType.GetClosestDefType().FindVirtualFunctionTargetMethodOnObjectType(declMethod); if (!implMethod.IsAbstract) { MethodDesc canonImplMethod = implMethod.GetCanonMethodTarget(CanonicalFormKind.Specific); objData.EmitPointerReloc(factory.MethodEntrypoint(canonImplMethod, implMethod.OwningType.IsValueType)); } else { objData.EmitZeroPointer(); } } }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder objData = new ObjectDataBuilder(factory); objData.DefinedSymbols.Add(this); objData.RequirePointerAlignment(); objData.EmitZeroPointer(); objData.EmitZeroPointer(); return(objData.ToObjectData()); }
protected virtual void OutputVirtualSlots(NodeFactory factory, ref ObjectDataBuilder objData, TypeDesc implType, TypeDesc declType) { Debug.Assert(EmitVirtualSlotsAndInterfaces); 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()) { // Note: Canonical type instantiations always have a generic dictionary vtable slot, but it's empty if (declType.IsCanonicalSubtype(CanonicalFormKind.Any)) { objData.EmitZeroPointer(); } else { 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]; // No generic virtual methods can appear in the vtable! Debug.Assert(!declMethod.HasInstantiation); MethodDesc implMethod = implType.GetClosestDefType().FindVirtualFunctionTargetMethodOnObjectType(declMethod); if (!implMethod.IsAbstract) { MethodDesc canonImplMethod = implMethod.GetCanonMethodTarget(CanonicalFormKind.Specific); objData.EmitPointerReloc(factory.MethodEntrypoint(canonImplMethod, implMethod.OwningType.IsValueType)); } else { objData.EmitZeroPointer(); } } }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly) { ObjectDataBuilder builder = new ObjectDataBuilder(factory); // If the type has a class constructor, its non-GC statics section is prefixed // by System.Runtime.CompilerServices.StaticClassConstructionContext struct. if (factory.TypeSystemContext.HasLazyStaticConstructor(_type)) { int alignmentRequired = Math.Max(_type.NonGCStaticFieldAlignment, GetClassConstructorContextAlignment(_type.Context.Target)); int classConstructorContextStorageSize = GetClassConstructorContextStorageSize(factory.Target, _type); builder.RequireAlignment(alignmentRequired); Debug.Assert(classConstructorContextStorageSize >= GetClassConstructorContextSize(_type.Context.Target)); // Add padding before the context if alignment forces us to do so builder.EmitZeros(classConstructorContextStorageSize - GetClassConstructorContextSize(_type.Context.Target)); // Emit the actual StaticClassConstructionContext var cctorMethod = _type.GetStaticConstructor(); builder.EmitPointerReloc(factory.MethodEntrypoint(cctorMethod)); builder.EmitZeroPointer(); } else { builder.RequireAlignment(_type.NonGCStaticFieldAlignment); } builder.EmitZeros(_type.NonGCStaticFieldSize); builder.DefinedSymbols.Add(this); return(builder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder dataBuilder = new ObjectDataBuilder(factory); dataBuilder.Alignment = 16; dataBuilder.DefinedSymbols.Add(this); short flags = (short)EETypeKind.GenericTypeDefEEType; if (_type.IsValueType) { flags |= (short)EETypeFlags.ValueTypeFlag; } if (_type.IsInterface) { flags |= (short)EETypeFlags.IsInterfaceFlag; } dataBuilder.EmitShort((short)_type.Instantiation.Length); dataBuilder.EmitShort(flags); dataBuilder.EmitInt(0); // Base size is always 0 dataBuilder.EmitZeroPointer(); // No related type dataBuilder.EmitShort(0); // No VTable dataBuilder.EmitShort(0); // No interface map dataBuilder.EmitInt(_type.GetHashCode()); dataBuilder.EmitPointerReloc(factory.ModuleManagerIndirection); return(dataBuilder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder objData = new ObjectDataBuilder(factory); // The interface dispatch cell has an alignment requirement of 2 * [Pointer size] as part of the // synchronization mechanism of the two values in the runtime. objData.Alignment = _targetMethod.Context.Target.PointerSize * 2; objData.DefinedSymbols.Add(this); objData.EmitPointerReloc(factory.ExternSymbol("RhpInitialDynamicInterfaceDispatch")); // The second cell field uses the two lower-order bits to communicate the contents. // We add 1 to signal IDC_CachePointerIsInterfacePointer. See src\Native\Runtime\inc\rhbinder.h. objData.EmitPointerReloc(factory.NecessaryTypeSymbol(_targetMethod.OwningType), 1); // End the run of dispatch cells objData.EmitZeroPointer(); // Avoid consulting VTable slots until they're guaranteed complete during final data emission if (!relocsOnly) { int interfaceMethodSlot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, _targetMethod); if (factory.Target.PointerSize == 8) { objData.EmitLong(interfaceMethodSlot); } else { throw new NotImplementedException(); } } return objData.ToObjectData(); }
public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly) { dataBuilder.EmitZeroPointer(); // Sync block DefType systemStringType = factory.TypeSystemContext.GetWellKnownType(WellKnownType.String); // // The GC requires a direct reference to frozen objects' EETypes. If System.String will be compiled into a separate // binary, it must be cloned into this one. // if (factory.CompilationModuleGroup.ShouldReferenceThroughImportTable(systemStringType)) { dataBuilder.EmitPointerReloc(factory.ConstructedClonedTypeSymbol(systemStringType)); } else { dataBuilder.EmitPointerReloc(factory.ConstructedTypeSymbol(systemStringType)); } dataBuilder.EmitInt(_data.Length); foreach (char c in _data) { dataBuilder.EmitShort((short)c); } // Null-terminate for friendliness with interop dataBuilder.EmitShort(0); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); builder.AddSymbol(this); ISymbolNode nameSymbol = factory.ConstantUtf8String(_pInvokeModuleData.ModuleName); ISymbolNode moduleTypeSymbol = factory.NecessaryTypeSymbol(_pInvokeModuleData.DeclaringModule.GetGlobalModuleType()); // // Emit a ModuleFixupCell struct // builder.EmitZeroPointer(); builder.EmitPointerReloc(nameSymbol); builder.EmitPointerReloc(moduleTypeSymbol); uint dllImportSearchPath = 0; if (_pInvokeModuleData.DllImportSearchPath.HasValue) { dllImportSearchPath = (uint)_pInvokeModuleData.DllImportSearchPath.Value; Debug.Assert((dllImportSearchPath & InteropDataConstants.HasDllImportSearchPath) == 0); dllImportSearchPath |= InteropDataConstants.HasDllImportSearchPath; } builder.EmitInt((int)dllImportSearchPath); return(builder.ToObjectData()); }
private void OutputVirtualSlots(NodeFactory factory, ref ObjectDataBuilder objData, TypeDesc implType, TypeDesc declType) { declType = declType.GetClosestMetadataType(); 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.GetClosestMetadataType().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(); } } }
private void OutputRelatedType(NodeFactory factory, ref ObjectDataBuilder objData) { ISymbolNode relatedTypeNode = null; if (_type.IsArray || _type.IsPointer) { var parameterType = ((ParameterizedType)_type).ParameterType; relatedTypeNode = factory.NecessaryTypeSymbol(parameterType); } else { TypeDesc baseType = _type.BaseType; if (baseType != null) { if (_constructed) { relatedTypeNode = factory.ConstructedTypeSymbol(baseType); } else { relatedTypeNode = factory.NecessaryTypeSymbol(baseType); } } } if (relatedTypeNode != null) { objData.EmitPointerReloc(relatedTypeNode); } else { objData.EmitZeroPointer(); } }
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(); } } } }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder objData = new ObjectDataBuilder(factory); // The interface dispatch cell has an alignment requirement of 2 * [Pointer size] as part of the // synchronization mechanism of the two values in the runtime. objData.Alignment = _targetMethod.Context.Target.PointerSize * 2; objData.DefinedSymbols.Add(this); objData.EmitPointerReloc(factory.ExternSymbol("RhpInitialDynamicInterfaceDispatch")); // The second cell field uses the two lower-order bits to communicate the contents. // We add 1 to signal IDC_CachePointerIsInterfacePointer. See src\Native\Runtime\inc\rhbinder.h. objData.EmitPointerReloc(factory.NecessaryTypeSymbol(_targetMethod.OwningType), 1); // End the run of dispatch cells objData.EmitZeroPointer(); int interfaceMethodSlot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, _targetMethod); if (factory.Target.PointerSize == 8) { objData.EmitLong(interfaceMethodSlot); } else { throw new NotImplementedException(); } return(objData.ToObjectData()); }
protected virtual void OutputRelatedType(NodeFactory factory, ref ObjectDataBuilder objData) { ISymbolNode relatedTypeNode = null; if (_type.IsArray || _type.IsPointer || _type.IsByRef) { var parameterType = ((ParameterizedType)_type).ParameterType; relatedTypeNode = factory.NecessaryTypeSymbol(parameterType); } else { TypeDesc baseType = _type.BaseType; if (baseType != null) { relatedTypeNode = GetBaseTypeNode(factory); } } if (relatedTypeNode != null) { objData.EmitPointerReloc(relatedTypeNode); } else { objData.EmitZeroPointer(); } }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory); builder.DefinedSymbols.Add(this); // // Emit a MethodFixupCell struct // // Address (to be fixed up at runtime) builder.EmitZeroPointer(); // Entry point name if (factory.Target.IsWindows && _entryPointName.StartsWith("#", StringComparison.OrdinalIgnoreCase)) { // Windows-specific ordinal import // CLR-compatible behavior: Strings that can't be parsed as a signed integer are treated as zero. int entrypointOrdinal; if (!int.TryParse(_entryPointName.Substring(1), out entrypointOrdinal)) entrypointOrdinal = 0; // CLR-compatible behavior: Ordinal imports are 16-bit on Windows. Discard rest of the bits. builder.EmitNaturalInt((ushort)entrypointOrdinal); } else { // Import by name builder.EmitPointerReloc(factory.ConstantUtf8String(_entryPointName)); } // Module fixup cell builder.EmitPointerReloc(factory.PInvokeModuleFixup(_moduleName)); return builder.ToObjectData(); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder objData = new ObjectDataBuilder(factory); objData.DefinedSymbols.Add(this); objData.RequirePointerAlignment(); objData.EmitZeroPointer(); return objData.ToObjectData(); }
public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly) { // Sync Block dataBuilder.EmitZeroPointer(); // byte contents _data.WriteContent(ref dataBuilder, factory); }
protected override void OutputInterfaceMap(NodeFactory factory, ref ObjectDataBuilder objData) { foreach (var itf in _type.RuntimeInterfaces) { // Interface omitted for canonical instantiations (constructed at runtime for dynamic types from the native layout info) objData.EmitZeroPointer(); } }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder objData = new ObjectDataBuilder(factory); // The interface dispatch cell has an alignment requirement of 2 * [Pointer size] as part of the // synchronization mechanism of the two values in the runtime. objData.RequireInitialAlignment(_targetMethod.Context.Target.PointerSize * 2); objData.AddSymbol(this); if (factory.Target.Architecture == TargetArchitecture.ARM) { objData.EmitPointerReloc(factory.InitialInterfaceDispatchStub); } else { objData.EmitPointerReloc(factory.ExternSymbol("RhpInitialDynamicInterfaceDispatch")); } if (factory.Target.Abi == TargetAbi.CoreRT) { // TODO: Enable Indirect Pointer for Interface Dispatch Cell. See https://github.com/dotnet/corert/issues/2542 objData.EmitPointerReloc(factory.NecessaryTypeSymbol(_targetMethod.OwningType), (int)InterfaceDispatchCellCachePointerFlags.CachePointerIsInterfacePointerOrMetadataToken); } else { if (factory.CompilationModuleGroup.ContainsType(_targetMethod.OwningType)) { objData.EmitReloc(factory.NecessaryTypeSymbol(_targetMethod.OwningType), RelocType.IMAGE_REL_BASED_RELPTR32, (int)InterfaceDispatchCellCachePointerFlags.CachePointerIsInterfaceRelativePointer); } else { objData.EmitReloc(factory.NecessaryTypeSymbol(_targetMethod.OwningType), RelocType.IMAGE_REL_BASED_RELPTR32, (int)InterfaceDispatchCellCachePointerFlags.CachePointerIsIndirectedInterfaceRelativePointer); } if (objData.TargetPointerSize == 8) { // IMAGE_REL_BASED_RELPTR is a 32-bit relocation. However, the cell needs a full pointer // width there since a pointer to the cache will be written into the cell. Emit additional // 32 bits on targets whose pointer size is 64 bit. objData.EmitInt(0); } } // End the run of dispatch cells objData.EmitZeroPointer(); // Avoid consulting VTable slots until they're guaranteed complete during final data emission if (!relocsOnly) { objData.EmitNaturalInt(VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, _targetMethod)); } return(objData.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder dataBuilder = new ObjectDataBuilder(factory, relocsOnly); dataBuilder.RequireInitialPointerAlignment(); dataBuilder.AddSymbol(this); EETypeRareFlags rareFlags = 0; short flags = (short)EETypeKind.GenericTypeDefEEType; if (_type.IsValueType) { flags |= (short)EETypeFlags.ValueTypeFlag; } if (_type.IsInterface) { flags |= (short)EETypeFlags.IsInterfaceFlag; } if (factory.TypeSystemContext.HasLazyStaticConstructor(_type)) { rareFlags = rareFlags | EETypeRareFlags.HasCctorFlag; } if (_type.IsByRefLike) { rareFlags |= EETypeRareFlags.IsByRefLikeFlag; } if (rareFlags != 0) { _optionalFieldsBuilder.SetFieldValue(EETypeOptionalFieldTag.RareFlags, (uint)rareFlags); } if (HasOptionalFields) { flags |= (short)EETypeFlags.OptionalFieldsFlag; } if (_type.IsEnum) { flags |= (short)EETypeBuilderHelpers.ComputeElementTypeFlags(_type); } dataBuilder.EmitShort((short)_type.Instantiation.Length); dataBuilder.EmitShort(flags); dataBuilder.EmitInt(0); // Base size is always 0 dataBuilder.EmitZeroPointer(); // No related type dataBuilder.EmitShort(0); // No VTable dataBuilder.EmitShort(0); // No interface map dataBuilder.EmitInt(_type.GetHashCode()); dataBuilder.EmitPointerReloc(factory.TypeManagerIndirection); if (HasOptionalFields) { dataBuilder.EmitPointerReloc(_optionalFieldsNode); } return(dataBuilder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder objData = new ObjectDataBuilder(factory); objData.RequireInitialPointerAlignment(); objData.AddSymbol(this); // Emit an aliased symbol named _tls_index for native P/Invoke code that uses TLS. This is required // because we do not link against libcmt.lib. ObjectAndOffsetSymbolNode aliasedSymbol = new ObjectAndOffsetSymbolNode(this, objData.CountBytes, "_tls_index", false); objData.AddSymbol(aliasedSymbol); // This is the TLS index field which is a 4-byte integer. Emit an 8-byte interger which includes a // 4-byte padding to make an pointer-sized alignment for the subsequent fields for all targets. objData.EmitLong(0); // Allocate and initialize the IMAGE_TLS_DIRECTORY PE data structure used by the OS loader to determine // TLS allocations. The structure is defined by the OS as following: /* * struct _IMAGE_TLS_DIRECTORY32 * { * DWORD StartAddressOfRawData; * DWORD EndAddressOfRawData; * DWORD AddressOfIndex; * DWORD AddressOfCallBacks; * DWORD SizeOfZeroFill; * DWORD Characteristics; * } * * struct _IMAGE_TLS_DIRECTORY64 * { * ULONGLONG StartAddressOfRawData; * ULONGLONG EndAddressOfRawData; * ULONGLONG AddressOfIndex; * ULONGLONG AddressOfCallBacks; * DWORD SizeOfZeroFill; * DWORD Characteristics; * } */ // In order to utilize linker support, the struct variable needs to be named _tls_used ObjectAndOffsetSymbolNode structSymbol = new ObjectAndOffsetSymbolNode(this, objData.CountBytes, "_tls_used", false); objData.AddSymbol(structSymbol); objData.EmitPointerReloc(factory.ThreadStaticsRegion.StartSymbol); // start of tls data objData.EmitPointerReloc(factory.ThreadStaticsRegion.EndSymbol); // end of tls data objData.EmitPointerReloc(this); // address of tls_index objData.EmitZeroPointer(); // pointer to call back array objData.EmitInt(0); // size of tls zero fill objData.EmitInt(0); // characteristics return(objData.ToObjectData()); }
protected virtual void OutputRelatedType(NodeFactory factory, ref ObjectDataBuilder objData) { ISymbolNode relatedTypeNode = GetRelatedTypeNode(factory); if (relatedTypeNode != null) { objData.EmitPointerReloc(relatedTypeNode); } else { objData.EmitZeroPointer(); } }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory); builder.DefinedSymbols.Add(this); // // Emit a MethodFixupCell struct // builder.EmitZeroPointer(); builder.EmitPointerReloc(factory.ConstantUtf8String(_entryPointName)); builder.EmitPointerReloc(factory.PInvokeModuleFixup(_moduleName)); return builder.ToObjectData(); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly) { ObjectDataBuilder objData = new ObjectDataBuilder(factory); objData.Alignment = 16; objData.DefinedSymbols.Add(this); // Todo: Generic Type Definition EETypes // Early-out just to prevent crashing at compile time... if (_type.HasInstantiation && _type.IsTypeDefinition) { objData.EmitZeroPointer(); return(objData.ToObjectData()); } ComputeOptionalEETypeFields(factory); OutputComponentSize(ref objData); OutputFlags(factory, ref objData); OutputBaseSize(ref objData); OutputRelatedType(factory, ref objData); // Avoid consulting VTable slots until they're guaranteed complete during final data emission if (!relocsOnly) { OutputVirtualSlotAndInterfaceCount(factory, ref objData); } objData.EmitInt(_type.GetHashCode()); objData.EmitPointerReloc(factory.ModuleManagerIndirection); if (_constructed) { // Avoid consulting VTable slots until they're guaranteed complete during final data emission if (!relocsOnly) { OutputVirtualSlots(factory, ref objData, _type, _type); } OutputInterfaceMap(factory, ref objData); } OutputFinalizerMethod(factory, ref objData); OutputOptionalFields(factory, ref objData); OutputNullableTypeParameter(factory, ref objData); return(objData.ToObjectData()); }
public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly) { dataBuilder.EmitZeroPointer(); // Sync block dataBuilder.EmitPointerReloc(GetEETypeNode(factory)); dataBuilder.EmitInt(_data.Length); foreach (char c in _data) { dataBuilder.EmitShort((short)c); } // Null-terminate for friendliness with interop dataBuilder.EmitShort(0); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory); builder.DefinedSymbols.Add(this); // // Emit a MethodFixupCell struct // builder.EmitZeroPointer(); builder.EmitPointerReloc(factory.ConstantUtf8String(_entryPointName)); builder.EmitPointerReloc(factory.PInvokeModuleFixup(_moduleName)); return(builder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); builder.AddSymbol(this); ISymbolNode nameSymbol = factory.ConstantUtf8String(_moduleName); // // Emit a ModuleFixupCell struct // builder.EmitZeroPointer(); builder.EmitPointerReloc(nameSymbol); return(builder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory); builder.DefinedSymbols.Add(this); ISymbolNode nameSymbol = factory.Target.IsWindows ? factory.ConstantUtf16String(_moduleName) : factory.ConstantUtf8String(_moduleName); // // Emit a ModuleFixupCell struct // builder.EmitZeroPointer(); builder.EmitPointerReloc(nameSymbol); return builder.ToObjectData(); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); builder.RequireInitialPointerAlignment(); builder.AddSymbol(this); // // Emit a MethodFixupCell struct // // Address (to be fixed up at runtime) builder.EmitZeroPointer(); // Entry point name string entryPointName = _pInvokeMethodData.EntryPointName; if (factory.Target.IsWindows && entryPointName.StartsWith("#", StringComparison.OrdinalIgnoreCase)) { // Windows-specific ordinal import // CLR-compatible behavior: Strings that can't be parsed as a signed integer are treated as zero. int entrypointOrdinal; if (!int.TryParse(entryPointName.Substring(1), out entrypointOrdinal)) { entrypointOrdinal = 0; } // CLR-compatible behavior: Ordinal imports are 16-bit on Windows. Discard rest of the bits. builder.EmitNaturalInt((ushort)entrypointOrdinal); } else { // Import by name builder.EmitPointerReloc(factory.ConstantUtf8String(entryPointName)); } // Module fixup cell builder.EmitPointerReloc(factory.PInvokeModuleFixup(_pInvokeMethodData.ModuleData)); builder.EmitInt((int)_pInvokeMethodData.CharSetMangling); return(builder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); MetadataType type = _preinitializationInfo.Type; builder.RequireInitialAlignment(factory.Target.PointerSize); // GC static fields don't begin at offset 0, need to subtract that. int initialOffset = CompilerMetadataFieldLayoutAlgorithm.GetGCStaticFieldOffset(factory.TypeSystemContext).AsInt; foreach (FieldDesc field in type.GetFields()) { if (!field.IsStatic || field.HasRva || field.IsLiteral || field.IsThreadStatic || !field.HasGCStaticBase) { continue; } int padding = field.Offset.AsInt - initialOffset - builder.CountBytes; Debug.Assert(padding >= 0); builder.EmitZeros(padding); TypePreinit.ISerializableValue val = _preinitializationInfo.GetFieldValue(field); int currentOffset = builder.CountBytes; if (val != null) { val.WriteFieldData(ref builder, field, factory); } else { builder.EmitZeroPointer(); } Debug.Assert(builder.CountBytes - currentOffset == field.FieldType.GetElementSize().AsInt); } int pad = _preinitializationInfo.Type.GCStaticFieldSize.AsInt - builder.CountBytes - initialOffset; Debug.Assert(pad >= 0); builder.EmitZeros(pad); builder.AddSymbol(this); return(builder.ToObjectData()); }
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]; 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."); } MethodDesc implMethod = implType.GetClosestDefType().FindVirtualFunctionTargetMethodOnObjectType(declMethod); if (!implMethod.IsAbstract) { MethodDesc canonImplMethod = implMethod.GetCanonMethodTarget(CanonicalFormKind.Specific); objData.EmitPointerReloc(factory.MethodEntrypoint(canonImplMethod, implMethod.OwningType.IsValueType)); } else { objData.EmitZeroPointer(); } } }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // TODO: define _tls_used as comdat select any when multiple object files present. UtcNodeFactory hostedFactory = factory as UtcNodeFactory; ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly); objData.RequireInitialPointerAlignment(); objData.AddSymbol(this); // Allocate and initialize the IMAGE_TLS_DIRECTORY PE data structure used by the OS loader to determine // TLS allocations. The structure is defined by the OS as following: /* * struct _IMAGE_TLS_DIRECTORY32 * { * DWORD StartAddressOfRawData; * DWORD EndAddressOfRawData; * DWORD AddressOfIndex; * DWORD AddressOfCallBacks; * DWORD SizeOfZeroFill; * DWORD Characteristics; * } * * struct _IMAGE_TLS_DIRECTORY64 * { * ULONGLONG StartAddressOfRawData; * ULONGLONG EndAddressOfRawData; * ULONGLONG AddressOfIndex; * ULONGLONG AddressOfCallBacks; * DWORD SizeOfZeroFill; * DWORD Characteristics; * } */ // In order to utilize linker support, the struct variable needs to be named _tls_used objData.EmitPointerReloc(hostedFactory.TlsStart); // start of tls data objData.EmitPointerReloc(hostedFactory.TlsEnd); // end of tls data objData.EmitPointerReloc(hostedFactory.ThreadStaticsIndex); // address of tls_index objData.EmitZeroPointer(); // pointer to call back array objData.EmitInt(0); // size of tls zero fill objData.EmitInt(0); // characteristics return(objData.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly); objData.RequireInitialPointerAlignment(); objData.AddSymbol(this); if (factory.MetadataManager.SupportsReflection) { NativeLayoutFieldLdTokenVertexNode ldtokenSigNode = factory.NativeLayout.FieldLdTokenVertex(_targetField); objData.EmitPointerReloc(factory.NativeLayout.NativeLayoutSignature(ldtokenSigNode, s_NativeLayoutSignaturePrefix, _targetField)); } else { objData.EmitZeroPointer(); } return(objData.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder dataBuilder = new ObjectDataBuilder(factory, relocsOnly); dataBuilder.RequireInitialPointerAlignment(); dataBuilder.AddSymbol(this); EETypeRareFlags rareFlags = 0; ushort flags = EETypeBuilderHelpers.ComputeFlags(_type); if (factory.PreinitializationManager.HasLazyStaticConstructor(_type)) { rareFlags = rareFlags | EETypeRareFlags.HasCctorFlag; } if (_type.IsByRefLike) { rareFlags |= EETypeRareFlags.IsByRefLikeFlag; } if (rareFlags != 0) { _optionalFieldsBuilder.SetFieldValue(EETypeOptionalFieldTag.RareFlags, (uint)rareFlags); } if (HasOptionalFields) { flags |= (ushort)EETypeFlags.OptionalFieldsFlag; } dataBuilder.EmitShort((short)_type.Instantiation.Length); dataBuilder.EmitUShort(flags); dataBuilder.EmitInt(0); // Base size is always 0 dataBuilder.EmitZeroPointer(); // No related type dataBuilder.EmitShort(0); // No VTable dataBuilder.EmitShort(0); // No interface map dataBuilder.EmitInt(_type.GetHashCode()); OutputTypeManagerIndirection(factory, ref dataBuilder); OutputWritableData(factory, ref dataBuilder); OutputOptionalFields(factory, ref dataBuilder); return(dataBuilder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory); builder.DefinedSymbols.Add(this); // // Emit a ModuleFixupCell struct // builder.EmitZeroPointer(); Encoding encoding = factory.Target.IsWindows ? Encoding.Unicode : Encoding.UTF8; int moduleNameBytesCount = encoding.GetByteCount(_moduleName); byte[] moduleNameBytes = new byte[moduleNameBytesCount + 2]; encoding.GetBytes(_moduleName, 0, _moduleName.Length, moduleNameBytes, 0); builder.EmitPointerReloc(factory.ReadOnlyDataBlob("__modulename_" + _moduleName, moduleNameBytes, 2)); return builder.ToObjectData(); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory); builder.DefinedSymbols.Add(this); // // Emit a MethodFixupCell struct // builder.EmitZeroPointer(); int entryPointBytesCount = Encoding.UTF8.GetByteCount(_entryPointName); byte[] entryPointNameBytes = new byte[entryPointBytesCount + 1]; Encoding.UTF8.GetBytes(_entryPointName, 0, _entryPointName.Length, entryPointNameBytes, 0); builder.EmitPointerReloc(factory.ReadOnlyDataBlob("__pinvokename_" + _entryPointName, entryPointNameBytes, 1)); builder.EmitPointerReloc(factory.PInvokeModuleFixup(_moduleName)); return builder.ToObjectData(); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly) { ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); // If the type has a class constructor, its non-GC statics section is prefixed // by System.Runtime.CompilerServices.StaticClassConstructionContext struct. if (factory.TypeSystemContext.HasLazyStaticConstructor(_type)) { int alignmentRequired = Math.Max(_type.NonGCStaticFieldAlignment.AsInt, GetClassConstructorContextAlignment(_type.Context.Target)); int classConstructorContextStorageSize = GetClassConstructorContextStorageSize(factory.Target, _type); builder.RequireInitialAlignment(alignmentRequired); Debug.Assert(classConstructorContextStorageSize >= GetClassConstructorContextSize(_type.Context.Target)); // Add padding before the context if alignment forces us to do so builder.EmitZeros(classConstructorContextStorageSize - GetClassConstructorContextSize(_type.Context.Target)); // Emit the actual StaticClassConstructionContext MethodDesc cctorMethod = _type.GetStaticConstructor(); MethodDesc canonCctorMethod = cctorMethod.GetCanonMethodTarget(CanonicalFormKind.Specific); if (cctorMethod != canonCctorMethod) { builder.EmitPointerReloc(factory.FatFunctionPointer(cctorMethod), FatFunctionPointerConstants.Offset); } else { builder.EmitPointerReloc(factory.MethodEntrypoint(cctorMethod)); } builder.EmitZeroPointer(); } else { builder.RequireInitialAlignment(_type.NonGCStaticFieldAlignment.AsInt); } builder.EmitZeros(_type.NonGCStaticFieldSize.AsInt); builder.AddSymbol(this); return(builder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory); builder.DefinedSymbols.Add(this); // // Emit a MethodFixupCell struct // builder.EmitZeroPointer(); int entryPointBytesCount = Encoding.UTF8.GetByteCount(_entryPointName); byte[] entryPointNameBytes = new byte[entryPointBytesCount + 1]; Encoding.UTF8.GetBytes(_entryPointName, 0, _entryPointName.Length, entryPointNameBytes, 0); builder.EmitPointerReloc(factory.ReadOnlyDataBlob("__pinvokename_" + _entryPointName, entryPointNameBytes, 1)); builder.EmitPointerReloc(factory.PInvokeModuleFixup(_moduleName)); return(builder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder dataBuilder = new ObjectDataBuilder(factory); dataBuilder.Alignment = 16; dataBuilder.DefinedSymbols.Add(this); short flags = (short)EETypeKind.GenericTypeDefEEType; if (_type.IsValueType) flags |= (short)EETypeFlags.ValueTypeFlag; if (_type.IsInterface) flags |= (short)EETypeFlags.IsInterfaceFlag; dataBuilder.EmitShort((short)_type.Instantiation.Length); dataBuilder.EmitShort(flags); dataBuilder.EmitInt(0); // Base size is always 0 dataBuilder.EmitZeroPointer(); // No related type dataBuilder.EmitShort(0); // No VTable dataBuilder.EmitShort(0); // No interface map dataBuilder.EmitInt(_type.GetHashCode()); dataBuilder.EmitPointerReloc(factory.ModuleManagerIndirection); return dataBuilder.ToObjectData(); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder dataBuilder = new ObjectDataBuilder(factory); dataBuilder.Alignment = dataBuilder.TargetPointerSize; dataBuilder.DefinedSymbols.Add(this); EETypeRareFlags rareFlags = 0; short flags = (short)EETypeKind.GenericTypeDefEEType; if (_type.IsValueType) flags |= (short)EETypeFlags.ValueTypeFlag; if (_type.IsInterface) flags |= (short)EETypeFlags.IsInterfaceFlag; if (factory.TypeSystemContext.HasLazyStaticConstructor(_type)) rareFlags = rareFlags | EETypeRareFlags.HasCctorFlag; if (rareFlags != 0) _optionalFieldsBuilder.SetFieldValue(EETypeOptionalFieldTag.RareFlags, (uint)rareFlags); if (_optionalFieldsBuilder.IsAtLeastOneFieldUsed()) flags |= (short)EETypeFlags.OptionalFieldsFlag; dataBuilder.EmitShort((short)_type.Instantiation.Length); dataBuilder.EmitShort(flags); dataBuilder.EmitInt(0); // Base size is always 0 dataBuilder.EmitZeroPointer(); // No related type dataBuilder.EmitShort(0); // No VTable dataBuilder.EmitShort(0); // No interface map dataBuilder.EmitInt(_type.GetHashCode()); dataBuilder.EmitPointerReloc(factory.ModuleManagerIndirection); if (_optionalFieldsBuilder.IsAtLeastOneFieldUsed()) { dataBuilder.EmitPointerReloc(factory.EETypeOptionalFields(_optionalFieldsBuilder)); } return dataBuilder.ToObjectData(); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly) { ObjectDataBuilder builder = new ObjectDataBuilder(factory); // If the type has a class constructor, its non-GC statics section is prefixed // by System.Runtime.CompilerServices.StaticClassConstructionContext struct. if (factory.TypeSystemContext.HasLazyStaticConstructor(_type)) { int alignmentRequired = Math.Max(_type.NonGCStaticFieldAlignment, GetClassConstructorContextAlignment(_type.Context.Target)); int classConstructorContextStorageSize = GetClassConstructorContextStorageSize(factory.Target, _type); builder.RequireAlignment(alignmentRequired); Debug.Assert(classConstructorContextStorageSize >= GetClassConstructorContextSize(_type.Context.Target)); // Add padding before the context if alignment forces us to do so builder.EmitZeros(classConstructorContextStorageSize - GetClassConstructorContextSize(_type.Context.Target)); // Emit the actual StaticClassConstructionContext MethodDesc cctorMethod = _type.GetStaticConstructor(); MethodDesc canonCctorMethod = cctorMethod.GetCanonMethodTarget(CanonicalFormKind.Specific); if (cctorMethod != canonCctorMethod) builder.EmitPointerReloc(factory.FatFunctionPointer(cctorMethod), FatFunctionPointerConstants.Offset); else builder.EmitPointerReloc(factory.MethodEntrypoint(cctorMethod)); builder.EmitZeroPointer(); } else { builder.RequireAlignment(_type.NonGCStaticFieldAlignment); } builder.EmitZeros(_type.NonGCStaticFieldSize); builder.DefinedSymbols.Add(this); return builder.ToObjectData(); }
public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly) { dataBuilder.EmitZeroPointer(); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly) { ObjectDataBuilder objData = new ObjectDataBuilder(factory); objData.Alignment = 16; objData.DefinedSymbols.Add(this); if (_type.IsArray) { objData.EmitShort((short)((ArrayType)_type).ElementType.GetElementSize()); // m_ComponentSize objData.EmitShort(0x4); // m_flags: IsArray(0x4) } else if (_type.IsString) { objData.EmitShort(2); // m_ComponentSize objData.EmitShort(0); // m_flags: 0 } else { objData.EmitShort(0); // m_ComponentSize objData.EmitShort(0); // m_flags: 0 } int pointerSize = _type.Context.Target.PointerSize; int minimumObjectSize = pointerSize * 3; int objectSize; if (_type is MetadataType) { objectSize = pointerSize + ((MetadataType)_type).InstanceByteCount; // +pointerSize for SyncBlock } else if (_type is ArrayType) { objectSize = 3 * pointerSize; // SyncBlock + EETypePtr + Length int rank = ((ArrayType)_type).Rank; if (rank > 1) objectSize += 2 * _type.Context.GetWellKnownType(WellKnownType.Int32).GetElementSize() * rank; } else throw new NotImplementedException(); objectSize = AlignmentHelper.AlignUp(objectSize, pointerSize); objectSize = Math.Max(minimumObjectSize, objectSize); if (_type.IsString) { // If this is a string, throw away objectSize we computed so far. Strings are special. // SyncBlock + EETypePtr + length + firstChar objectSize = 2 * pointerSize + _type.Context.GetWellKnownType(WellKnownType.Int32).GetElementSize() + _type.Context.GetWellKnownType(WellKnownType.Char).GetElementSize(); } objData.EmitInt(objectSize); if (Type.BaseType != null) { if (_constructed) { objData.EmitPointerReloc(factory.ConstructedTypeSymbol(Type.BaseType)); } else { objData.EmitPointerReloc(factory.NecessaryTypeSymbol(Type.BaseType)); } } else { objData.EmitZeroPointer(); } if (_constructed) { OutputVirtualSlots(ref objData, _type, _type, factory); } return objData.ToObjectData(); }
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(); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory); builder.Alignment = factory.Target.PointerSize; builder.DefinedSymbols.Add(this); // Don't bother sorting if we're not emitting the contents if (!relocsOnly) _items.Sort((x, y) => Comparer<int>.Default.Compare((int)x.Id, (int)y.Id)); // ReadyToRunHeader.Magic builder.EmitInt((int)(ReadyToRunHeaderConstants.Signature)); // ReadyToRunHeader.MajorVersion builder.EmitShort((short)(ReadyToRunHeaderConstants.CurrentMajorVersion)); builder.EmitShort((short)(ReadyToRunHeaderConstants.CurrentMinorVersion)); // ReadyToRunHeader.Flags builder.EmitInt(0); // ReadyToRunHeader.NumberOfSections var sectionCountReservation = builder.ReserveShort(); // ReadyToRunHeader.EntrySize builder.EmitByte((byte)(8 + 2 * factory.Target.PointerSize)); // ReadyToRunHeader.EntryType builder.EmitByte(1); int count = 0; foreach (var item in _items) { // Skip empty entries if (item.Node.ShouldSkipEmittingObjectNode(factory)) continue; builder.EmitInt((int)item.Id); ModuleInfoFlags flags = 0; if (item.EndSymbol != null) { flags |= ModuleInfoFlags.HasEndPointer; } builder.EmitInt((int)flags); builder.EmitPointerReloc(item.StartSymbol); if (item.EndSymbol != null) { builder.EmitPointerReloc(item.EndSymbol); } else { builder.EmitZeroPointer(); } count++; } builder.EmitShort(sectionCountReservation, checked((short)count)); return builder.ToObjectData(); }
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(); } }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly) { ObjectDataBuilder objData = new ObjectDataBuilder(factory); objData.Alignment = 16; objData.DefinedSymbols.Add(this); // Todo: Generic Type Definition EETypes // Early-out just to prevent crashing at compile time... if (_type.HasInstantiation && _type.IsTypeDefinition) { objData.EmitZeroPointer(); return objData.ToObjectData(); } ComputeOptionalEETypeFields(factory); OutputComponentSize(ref objData); OutputFlags(factory, ref objData); OutputBaseSize(ref objData); OutputRelatedType(factory, ref objData); OutputVirtualSlotAndInterfaceCount(factory, ref objData); objData.EmitInt(_type.GetHashCode()); if (_constructed) { OutputVirtualSlots(factory, ref objData, _type, _type); OutputInterfaceMap(factory, ref objData); } OutputFinalizerMethod(factory, ref objData); OutputOptionalFields(factory, ref objData); OutputNullableTypeParameter(factory, ref objData); return objData.ToObjectData(); }
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(); } } }
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(); } } }