| //===- MCCodeView.h - Machine Code CodeView support -------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // Holds state from .cv_file and .cv_loc directives for later emission. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_MC_MCCODEVIEW_H |
| #define LLVM_MC_MCCODEVIEW_H |
| |
| #include "llvm/ADT/StringMap.h" |
| #include "llvm/ADT/StringRef.h" |
| #include "llvm/MC/MCFragment.h" |
| #include "llvm/MC/MCObjectStreamer.h" |
| #include <map> |
| #include <vector> |
| |
| namespace llvm { |
| class MCContext; |
| class MCObjectStreamer; |
| class MCStreamer; |
| class CodeViewContext; |
| |
| /// Instances of this class represent the information from a |
| /// .cv_loc directive. |
| class MCCVLoc { |
| const MCSymbol *Label = nullptr; |
| uint32_t FunctionId; |
| uint32_t FileNum; |
| uint32_t Line; |
| uint16_t Column; |
| uint16_t PrologueEnd : 1; |
| uint16_t IsStmt : 1; |
| |
| private: // CodeViewContext manages these |
| friend class CodeViewContext; |
| MCCVLoc(const MCSymbol *Label, unsigned functionid, unsigned fileNum, |
| unsigned line, unsigned column, bool prologueend, bool isstmt) |
| : Label(Label), FunctionId(functionid), FileNum(fileNum), Line(line), |
| Column(column), PrologueEnd(prologueend), IsStmt(isstmt) {} |
| |
| // Allow the default copy constructor and assignment operator to be used |
| // for an MCCVLoc object. |
| |
| public: |
| const MCSymbol *getLabel() const { return Label; } |
| |
| unsigned getFunctionId() const { return FunctionId; } |
| |
| /// Get the FileNum of this MCCVLoc. |
| unsigned getFileNum() const { return FileNum; } |
| |
| /// Get the Line of this MCCVLoc. |
| unsigned getLine() const { return Line; } |
| |
| /// Get the Column of this MCCVLoc. |
| unsigned getColumn() const { return Column; } |
| |
| bool isPrologueEnd() const { return PrologueEnd; } |
| bool isStmt() const { return IsStmt; } |
| |
| void setLabel(const MCSymbol *L) { Label = L; } |
| |
| void setFunctionId(unsigned FID) { FunctionId = FID; } |
| |
| /// Set the FileNum of this MCCVLoc. |
| void setFileNum(unsigned fileNum) { FileNum = fileNum; } |
| |
| /// Set the Line of this MCCVLoc. |
| void setLine(unsigned line) { Line = line; } |
| |
| /// Set the Column of this MCCVLoc. |
| void setColumn(unsigned column) { |
| assert(column <= UINT16_MAX); |
| Column = column; |
| } |
| |
| void setPrologueEnd(bool PE) { PrologueEnd = PE; } |
| void setIsStmt(bool IS) { IsStmt = IS; } |
| }; |
| |
| /// Information describing a function or inlined call site introduced by |
| /// .cv_func_id or .cv_inline_site_id. Accumulates information from .cv_loc |
| /// directives used with this function's id or the id of an inlined call site |
| /// within this function or inlined call site. |
| struct MCCVFunctionInfo { |
| /// If this represents an inlined call site, then ParentFuncIdPlusOne will be |
| /// the parent function id plus one. If this represents a normal function, |
| /// then there is no parent, and ParentFuncIdPlusOne will be FunctionSentinel. |
| /// If this struct is an unallocated slot in the function info vector, then |
| /// ParentFuncIdPlusOne will be zero. |
| unsigned ParentFuncIdPlusOne = 0; |
| |
| enum : unsigned { FunctionSentinel = ~0U }; |
| |
| struct LineInfo { |
| unsigned File; |
| unsigned Line; |
| unsigned Col; |
| }; |
| |
| LineInfo InlinedAt; |
| |
| /// The section of the first .cv_loc directive used for this function, or null |
| /// if none has been seen yet. |
| MCSection *Section = nullptr; |
| |
| /// Map from inlined call site id to the inlined at location to use for that |
| /// call site. Call chains are collapsed, so for the call chain 'f -> g -> h', |
| /// the InlinedAtMap of 'f' will contain entries for 'g' and 'h' that both |
| /// list the line info for the 'g' call site. |
| DenseMap<unsigned, LineInfo> InlinedAtMap; |
| |
| /// Returns true if this is function info has not yet been used in a |
| /// .cv_func_id or .cv_inline_site_id directive. |
| bool isUnallocatedFunctionInfo() const { return ParentFuncIdPlusOne == 0; } |
| |
| /// Returns true if this represents an inlined call site, meaning |
| /// ParentFuncIdPlusOne is neither zero nor ~0U. |
| bool isInlinedCallSite() const { |
| return !isUnallocatedFunctionInfo() && |
| ParentFuncIdPlusOne != FunctionSentinel; |
| } |
| |
| unsigned getParentFuncId() const { |
| assert(isInlinedCallSite()); |
| return ParentFuncIdPlusOne - 1; |
| } |
| }; |
| |
| /// Holds state from .cv_file and .cv_loc directives for later emission. |
| class CodeViewContext { |
| public: |
| CodeViewContext(); |
| ~CodeViewContext(); |
| |
| bool isValidFileNumber(unsigned FileNumber) const; |
| bool addFile(MCStreamer &OS, unsigned FileNumber, StringRef Filename, |
| ArrayRef<uint8_t> ChecksumBytes, uint8_t ChecksumKind); |
| |
| /// Records the function id of a normal function. Returns false if the |
| /// function id has already been used, and true otherwise. |
| bool recordFunctionId(unsigned FuncId); |
| |
| /// Records the function id of an inlined call site. Records the "inlined at" |
| /// location info of the call site, including what function or inlined call |
| /// site it was inlined into. Returns false if the function id has already |
| /// been used, and true otherwise. |
| bool recordInlinedCallSiteId(unsigned FuncId, unsigned IAFunc, |
| unsigned IAFile, unsigned IALine, |
| unsigned IACol); |
| |
| /// Retreive the function info if this is a valid function id, or nullptr. |
| MCCVFunctionInfo *getCVFunctionInfo(unsigned FuncId); |
| |
| /// Saves the information from the currently parsed .cv_loc directive |
| /// and sets CVLocSeen. When the next instruction is assembled an entry |
| /// in the line number table with this information and the address of the |
| /// instruction will be created. |
| void recordCVLoc(MCContext &Ctx, const MCSymbol *Label, unsigned FunctionId, |
| unsigned FileNo, unsigned Line, unsigned Column, |
| bool PrologueEnd, bool IsStmt); |
| |
| bool isValidCVFileNumber(unsigned FileNumber); |
| |
| /// Add a line entry. |
| void addLineEntry(const MCCVLoc &LineEntry); |
| |
| std::vector<MCCVLoc> getFunctionLineEntries(unsigned FuncId); |
| |
| std::pair<size_t, size_t> getLineExtent(unsigned FuncId); |
| |
| ArrayRef<MCCVLoc> getLinesForExtent(size_t L, size_t R); |
| |
| /// Emits a line table substream. |
| void emitLineTableForFunction(MCObjectStreamer &OS, unsigned FuncId, |
| const MCSymbol *FuncBegin, |
| const MCSymbol *FuncEnd); |
| |
| void emitInlineLineTableForFunction(MCObjectStreamer &OS, |
| unsigned PrimaryFunctionId, |
| unsigned SourceFileId, |
| unsigned SourceLineNum, |
| const MCSymbol *FnStartSym, |
| const MCSymbol *FnEndSym); |
| |
| /// Encodes the binary annotations once we have a layout. |
| void encodeInlineLineTable(MCAsmLayout &Layout, |
| MCCVInlineLineTableFragment &F); |
| |
| void |
| emitDefRange(MCObjectStreamer &OS, |
| ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, |
| StringRef FixedSizePortion); |
| |
| void encodeDefRange(MCAsmLayout &Layout, MCCVDefRangeFragment &F); |
| |
| /// Emits the string table substream. |
| void emitStringTable(MCObjectStreamer &OS); |
| |
| /// Emits the file checksum substream. |
| void emitFileChecksums(MCObjectStreamer &OS); |
| |
| /// Emits the offset into the checksum table of the given file number. |
| void emitFileChecksumOffset(MCObjectStreamer &OS, unsigned FileNo); |
| |
| /// Add something to the string table. Returns the final string as well as |
| /// offset into the string table. |
| std::pair<StringRef, unsigned> addToStringTable(StringRef S); |
| |
| private: |
| /// Map from string to string table offset. |
| StringMap<unsigned> StringTable; |
| |
| /// The fragment that ultimately holds our strings. |
| MCDataFragment *StrTabFragment = nullptr; |
| bool InsertedStrTabFragment = false; |
| |
| MCDataFragment *getStringTableFragment(); |
| |
| /// Get a string table offset. |
| unsigned getStringTableOffset(StringRef S); |
| |
| struct FileInfo { |
| unsigned StringTableOffset; |
| |
| // Indicates if this FileInfo corresponds to an actual file, or hasn't been |
| // set yet. |
| bool Assigned = false; |
| |
| uint8_t ChecksumKind; |
| |
| ArrayRef<uint8_t> Checksum; |
| |
| // Checksum offset stored as a symbol because it might be requested |
| // before it has been calculated, so a fixup may be needed. |
| MCSymbol *ChecksumTableOffset; |
| }; |
| |
| /// Array storing added file information. |
| SmallVector<FileInfo, 4> Files; |
| |
| /// The offset of the first and last .cv_loc directive for a given function |
| /// id. |
| std::map<unsigned, std::pair<size_t, size_t>> MCCVLineStartStop; |
| |
| /// A collection of MCCVLoc for each section. |
| std::vector<MCCVLoc> MCCVLines; |
| |
| /// All known functions and inlined call sites, indexed by function id. |
| std::vector<MCCVFunctionInfo> Functions; |
| |
| /// Indicate whether we have already laid out the checksum table addresses or |
| /// not. |
| bool ChecksumOffsetsAssigned = false; |
| }; |
| |
| } // end namespace llvm |
| #endif |