| File: Compiler\ObjectWriter\Dwarf\DwarfLineSequenceWriter.cs | Web Access |
| Project: src\runtime\src\coreclr\tools\aot\ILCompiler.Compiler\ILCompiler.Compiler.csproj (ILCompiler.Compiler) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Buffers; using System.Diagnostics; using ILCompiler.DependencyAnalysis; using Internal.Text; using static ILCompiler.ObjectWriter.DwarfNative; namespace ILCompiler.ObjectWriter { internal sealed class DwarfLineSequenceWriter { private readonly ArrayBufferWriter<byte> _writer; private readonly Utf8String _sectionName; private readonly byte _minimumInstructionLength; private readonly uint _maxDeltaAddressPerSpecialCode; // DWARF state machine private ulong _address; private int _fileNameIndex; private int _line = 1; private int _column; public DwarfLineSequenceWriter(Utf8String sectionName, byte minimumInstructionLength) { _writer = new ArrayBufferWriter<byte>(); _sectionName = sectionName; // Calculations hard code this Debug.Assert(DwarfLineProgramTableWriter.MaximumOperationsPerInstruction == 1); byte maxOperationAdvance = (255 - DwarfLineProgramTableWriter.OpCodeBase) / DwarfLineProgramTableWriter.LineRange; _maxDeltaAddressPerSpecialCode = (uint)(maxOperationAdvance * minimumInstructionLength); _minimumInstructionLength = minimumInstructionLength; } private void WriteByte(byte value) { _writer.GetSpan(1)[0] = value; _writer.Advance(1); } private void WriteULEB128(ulong value) => DwarfHelper.WriteULEB128(_writer, value); private void WriteSLEB128(long value) => DwarfHelper.WriteSLEB128(_writer, value); public void EmitLineInfo(int fileNameIndex, long methodAddress, NativeSequencePoint sequencePoint) { if (_column != sequencePoint.ColNumber) { _column = sequencePoint.ColNumber; WriteByte(DW_LNS_set_column); WriteULEB128((uint)_column); } if (_fileNameIndex != fileNameIndex) { _fileNameIndex = fileNameIndex; WriteByte(DW_LNS_set_file); WriteULEB128((uint)_fileNameIndex); } int deltaLine = sequencePoint.LineNumber - _line; if (deltaLine != 0) { bool canEncodeLineInSpecialCode = deltaLine >= DwarfLineProgramTableWriter.LineBase && deltaLine < DwarfLineProgramTableWriter.LineBase + DwarfLineProgramTableWriter.LineRange; if (!canEncodeLineInSpecialCode) { WriteByte(DW_LNS_advance_line); WriteSLEB128(deltaLine); deltaLine = 0; } } ulong deltaAddress = (ulong)sequencePoint.NativeOffset + (ulong)methodAddress - _address; if (deltaAddress > _maxDeltaAddressPerSpecialCode && deltaAddress <= (2U * _maxDeltaAddressPerSpecialCode)) { deltaAddress -= _maxDeltaAddressPerSpecialCode; WriteByte(DW_LNS_const_add_pc); } if (deltaAddress > 0 || deltaLine != 0) { ulong operationAdvance = deltaAddress / _minimumInstructionLength; ulong opcode = operationAdvance * DwarfLineProgramTableWriter.LineRange + DwarfLineProgramTableWriter.OpCodeBase + (ulong)(deltaLine - DwarfLineProgramTableWriter.LineBase); if (opcode > 255) { WriteByte(DW_LNS_advance_pc); WriteULEB128((uint)operationAdvance); if (deltaLine != 0) { WriteByte((byte)(DwarfLineProgramTableWriter.OpCodeBase + deltaLine - DwarfLineProgramTableWriter.LineBase)); } else { WriteByte(DW_LNS_copy); } } else { WriteByte((byte)opcode); } } _line = sequencePoint.LineNumber; _address = (ulong)sequencePoint.NativeOffset + (ulong)methodAddress; } public void Write(SectionWriter lineSection, byte targetPointerSize, RelocType codeRelocType) { // Set the address to beginning of section lineSection.Write([0, (byte)(1u + targetPointerSize), DW_LNE_set_address]); lineSection.EmitSymbolReference(codeRelocType, _sectionName, 0); lineSection.Write(_writer.WrittenSpan); lineSection.Write([0, 1, DW_LNE_end_sequence]); } } }