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(); builder.EmitPointerReloc(factory.ExactCallableAddress(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, 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 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()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly) { Debug.Assert(MethodHasAssociatedData(factory, _methodNode)); ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly); objData.RequireInitialAlignment(1); objData.AddSymbol(this); AssociatedDataFlags flags = AssociatedDataFlags.None; var flagsReservation = objData.ReserveByte(); ISpecialUnboxThunkNode unboxThunkNode = _methodNode as ISpecialUnboxThunkNode; if (unboxThunkNode != null && unboxThunkNode.IsSpecialUnboxingThunk) { flags |= AssociatedDataFlags.HasUnboxingStubTarget; objData.EmitReloc(unboxThunkNode.GetUnboxingThunkTarget(factory), RelocType.IMAGE_REL_BASED_RELPTR32); } objData.EmitByte(flagsReservation, (byte)flags); return(objData.ToObjectData()); }
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++) { IMethodNode relocTarget = _sealedVTableEntries[i].GetTarget(factory, _type); if (factory.Target.SupportsRelativePointers) { objData.EmitReloc(relocTarget, RelocType.IMAGE_REL_BASED_RELPTR32); } else { objData.EmitPointerReloc(relocTarget); } } } return(objData.ToObjectData()); }
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); builder.RequireInitialAlignment(factory.Target.SupportsRelativePointers ? 4 : factory.Target.PointerSize); 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()); }
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) { 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) { // Emit a 4-byte integer flag with initial value of 0. // TODO: define it as "comdat select any" when multiple object files present. ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly); objData.RequireInitialAlignment(4); objData.AddSymbol(this); objData.EmitInt(0); return(objData.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { Debug.Assert(factory.Target.IsWindows); ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly); objData.RequireInitialAlignment(factory.Target.MinimumFunctionAlignment); objData.AddSymbol(this); return(objData.ToObjectData()); }
public static ObjectData GetDataForPreInitDataField( ISymbolDefinitionNode node, MetadataType _type, List <PreInitFieldInfo> sortedPreInitFields, int startOffset, NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); builder.RequireInitialAlignment(_type.GCStaticFieldAlignment.AsInt); int staticOffset = startOffset; int staticOffsetEnd = _type.GCStaticFieldSize.AsInt; int idx = 0; while (staticOffset < staticOffsetEnd) { PreInitFieldInfo fieldInfo = idx < sortedPreInitFields.Count ? sortedPreInitFields[idx] : null; int writeTo = staticOffsetEnd; if (fieldInfo != null) { writeTo = fieldInfo.Field.Offset.AsInt; } // Emit the zero before the next preinitField builder.EmitZeros(writeTo - staticOffset); staticOffset = writeTo; if (fieldInfo != null) { int count = builder.CountBytes; if (fieldInfo.Field.FieldType.IsValueType) { // Emit inlined data for value types fieldInfo.WriteData(ref builder, factory); } else { // Emit a pointer reloc to the frozen data for reference types builder.EmitPointerReloc(factory.SerializedFrozenArray(fieldInfo)); } staticOffset += builder.CountBytes - count; idx++; } } builder.AddSymbol(node); return(builder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly); objData.RequireInitialAlignment(16); objData.AddSymbol(this); if (!relocsOnly) { EmitDispatchMap(ref objData, factory); } return(objData.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly); objData.RequireInitialAlignment(1); objData.AddSymbol(this); if (!relocsOnly) { _owner.ComputeOptionalEETypeFields(factory, relocsOnly: false); objData.EmitBytes(_owner.GetOptionalFieldsData()); } return(objData.ToObjectData()); }
public override void EncodeData(ref ObjectDataBuilder builder, NodeFactory factory, bool relocsOnly) { if (factory.Target.Abi == TargetAbi.CoreRT) { // 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)); } else { builder.RequireInitialAlignment(_type.ThreadStaticFieldAlignment.AsInt); builder.EmitZeros(_type.ThreadStaticFieldSize.AsInt); } }
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()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory); builder.RequireInitialPointerAlignment(); if (factory.Target.Abi == TargetAbi.CoreRT) { builder.EmitPointerReloc(GetGCStaticEETypeNode(factory), 1); } else { builder.RequireInitialAlignment(_type.GCStaticFieldAlignment); builder.EmitZeros(_type.GCStaticFieldSize); } builder.AddSymbol(this); return(builder.ToObjectData()); }
public static ObjectData GetDataForPreInitDataField( ISymbolDefinitionNode node, MetadataType _type, List <PreInitFieldInfo> sortedPreInitFields, int startOffset, NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); builder.RequireInitialAlignment(_type.GCStaticFieldAlignment.AsInt); int staticOffset = startOffset; int staticOffsetEnd = _type.GCStaticFieldSize.AsInt; int idx = 0; while (staticOffset < staticOffsetEnd) { int writeTo = staticOffsetEnd; if (idx < sortedPreInitFields.Count) { writeTo = sortedPreInitFields[idx].Field.Offset.AsInt; } // Emit the zero before the next preinitField builder.EmitZeros(writeTo - staticOffset); staticOffset = writeTo; // Emit a pointer reloc to the frozen data if (idx < sortedPreInitFields.Count) { builder.EmitPointerReloc(factory.SerializedFrozenArray(sortedPreInitFields[idx])); idx++; staticOffset += factory.Target.PointerSize; } } builder.AddSymbol(node); return(builder.ToObjectData()); }
protected override void GetElementDataForNodes(ref ObjectDataBuilder builder, NodeFactory factory, bool relocsOnly) { if (relocsOnly) { return; } // 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. builder.RequireInitialAlignment(factory.Target.PointerSize * 2); // This number chosen to be high enough that the cost of recording slot numbers is cheap. const int InterfaceDispatchCellRunLength = 32; const int NoSlot = -1; // // We emit the individual dispatch cells in groups. The purpose of the grouping is to save // us the number of slots we need to emit. The grouping looks like this: // // DispatchCell1 // DispatchCell2 // ... // DispatchCellN // Null // Slot of the above dispatch cells // int runLength = 0; int currentSlot = NoSlot; foreach (InterfaceDispatchCellNode node in NodesList) { MethodDesc targetMethod = node.TargetMethod; int targetSlot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, targetMethod, targetMethod.OwningType); if (currentSlot == NoSlot) { // This is the first dispatch cell we're emitting currentSlot = targetSlot; } else if (currentSlot != targetSlot || runLength == InterfaceDispatchCellRunLength) { // Make sure we are sorted Debug.Assert(targetSlot >= currentSlot); // End the run of dispatch cells builder.EmitZeroPointer(); builder.EmitNaturalInt(currentSlot); currentSlot = targetSlot; runLength = 0; } node.InitializeOffsetFromBeginningOfArray(builder.CountBytes); node.EncodeData(ref builder, factory, relocsOnly); builder.AddSymbol(node); runLength++; } if (runLength > 0) { // End the run of dispatch cells builder.EmitZeroPointer(); builder.EmitNaturalInt(currentSlot); } }
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.PreinitializationManager.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(); builder.EmitPointerReloc(factory.ExactCallableAddress(cctorMethod)); builder.EmitZeroPointer(); } else { builder.RequireInitialAlignment(_type.NonGCStaticFieldAlignment.AsInt); } if (_preinitializationManager.IsPreinitialized(_type)) { TypePreinit.PreinitializationInfo preinitInfo = _preinitializationManager.GetPreinitializationInfo(_type); int initialOffset = builder.CountBytes; foreach (FieldDesc field in _type.GetFields()) { if (!field.IsStatic || field.HasRva || field.IsLiteral || field.IsThreadStatic || field.HasGCStaticBase) { continue; } int padding = field.Offset.AsInt - builder.CountBytes + initialOffset; Debug.Assert(padding >= 0); builder.EmitZeros(padding); TypePreinit.ISerializableValue val = preinitInfo.GetFieldValue(field); int currentOffset = builder.CountBytes; val.WriteFieldData(ref builder, factory); Debug.Assert(builder.CountBytes - currentOffset == field.FieldType.GetElementSize().AsInt); } int pad = _type.NonGCStaticFieldSize.AsInt - builder.CountBytes + initialOffset; Debug.Assert(pad >= 0); builder.EmitZeros(pad); } else { builder.EmitZeros(_type.NonGCStaticFieldSize.AsInt); } builder.AddSymbol(this); 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(); builder.EmitPointerReloc(factory.ExactCallableAddress(cctorMethod)); builder.EmitZeroPointer(); } else { builder.RequireInitialAlignment(_type.NonGCStaticFieldAlignment.AsInt); } if (_sortedPreInitFields != null) { int staticOffsetBegin = builder.CountBytes; int staticOffsetEnd = builder.CountBytes + _type.NonGCStaticFieldSize.AsInt; int staticOffset = staticOffsetBegin; int idx = 0; while (staticOffset < staticOffsetEnd) { int writeTo = staticOffsetEnd; if (idx < _sortedPreInitFields.Count) { writeTo = staticOffsetBegin + _sortedPreInitFields[idx].Field.Offset.AsInt; } // Emit the zeros before the next preinitField builder.EmitZeros(writeTo - staticOffset); staticOffset = writeTo; // Emit the data if (idx < _sortedPreInitFields.Count) { _sortedPreInitFields[idx].WriteData(ref builder, factory); idx++; staticOffset = builder.CountBytes; } } } else { builder.EmitZeros(_type.NonGCStaticFieldSize.AsInt); } builder.AddSymbol(this); return(builder.ToObjectData()); }