public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); builder.RequireInitialPointerAlignment(); if (factory.Target.Abi == TargetAbi.CoreRT) { int delta = GCStaticRegionConstants.Uninitialized; // Set the flag that indicates next pointer following EEType is the preinit data if (_preInitFieldInfos != null) { delta |= GCStaticRegionConstants.HasPreInitializedData; } builder.EmitPointerReloc(GetGCStaticEETypeNode(factory), delta); if (_preInitFieldInfos != null) { builder.EmitPointerReloc(factory.GCStaticsPreInitDataNode(_type)); } } else { builder.RequireInitialAlignment(_type.GCStaticFieldAlignment.AsInt); // @TODO - emit the frozen array node reloc builder.EmitZeros(_type.GCStaticFieldSize.AsInt); } builder.AddSymbol(this); return(builder.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); }
private void OutputGenericInstantiationDetails(NodeFactory factory, ref ObjectDataBuilder objData) { if (_type.HasInstantiation && !_type.IsTypeDefinition) { objData.EmitPointerReloc(factory.NecessaryTypeSymbol(_type.GetTypeDefinition())); GenericCompositionDetails details; if (_type.GetTypeDefinition() == factory.ArrayOfTEnumeratorType) { // Generic array enumerators use special variance rules recognized by the runtime details = new GenericCompositionDetails(_type.Instantiation, new[] { GenericVariance.ArrayCovariant }); } else if (factory.TypeSystemContext.IsGenericArrayInterfaceType(_type)) { // Runtime casting logic relies on all interface types implemented on arrays // to have the variant flag set (even if all the arguments are non-variant). // This supports e.g. casting uint[] to ICollection<int> details = new GenericCompositionDetails(_type, forceVarianceInfo: true); } else { details = new GenericCompositionDetails(_type); } objData.EmitPointerReloc(factory.GenericComposition(details)); } }
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) { 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(); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); builder.RequireInitialPointerAlignment(); int delta = GCStaticRegionConstants.Uninitialized; // Set the flag that indicates next pointer following EEType is the preinit data bool isPreinitialized = _preinitializationInfo != null && _preinitializationInfo.IsPreinitialized; if (isPreinitialized) { delta |= GCStaticRegionConstants.HasPreInitializedData; } builder.EmitPointerReloc(GetGCStaticEETypeNode(factory), delta); if (isPreinitialized) { builder.EmitPointerReloc(factory.GCStaticsPreInitDataNode(_type)); } builder.AddSymbol(this); return(builder.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) { 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 GenericDictionaryNode dictionary; if (canonMethod.RequiresInstMethodDescArg()) { dictionary = factory.MethodGenericDictionary(Method); } else { Debug.Assert(canonMethod.RequiresInstMethodTableArg()); dictionary = factory.TypeGenericDictionary(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(dictionary)); 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(_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()); }
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 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()); }
public override void EncodeData(ref ObjectDataBuilder objData, NodeFactory factory, bool relocsOnly) { TargetArchitecture targetArchitecture = factory.Target.Architecture; if (targetArchitecture == TargetArchitecture.ARM) { objData.EmitPointerReloc(factory.InitialInterfaceDispatchStub); } else { objData.EmitPointerReloc(factory.ExternSymbol("RhpInitialDynamicInterfaceDispatch")); } IEETypeNode interfaceType = factory.NecessaryTypeSymbol(_targetMethod.OwningType); if (interfaceType.RepresentsIndirectionCell) { objData.EmitReloc(interfaceType, RelocType.IMAGE_REL_BASED_RELPTR32, (int)InterfaceDispatchCellCachePointerFlags.CachePointerIsIndirectedInterfaceRelativePointer); } else { objData.EmitReloc(interfaceType, RelocType.IMAGE_REL_BASED_RELPTR32, (int)InterfaceDispatchCellCachePointerFlags.CachePointerIsInterfaceRelativePointer); } 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); } }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { var builder = new ObjectDataBuilder(factory, relocsOnly); // These need to be aligned the same as methods because they show up in same contexts builder.RequireInitialAlignment(factory.Target.MinimumFunctionAlignment); builder.AddSymbol(this); MethodDesc canonMethod = Method.GetCanonMethodTarget(CanonicalFormKind.Specific); // Pointer to the canonical body of the method builder.EmitPointerReloc(factory.MethodEntrypoint(canonMethod, _isUnboxingStub)); // 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()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this })); } Debug.Assert(_dynamicInvokeMethodContainerType != null); // Ensure the native layout blob has been saved factory.MetadataManager.NativeLayoutInfo.SaveNativeLayoutInfoWriter(factory); ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly); objData.RequireInitialPointerAlignment(); objData.AddSymbol(this); if (factory.Target.SupportsRelativePointers) { objData.EmitReloc(factory.NecessaryTypeSymbol(_dynamicInvokeMethodContainerType), RelocType.IMAGE_REL_BASED_RELPTR32); } else { objData.EmitPointerReloc(factory.NecessaryTypeSymbol(_dynamicInvokeMethodContainerType)); } List <KeyValuePair <MethodDesc, int> > sortedList = new List <KeyValuePair <MethodDesc, int> >(_methodToTemplateIndex); sortedList.Sort((firstEntry, secondEntry) => firstEntry.Value.CompareTo(secondEntry.Value)); for (int i = 0; i < sortedList.Count; i++) { var nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(sortedList[i].Key)); if (factory.Target.SupportsRelativePointers) { objData.EmitInt(nameAndSig.SavedVertex.VertexOffset); objData.EmitReloc(factory.MethodEntrypoint(sortedList[i].Key), RelocType.IMAGE_REL_BASED_RELPTR32); } else { objData.EmitNaturalInt(nameAndSig.SavedVertex.VertexOffset); objData.EmitPointerReloc(factory.MethodEntrypoint(sortedList[i].Key)); } } _endSymbol.SetSymbolOffset(objData.CountBytes); objData.AddSymbol(_endSymbol); // Prevent further adds now we're done writing #if DEBUG if (!relocsOnly) { _dataEmitted = true; } #endif return(objData.ToObjectData()); }
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 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); // 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 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()); }
public override void EmitDictionaryEntry(ref ObjectDataBuilder builder, NodeFactory factory, Instantiation typeInstantiation, Instantiation methodInstantiation, GenericDictionaryNode dictionary) { ISymbolNode target = GetTarget(factory, typeInstantiation, methodInstantiation, dictionary); if (target is IFatFunctionPointerNode) { builder.EmitPointerReloc(target, FatFunctionPointerConstants.Offset); } else { builder.EmitPointerReloc(target); } }
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 = 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) { if (factory.Target.Abi == TargetAbi.CoreRT || factory.Target.Abi == TargetAbi.CppCodegen) { ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); builder.RequireInitialPointerAlignment(); int delta = GCStaticRegionConstants.Uninitialized; // Set the flag that indicates next pointer following EEType is the preinit data if (_preInitFieldInfos != null) { delta |= GCStaticRegionConstants.HasPreInitializedData; } builder.EmitPointerReloc(GetGCStaticEETypeNode(factory), delta); if (_preInitFieldInfos != null) { builder.EmitPointerReloc(factory.GCStaticsPreInitDataNode(_type)); } builder.AddSymbol(this); return(builder.ToObjectData()); } else { if (_preInitFieldInfos == null) { ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); builder.RequireInitialPointerAlignment(); builder.EmitZeros(_type.GCStaticFieldSize.AsInt); builder.AddSymbol(this); return(builder.ToObjectData()); } else { _preInitFieldInfos.Sort(PreInitFieldInfo.FieldDescCompare); return(GCStaticsPreInitDataNode.GetDataForPreInitDataField(this, _type, _preInitFieldInfos, 0, factory, relocsOnly)); } } }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // This node does not trigger generation of other nodes. if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this })); } // Zero out the dictionary so that we AV if someone tries to insert after we're done. _insertedSymbolsDictionary = null; var builder = new ObjectDataBuilder(factory, relocsOnly); foreach (SymbolAndDelta symbolAndDelta in _insertedSymbols) { if (factory.Target.SupportsRelativePointers) { // TODO: set low bit if the linkage of the symbol is IAT_PVALUE. builder.EmitReloc(symbolAndDelta.Symbol, RelocType.IMAGE_REL_BASED_RELPTR32, symbolAndDelta.Delta); } else { builder.EmitPointerReloc(symbolAndDelta.Symbol, symbolAndDelta.Delta); } } _endSymbol.SetSymbolOffset(builder.CountBytes); builder.AddSymbol(this); builder.AddSymbol(_endSymbol); return(builder.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(); } }
protected override void OutputRelatedType(NodeFactory factory, ref ObjectDataBuilder objData) { // // Cloned types use the related type field to point via an IAT slot at their true implementation // objData.EmitPointerReloc(factory.NecessaryTypeSymbol(_type)); }
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()); }
protected override void OutputRelatedType(NodeFactory factory, ref ObjectDataBuilder objData) { // // Cloned types use the related type field to point via an IAT slot at their true implementation // objData.EmitPointerReloc(factory.NecessaryTypeSymbol(_type)); }
protected override void OutputInterfaceMap(NodeFactory factory, ref ObjectDataBuilder objData) { foreach (var itf in _type.RuntimeInterfaces) { objData.EmitPointerReloc(factory.NecessaryTypeSymbol(itf)); } }
private void OutputOptionalFields(NodeFactory factory, ref ObjectDataBuilder objData) { if (HasOptionalFields) { objData.EmitPointerReloc(_optionalFieldsNode); } }
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(); } } } }
private void OutputOptionalFields(NodeFactory factory, ref ObjectDataBuilder objData) { if (_optionalFieldsBuilder.IsAtLeastOneFieldUsed()) { objData.EmitPointerReloc(_optionalFieldsNode); } }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly) { ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly); objData.RequireInitialAlignment(4); objData.AddSymbol(this); if (BuildSealedVTableSlots(factory, relocsOnly)) { for (int i = 0; i < _sealedVTableEntries.Count; i++) { MethodDesc canonImplMethod = _sealedVTableEntries[i].GetCanonMethodTarget(CanonicalFormKind.Specific); IMethodNode relocTarget = factory.MethodEntrypoint(canonImplMethod, _sealedVTableEntries[i].OwningType.IsValueType); if (factory.Target.SupportsRelativePointers) { objData.EmitReloc(relocTarget, RelocType.IMAGE_REL_BASED_RELPTR32); } else { objData.EmitPointerReloc(relocTarget); } } } return(objData.ToObjectData()); }
private void OutputNullableTypeParameter(NodeFactory factory, ref ObjectDataBuilder objData) { if (_type.IsNullable) { objData.EmitPointerReloc(factory.NecessaryTypeSymbol(_type.Instantiation[0])); } }
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()); }
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(); } }
public override void EncodeData(ref ObjectDataBuilder builder, NodeFactory factory, bool relocsOnly) { // At runtime, an instance of the GCStaticEEType will be created and a GCHandle to it // will be written in this location. builder.RequireInitialPointerAlignment(); builder.EmitPointerReloc(GetGCStaticEETypeNode(factory)); }
public override void EncodeData(ref ObjectDataBuilder builder, NodeFactory factory, bool relocsOnly) { builder.RequirePointerAlignment(); // At runtime, an instance of the GCStaticEEType will be created and a GCHandle to it // will be written in this location. builder.EmitPointerReloc(GetGCStaticEETypeNode(factory)); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder objData = new ObjectDataBuilder(factory); objData.RequirePointerAlignment(); objData.DefinedSymbols.Add(this); objData.EmitPointerReloc(factory.ReadyToRunHeader); return objData.ToObjectData(); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { var builder = new ObjectDataBuilder(factory); builder.RequirePointerAlignment(); builder.DefinedSymbols.Add(this); builder.EmitPointerReloc(_indirectedNode); return builder.ToObjectData(); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory); builder.RequirePointerAlignment(); builder.EmitPointerReloc(GetGCStaticEETypeNode(factory), 1); builder.DefinedSymbols.Add(this); return builder.ToObjectData(); }
public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly) { dataBuilder.RequirePointerAlignment(); StringDataNode stringDataNode = factory.StringData(_data); if (!relocsOnly) stringDataNode.SetId(base.Offset); dataBuilder.EmitPointerReloc(stringDataNode); }
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(); }
protected virtual void EmitDataInternal(ref ObjectDataBuilder builder, NodeFactory factory) { DictionaryLayoutNode layout = GetDictionaryLayout(factory); Instantiation typeInst = this.TypeInstantiation; Instantiation methodInst = this.MethodInstantiation; foreach (var entry in layout.Entries) { ISymbolNode targetNode = entry.GetTarget(factory, typeInst, methodInst); builder.EmitPointerReloc(targetNode); } }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder objData = new ObjectDataBuilder(factory); objData.Alignment = factory.Target.PointerSize; objData.DefinedSymbols.Add(this); foreach (var map in _dispatchMaps) { objData.EmitPointerReloc(map); } return objData.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 = 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); 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 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) { ObjectDataBuilder objData = new ObjectDataBuilder(factory); objData.Alignment = objData.TargetPointerSize; objData.DefinedSymbols.Add(this); ComputeOptionalEETypeFields(factory); OutputGCDesc(ref objData); 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.TypeManagerIndirection); // 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); OutputGenericInstantiationDetails(factory, ref objData); return objData.ToObjectData(); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly) { ObjectDataBuilder dataBuilder = new ObjectDataBuilder(factory); dataBuilder.Alignment = 16; dataBuilder.DefinedSymbols.Add(this); // +2 for SyncBlock and EETypePtr field int totalSize = (_gcMap.Size + 2) * _target.PointerSize; // We only need to check for containsPointers because ThreadStatics are always allocated // on the GC heap (no matter what "HasGCStaticBase" says). // If that ever changes, we can assume "true" and switch this to an assert. bool containsPointers = _gcMap.NumSeries > 0; if (containsPointers) { GCDescEncoder.EncodeStandardGCDesc(ref dataBuilder, _gcMap, totalSize, 0); } Debug.Assert(dataBuilder.CountBytes == Offset); dataBuilder.EmitShort(0); // ComponentSize is always 0 short flags = 0; if (containsPointers) flags |= (short)EETypeFlags.HasPointersFlag; dataBuilder.EmitShort(flags); totalSize = Math.Max(totalSize, _target.PointerSize * 3); // minimum GC eetype size is 3 pointers dataBuilder.EmitInt(totalSize); // Related type: System.Object. This allows storing an instance of this type in an array of objects. dataBuilder.EmitPointerReloc(factory.NecessaryTypeSymbol(factory.TypeSystemContext.GetWellKnownType(WellKnownType.Object))); return dataBuilder.ToObjectData(); }
private void OutputFinalizerMethod(NodeFactory factory, ref ObjectDataBuilder objData) { MethodDesc finalizerMethod = _type.GetFinalizer(); if (finalizerMethod != null) { objData.EmitPointerReloc(factory.MethodEntrypoint(finalizerMethod)); } }
private void OutputOptionalFields(NodeFactory factory, ref ObjectDataBuilder objData) { if(_optionalFieldsBuilder.IsAtLeastOneFieldUsed()) { objData.EmitPointerReloc(factory.EETypeOptionalFields(_optionalFieldsBuilder)); } }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // This node does not trigger generation of other nodes. if (relocsOnly) return new ObjectData(Array.Empty<byte>(), Array.Empty<Relocation>(), 1, new ISymbolNode[] { this }); ObjectDataBuilder builder = new ObjectDataBuilder(factory); foreach (var mappingEntry in factory.MetadataManager.GetTypeDefinitionMapping()) { if (!factory.CompilationModuleGroup.ContainsType(mappingEntry.Entity)) continue; // We are looking for any EEType - constructed or not, it has to be in the mapping // table so that we can map it to metadata. EETypeNode node = null; if (!mappingEntry.Entity.IsGenericDefinition) { node = factory.ConstructedTypeSymbol(mappingEntry.Entity) as EETypeNode; } if (node == null || !node.Marked) { // This might have been a typeof() expression. node = factory.NecessaryTypeSymbol(mappingEntry.Entity) as EETypeNode; } if (node.Marked) { // TODO: this format got very inefficient due to not being able to use RVAs // replace with a hash table builder.EmitPointerReloc(node); builder.EmitInt(mappingEntry.MetadataHandle); if (factory.Target.PointerSize == 8) builder.EmitInt(0); // Pad } } _endSymbol.SetSymbolOffset(builder.CountBytes); builder.DefinedSymbols.Add(this); builder.DefinedSymbols.Add(_endSymbol); return builder.ToObjectData(); }
protected override void OutputInterfaceMap(NodeFactory factory, ref ObjectDataBuilder objData) { foreach (var itf in _type.RuntimeInterfaces) { objData.EmitPointerReloc(factory.NecessaryTypeSymbol(itf)); } }
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(); } } }
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(); } }
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)); } }
private void OutputOptionalFields(NodeFactory factory, ref ObjectDataBuilder objData) { if (HasOptionalFields) { objData.EmitPointerReloc(_optionalFieldsNode); } }
private void OutputNullableTypeParameter(NodeFactory factory, ref ObjectDataBuilder objData) { if (_type.IsNullable) { objData.EmitPointerReloc(factory.NecessaryTypeSymbol(_type.Instantiation[0])); } }
private void OutputGenericInstantiationDetails(NodeFactory factory, ref ObjectDataBuilder objData) { if (_type.HasInstantiation && !_type.IsTypeDefinition) { objData.EmitPointerReloc(factory.NecessaryTypeSymbol(_type.GetTypeDefinition())); GenericCompositionDetails details; if (_type.GetTypeDefinition() == factory.ArrayOfTEnumeratorType) { // Generic array enumerators use special variance rules recognized by the runtime details = new GenericCompositionDetails(_type.Instantiation, new[] { GenericVariance.ArrayCovariant }); } else details = new GenericCompositionDetails(_type); objData.EmitPointerReloc(factory.GenericComposition(details)); } }