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 })); } NativeWriter writer = new NativeWriter(); Section section = writer.NewSection(); VertexArray vertexArray = new VertexArray(section); section.Place(vertexArray); ReadyToRunCodegenNodeFactory r2rFactory = (ReadyToRunCodegenNodeFactory)factory; foreach (MethodWithGCInfo method in r2rFactory.EnumerateCompiledMethods()) { MemoryStream methodDebugBlob = new MemoryStream(); byte[] bounds = CreateBoundsBlobForMethod(method); byte[] vars = CreateVarBlobForMethod(method); NibbleWriter nibbleWriter = new NibbleWriter(); nibbleWriter.WriteUInt((uint)(bounds?.Length ?? 0)); nibbleWriter.WriteUInt((uint)(vars?.Length ?? 0)); byte[] header = nibbleWriter.ToArray(); methodDebugBlob.Write(header, 0, header.Length); if (bounds?.Length > 0) { methodDebugBlob.Write(bounds, 0, bounds.Length); } if (vars?.Length > 0) { methodDebugBlob.Write(vars, 0, vars.Length); } BlobVertex debugBlob = new BlobVertex(methodDebugBlob.ToArray()); vertexArray.Set(r2rFactory.RuntimeFunctionsTable.GetIndex(method), new DebugInfoVertex(debugBlob)); } vertexArray.ExpandLayout(); MemoryStream writerContent = new MemoryStream(); writer.Save(writerContent); return(new ObjectData( data: writerContent.ToArray(), relocs: null, alignment: 8, definedSymbols: new ISymbolDefinitionNode[] { this })); }
public static byte[] CreateBoundsBlobForMethod(OffsetMapping[] offsetMapping) { if (offsetMapping == null || offsetMapping.Length == 0) { return(null); } NibbleWriter writer = new NibbleWriter(); writer.WriteUInt((uint)offsetMapping.Length); uint previousNativeOffset = 0; foreach (var locInfo in offsetMapping) { writer.WriteUInt(locInfo.nativeOffset - previousNativeOffset); writer.WriteUInt(locInfo.ilOffset + 3); // Count of items in Internal.JitInterface.MappingTypes to adjust the IL offset by writer.WriteUInt((uint)locInfo.source); previousNativeOffset = locInfo.nativeOffset; } return(writer.ToArray()); }
private byte[] CreateBoundsBlobForMethod(MethodWithGCInfo method) { if (method.DebugLocInfos == null || method.DebugLocInfos.Length == 0) { return(null); } NibbleWriter writer = new NibbleWriter(); writer.WriteUInt((uint)method.DebugLocInfos.Length); uint previousNativeOffset = 0; foreach (var locInfo in method.DebugLocInfos) { writer.WriteUInt(locInfo.nativeOffset - previousNativeOffset); writer.WriteUInt(locInfo.ilOffset + 3); // Count of items in Internal.JitInterface.MappingTypes to adjust the IL offset by writer.WriteUInt((uint)locInfo.source); previousNativeOffset = locInfo.nativeOffset; } return(writer.ToArray()); }
public byte[] GetFixupBlob(NodeFactory factory) { Relocation[] relocations = GetData(factory, relocsOnly: true).Relocs; if (relocations == null) { return(null); } List <FixupCell> fixupCells = null; foreach (Relocation reloc in relocations) { if (reloc.Target is Import fixupCell && fixupCell.EmitPrecode) { if (fixupCells == null) { fixupCells = new List <FixupCell>(); } fixupCells.Add(new FixupCell(fixupCell.Table.IndexFromBeginningOfArray, fixupCell.OffsetFromBeginningOfArray)); } } if (fixupCells == null) { return(null); } fixupCells.Sort(FixupCell.Comparer); NibbleWriter writer = new NibbleWriter(); int curTableIndex = -1; int curOffset = 0; foreach (FixupCell cell in fixupCells) { Debug.Assert(cell.ImportOffset % factory.Target.PointerSize == 0); int offset = cell.ImportOffset / factory.Target.PointerSize; if (cell.TableIndex != curTableIndex) { // Write delta relative to the previous table index Debug.Assert(cell.TableIndex > curTableIndex); if (curTableIndex != -1) { writer.WriteUInt(0); // table separator, so add except for the first entry writer.WriteUInt((uint)(cell.TableIndex - curTableIndex)); // add table index delta } else { writer.WriteUInt((uint)cell.TableIndex); } curTableIndex = cell.TableIndex; // This is the first fixup in the current table. // We will write it out completely (without delta-encoding) writer.WriteUInt((uint)offset); } else if (offset != curOffset) // ignore duplicate fixup cells { // This is not the first entry in the current table. // We will write out the delta relative to the previous fixup value int delta = offset - curOffset; Debug.Assert(delta > 0); writer.WriteUInt((uint)delta); } // future entries for this table would be relative to this rva curOffset = offset; } writer.WriteUInt(0); // table separator writer.WriteUInt(0); // fixup list ends return(writer.ToArray()); }
public byte[] GetFixupBlob(NodeFactory factory) { Relocation[] relocations = GetData(factory, relocsOnly: true).Relocs; if (relocations == null) { return(null); } List <FixupCell> fixupCells = null; foreach (Relocation reloc in relocations) { if (reloc.Target is Import fixupCell && fixupCell.EmitPrecode) { if (fixupCells == null) { fixupCells = new List <FixupCell>(); } fixupCells.Add(new FixupCell(fixupCell.Table.IndexFromBeginningOfArray, fixupCell.OffsetFromBeginningOfArray)); } } foreach (ISymbolNode node in _fixups) { if (fixupCells == null) { fixupCells = new List <FixupCell>(); } Import fixupCell = (Import)node; fixupCells.Add(new FixupCell(fixupCell.Table.IndexFromBeginningOfArray, fixupCell.OffsetFromBeginningOfArray)); } if (fixupCells == null) { return(null); } fixupCells.MergeSortAllowDuplicates(FixupCell.Comparer); // Deduplicate fixupCells int j = 0; for (int i = 1; i < fixupCells.Count; i++) { if (FixupCell.Comparer.Compare(fixupCells[j], fixupCells[i]) != 0) { j++; if (i != j) { fixupCells[j] = fixupCells[i]; } } } // Move j to point after the last valid fixupCell in the array j++; if (j < fixupCells.Count) { fixupCells.RemoveRange(j, fixupCells.Count - j); } NibbleWriter writer = new NibbleWriter(); int curTableIndex = -1; int curOffset = 0; foreach (FixupCell cell in fixupCells) { Debug.Assert(cell.ImportOffset % factory.Target.PointerSize == 0); int offset = cell.ImportOffset / factory.Target.PointerSize; if (cell.TableIndex != curTableIndex) { // Write delta relative to the previous table index Debug.Assert(cell.TableIndex > curTableIndex); if (curTableIndex != -1) { writer.WriteUInt(0); // table separator, so add except for the first entry writer.WriteUInt((uint)(cell.TableIndex - curTableIndex)); // add table index delta } else { writer.WriteUInt((uint)cell.TableIndex); } curTableIndex = cell.TableIndex; // This is the first fixup in the current table. // We will write it out completely (without delta-encoding) writer.WriteUInt((uint)offset); } else if (offset != curOffset) // ignore duplicate fixup cells { // This is not the first entry in the current table. // We will write out the delta relative to the previous fixup value int delta = offset - curOffset; Debug.Assert(delta > 0); writer.WriteUInt((uint)delta); } // future entries for this table would be relative to this rva curOffset = offset; } writer.WriteUInt(0); // table separator writer.WriteUInt(0); // fixup list ends return(writer.ToArray()); }
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 })); } NativeWriter writer = new NativeWriter(); Section section = writer.NewSection(); VertexArray vertexArray = new VertexArray(section); section.Place(vertexArray); Dictionary <byte[], BlobVertex> blobCache = new Dictionary <byte[], BlobVertex>(ByteArrayComparer.Instance); foreach (MethodWithGCInfo method in factory.EnumerateCompiledMethods()) { MemoryStream methodDebugBlob = new MemoryStream(); byte[] bounds = method.DebugLocInfos; byte[] vars = method.DebugVarInfos; NibbleWriter nibbleWriter = new NibbleWriter(); nibbleWriter.WriteUInt((uint)(bounds?.Length ?? 0)); nibbleWriter.WriteUInt((uint)(vars?.Length ?? 0)); byte[] header = nibbleWriter.ToArray(); methodDebugBlob.Write(header, 0, header.Length); if (bounds?.Length > 0) { methodDebugBlob.Write(bounds, 0, bounds.Length); } if (vars?.Length > 0) { methodDebugBlob.Write(vars, 0, vars.Length); } byte[] debugBlobArrayKey = methodDebugBlob.ToArray(); if (!blobCache.TryGetValue(debugBlobArrayKey, out BlobVertex debugBlob)) { debugBlob = new BlobVertex(methodDebugBlob.ToArray()); blobCache.Add(debugBlobArrayKey, debugBlob); } vertexArray.Set(factory.RuntimeFunctionsTable.GetIndex(method), new DebugInfoVertex(debugBlob)); } vertexArray.ExpandLayout(); MemoryStream writerContent = new MemoryStream(); writer.Save(writerContent); return(new ObjectData( data: writerContent.ToArray(), relocs: null, alignment: 8, definedSymbols: new ISymbolDefinitionNode[] { this })); }
public static byte[] CreateVarBlobForMethod(NativeVarInfo[] varInfos) { if (varInfos == null || varInfos.Length == 0) { return(null); } NibbleWriter writer = new NibbleWriter(); writer.WriteUInt((uint)varInfos.Length); foreach (var nativeVarInfo in varInfos) { writer.WriteUInt(nativeVarInfo.startOffset); writer.WriteUInt(nativeVarInfo.endOffset - nativeVarInfo.startOffset); writer.WriteUInt((uint)(nativeVarInfo.varNumber - (int)ILNum.MAX_ILNUM)); VarLocType varLocType = nativeVarInfo.varLoc.LocationType; writer.WriteUInt((uint)varLocType); switch (varLocType) { case VarLocType.VLT_REG: case VarLocType.VLT_REG_FP: case VarLocType.VLT_REG_BYREF: writer.WriteUInt((uint)nativeVarInfo.varLoc.B); break; case VarLocType.VLT_STK: case VarLocType.VLT_STK_BYREF: writer.WriteUInt((uint)nativeVarInfo.varLoc.B); writer.WriteInt(nativeVarInfo.varLoc.C); break; case VarLocType.VLT_REG_REG: writer.WriteUInt((uint)nativeVarInfo.varLoc.B); writer.WriteUInt((uint)nativeVarInfo.varLoc.C); break; case VarLocType.VLT_REG_STK: writer.WriteUInt((uint)nativeVarInfo.varLoc.B); writer.WriteUInt((uint)nativeVarInfo.varLoc.C); writer.WriteInt(nativeVarInfo.varLoc.D); break; case VarLocType.VLT_STK_REG: writer.WriteInt(nativeVarInfo.varLoc.B); writer.WriteUInt((uint)nativeVarInfo.varLoc.C); writer.WriteUInt((uint)nativeVarInfo.varLoc.D); break; case VarLocType.VLT_STK2: writer.WriteUInt((uint)nativeVarInfo.varLoc.B); writer.WriteInt(nativeVarInfo.varLoc.C); break; case VarLocType.VLT_FPSTK: writer.WriteUInt((uint)nativeVarInfo.varLoc.B); break; case VarLocType.VLT_FIXED_VA: writer.WriteUInt((uint)nativeVarInfo.varLoc.B); break; default: throw new BadImageFormatException("Unexpected var loc type"); } } return(writer.ToArray()); }
public static byte[] CreateVarBlobForMethod(NativeVarInfo[] varInfos, TargetDetails target) { if (varInfos == null || varInfos.Length == 0) { return(null); } bool isX86 = target.Architecture == TargetArchitecture.X86; NibbleWriter writer = new NibbleWriter(); writer.WriteUInt((uint)varInfos.Length); foreach (var nativeVarInfo in varInfos) { writer.WriteUInt(nativeVarInfo.startOffset); writer.WriteUInt(nativeVarInfo.endOffset - nativeVarInfo.startOffset); writer.WriteUInt((uint)(nativeVarInfo.varNumber - (int)ILNum.MAX_ILNUM)); VarLocType varLocType = nativeVarInfo.varLoc.LocationType; writer.WriteUInt((uint)varLocType); switch (varLocType) { case VarLocType.VLT_REG: case VarLocType.VLT_REG_FP: case VarLocType.VLT_REG_BYREF: writer.WriteUInt((uint)nativeVarInfo.varLoc.B); break; case VarLocType.VLT_STK: case VarLocType.VLT_STK_BYREF: writer.WriteUInt((uint)nativeVarInfo.varLoc.B); WriteEncodedStackOffset(writer, nativeVarInfo.varLoc.C, assume4ByteAligned: isX86); break; case VarLocType.VLT_REG_REG: writer.WriteUInt((uint)nativeVarInfo.varLoc.B); writer.WriteUInt((uint)nativeVarInfo.varLoc.C); break; case VarLocType.VLT_REG_STK: writer.WriteUInt((uint)nativeVarInfo.varLoc.B); writer.WriteUInt((uint)nativeVarInfo.varLoc.C); WriteEncodedStackOffset(writer, nativeVarInfo.varLoc.D, assume4ByteAligned: isX86); break; case VarLocType.VLT_STK_REG: WriteEncodedStackOffset(writer, nativeVarInfo.varLoc.B, assume4ByteAligned: isX86); writer.WriteUInt((uint)nativeVarInfo.varLoc.C); writer.WriteUInt((uint)nativeVarInfo.varLoc.D); break; case VarLocType.VLT_STK2: writer.WriteUInt((uint)nativeVarInfo.varLoc.B); WriteEncodedStackOffset(writer, nativeVarInfo.varLoc.C, assume4ByteAligned: isX86); break; case VarLocType.VLT_FPSTK: writer.WriteUInt((uint)nativeVarInfo.varLoc.B); break; case VarLocType.VLT_FIXED_VA: writer.WriteUInt((uint)nativeVarInfo.varLoc.B); break; default: throw new BadImageFormatException("Unexpected var loc type"); }