LCOV - code coverage report
Current view: top level - include/llvm/MC - MCCodeView.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 47 47 100.0 %
Date: 2017-09-14 15:23:50 Functions: 3 3 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- 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             : 
      24             : namespace llvm {
      25             : class MCContext;
      26             : class MCObjectStreamer;
      27             : class MCStreamer;
      28             : class CodeViewContext;
      29             : 
      30             : /// \brief Instances of this class represent the information from a
      31             : /// .cv_loc directive.
      32             : class MCCVLoc {
      33             :   uint32_t FunctionId;
      34             :   uint32_t FileNum;
      35             :   uint32_t Line;
      36             :   uint16_t Column;
      37             :   uint16_t PrologueEnd : 1;
      38             :   uint16_t IsStmt : 1;
      39             : 
      40             : private: // CodeViewContext manages these
      41             :   friend class CodeViewContext;
      42             :   MCCVLoc(unsigned functionid, unsigned fileNum, unsigned line, unsigned column,
      43             :           bool prologueend, bool isstmt)
      44        3729 :       : FunctionId(functionid), FileNum(fileNum), Line(line), Column(column),
      45        3729 :         PrologueEnd(prologueend), IsStmt(isstmt) {}
      46             : 
      47             :   // Allow the default copy constructor and assignment operator to be used
      48             :   // for an MCCVLoc object.
      49             : 
      50             : public:
      51             :   unsigned getFunctionId() const { return FunctionId; }
      52             : 
      53             :   /// \brief Get the FileNum of this MCCVLoc.
      54             :   unsigned getFileNum() const { return FileNum; }
      55             : 
      56             :   /// \brief Get the Line of this MCCVLoc.
      57             :   unsigned getLine() const { return Line; }
      58             : 
      59             :   /// \brief Get the Column of this MCCVLoc.
      60             :   unsigned getColumn() const { return Column; }
      61             : 
      62             :   bool isPrologueEnd() const { return PrologueEnd; }
      63         525 :   bool isStmt() const { return IsStmt; }
      64             : 
      65         562 :   void setFunctionId(unsigned FID) { FunctionId = FID; }
      66             : 
      67             :   /// \brief Set the FileNum of this MCCVLoc.
      68         628 :   void setFileNum(unsigned fileNum) { FileNum = fileNum; }
      69             : 
      70             :   /// \brief Set the Line of this MCCVLoc.
      71         628 :   void setLine(unsigned line) { Line = line; }
      72             : 
      73             :   /// \brief Set the Column of this MCCVLoc.
      74             :   void setColumn(unsigned column) {
      75             :     assert(column <= UINT16_MAX);
      76         562 :     Column = column;
      77             :   }
      78             : 
      79         562 :   void setPrologueEnd(bool PE) { PrologueEnd = PE; }
      80         562 :   void setIsStmt(bool IS) { IsStmt = IS; }
      81             : };
      82             : 
      83             : /// \brief Instances of this class represent the line information for
      84             : /// the CodeView line table entries.  Which is created after a machine
      85             : /// instruction is assembled and uses an address from a temporary label
      86             : /// created at the current address in the current section and the info from
      87             : /// the last .cv_loc directive seen as stored in the context.
      88             : class MCCVLineEntry : public MCCVLoc {
      89             :   const MCSymbol *Label;
      90             : 
      91             : private:
      92             :   // Allow the default copy constructor and assignment operator to be used
      93             :   // for an MCCVLineEntry object.
      94             : 
      95             : public:
      96             :   // Constructor to create an MCCVLineEntry given a symbol and the dwarf loc.
      97             :   MCCVLineEntry(const MCSymbol *Label, const MCCVLoc loc)
      98         396 :       : MCCVLoc(loc), Label(Label) {}
      99             : 
     100             :   const MCSymbol *getLabel() const { return Label; }
     101             : 
     102             :   // This is called when an instruction is assembled into the specified
     103             :   // section and if there is information from the last .cv_loc directive that
     104             :   // has yet to have a line entry made for it is made.
     105             :   static void Make(MCObjectStreamer *MCOS);
     106             : };
     107             : 
     108             : /// Information describing a function or inlined call site introduced by
     109             : /// .cv_func_id or .cv_inline_site_id. Accumulates information from .cv_loc
     110             : /// directives used with this function's id or the id of an inlined call site
     111             : /// within this function or inlined call site.
     112        1248 : struct MCCVFunctionInfo {
     113             :   /// If this represents an inlined call site, then ParentFuncIdPlusOne will be
     114             :   /// the parent function id plus one. If this represents a normal function,
     115             :   /// then there is no parent, and ParentFuncIdPlusOne will be FunctionSentinel.
     116             :   /// If this struct is an unallocated slot in the function info vector, then
     117             :   /// ParentFuncIdPlusOne will be zero.
     118             :   unsigned ParentFuncIdPlusOne = 0;
     119             : 
     120             :   enum : unsigned { FunctionSentinel = ~0U };
     121             : 
     122             :   struct LineInfo {
     123             :     unsigned File;
     124             :     unsigned Line;
     125             :     unsigned Col;
     126             :   };
     127             : 
     128             :   LineInfo InlinedAt;
     129             : 
     130             :   /// The section of the first .cv_loc directive used for this function, or null
     131             :   /// if none has been seen yet.
     132             :   MCSection *Section = nullptr;
     133             : 
     134             :   /// Map from inlined call site id to the inlined at location to use for that
     135             :   /// call site. Call chains are collapsed, so for the call chain 'f -> g -> h',
     136             :   /// the InlinedAtMap of 'f' will contain entries for 'g' and 'h' that both
     137             :   /// list the line info for the 'g' call site.
     138             :   DenseMap<unsigned, LineInfo> InlinedAtMap;
     139             : 
     140             :   /// Returns true if this is function info has not yet been used in a
     141             :   /// .cv_func_id or .cv_inline_site_id directive.
     142             :   bool isUnallocatedFunctionInfo() const { return ParentFuncIdPlusOne == 0; }
     143             : 
     144             :   /// Returns true if this represents an inlined call site, meaning
     145             :   /// ParentFuncIdPlusOne is neither zero nor ~0U.
     146             :   bool isInlinedCallSite() const {
     147          68 :     return !isUnallocatedFunctionInfo() &&
     148             :            ParentFuncIdPlusOne != FunctionSentinel;
     149             :   }
     150             : 
     151             :   unsigned getParentFuncId() const {
     152             :     assert(isInlinedCallSite());
     153          38 :     return ParentFuncIdPlusOne - 1;
     154             :   }
     155             : };
     156             : 
     157             : /// Holds state from .cv_file and .cv_loc directives for later emission.
     158             : class CodeViewContext {
     159             : public:
     160             :   CodeViewContext();
     161             :   ~CodeViewContext();
     162             : 
     163             :   bool isValidFileNumber(unsigned FileNumber) const;
     164             :   bool addFile(unsigned FileNumber, StringRef Filename);
     165             :   ArrayRef<StringRef> getFilenames() { return Filenames; }
     166             : 
     167             :   /// Records the function id of a normal function. Returns false if the
     168             :   /// function id has already been used, and true otherwise.
     169             :   bool recordFunctionId(unsigned FuncId);
     170             : 
     171             :   /// Records the function id of an inlined call site. Records the "inlined at"
     172             :   /// location info of the call site, including what function or inlined call
     173             :   /// site it was inlined into. Returns false if the function id has already
     174             :   /// been used, and true otherwise.
     175             :   bool recordInlinedCallSiteId(unsigned FuncId, unsigned IAFunc,
     176             :                                unsigned IAFile, unsigned IALine,
     177             :                                unsigned IACol);
     178             : 
     179             :   /// Retreive the function info if this is a valid function id, or nullptr.
     180             :   MCCVFunctionInfo *getCVFunctionInfo(unsigned FuncId) {
     181        1396 :     if (FuncId >= Functions.size())
     182             :       return nullptr;
     183        1396 :     if (Functions[FuncId].isUnallocatedFunctionInfo())
     184             :       return nullptr;
     185         698 :     return &Functions[FuncId];
     186             :   }
     187             : 
     188             :   /// Saves the information from the currently parsed .cv_loc directive
     189             :   /// and sets CVLocSeen.  When the next instruction is assembled an entry
     190             :   /// in the line number table with this information and the address of the
     191             :   /// instruction will be created.
     192             :   void setCurrentCVLoc(unsigned FunctionId, unsigned FileNo, unsigned Line,
     193             :                        unsigned Column, bool PrologueEnd, bool IsStmt) {
     194        1124 :     CurrentCVLoc.setFunctionId(FunctionId);
     195        1124 :     CurrentCVLoc.setFileNum(FileNo);
     196        1124 :     CurrentCVLoc.setLine(Line);
     197        1124 :     CurrentCVLoc.setColumn(Column);
     198        1124 :     CurrentCVLoc.setPrologueEnd(PrologueEnd);
     199        1124 :     CurrentCVLoc.setIsStmt(IsStmt);
     200         562 :     CVLocSeen = true;
     201             :   }
     202         330 :   void clearCVLocSeen() { CVLocSeen = false; }
     203             : 
     204             :   bool getCVLocSeen() { return CVLocSeen; }
     205             :   const MCCVLoc &getCurrentCVLoc() { return CurrentCVLoc; }
     206             : 
     207             :   bool isValidCVFileNumber(unsigned FileNumber);
     208             : 
     209             :   /// \brief Add a line entry.
     210         330 :   void addLineEntry(const MCCVLineEntry &LineEntry) {
     211         660 :     size_t Offset = MCCVLines.size();
     212             :     auto I = MCCVLineStartStop.insert(
     213        1320 :         {LineEntry.getFunctionId(), {Offset, Offset + 1}});
     214         330 :     if (!I.second)
     215         438 :       I.first->second.second = Offset + 1;
     216         330 :     MCCVLines.push_back(LineEntry);
     217         330 :   }
     218             : 
     219          92 :   std::vector<MCCVLineEntry> getFunctionLineEntries(unsigned FuncId) {
     220          92 :     std::vector<MCCVLineEntry> FilteredLines;
     221             : 
     222         184 :     auto I = MCCVLineStartStop.find(FuncId);
     223         184 :     if (I != MCCVLineStartStop.end())
     224         494 :       for (size_t Idx = I->second.first, End = I->second.second; Idx != End;
     225             :            ++Idx)
     226         632 :         if (MCCVLines[Idx].getFunctionId() == FuncId)
     227         292 :           FilteredLines.push_back(MCCVLines[Idx]);
     228          92 :     return FilteredLines;
     229             :   }
     230             : 
     231          84 :   std::pair<size_t, size_t> getLineExtent(unsigned FuncId) {
     232         168 :     auto I = MCCVLineStartStop.find(FuncId);
     233             :     // Return an empty extent if there are no cv_locs for this function id.
     234         168 :     if (I == MCCVLineStartStop.end())
     235          18 :       return {~0ULL, 0};
     236          75 :     return I->second;
     237             :   }
     238             : 
     239             :   ArrayRef<MCCVLineEntry> getLinesForExtent(size_t L, size_t R) {
     240          66 :     if (R <= L)
     241             :       return None;
     242         264 :     if (L >= MCCVLines.size())
     243             :       return None;
     244         240 :     return makeArrayRef(&MCCVLines[L], R - L);
     245             :   }
     246             : 
     247             :   /// Emits a line table substream.
     248             :   void emitLineTableForFunction(MCObjectStreamer &OS, unsigned FuncId,
     249             :                                 const MCSymbol *FuncBegin,
     250             :                                 const MCSymbol *FuncEnd);
     251             : 
     252             :   void emitInlineLineTableForFunction(MCObjectStreamer &OS,
     253             :                                       unsigned PrimaryFunctionId,
     254             :                                       unsigned SourceFileId,
     255             :                                       unsigned SourceLineNum,
     256             :                                       const MCSymbol *FnStartSym,
     257             :                                       const MCSymbol *FnEndSym);
     258             : 
     259             :   /// Encodes the binary annotations once we have a layout.
     260             :   void encodeInlineLineTable(MCAsmLayout &Layout,
     261             :                              MCCVInlineLineTableFragment &F);
     262             : 
     263             :   void
     264             :   emitDefRange(MCObjectStreamer &OS,
     265             :                ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
     266             :                StringRef FixedSizePortion);
     267             : 
     268             :   void encodeDefRange(MCAsmLayout &Layout, MCCVDefRangeFragment &F);
     269             : 
     270             :   /// Emits the string table substream.
     271             :   void emitStringTable(MCObjectStreamer &OS);
     272             : 
     273             :   /// Emits the file checksum substream.
     274             :   void emitFileChecksums(MCObjectStreamer &OS);
     275             : 
     276             : private:
     277             :   /// The current CodeView line information from the last .cv_loc directive.
     278             :   MCCVLoc CurrentCVLoc = MCCVLoc(0, 0, 0, 0, false, true);
     279             :   bool CVLocSeen = false;
     280             : 
     281             :   /// Map from string to string table offset.
     282             :   StringMap<unsigned> StringTable;
     283             : 
     284             :   /// The fragment that ultimately holds our strings.
     285             :   MCDataFragment *StrTabFragment = nullptr;
     286             :   bool InsertedStrTabFragment = false;
     287             : 
     288             :   MCDataFragment *getStringTableFragment();
     289             : 
     290             :   /// Add something to the string table.
     291             :   StringRef addToStringTable(StringRef S);
     292             : 
     293             :   /// Get a string table offset.
     294             :   unsigned getStringTableOffset(StringRef S);
     295             : 
     296             :   /// An array of absolute paths. Eventually this may include the file checksum.
     297             :   SmallVector<StringRef, 4> Filenames;
     298             : 
     299             :   /// The offset of the first and last .cv_loc directive for a given function
     300             :   /// id.
     301             :   std::map<unsigned, std::pair<size_t, size_t>> MCCVLineStartStop;
     302             : 
     303             :   /// A collection of MCCVLineEntry for each section.
     304             :   std::vector<MCCVLineEntry> MCCVLines;
     305             : 
     306             :   /// All known functions and inlined call sites, indexed by function id.
     307             :   std::vector<MCCVFunctionInfo> Functions;
     308             : };
     309             : 
     310             : } // end namespace llvm
     311             : #endif

Generated by: LCOV version 1.13