LLVM 23.0.0git
LineTable.h
Go to the documentation of this file.
1//===- LineTable.h ----------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_DEBUGINFO_GSYM_LINETABLE_H
10#define LLVM_DEBUGINFO_GSYM_LINETABLE_H
11
14#include "llvm/Support/Error.h"
15#include <cstdint>
16#include <vector>
17
18namespace llvm {
19namespace gsym {
20
21struct FunctionInfo;
22class FileWriter;
23
24/// LineTable class contains deserialized versions of line tables for each
25/// function's address ranges.
26///
27/// When saved to disk, the line table is encoded using a modified version of
28/// the DWARF line tables that only tracks address to source file and line.
29///
30/// ENCODING
31///
32/// The line table starts with a small prolog that contains the following
33/// values:
34///
35/// ENCODING NAME DESCRIPTION
36/// ======== =========== ====================================================
37/// SLEB MinDelta The min line delta for special opcodes that advance
38/// the address and line number.
39/// SLEB MaxDelta The max line delta for single byte opcodes that
40/// advance the address and line number.
41/// ULEB FirstLine The value of the first source line number to
42/// initialize the LineEntry with.
43///
44/// Once these prolog items are read, we initialize a LineEntry struct with
45/// the start address of the function from the FunctionInfo's address range,
46/// a default file index of 1, and the line number set to "FirstLine" from
47/// the prolog above:
48///
49/// LineEntry Row(BaseAddr, 1, FirstLine);
50///
51/// The line table state machine is now initialized and ready to be parsed.
52/// The stream that follows this encodes the line entries in a compact
53/// form. Some opcodes cause "Row" to be modified and some opcodes may also
54/// push "Row" onto the end of the "LineTable.Lines" vector. The end result
55/// is a vector of LineEntry structs that is sorted in ascending address
56/// order.
57///
58/// NORMAL OPCODES
59///
60/// The opcodes 0 through 3 are normal in opcodes. Their encoding and
61/// descriptions are listed below:
62///
63/// ENCODING ENUMERATION VALUE DESCRIPTION
64/// ======== ================ ===== ========================================
65/// LTOC_EndSequence 0x00 Parsing is done.
66/// ULEB LTOC_SetFile 0x01 Row.File = ULEB
67/// ULEB LTOC_AdvancePC 0x02 Row.Addr += ULEB, push "Row".
68/// SLEB LTOC_AdvanceLine 0x03 Row.Line += SLEB
69/// LTOC_FirstSpecial 0x04 First special opcode (see SPECIAL
70/// OPCODES below).
71///
72/// SPECIAL OPCODES
73///
74/// Opcodes LTOC_FirstSpecial through 255 are special opcodes that always
75/// increment both the Row.Addr and Row.Line and push "Row" onto the
76/// LineEntry.Lines array. They do this by using some of the bits to
77/// increment/decrement the source line number, and some of the bits to
78/// increment the address. Line numbers can go up or down when making line
79/// tables, where addresses always only increase since line tables are sorted
80/// by address.
81///
82/// In order to calculate the amount to increment the line and address for
83/// these special opcodes, we calculate the number of values reserved for the
84/// line increment/decrement using the "MinDelta" and "MaxDelta" from the
85/// prolog:
86///
87/// const int64_t LineRange = MaxDelta - MinDelta + 1;
88///
89/// Then we can adjust the opcode to not include any of the normal opcodes:
90///
91/// const uint8_t AdjustedOp = Opcode - LTOC_FirstSpecial;
92///
93/// And we can calculate the line offset, and address offset:
94///
95/// const int64_t LineDelta = MinDelta + (AdjustedOp % LineRange);
96/// const uint64_t AddrDelta = (AdjustedOp / LineRange);
97///
98/// And use these to modify our "Row":
99///
100/// Row.Line += LineDelta;
101/// Row.Addr += AddrDelta;
102///
103/// And push a row onto the line table:
104///
105/// Lines.push_back(Row);
106///
107/// This is verify similar to the way that DWARF encodes its line tables. The
108/// only difference is the DWARF line tables have more normal opcodes and the
109/// "Row" contains more members, like source column number, bools for end of
110/// prologue, beginnging of epilogue, is statement and many others. There are
111/// also more complex rules that happen for the extra normal opcodes. By
112/// leaving these extra opcodes out, we leave more bits for the special
113/// opcodes that allows us to encode line tables in fewer bytes than standard
114/// DWARF encodings.
115///
116/// Opcodes that will push "Row" onto the LineEntry.Lines include the
117/// LTOC_AdvancePC opcode and all special opcodes. All other opcodes
118/// only modify the current "Row", or cause the line table to end.
120 typedef std::vector<gsym::LineEntry> Collection;
121 Collection Lines; ///< All line entries in the line table.
122public:
123 /// Lookup a single address within a line table's data.
124 ///
125 /// Clients have the option to decode an entire line table using
126 /// LineTable::decode() or just find a single matching entry using this
127 /// function. The benefit of using this function is that parsed LineEntry
128 /// objects that do not match will not be stored in an array. This will avoid
129 /// memory allocation costs and parsing can stop once a match has been found.
130 ///
131 /// \param Data The binary stream to read the data from. This object must
132 /// have the data for the LineTable object starting at offset zero. The data
133 /// can contain more data than needed.
134 ///
135 /// \param BaseAddr The base address to use when decoding the line table.
136 /// This will be the FunctionInfo's start address and will be used to
137 /// initialize the line table row prior to parsing any opcodes.
138 ///
139 /// \returns An LineEntry object if a match is found, error otherwise.
141 uint64_t BaseAddr, uint64_t Addr);
142
143 /// Decode an LineTable object from a binary data stream.
144 ///
145 /// \param Data The binary stream to read the data from. This object must
146 /// have the data for the LineTable object starting at offset zero. The data
147 /// can contain more data than needed.
148 ///
149 /// \param BaseAddr The base address to use when decoding the line table.
150 /// This will be the FunctionInfo's start address and will be used to
151 /// initialize the line table row prior to parsing any opcodes.
152 ///
153 /// \returns An LineTable or an error describing the issue that was
154 /// encountered during decoding.
156 uint64_t BaseAddr);
157 /// Encode this LineTable object into FileWriter stream.
158 ///
159 /// \param O The binary stream to write the data to at the current file
160 /// position.
161 ///
162 /// \param BaseAddr The base address to use when decoding the line table.
163 /// This will be the FunctionInfo's start address.
164 ///
165 /// \returns An error object that indicates success or failure or the
166 /// encoding process.
167 LLVM_ABI llvm::Error encode(FileWriter &O, uint64_t BaseAddr) const;
168 bool empty() const { return Lines.empty(); }
169 void clear() { Lines.clear(); }
170 /// Return the first line entry if the line table isn't empty.
171 ///
172 /// \returns An optional line entry with the first line entry if the line
173 /// table isn't empty, or std::nullopt if the line table is emtpy.
174 std::optional<LineEntry> first() const {
175 if (Lines.empty())
176 return std::nullopt;
177 return Lines.front();
178 }
179 /// Return the last line entry if the line table isn't empty.
180 ///
181 /// \returns An optional line entry with the last line entry if the line
182 /// table isn't empty, or std::nullopt if the line table is emtpy.
183 std::optional<LineEntry> last() const {
184 if (Lines.empty())
185 return std::nullopt;
186 return Lines.back();
187 }
188 void push(const LineEntry &LE) {
189 Lines.push_back(LE);
190 }
191 size_t isValid() const {
192 return !Lines.empty();
193 }
194 size_t size() const {
195 return Lines.size();
196 }
197 LineEntry &get(size_t i) {
198 assert(i < Lines.size());
199 return Lines[i];
200 }
201 const LineEntry &get(size_t i) const {
202 assert(i < Lines.size());
203 return Lines[i];
204 }
206 return get(i);
207 }
208 const LineEntry &operator[](size_t i) const {
209 return get(i);
210 }
211 bool operator==(const LineTable &RHS) const {
212 return Lines == RHS.Lines;
213 }
214 bool operator!=(const LineTable &RHS) const {
215 return Lines != RHS.Lines;
216 }
217 bool operator<(const LineTable &RHS) const {
218 const auto LHSSize = Lines.size();
219 const auto RHSSize = RHS.Lines.size();
220 if (LHSSize == RHSSize)
221 return Lines < RHS.Lines;
222 return LHSSize < RHSSize;
223 }
224 Collection::const_iterator begin() const { return Lines.begin(); }
225 Collection::const_iterator end() const { return Lines.end(); }
226
227};
228
230
231} // namespace gsym
232} // namespace llvm
233
234#endif // LLVM_DEBUGINFO_GSYM_LINETABLE_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_ABI
Definition Compiler.h:215
Value * RHS
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
Tagged union holding either a T or a Error.
Definition Error.h:485
A simplified binary data writer class that doesn't require targets, target definitions,...
Definition FileWriter.h:30
A DataExtractor subclass that adds GSYM-specific string offset support.
LineTable class contains deserialized versions of line tables for each function's address ranges.
Definition LineTable.h:119
bool operator==(const LineTable &RHS) const
Definition LineTable.h:211
Collection::const_iterator begin() const
Definition LineTable.h:224
void push(const LineEntry &LE)
Definition LineTable.h:188
bool empty() const
Definition LineTable.h:168
static LLVM_ABI Expected< LineEntry > lookup(GsymDataExtractor &Data, uint64_t BaseAddr, uint64_t Addr)
Lookup a single address within a line table's data.
Collection::const_iterator end() const
Definition LineTable.h:225
std::optional< LineEntry > last() const
Return the last line entry if the line table isn't empty.
Definition LineTable.h:183
LLVM_ABI llvm::Error encode(FileWriter &O, uint64_t BaseAddr) const
Encode this LineTable object into FileWriter stream.
size_t size() const
Definition LineTable.h:194
const LineEntry & get(size_t i) const
Definition LineTable.h:201
static LLVM_ABI llvm::Expected< LineTable > decode(GsymDataExtractor &Data, uint64_t BaseAddr)
Decode an LineTable object from a binary data stream.
const LineEntry & operator[](size_t i) const
Definition LineTable.h:208
LineEntry & operator[](size_t i)
Definition LineTable.h:205
size_t isValid() const
Definition LineTable.h:191
bool operator<(const LineTable &RHS) const
Definition LineTable.h:217
LineEntry & get(size_t i)
Definition LineTable.h:197
std::optional< LineEntry > first() const
Return the first line entry if the line table isn't empty.
Definition LineTable.h:174
bool operator!=(const LineTable &RHS) const
Definition LineTable.h:214
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
LLVM_ABI raw_ostream & operator<<(raw_ostream &OS, const CallSiteInfo &CSI)
This is an optimization pass for GlobalISel generic memory operations.
Function information in GSYM files encodes information for one contiguous address range.
Line entries are used to encode the line tables in FunctionInfo objects.
Definition LineEntry.h:22