blob: 2678cf4388f8d3b56c89320398cd1306e713de7a [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- MCCodeView.h - Machine Code CodeView support -------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Holds state from .cv_file and .cv_loc directives for later emission.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_MC_MCCODEVIEW_H
15#define LLVM_MC_MCCODEVIEW_H
16
17#include "llvm/ADT/StringMap.h"
18#include "llvm/ADT/StringRef.h"
19#include "llvm/MC/MCFragment.h"
20#include "llvm/MC/MCObjectStreamer.h"
21#include <map>
22#include <vector>
23
24namespace llvm {
25class MCContext;
26class MCObjectStreamer;
27class MCStreamer;
28class CodeViewContext;
29
Andrew Scullcdfcccc2018-10-05 20:58:37 +010030/// Instances of this class represent the information from a
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010031/// .cv_loc directive.
32class MCCVLoc {
Andrew Scull0372a572018-11-16 15:47:06 +000033 const MCSymbol *Label = nullptr;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010034 uint32_t FunctionId;
35 uint32_t FileNum;
36 uint32_t Line;
37 uint16_t Column;
38 uint16_t PrologueEnd : 1;
39 uint16_t IsStmt : 1;
40
41private: // CodeViewContext manages these
42 friend class CodeViewContext;
Andrew Scull0372a572018-11-16 15:47:06 +000043 MCCVLoc(const MCSymbol *Label, unsigned functionid, unsigned fileNum,
44 unsigned line, unsigned column, bool prologueend, bool isstmt)
45 : Label(Label), FunctionId(functionid), FileNum(fileNum), Line(line),
46 Column(column), PrologueEnd(prologueend), IsStmt(isstmt) {}
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010047
48 // Allow the default copy constructor and assignment operator to be used
49 // for an MCCVLoc object.
50
51public:
Andrew Scull0372a572018-11-16 15:47:06 +000052 const MCSymbol *getLabel() const { return Label; }
53
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010054 unsigned getFunctionId() const { return FunctionId; }
55
Andrew Scullcdfcccc2018-10-05 20:58:37 +010056 /// Get the FileNum of this MCCVLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010057 unsigned getFileNum() const { return FileNum; }
58
Andrew Scullcdfcccc2018-10-05 20:58:37 +010059 /// Get the Line of this MCCVLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010060 unsigned getLine() const { return Line; }
61
Andrew Scullcdfcccc2018-10-05 20:58:37 +010062 /// Get the Column of this MCCVLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010063 unsigned getColumn() const { return Column; }
64
65 bool isPrologueEnd() const { return PrologueEnd; }
66 bool isStmt() const { return IsStmt; }
67
Andrew Scull0372a572018-11-16 15:47:06 +000068 void setLabel(const MCSymbol *L) { Label = L; }
69
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010070 void setFunctionId(unsigned FID) { FunctionId = FID; }
71
Andrew Scullcdfcccc2018-10-05 20:58:37 +010072 /// Set the FileNum of this MCCVLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010073 void setFileNum(unsigned fileNum) { FileNum = fileNum; }
74
Andrew Scullcdfcccc2018-10-05 20:58:37 +010075 /// Set the Line of this MCCVLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010076 void setLine(unsigned line) { Line = line; }
77
Andrew Scullcdfcccc2018-10-05 20:58:37 +010078 /// Set the Column of this MCCVLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010079 void setColumn(unsigned column) {
80 assert(column <= UINT16_MAX);
81 Column = column;
82 }
83
84 void setPrologueEnd(bool PE) { PrologueEnd = PE; }
85 void setIsStmt(bool IS) { IsStmt = IS; }
86};
87
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010088/// Information describing a function or inlined call site introduced by
89/// .cv_func_id or .cv_inline_site_id. Accumulates information from .cv_loc
90/// directives used with this function's id or the id of an inlined call site
91/// within this function or inlined call site.
92struct MCCVFunctionInfo {
93 /// If this represents an inlined call site, then ParentFuncIdPlusOne will be
94 /// the parent function id plus one. If this represents a normal function,
95 /// then there is no parent, and ParentFuncIdPlusOne will be FunctionSentinel.
96 /// If this struct is an unallocated slot in the function info vector, then
97 /// ParentFuncIdPlusOne will be zero.
98 unsigned ParentFuncIdPlusOne = 0;
99
100 enum : unsigned { FunctionSentinel = ~0U };
101
102 struct LineInfo {
103 unsigned File;
104 unsigned Line;
105 unsigned Col;
106 };
107
108 LineInfo InlinedAt;
109
110 /// The section of the first .cv_loc directive used for this function, or null
111 /// if none has been seen yet.
112 MCSection *Section = nullptr;
113
114 /// Map from inlined call site id to the inlined at location to use for that
115 /// call site. Call chains are collapsed, so for the call chain 'f -> g -> h',
116 /// the InlinedAtMap of 'f' will contain entries for 'g' and 'h' that both
117 /// list the line info for the 'g' call site.
118 DenseMap<unsigned, LineInfo> InlinedAtMap;
119
120 /// Returns true if this is function info has not yet been used in a
121 /// .cv_func_id or .cv_inline_site_id directive.
122 bool isUnallocatedFunctionInfo() const { return ParentFuncIdPlusOne == 0; }
123
124 /// Returns true if this represents an inlined call site, meaning
125 /// ParentFuncIdPlusOne is neither zero nor ~0U.
126 bool isInlinedCallSite() const {
127 return !isUnallocatedFunctionInfo() &&
128 ParentFuncIdPlusOne != FunctionSentinel;
129 }
130
131 unsigned getParentFuncId() const {
132 assert(isInlinedCallSite());
133 return ParentFuncIdPlusOne - 1;
134 }
135};
136
137/// Holds state from .cv_file and .cv_loc directives for later emission.
138class CodeViewContext {
139public:
140 CodeViewContext();
141 ~CodeViewContext();
142
143 bool isValidFileNumber(unsigned FileNumber) const;
144 bool addFile(MCStreamer &OS, unsigned FileNumber, StringRef Filename,
145 ArrayRef<uint8_t> ChecksumBytes, uint8_t ChecksumKind);
146
147 /// Records the function id of a normal function. Returns false if the
148 /// function id has already been used, and true otherwise.
149 bool recordFunctionId(unsigned FuncId);
150
151 /// Records the function id of an inlined call site. Records the "inlined at"
152 /// location info of the call site, including what function or inlined call
153 /// site it was inlined into. Returns false if the function id has already
154 /// been used, and true otherwise.
155 bool recordInlinedCallSiteId(unsigned FuncId, unsigned IAFunc,
156 unsigned IAFile, unsigned IALine,
157 unsigned IACol);
158
159 /// Retreive the function info if this is a valid function id, or nullptr.
160 MCCVFunctionInfo *getCVFunctionInfo(unsigned FuncId);
161
162 /// Saves the information from the currently parsed .cv_loc directive
163 /// and sets CVLocSeen. When the next instruction is assembled an entry
164 /// in the line number table with this information and the address of the
165 /// instruction will be created.
Andrew Scull0372a572018-11-16 15:47:06 +0000166 void recordCVLoc(MCContext &Ctx, const MCSymbol *Label, unsigned FunctionId,
167 unsigned FileNo, unsigned Line, unsigned Column,
168 bool PrologueEnd, bool IsStmt);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100169
170 bool isValidCVFileNumber(unsigned FileNumber);
171
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100172 /// Add a line entry.
Andrew Scull0372a572018-11-16 15:47:06 +0000173 void addLineEntry(const MCCVLoc &LineEntry);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100174
Andrew Scull0372a572018-11-16 15:47:06 +0000175 std::vector<MCCVLoc> getFunctionLineEntries(unsigned FuncId);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100176
177 std::pair<size_t, size_t> getLineExtent(unsigned FuncId);
178
Andrew Scull0372a572018-11-16 15:47:06 +0000179 ArrayRef<MCCVLoc> getLinesForExtent(size_t L, size_t R);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100180
181 /// Emits a line table substream.
182 void emitLineTableForFunction(MCObjectStreamer &OS, unsigned FuncId,
183 const MCSymbol *FuncBegin,
184 const MCSymbol *FuncEnd);
185
186 void emitInlineLineTableForFunction(MCObjectStreamer &OS,
187 unsigned PrimaryFunctionId,
188 unsigned SourceFileId,
189 unsigned SourceLineNum,
190 const MCSymbol *FnStartSym,
191 const MCSymbol *FnEndSym);
192
193 /// Encodes the binary annotations once we have a layout.
194 void encodeInlineLineTable(MCAsmLayout &Layout,
195 MCCVInlineLineTableFragment &F);
196
197 void
198 emitDefRange(MCObjectStreamer &OS,
199 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
200 StringRef FixedSizePortion);
201
202 void encodeDefRange(MCAsmLayout &Layout, MCCVDefRangeFragment &F);
203
204 /// Emits the string table substream.
205 void emitStringTable(MCObjectStreamer &OS);
206
207 /// Emits the file checksum substream.
208 void emitFileChecksums(MCObjectStreamer &OS);
209
210 /// Emits the offset into the checksum table of the given file number.
211 void emitFileChecksumOffset(MCObjectStreamer &OS, unsigned FileNo);
212
213 /// Add something to the string table. Returns the final string as well as
214 /// offset into the string table.
215 std::pair<StringRef, unsigned> addToStringTable(StringRef S);
216
217private:
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100218 /// Map from string to string table offset.
219 StringMap<unsigned> StringTable;
220
221 /// The fragment that ultimately holds our strings.
222 MCDataFragment *StrTabFragment = nullptr;
223 bool InsertedStrTabFragment = false;
224
225 MCDataFragment *getStringTableFragment();
226
227 /// Get a string table offset.
228 unsigned getStringTableOffset(StringRef S);
229
230 struct FileInfo {
231 unsigned StringTableOffset;
232
233 // Indicates if this FileInfo corresponds to an actual file, or hasn't been
234 // set yet.
235 bool Assigned = false;
236
237 uint8_t ChecksumKind;
238
239 ArrayRef<uint8_t> Checksum;
240
241 // Checksum offset stored as a symbol because it might be requested
242 // before it has been calculated, so a fixup may be needed.
243 MCSymbol *ChecksumTableOffset;
244 };
245
246 /// Array storing added file information.
247 SmallVector<FileInfo, 4> Files;
248
249 /// The offset of the first and last .cv_loc directive for a given function
250 /// id.
251 std::map<unsigned, std::pair<size_t, size_t>> MCCVLineStartStop;
252
Andrew Scull0372a572018-11-16 15:47:06 +0000253 /// A collection of MCCVLoc for each section.
254 std::vector<MCCVLoc> MCCVLines;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100255
256 /// All known functions and inlined call sites, indexed by function id.
257 std::vector<MCCVFunctionInfo> Functions;
258
259 /// Indicate whether we have already laid out the checksum table addresses or
260 /// not.
261 bool ChecksumOffsetsAssigned = false;
262};
263
264} // end namespace llvm
265#endif