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 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 = false) { bool hasVariance = false; foreach (var argVariance in _details.Variance) { if (argVariance != 0) { hasVariance = true; break; } } var builder = new ObjectDataBuilder(factory); builder.DefinedSymbols.Add(this); builder.RequirePointerAlignment(); builder.EmitShort((short)checked ((UInt16)_details.Instantiation.Length)); builder.EmitByte((byte)(hasVariance ? 1 : 0)); // TODO: general purpose padding builder.EmitByte(0); if (factory.Target.PointerSize == 8) { builder.EmitInt(0); } foreach (var typeArg in _details.Instantiation) { builder.EmitPointerReloc(factory.NecessaryTypeSymbol(typeArg)); } if (hasVariance) { foreach (var argVariance in _details.Variance) { builder.EmitByte(checked ((byte)argVariance)); } } 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) { ObjectDataBuilder dataBuilder = new ObjectDataBuilder(factory, relocsOnly); dataBuilder.RequireInitialPointerAlignment(); dataBuilder.AddSymbol(this); // +1 for SyncBlock (static size already includes MethodTable) Debug.Assert(factory.Target.Abi == TargetAbi.NativeAot || factory.Target.Abi == TargetAbi.CppCodegen); int totalSize = (_gcMap.Size + 1) * _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 == ((ISymbolDefinitionNode)this).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 MethodTable 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()); }
public override void EncodeData(ref ObjectDataBuilder builder, NodeFactory factory, bool relocsOnly) { int gcFieldCount = 0; int startIndex = 0; int numSeries = 0; for (int i = 0; i < _gcMap.Size; i++) { // Skip non-GC fields if (!_gcMap[i]) { continue; } gcFieldCount++; if (i == 0 || !_gcMap[i - 1]) { // The cell starts a new series startIndex = i; } if (i == _gcMap.Size - 1 || !_gcMap[i + 1]) { // The cell ends the current series builder.EmitInt(gcFieldCount); if (_isThreadStatic) { builder.EmitReloc((factory as UtcNodeFactory).TlsStart, RelocType.IMAGE_REL_SECREL, startIndex * factory.Target.PointerSize); } else { builder.EmitReloc(factory.TypeGCStaticsSymbol(_type), RelocType.IMAGE_REL_BASED_RELPTR32, startIndex * factory.Target.PointerSize); } gcFieldCount = 0; numSeries++; } } Debug.Assert(numSeries == NumSeries); }
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); // This is just so that EEType::Validate doesn't blow up at runtime dataBuilder.EmitPointerReloc(this); // Related type: itself return(dataBuilder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // TODO: define _tls_index as "comdat select any" when multiple object files present. ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly); 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. objData.EmitInt(0); return(objData.ToObjectData()); }
protected override void GetElementDataForNodes(ref ObjectDataBuilder builder, NodeFactory factory, bool relocsOnly) { int numSeries = 0; foreach (GCStaticDescNode descNode in NodesList) { numSeries += descNode.NumSeries; } builder.EmitInt(numSeries); foreach (GCStaticDescNode node in NodesList) { if (!relocsOnly) { node.Offset = builder.CountBytes; } node.EncodeData(ref builder, factory, relocsOnly); } }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder objData = new ObjectDataBuilder(factory); objData.Alignment = 16; objData.DefinedSymbols.Add(this); if (!relocsOnly) { var entries = BuildDispatchMap(factory); objData.EmitInt(entries.Length); foreach (var entry in entries) { objData.EmitShort(entry.InterfaceIndex); objData.EmitShort(entry.InterfaceMethodSlot); objData.EmitShort(entry.ImplementationMethodSlot); } } return(objData.ToObjectData()); }
protected override void GetElementDataForNodes(ref ObjectDataBuilder builder, NodeFactory factory, bool relocsOnly) { int numSeries = 0; foreach (GCStaticDescNode descNode in NodesList) { numSeries += descNode.NumSeries; } builder.EmitInt(numSeries); foreach (GCStaticDescNode node in NodesList) { if (!relocsOnly) { node.InitializeOffsetFromBeginningOfArray(builder.CountBytes); } node.EncodeData(ref builder, factory, relocsOnly); builder.AddSymbol(node); } }
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); if (null == _optionalFieldsNode) { _optionalFieldsNode = factory.EETypeOptionalFields(_optionalFieldsBuilder); } 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); OutputFinalizerMethod(factory, ref objData); OutputOptionalFields(factory, ref objData); OutputNullableTypeParameter(factory, ref objData); } return(objData.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 = false) { Debug.Assert((EETypeNode.GetVTableOffset(factory.Target.PointerSize) % factory.Target.PointerSize) == 0, "vtable offset must be aligned"); ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly); objData.AddSymbol(this); if (!relocsOnly) { int tableOffset; if (_targetMethod.OwningType.IsInterface) { tableOffset = 0; } else { tableOffset = EETypeNode.GetVTableOffset(factory.Target.PointerSize) / factory.Target.PointerSize; } objData.EmitInt(tableOffset + VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, _targetMethod, _targetMethod.OwningType)); } return(objData.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // The dependency tracking of this node currently does nothing because the data emission relies // the set of compiled methods which has an incomplete state during dependency tracking. if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this })); } ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly); objData.RequireInitialPointerAlignment(); objData.AddSymbol(this); objData.AddSymbol(_endSymbol); foreach (var mappingEntry in factory.MetadataManager.GetStackTraceMapping(factory)) { objData.EmitReloc(factory.MethodEntrypoint(mappingEntry.Entity), RelocType.IMAGE_REL_BASED_RELPTR32); objData.EmitInt(mappingEntry.MetadataHandle); } _endSymbol.SetSymbolOffset(objData.CountBytes); return(objData.ToObjectData()); }
private void OutputBaseSize(ref ObjectDataBuilder objData) { int pointerSize = _type.Context.Target.PointerSize; int minimumObjectSize = pointerSize * 3; int objectSize; if (_type.IsDefType) { objectSize = pointerSize + ((DefType)_type).InstanceByteCount; // +pointerSize for SyncBlock if (_type.IsValueType) objectSize += pointerSize; // + EETypePtr field inherited from System.Object } else if (_type.IsArray) { objectSize = 3 * pointerSize; // SyncBlock + EETypePtr + Length if (_type.IsMdArray) objectSize += 2 * _type.Context.GetWellKnownType(WellKnownType.Int32).GetElementSize() * ((ArrayType)_type).Rank; } else if (_type.IsPointer) { // These never get boxed and don't have a base size. Use a sentinel value recognized by the runtime. objData.EmitInt(ParameterizedTypeShapeConstants.Pointer); return; } else if (_type.IsByRef) { // These never get boxed and don't have a base size. Use a sentinel value recognized by the runtime. objData.EmitInt(ParameterizedTypeShapeConstants.ByRef); return; } 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); }
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 = 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(); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder objData = new ObjectDataBuilder(factory); objData.Alignment = 16; objData.DefinedSymbols.Add(this); if (!relocsOnly) { var entries = BuildDispatchMap(factory); objData.EmitInt(entries.Length); foreach (var entry in entries) { objData.EmitShort(entry.InterfaceIndex); objData.EmitShort(entry.InterfaceMethodSlot); objData.EmitShort(entry.ImplementationMethodSlot); } } 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 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(); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly) { ObjectDataBuilder dataBuilder = new ObjectDataBuilder(factory); dataBuilder.Alignment = 16; dataBuilder.DefinedSymbols.Add(this); bool hasPointers = NumSeries > 0; if (hasPointers) { for (int i = ((_runLengths.Length / 2) * 2) - 1; i >= 0; i--) { if (_targetPointerSize == 4) { dataBuilder.EmitInt(_runLengths[i]); } else { dataBuilder.EmitLong(_runLengths[i]); } } if (_targetPointerSize == 4) { dataBuilder.EmitInt(NumSeries); } else { dataBuilder.EmitLong(NumSeries); } } int totalSize = 0; foreach (int run in _runLengths) { totalSize += run * _targetPointerSize; } dataBuilder.EmitShort(0); // ComponentSize is always 0 if (hasPointers) dataBuilder.EmitShort(0x20); // TypeFlags.HasPointers else dataBuilder.EmitShort(0x00); totalSize = Math.Max(totalSize, _targetPointerSize * 3); // minimum GC eetype size is 3 pointers dataBuilder.EmitInt(totalSize); return dataBuilder.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(); }
protected override void EmitDataInternal(ref ObjectDataBuilder builder, NodeFactory factory) { // Method generic dictionaries get prefixed by the hash code of the owning method // to allow quick lookups of additional details by the type loader. if (builder.TargetPointerSize == 8) builder.EmitInt(0); builder.EmitInt(_owningMethod.GetHashCode()); Debug.Assert(builder.CountBytes == Offset); base.EmitDataInternal(ref builder, factory); }
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()); }
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 })); } ObjectDataBuilder objDataBuilder = new ObjectDataBuilder(factory, relocsOnly); // Emit number of dictionaries in table objDataBuilder.AddSymbol(this); IReadOnlyCollection <GenericDictionaryNode> dictionariesEmitted = factory.MetadataManager.GetCompiledGenericDictionaries(); objDataBuilder.EmitInt(dictionariesEmitted.Count); DebugInfoBlob signatureData = new DebugInfoBlob(); BlobBuilder signatureBlobBuilder = new BlobBuilder(); BlobBuilder signatureLenBuilder = new BlobBuilder(); ManagedBinaryEmitter pseudoAssembly = factory.WindowsDebugData.DebugPseudoAssemblySection.PseudoAssembly; foreach (GenericDictionaryNode dictionary in dictionariesEmitted) { objDataBuilder.EmitReloc(dictionary, RelocType.IMAGE_REL_BASED_ADDR32NB); objDataBuilder.EmitUInt(signatureData.Size()); signatureBlobBuilder.Clear(); int typeDictLen = dictionary.TypeInstantiation.IsNull ? 0 : dictionary.TypeInstantiation.Length; int methodDictLen = dictionary.MethodInstantiation.IsNull ? 0 : dictionary.MethodInstantiation.Length; signatureBlobBuilder.WriteCompressedInteger(typeDictLen + methodDictLen); if (typeDictLen != 0) { foreach (TypeDesc type in dictionary.TypeInstantiation) { pseudoAssembly.EncodeSignatureForType(type, signatureBlobBuilder); } } if (methodDictLen != 0) { foreach (TypeDesc type in dictionary.MethodInstantiation) { pseudoAssembly.EncodeSignatureForType(type, signatureBlobBuilder); } } int blobSize = signatureBlobBuilder.Count; signatureLenBuilder.Clear(); signatureLenBuilder.WriteCompressedInteger(blobSize); // Prepend the signature data with a length signatureData.WriteBuffer(signatureLenBuilder); // And then attach the actual signature data signatureData.WriteBuffer(signatureBlobBuilder); } // Attach signature information to end after all of the rva/offset pairs objDataBuilder.EmitBytes(signatureData.ToArray()); return(objDataBuilder.ToObjectData()); }
protected override void OutputBaseSize(ref ObjectDataBuilder objData) { // Canonical definition types will have their base size set to the minimum objData.EmitInt(MinimumObjectSize); }
protected virtual void OutputBaseSize(ref ObjectDataBuilder objData) { int pointerSize = _type.Context.Target.PointerSize; int objectSize; if (_type.IsDefType) { LayoutInt instanceByteCount = ((DefType)_type).InstanceByteCount; if (instanceByteCount.IsIndeterminate) { // Some value must be put in, but the specific value doesn't matter as it // isn't used for specific instantiations, and the universal canon eetype // is never associated with an allocated object. objectSize = pointerSize; } else { objectSize = pointerSize + ((DefType)_type).InstanceByteCount.AsInt; // +pointerSize for SyncBlock } if (_type.IsValueType) { objectSize += pointerSize; // + EETypePtr field inherited from System.Object } } else if (_type.IsArray) { objectSize = 3 * pointerSize; // SyncBlock + EETypePtr + Length if (_type.IsMdArray) { objectSize += 2 * sizeof(int) * ((ArrayType)_type).Rank; } } else if (_type.IsPointer) { // These never get boxed and don't have a base size. Use a sentinel value recognized by the runtime. objData.EmitInt(ParameterizedTypeShapeConstants.Pointer); return; } else if (_type.IsByRef) { // These never get boxed and don't have a base size. Use a sentinel value recognized by the runtime. objData.EmitInt(ParameterizedTypeShapeConstants.ByRef); return; } 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 + sizeof(int) + sizeof(char); } objData.EmitInt(objectSize); }
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; var node = factory.ConstructedTypeSymbol(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(); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly) { ObjectDataBuilder objData = new ObjectDataBuilder(factory); objData.Alignment = 16; objData.DefinedSymbols.Add(this); ComputeOptionalEETypeFields(factory); if (null == _optionalFieldsNode) { _optionalFieldsNode = factory.EETypeOptionalFields(_optionalFieldsBuilder); } 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); OutputFinalizerMethod(factory, ref objData); OutputOptionalFields(factory, ref objData); OutputNullableTypeParameter(factory, ref objData); } return objData.ToObjectData(); }
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 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 OutputBaseSize(ref ObjectDataBuilder objData) { 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 if (_type is PointerType) { // Object size 0 is a sentinel value in the runtime for parameterized types that means "Pointer Type" objData.EmitInt(0); return; } 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); }
void EmitDispatchMap(ref ObjectDataBuilder builder, NodeFactory factory) { var entryCountReservation = builder.ReserveInt(); int entryCount = 0; for (int interfaceIndex = 0; interfaceIndex < _type.RuntimeInterfaces.Length; interfaceIndex++) { var interfaceType = _type.RuntimeInterfaces[interfaceIndex]; Debug.Assert(interfaceType.IsInterface); IReadOnlyList<MethodDesc> virtualSlots = factory.VTable(interfaceType).Slots; for (int interfaceMethodSlot = 0; interfaceMethodSlot < virtualSlots.Count; interfaceMethodSlot++) { MethodDesc declMethod = virtualSlots[interfaceMethodSlot]; var implMethod = _type.GetClosestDefType().ResolveInterfaceMethodToVirtualMethodOnType(declMethod); // Interface methods first implemented by a base type in the hierarchy will return null for the implMethod (runtime interface // dispatch will walk the inheritance chain). if (implMethod != null) { builder.EmitShort(checked((short)interfaceIndex)); builder.EmitShort(checked((short)interfaceMethodSlot)); builder.EmitShort(checked((short)VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, implMethod))); entryCount++; } } } builder.EmitInt(entryCountReservation, entryCount); }
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 = false) { if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this })); } // 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 (_methodToTemplateIndex == null) { BuildMethodToIdMap(factory); } TypeDesc containerType = null; foreach (var method in _methodToTemplateIndex.Keys) { Debug.Assert(containerType == null || containerType == method.OwningType); containerType = method.OwningType; #if !DEBUG break; #endif } if (factory.Target.SupportsRelativePointers) { objData.EmitReloc(factory.NecessaryTypeSymbol(containerType), RelocType.IMAGE_REL_BASED_RELPTR32); } else { objData.EmitPointerReloc(factory.NecessaryTypeSymbol(containerType)); } 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); 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 == ((ISymbolNode)this).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); // This is just so that EEType::Validate doesn't blow up at runtime dataBuilder.EmitPointerReloc(this); // Related type: itself return dataBuilder.ToObjectData(); }