1 //===- MCCodeView.h - Machine Code CodeView support -------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // Holds state from .cv_file and .cv_loc directives for later emission.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_MC_MCCODEVIEW_H
14 #define LLVM_MC_MCCODEVIEW_H
16 #include "llvm/ADT/StringMap.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/MC/MCFragment.h"
19 #include "llvm/MC/MCObjectStreamer.h"
25 class MCObjectStreamer
;
27 class CodeViewContext
;
29 /// Instances of this class represent the information from a
30 /// .cv_loc directive.
32 const MCSymbol
*Label
= nullptr;
37 uint16_t PrologueEnd
: 1;
40 private: // CodeViewContext manages these
41 friend class CodeViewContext
;
42 MCCVLoc(const MCSymbol
*Label
, unsigned functionid
, unsigned fileNum
,
43 unsigned line
, unsigned column
, bool prologueend
, bool isstmt
)
44 : Label(Label
), FunctionId(functionid
), FileNum(fileNum
), Line(line
),
45 Column(column
), PrologueEnd(prologueend
), IsStmt(isstmt
) {}
47 // Allow the default copy constructor and assignment operator to be used
48 // for an MCCVLoc object.
51 const MCSymbol
*getLabel() const { return Label
; }
53 unsigned getFunctionId() const { return FunctionId
; }
55 /// Get the FileNum of this MCCVLoc.
56 unsigned getFileNum() const { return FileNum
; }
58 /// Get the Line of this MCCVLoc.
59 unsigned getLine() const { return Line
; }
61 /// Get the Column of this MCCVLoc.
62 unsigned getColumn() const { return Column
; }
64 bool isPrologueEnd() const { return PrologueEnd
; }
65 bool isStmt() const { return IsStmt
; }
67 void setLabel(const MCSymbol
*L
) { Label
= L
; }
69 void setFunctionId(unsigned FID
) { FunctionId
= FID
; }
71 /// Set the FileNum of this MCCVLoc.
72 void setFileNum(unsigned fileNum
) { FileNum
= fileNum
; }
74 /// Set the Line of this MCCVLoc.
75 void setLine(unsigned line
) { Line
= line
; }
77 /// Set the Column of this MCCVLoc.
78 void setColumn(unsigned column
) {
79 assert(column
<= UINT16_MAX
);
83 void setPrologueEnd(bool PE
) { PrologueEnd
= PE
; }
84 void setIsStmt(bool IS
) { IsStmt
= IS
; }
87 /// Information describing a function or inlined call site introduced by
88 /// .cv_func_id or .cv_inline_site_id. Accumulates information from .cv_loc
89 /// directives used with this function's id or the id of an inlined call site
90 /// within this function or inlined call site.
91 struct MCCVFunctionInfo
{
92 /// If this represents an inlined call site, then ParentFuncIdPlusOne will be
93 /// the parent function id plus one. If this represents a normal function,
94 /// then there is no parent, and ParentFuncIdPlusOne will be FunctionSentinel.
95 /// If this struct is an unallocated slot in the function info vector, then
96 /// ParentFuncIdPlusOne will be zero.
97 unsigned ParentFuncIdPlusOne
= 0;
99 enum : unsigned { FunctionSentinel
= ~0U };
109 /// The section of the first .cv_loc directive used for this function, or null
110 /// if none has been seen yet.
111 MCSection
*Section
= nullptr;
113 /// Map from inlined call site id to the inlined at location to use for that
114 /// call site. Call chains are collapsed, so for the call chain 'f -> g -> h',
115 /// the InlinedAtMap of 'f' will contain entries for 'g' and 'h' that both
116 /// list the line info for the 'g' call site.
117 DenseMap
<unsigned, LineInfo
> InlinedAtMap
;
119 /// Returns true if this is function info has not yet been used in a
120 /// .cv_func_id or .cv_inline_site_id directive.
121 bool isUnallocatedFunctionInfo() const { return ParentFuncIdPlusOne
== 0; }
123 /// Returns true if this represents an inlined call site, meaning
124 /// ParentFuncIdPlusOne is neither zero nor ~0U.
125 bool isInlinedCallSite() const {
126 return !isUnallocatedFunctionInfo() &&
127 ParentFuncIdPlusOne
!= FunctionSentinel
;
130 unsigned getParentFuncId() const {
131 assert(isInlinedCallSite());
132 return ParentFuncIdPlusOne
- 1;
136 /// Holds state from .cv_file and .cv_loc directives for later emission.
137 class CodeViewContext
{
142 bool isValidFileNumber(unsigned FileNumber
) const;
143 bool addFile(MCStreamer
&OS
, unsigned FileNumber
, StringRef Filename
,
144 ArrayRef
<uint8_t> ChecksumBytes
, uint8_t ChecksumKind
);
146 /// Records the function id of a normal function. Returns false if the
147 /// function id has already been used, and true otherwise.
148 bool recordFunctionId(unsigned FuncId
);
150 /// Records the function id of an inlined call site. Records the "inlined at"
151 /// location info of the call site, including what function or inlined call
152 /// site it was inlined into. Returns false if the function id has already
153 /// been used, and true otherwise.
154 bool recordInlinedCallSiteId(unsigned FuncId
, unsigned IAFunc
,
155 unsigned IAFile
, unsigned IALine
,
158 /// Retreive the function info if this is a valid function id, or nullptr.
159 MCCVFunctionInfo
*getCVFunctionInfo(unsigned FuncId
);
161 /// Saves the information from the currently parsed .cv_loc directive
162 /// and sets CVLocSeen. When the next instruction is assembled an entry
163 /// in the line number table with this information and the address of the
164 /// instruction will be created.
165 void recordCVLoc(MCContext
&Ctx
, const MCSymbol
*Label
, unsigned FunctionId
,
166 unsigned FileNo
, unsigned Line
, unsigned Column
,
167 bool PrologueEnd
, bool IsStmt
);
169 bool isValidCVFileNumber(unsigned FileNumber
);
171 /// Add a line entry.
172 void addLineEntry(const MCCVLoc
&LineEntry
);
174 std::vector
<MCCVLoc
> getFunctionLineEntries(unsigned FuncId
);
176 std::pair
<size_t, size_t> getLineExtent(unsigned FuncId
);
178 ArrayRef
<MCCVLoc
> getLinesForExtent(size_t L
, size_t R
);
180 /// Emits a line table substream.
181 void emitLineTableForFunction(MCObjectStreamer
&OS
, unsigned FuncId
,
182 const MCSymbol
*FuncBegin
,
183 const MCSymbol
*FuncEnd
);
185 void emitInlineLineTableForFunction(MCObjectStreamer
&OS
,
186 unsigned PrimaryFunctionId
,
187 unsigned SourceFileId
,
188 unsigned SourceLineNum
,
189 const MCSymbol
*FnStartSym
,
190 const MCSymbol
*FnEndSym
);
192 /// Encodes the binary annotations once we have a layout.
193 void encodeInlineLineTable(MCAsmLayout
&Layout
,
194 MCCVInlineLineTableFragment
&F
);
197 emitDefRange(MCObjectStreamer
&OS
,
198 ArrayRef
<std::pair
<const MCSymbol
*, const MCSymbol
*>> Ranges
,
199 StringRef FixedSizePortion
);
201 void encodeDefRange(MCAsmLayout
&Layout
, MCCVDefRangeFragment
&F
);
203 /// Emits the string table substream.
204 void emitStringTable(MCObjectStreamer
&OS
);
206 /// Emits the file checksum substream.
207 void emitFileChecksums(MCObjectStreamer
&OS
);
209 /// Emits the offset into the checksum table of the given file number.
210 void emitFileChecksumOffset(MCObjectStreamer
&OS
, unsigned FileNo
);
212 /// Add something to the string table. Returns the final string as well as
213 /// offset into the string table.
214 std::pair
<StringRef
, unsigned> addToStringTable(StringRef S
);
217 /// Map from string to string table offset.
218 StringMap
<unsigned> StringTable
;
220 /// The fragment that ultimately holds our strings.
221 MCDataFragment
*StrTabFragment
= nullptr;
222 bool InsertedStrTabFragment
= false;
224 MCDataFragment
*getStringTableFragment();
226 /// Get a string table offset.
227 unsigned getStringTableOffset(StringRef S
);
230 unsigned StringTableOffset
;
232 // Indicates if this FileInfo corresponds to an actual file, or hasn't been
234 bool Assigned
= false;
236 uint8_t ChecksumKind
;
238 ArrayRef
<uint8_t> Checksum
;
240 // Checksum offset stored as a symbol because it might be requested
241 // before it has been calculated, so a fixup may be needed.
242 MCSymbol
*ChecksumTableOffset
;
245 /// Array storing added file information.
246 SmallVector
<FileInfo
, 4> Files
;
248 /// The offset of the first and last .cv_loc directive for a given function
250 std::map
<unsigned, std::pair
<size_t, size_t>> MCCVLineStartStop
;
252 /// A collection of MCCVLoc for each section.
253 std::vector
<MCCVLoc
> MCCVLines
;
255 /// All known functions and inlined call sites, indexed by function id.
256 std::vector
<MCCVFunctionInfo
> Functions
;
258 /// Indicate whether we have already laid out the checksum table addresses or
260 bool ChecksumOffsetsAssigned
= false;
263 } // end namespace llvm