public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { if (_methods.Count == 0 || relocsOnly) { return new ObjectData( data: Array.Empty<byte>(), relocs: Array.Empty<Relocation>(), alignment: 1, definedSymbols: new ISymbolDefinitionNode[] { this }); } _methods.Sort(new CompilerComparer()); GCRefMapBuilder builder = new GCRefMapBuilder(factory.Target, relocsOnly); builder.Builder.RequireInitialAlignment(4); builder.Builder.AddSymbol(this); // First, emit the initial ref map offset and reserve the offset map entries int offsetCount = _methods.Count / GCREFMAP_LOOKUP_STRIDE; builder.Builder.EmitInt((offsetCount + 1) * sizeof(int)); ObjectDataBuilder.Reservation[] offsets = new ObjectDataBuilder.Reservation[offsetCount]; for (int offsetIndex = 0; offsetIndex < offsetCount; offsetIndex++) { offsets[offsetIndex] = builder.Builder.ReserveInt(); } // Next, generate the actual method GC ref maps and update the offset map int nextOffsetIndex = 0; int nextMethodIndex = GCREFMAP_LOOKUP_STRIDE - 1; for (int methodIndex = 0; methodIndex < _methods.Count; methodIndex++) { IMethodNode methodNode = _methods[methodIndex]; if (methodNode == null) { // Flush an empty GC ref map block to prevent // the indexed records from falling out of sync with methods builder.Flush(); } else { bool isUnboxingStub = false; if (methodNode is DelayLoadHelperImport methodImport) { isUnboxingStub = ((MethodFixupSignature)methodImport.ImportSignature.Target).IsUnboxingStub; } builder.GetCallRefMap(methodNode.Method, isUnboxingStub); } if (methodIndex >= nextMethodIndex) { builder.Builder.EmitInt(offsets[nextOffsetIndex], builder.Builder.CountBytes); nextOffsetIndex++; nextMethodIndex += GCREFMAP_LOOKUP_STRIDE; } } Debug.Assert(nextOffsetIndex == offsets.Length); return builder.Builder.ToObjectData(); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { if (_methods.Count == 0 || relocsOnly) { return(new ObjectData( data: Array.Empty <byte>(), relocs: Array.Empty <Relocation>(), alignment: 1, definedSymbols: new ISymbolDefinitionNode[] { this })); } GCRefMapBuilder builder = new GCRefMapBuilder(factory, relocsOnly); builder.Builder.RequireInitialAlignment(4); builder.Builder.AddSymbol(this); // First, emit the initial ref map offset and reserve the offset map entries int offsetCount = _methods.Count / GCREFMAP_LOOKUP_STRIDE; builder.Builder.EmitInt((offsetCount + 1) * sizeof(int)); ObjectDataBuilder.Reservation[] offsets = new ObjectDataBuilder.Reservation[offsetCount]; for (int offsetIndex = 0; offsetIndex < offsetCount; offsetIndex++) { offsets[offsetIndex] = builder.Builder.ReserveInt(); } // Next, generate the actual method GC ref maps and update the offset map int nextOffsetIndex = 0; int nextMethodIndex = GCREFMAP_LOOKUP_STRIDE - 1; for (int methodIndex = 0; methodIndex < _methods.Count; methodIndex++) { if (methodIndex >= nextMethodIndex) { builder.Builder.EmitInt(offsets[nextOffsetIndex], builder.Builder.CountBytes); nextOffsetIndex++; nextMethodIndex += GCREFMAP_LOOKUP_STRIDE; } MethodWithGCInfo methodNode = _methods[methodIndex]; if (methodNode == null || methodNode.IsEmpty) { // Flush an empty GC ref map block to prevent // the indexed records from falling out of sync with methods builder.Flush(); } else { builder.GetCallRefMap(methodNode.Method); } } Debug.Assert(nextOffsetIndex == offsets.Length); return(builder.Builder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); builder.RequireInitialPointerAlignment(); builder.AddSymbol(this); EmitHeaderPrefix(ref builder); // Don't bother sorting if we're not emitting the contents if (!relocsOnly) { _items.MergeSort((x, y) => Comparer <int> .Default.Compare((int)x.Id, (int)y.Id)); } // ReadyToRunHeader.Flags builder.EmitInt((int)_flags); // ReadyToRunHeader.NumberOfSections ObjectDataBuilder.Reservation sectionCountReservation = builder.ReserveInt(); int count = 0; foreach (var item in _items) { // Skip empty entries if (!relocsOnly && item.Node is ObjectNode on && on.ShouldSkipEmittingObjectNode(factory)) { continue; } // Unmarked nodes are not part of the graph if (!item.Node.Marked && !(item.Node is ObjectNode)) { Debug.Assert(item.Node is DelayLoadMethodCallThunkNodeRange); continue; } builder.EmitInt((int)item.Id); builder.EmitReloc(item.StartSymbol, RelocType.IMAGE_REL_BASED_ADDR32NB); // The header entry for the runtime functions table should not include the 4 byte 0xffffffff sentinel // value in the covered range. int delta = item.Id == ReadyToRunSectionType.RuntimeFunctions ? RuntimeFunctionsTableNode.SentinelSizeAdjustment : 0; builder.EmitReloc(item.StartSymbol, RelocType.IMAGE_REL_SYMBOL_SIZE, delta); count++; } builder.EmitInt(sectionCountReservation, count); return(builder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); builder.RequireInitialPointerAlignment(); builder.AddSymbol(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 ObjectDataBuilder.Reservation sectionCountReservation = builder.ReserveInt(); int count = 0; foreach (var item in _items) { // Skip empty entries if (!relocsOnly && item.Node.ShouldSkipEmittingObjectNode(factory)) { continue; } builder.EmitInt((int)item.Id); builder.EmitReloc(item.StartSymbol, RelocType.IMAGE_REL_BASED_ADDR32NB); if (!relocsOnly) { builder.EmitInt(item.Node.GetData(factory).Data.Length); } count++; } builder.EmitInt(sectionCountReservation, count); return(builder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); builder.RequireInitialPointerAlignment(); builder.AddSymbol(this); EmitHeaderPrefix(ref builder); // Don't bother sorting if we're not emitting the contents if (!relocsOnly) { _items.MergeSort((x, y) => Comparer <int> .Default.Compare((int)x.Id, (int)y.Id)); } // ReadyToRunHeader.Flags builder.EmitInt((int)_flags); // ReadyToRunHeader.NumberOfSections ObjectDataBuilder.Reservation sectionCountReservation = builder.ReserveInt(); int count = 0; foreach (var item in _items) { // Skip empty entries if (!relocsOnly && item.Node.ShouldSkipEmittingObjectNode(factory)) { continue; } builder.EmitInt((int)item.Id); builder.EmitReloc(item.StartSymbol, RelocType.IMAGE_REL_BASED_ADDR32NB); builder.EmitReloc(item.StartSymbol, RelocType.IMAGE_REL_SYMBOL_SIZE); count++; } builder.EmitInt(sectionCountReservation, count); return(builder.ToObjectData()); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { if (_methods.Count == 0 || relocsOnly) { return(new ObjectData( data: Array.Empty <byte>(), relocs: Array.Empty <Relocation>(), alignment: 1, definedSymbols: new ISymbolDefinitionNode[] { this })); } _methods.Sort(new CompilerComparer()); GCRefMapBuilder builder = new GCRefMapBuilder(factory.Target, relocsOnly); builder.Builder.RequireInitialAlignment(4); builder.Builder.AddSymbol(this); // First, emit the initial ref map offset and reserve the offset map entries int offsetCount = _methods.Count / GCREFMAP_LOOKUP_STRIDE; builder.Builder.EmitInt((offsetCount + 1) * sizeof(int)); ObjectDataBuilder.Reservation[] offsets = new ObjectDataBuilder.Reservation[offsetCount]; for (int offsetIndex = 0; offsetIndex < offsetCount; offsetIndex++) { offsets[offsetIndex] = builder.Builder.ReserveInt(); } // Next, generate the actual method GC ref maps and update the offset map int nextOffsetIndex = 0; int nextMethodIndex = GCREFMAP_LOOKUP_STRIDE - 1; for (int methodIndex = 0; methodIndex < _methods.Count; methodIndex++) { IMethodNode methodNode = _methods[methodIndex]; if (methodNode == null || (methodNode is LocalMethodImport localMethod && localMethod.MethodCodeNode.IsEmpty)) { // Flush an empty GC ref map block to prevent // the indexed records from falling out of sync with methods builder.Flush(); }