Exemplo n.º 1
0
        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 }));
        }
Exemplo n.º 2
0
 static void WriteEncodedStackOffset(NibbleWriter _writer, int offset, bool assume4ByteAligned)
 {
     if (assume4ByteAligned)
     {
         Debug.Assert(offset % 4 == 0);
         _writer.WriteInt(offset / 4);
     }
     else
     {
         _writer.WriteInt(offset);
     }
 }
Exemplo n.º 3
0
        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());
        }
Exemplo n.º 4
0
        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());
        }
Exemplo n.º 5
0
        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());
        }
Exemplo n.º 6
0
        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());
        }
Exemplo n.º 7
0
        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 }));
        }
Exemplo n.º 8
0
        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());
        }
Exemplo n.º 9
0
        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");
                }