Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:12

0001 //===- MCCodeView.h - Machine Code CodeView support -------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // Holds state from .cv_file and .cv_loc directives for later emission.
0010 //
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_MC_MCCODEVIEW_H
0014 #define LLVM_MC_MCCODEVIEW_H
0015 
0016 #include "llvm/ADT/ArrayRef.h"
0017 #include "llvm/ADT/DenseMap.h"
0018 #include "llvm/ADT/SmallVector.h"
0019 #include "llvm/ADT/StringMap.h"
0020 #include "llvm/ADT/StringRef.h"
0021 #include <map>
0022 #include <vector>
0023 
0024 namespace llvm {
0025 class MCAssembler;
0026 class MCCVDefRangeFragment;
0027 class MCCVInlineLineTableFragment;
0028 class MCDataFragment;
0029 class MCFragment;
0030 class MCSection;
0031 class MCSymbol;
0032 class MCContext;
0033 class MCObjectStreamer;
0034 class MCStreamer;
0035 
0036 /// Instances of this class represent the information from a
0037 /// .cv_loc directive.
0038 class MCCVLoc {
0039   const MCSymbol *Label = nullptr;
0040   uint32_t FunctionId;
0041   uint32_t FileNum;
0042   uint32_t Line;
0043   uint16_t Column;
0044   uint16_t PrologueEnd : 1;
0045   uint16_t IsStmt : 1;
0046 
0047 private: // CodeViewContext manages these
0048   friend class CodeViewContext;
0049   MCCVLoc(const MCSymbol *Label, unsigned functionid, unsigned fileNum,
0050           unsigned line, unsigned column, bool prologueend, bool isstmt)
0051       : Label(Label), FunctionId(functionid), FileNum(fileNum), Line(line),
0052         Column(column), PrologueEnd(prologueend), IsStmt(isstmt) {}
0053 
0054   // Allow the default copy constructor and assignment operator to be used
0055   // for an MCCVLoc object.
0056 
0057 public:
0058   const MCSymbol *getLabel() const { return Label; }
0059 
0060   unsigned getFunctionId() const { return FunctionId; }
0061 
0062   /// Get the FileNum of this MCCVLoc.
0063   unsigned getFileNum() const { return FileNum; }
0064 
0065   /// Get the Line of this MCCVLoc.
0066   unsigned getLine() const { return Line; }
0067 
0068   /// Get the Column of this MCCVLoc.
0069   unsigned getColumn() const { return Column; }
0070 
0071   bool isPrologueEnd() const { return PrologueEnd; }
0072   bool isStmt() const { return IsStmt; }
0073 
0074   void setLabel(const MCSymbol *L) { Label = L; }
0075 
0076   void setFunctionId(unsigned FID) { FunctionId = FID; }
0077 
0078   /// Set the FileNum of this MCCVLoc.
0079   void setFileNum(unsigned fileNum) { FileNum = fileNum; }
0080 
0081   /// Set the Line of this MCCVLoc.
0082   void setLine(unsigned line) { Line = line; }
0083 
0084   /// Set the Column of this MCCVLoc.
0085   void setColumn(unsigned column) {
0086     assert(column <= UINT16_MAX);
0087     Column = column;
0088   }
0089 
0090   void setPrologueEnd(bool PE) { PrologueEnd = PE; }
0091   void setIsStmt(bool IS) { IsStmt = IS; }
0092 };
0093 
0094 /// Information describing a function or inlined call site introduced by
0095 /// .cv_func_id or .cv_inline_site_id. Accumulates information from .cv_loc
0096 /// directives used with this function's id or the id of an inlined call site
0097 /// within this function or inlined call site.
0098 struct MCCVFunctionInfo {
0099   /// If this represents an inlined call site, then ParentFuncIdPlusOne will be
0100   /// the parent function id plus one. If this represents a normal function,
0101   /// then there is no parent, and ParentFuncIdPlusOne will be FunctionSentinel.
0102   /// If this struct is an unallocated slot in the function info vector, then
0103   /// ParentFuncIdPlusOne will be zero.
0104   unsigned ParentFuncIdPlusOne = 0;
0105 
0106   enum : unsigned { FunctionSentinel = ~0U };
0107 
0108   struct LineInfo {
0109     unsigned File;
0110     unsigned Line;
0111     unsigned Col;
0112   };
0113 
0114   LineInfo InlinedAt;
0115 
0116   /// The section of the first .cv_loc directive used for this function, or null
0117   /// if none has been seen yet.
0118   MCSection *Section = nullptr;
0119 
0120   /// Map from inlined call site id to the inlined at location to use for that
0121   /// call site. Call chains are collapsed, so for the call chain 'f -> g -> h',
0122   /// the InlinedAtMap of 'f' will contain entries for 'g' and 'h' that both
0123   /// list the line info for the 'g' call site.
0124   DenseMap<unsigned, LineInfo> InlinedAtMap;
0125 
0126   /// Returns true if this is function info has not yet been used in a
0127   /// .cv_func_id or .cv_inline_site_id directive.
0128   bool isUnallocatedFunctionInfo() const { return ParentFuncIdPlusOne == 0; }
0129 
0130   /// Returns true if this represents an inlined call site, meaning
0131   /// ParentFuncIdPlusOne is neither zero nor ~0U.
0132   bool isInlinedCallSite() const {
0133     return !isUnallocatedFunctionInfo() &&
0134            ParentFuncIdPlusOne != FunctionSentinel;
0135   }
0136 
0137   unsigned getParentFuncId() const {
0138     assert(isInlinedCallSite());
0139     return ParentFuncIdPlusOne - 1;
0140   }
0141 };
0142 
0143 /// Holds state from .cv_file and .cv_loc directives for later emission.
0144 class CodeViewContext {
0145 public:
0146   CodeViewContext(MCContext *MCCtx) : MCCtx(MCCtx) {}
0147 
0148   CodeViewContext &operator=(const CodeViewContext &other) = delete;
0149   CodeViewContext(const CodeViewContext &other) = delete;
0150 
0151   void finish();
0152 
0153   bool isValidFileNumber(unsigned FileNumber) const;
0154   bool addFile(MCStreamer &OS, unsigned FileNumber, StringRef Filename,
0155                ArrayRef<uint8_t> ChecksumBytes, uint8_t ChecksumKind);
0156 
0157   /// Records the function id of a normal function. Returns false if the
0158   /// function id has already been used, and true otherwise.
0159   bool recordFunctionId(unsigned FuncId);
0160 
0161   /// Records the function id of an inlined call site. Records the "inlined at"
0162   /// location info of the call site, including what function or inlined call
0163   /// site it was inlined into. Returns false if the function id has already
0164   /// been used, and true otherwise.
0165   bool recordInlinedCallSiteId(unsigned FuncId, unsigned IAFunc,
0166                                unsigned IAFile, unsigned IALine,
0167                                unsigned IACol);
0168 
0169   /// Retreive the function info if this is a valid function id, or nullptr.
0170   MCCVFunctionInfo *getCVFunctionInfo(unsigned FuncId);
0171 
0172   /// Saves the information from the currently parsed .cv_loc directive
0173   /// and sets CVLocSeen.  When the next instruction is assembled an entry
0174   /// in the line number table with this information and the address of the
0175   /// instruction will be created.
0176   void recordCVLoc(MCContext &Ctx, const MCSymbol *Label, unsigned FunctionId,
0177                    unsigned FileNo, unsigned Line, unsigned Column,
0178                    bool PrologueEnd, bool IsStmt);
0179 
0180   /// Add a line entry.
0181   void addLineEntry(const MCCVLoc &LineEntry);
0182 
0183   std::vector<MCCVLoc> getFunctionLineEntries(unsigned FuncId);
0184 
0185   std::pair<size_t, size_t> getLineExtent(unsigned FuncId);
0186   std::pair<size_t, size_t> getLineExtentIncludingInlinees(unsigned FuncId);
0187 
0188   ArrayRef<MCCVLoc> getLinesForExtent(size_t L, size_t R);
0189 
0190   /// Emits a line table substream.
0191   void emitLineTableForFunction(MCObjectStreamer &OS, unsigned FuncId,
0192                                 const MCSymbol *FuncBegin,
0193                                 const MCSymbol *FuncEnd);
0194 
0195   void emitInlineLineTableForFunction(MCObjectStreamer &OS,
0196                                       unsigned PrimaryFunctionId,
0197                                       unsigned SourceFileId,
0198                                       unsigned SourceLineNum,
0199                                       const MCSymbol *FnStartSym,
0200                                       const MCSymbol *FnEndSym);
0201 
0202   /// Encodes the binary annotations once we have a layout.
0203   void encodeInlineLineTable(const MCAssembler &Asm,
0204                              MCCVInlineLineTableFragment &F);
0205 
0206   MCFragment *
0207   emitDefRange(MCObjectStreamer &OS,
0208                ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
0209                StringRef FixedSizePortion);
0210 
0211   void encodeDefRange(const MCAssembler &Asm, MCCVDefRangeFragment &F);
0212 
0213   /// Emits the string table substream.
0214   void emitStringTable(MCObjectStreamer &OS);
0215 
0216   /// Emits the file checksum substream.
0217   void emitFileChecksums(MCObjectStreamer &OS);
0218 
0219   /// Emits the offset into the checksum table of the given file number.
0220   void emitFileChecksumOffset(MCObjectStreamer &OS, unsigned FileNo);
0221 
0222   /// Add something to the string table.  Returns the final string as well as
0223   /// offset into the string table.
0224   std::pair<StringRef, unsigned> addToStringTable(StringRef S);
0225 
0226 private:
0227   MCContext *MCCtx;
0228 
0229   /// Map from string to string table offset.
0230   StringMap<unsigned> StringTable;
0231 
0232   /// The fragment that ultimately holds our strings.
0233   MCDataFragment *StrTabFragment = nullptr;
0234   SmallVector<char, 0> StrTab = {'\0'};
0235 
0236   /// Get a string table offset.
0237   unsigned getStringTableOffset(StringRef S);
0238 
0239   struct FileInfo {
0240     unsigned StringTableOffset;
0241 
0242     // Indicates if this FileInfo corresponds to an actual file, or hasn't been
0243     // set yet.
0244     bool Assigned = false;
0245 
0246     uint8_t ChecksumKind;
0247 
0248     ArrayRef<uint8_t> Checksum;
0249 
0250     // Checksum offset stored as a symbol because it might be requested
0251     // before it has been calculated, so a fixup may be needed.
0252     MCSymbol *ChecksumTableOffset;
0253   };
0254 
0255   /// Array storing added file information.
0256   SmallVector<FileInfo, 4> Files;
0257 
0258   /// The offset of the first and last .cv_loc directive for a given function
0259   /// id.
0260   std::map<unsigned, std::pair<size_t, size_t>> MCCVLineStartStop;
0261 
0262   /// A collection of MCCVLoc for each section.
0263   std::vector<MCCVLoc> MCCVLines;
0264 
0265   /// All known functions and inlined call sites, indexed by function id.
0266   std::vector<MCCVFunctionInfo> Functions;
0267 
0268   /// Indicate whether we have already laid out the checksum table addresses or
0269   /// not.
0270   bool ChecksumOffsetsAssigned = false;
0271 };
0272 
0273 } // end namespace llvm
0274 #endif