Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- MCDwarf.h - Machine Code Dwarf support -------------------*- C++ -*-===//
  2. //
  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
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file contains the declaration of the MCDwarfFile to support the dwarf
  10. // .file directive and the .loc directive.
  11. //
  12. //===----------------------------------------------------------------------===//
  13.  
  14. #ifndef LLVM_MC_MCDWARF_H
  15. #define LLVM_MC_MCDWARF_H
  16.  
  17. #include "llvm/ADT/MapVector.h"
  18. #include "llvm/ADT/SmallVector.h"
  19. #include "llvm/ADT/StringMap.h"
  20. #include "llvm/ADT/StringRef.h"
  21. #include "llvm/MC/StringTableBuilder.h"
  22. #include "llvm/Support/Error.h"
  23. #include "llvm/Support/MD5.h"
  24. #include "llvm/Support/StringSaver.h"
  25. #include <cassert>
  26. #include <cstdint>
  27. #include <optional>
  28. #include <string>
  29. #include <utility>
  30. #include <vector>
  31.  
  32. namespace llvm {
  33.  
  34. template <typename T> class ArrayRef;
  35. class MCAsmBackend;
  36. class MCContext;
  37. class MCObjectStreamer;
  38. class MCSection;
  39. class MCStreamer;
  40. class MCSymbol;
  41. class raw_ostream;
  42. class SMLoc;
  43. class SourceMgr;
  44.  
  45. namespace mcdwarf {
  46. // Emit the common part of the DWARF 5 range/locations list tables header.
  47. MCSymbol *emitListsTableHeaderStart(MCStreamer &S);
  48. } // namespace mcdwarf
  49.  
  50. /// Manage the .debug_line_str section contents, if we use it.
  51. class MCDwarfLineStr {
  52.   BumpPtrAllocator Alloc;
  53.   StringSaver Saver{Alloc};
  54.   MCSymbol *LineStrLabel = nullptr;
  55.   StringTableBuilder LineStrings{StringTableBuilder::DWARF};
  56.   bool UseRelocs = false;
  57.  
  58. public:
  59.   /// Construct an instance that can emit .debug_line_str (for use in a normal
  60.   /// v5 line table).
  61.   explicit MCDwarfLineStr(MCContext &Ctx);
  62.  
  63.   StringSaver &getSaver() { return Saver; }
  64.  
  65.   /// Emit a reference to the string.
  66.   void emitRef(MCStreamer *MCOS, StringRef Path);
  67.  
  68.   /// Emit the .debug_line_str section if appropriate.
  69.   void emitSection(MCStreamer *MCOS);
  70.  
  71.   /// Returns finalized section.
  72.   SmallString<0> getFinalizedData();
  73. };
  74.  
  75. /// Instances of this class represent the name of the dwarf .file directive and
  76. /// its associated dwarf file number in the MC file. MCDwarfFile's are created
  77. /// and uniqued by the MCContext class. In Dwarf 4 file numbers start from 1;
  78. /// i.e. the entry with file number 1 is the first element in the vector of
  79. /// DwarfFiles and there is no MCDwarfFile with file number 0. In Dwarf 5 file
  80. /// numbers start from 0, with the MCDwarfFile with file number 0 being the
  81. /// primary source file, and file numbers correspond to their index in the
  82. /// vector.
  83. struct MCDwarfFile {
  84.   // The base name of the file without its directory path.
  85.   std::string Name;
  86.  
  87.   // The index into the list of directory names for this file name.
  88.   unsigned DirIndex = 0;
  89.  
  90.   /// The MD5 checksum, if there is one. Non-owning pointer to data allocated
  91.   /// in MCContext.
  92.   std::optional<MD5::MD5Result> Checksum;
  93.  
  94.   /// The source code of the file. Non-owning reference to data allocated in
  95.   /// MCContext.
  96.   std::optional<StringRef> Source;
  97. };
  98.  
  99. /// Instances of this class represent the information from a
  100. /// dwarf .loc directive.
  101. class MCDwarfLoc {
  102.   uint32_t FileNum;
  103.   uint32_t Line;
  104.   uint16_t Column;
  105.   // Flags (see #define's below)
  106.   uint8_t Flags;
  107.   uint8_t Isa;
  108.   uint32_t Discriminator;
  109.  
  110. // Flag that indicates the initial value of the is_stmt_start flag.
  111. #define DWARF2_LINE_DEFAULT_IS_STMT 1
  112.  
  113. #define DWARF2_FLAG_IS_STMT (1 << 0)
  114. #define DWARF2_FLAG_BASIC_BLOCK (1 << 1)
  115. #define DWARF2_FLAG_PROLOGUE_END (1 << 2)
  116. #define DWARF2_FLAG_EPILOGUE_BEGIN (1 << 3)
  117.  
  118. private: // MCContext manages these
  119.   friend class MCContext;
  120.   friend class MCDwarfLineEntry;
  121.  
  122.   MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags,
  123.              unsigned isa, unsigned discriminator)
  124.       : FileNum(fileNum), Line(line), Column(column), Flags(flags), Isa(isa),
  125.         Discriminator(discriminator) {}
  126.  
  127.   // Allow the default copy constructor and assignment operator to be used
  128.   // for an MCDwarfLoc object.
  129.  
  130. public:
  131.   /// Get the FileNum of this MCDwarfLoc.
  132.   unsigned getFileNum() const { return FileNum; }
  133.  
  134.   /// Get the Line of this MCDwarfLoc.
  135.   unsigned getLine() const { return Line; }
  136.  
  137.   /// Get the Column of this MCDwarfLoc.
  138.   unsigned getColumn() const { return Column; }
  139.  
  140.   /// Get the Flags of this MCDwarfLoc.
  141.   unsigned getFlags() const { return Flags; }
  142.  
  143.   /// Get the Isa of this MCDwarfLoc.
  144.   unsigned getIsa() const { return Isa; }
  145.  
  146.   /// Get the Discriminator of this MCDwarfLoc.
  147.   unsigned getDiscriminator() const { return Discriminator; }
  148.  
  149.   /// Set the FileNum of this MCDwarfLoc.
  150.   void setFileNum(unsigned fileNum) { FileNum = fileNum; }
  151.  
  152.   /// Set the Line of this MCDwarfLoc.
  153.   void setLine(unsigned line) { Line = line; }
  154.  
  155.   /// Set the Column of this MCDwarfLoc.
  156.   void setColumn(unsigned column) {
  157.     assert(column <= UINT16_MAX);
  158.     Column = column;
  159.   }
  160.  
  161.   /// Set the Flags of this MCDwarfLoc.
  162.   void setFlags(unsigned flags) {
  163.     assert(flags <= UINT8_MAX);
  164.     Flags = flags;
  165.   }
  166.  
  167.   /// Set the Isa of this MCDwarfLoc.
  168.   void setIsa(unsigned isa) {
  169.     assert(isa <= UINT8_MAX);
  170.     Isa = isa;
  171.   }
  172.  
  173.   /// Set the Discriminator of this MCDwarfLoc.
  174.   void setDiscriminator(unsigned discriminator) {
  175.     Discriminator = discriminator;
  176.   }
  177. };
  178.  
  179. /// Instances of this class represent the line information for
  180. /// the dwarf line table entries.  Which is created after a machine
  181. /// instruction is assembled and uses an address from a temporary label
  182. /// created at the current address in the current section and the info from
  183. /// the last .loc directive seen as stored in the context.
  184. class MCDwarfLineEntry : public MCDwarfLoc {
  185.   MCSymbol *Label;
  186.  
  187. private:
  188.   // Allow the default copy constructor and assignment operator to be used
  189.   // for an MCDwarfLineEntry object.
  190.  
  191. public:
  192.   // Constructor to create an MCDwarfLineEntry given a symbol and the dwarf loc.
  193.   MCDwarfLineEntry(MCSymbol *label, const MCDwarfLoc loc)
  194.       : MCDwarfLoc(loc), Label(label) {}
  195.  
  196.   MCSymbol *getLabel() const { return Label; }
  197.  
  198.   // This indicates the line entry is synthesized for an end entry.
  199.   bool IsEndEntry = false;
  200.  
  201.   // Override the label with the given EndLabel.
  202.   void setEndLabel(MCSymbol *EndLabel) {
  203.     Label = EndLabel;
  204.     IsEndEntry = true;
  205.   }
  206.  
  207.   // This is called when an instruction is assembled into the specified
  208.   // section and if there is information from the last .loc directive that
  209.   // has yet to have a line entry made for it is made.
  210.   static void make(MCStreamer *MCOS, MCSection *Section);
  211. };
  212.  
  213. /// Instances of this class represent the line information for a compile
  214. /// unit where machine instructions have been assembled after seeing .loc
  215. /// directives.  This is the information used to build the dwarf line
  216. /// table for a section.
  217. class MCLineSection {
  218. public:
  219.   // Add an entry to this MCLineSection's line entries.
  220.   void addLineEntry(const MCDwarfLineEntry &LineEntry, MCSection *Sec) {
  221.     MCLineDivisions[Sec].push_back(LineEntry);
  222.   }
  223.  
  224.   // Add an end entry by cloning the last entry, if exists, for the section
  225.   // the given EndLabel belongs to. The label is replaced by the given EndLabel.
  226.   void addEndEntry(MCSymbol *EndLabel);
  227.  
  228.   using MCDwarfLineEntryCollection = std::vector<MCDwarfLineEntry>;
  229.   using iterator = MCDwarfLineEntryCollection::iterator;
  230.   using const_iterator = MCDwarfLineEntryCollection::const_iterator;
  231.   using MCLineDivisionMap = MapVector<MCSection *, MCDwarfLineEntryCollection>;
  232.  
  233. private:
  234.   // A collection of MCDwarfLineEntry for each section.
  235.   MCLineDivisionMap MCLineDivisions;
  236.  
  237. public:
  238.   // Returns the collection of MCDwarfLineEntry for a given Compile Unit ID.
  239.   const MCLineDivisionMap &getMCLineEntries() const {
  240.     return MCLineDivisions;
  241.   }
  242. };
  243.  
  244. struct MCDwarfLineTableParams {
  245.   /// First special line opcode - leave room for the standard opcodes.
  246.   /// Note: If you want to change this, you'll have to update the
  247.   /// "StandardOpcodeLengths" table that is emitted in
  248.   /// \c Emit().
  249.   uint8_t DWARF2LineOpcodeBase = 13;
  250.   /// Minimum line offset in a special line info. opcode.  The value
  251.   /// -5 was chosen to give a reasonable range of values.
  252.   int8_t DWARF2LineBase = -5;
  253.   /// Range of line offsets in a special line info. opcode.
  254.   uint8_t DWARF2LineRange = 14;
  255. };
  256.  
  257. struct MCDwarfLineTableHeader {
  258.   MCSymbol *Label = nullptr;
  259.   SmallVector<std::string, 3> MCDwarfDirs;
  260.   SmallVector<MCDwarfFile, 3> MCDwarfFiles;
  261.   StringMap<unsigned> SourceIdMap;
  262.   std::string CompilationDir;
  263.   MCDwarfFile RootFile;
  264.   bool HasSource = false;
  265. private:
  266.   bool HasAllMD5 = true;
  267.   bool HasAnyMD5 = false;
  268.  
  269. public:
  270.   MCDwarfLineTableHeader() = default;
  271.  
  272.   Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName,
  273.                                 std::optional<MD5::MD5Result> Checksum,
  274.                                 std::optional<StringRef> Source,
  275.                                 uint16_t DwarfVersion, unsigned FileNumber = 0);
  276.   std::pair<MCSymbol *, MCSymbol *>
  277.   Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
  278.        std::optional<MCDwarfLineStr> &LineStr) const;
  279.   std::pair<MCSymbol *, MCSymbol *>
  280.   Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
  281.        ArrayRef<char> SpecialOpcodeLengths,
  282.        std::optional<MCDwarfLineStr> &LineStr) const;
  283.   void resetMD5Usage() {
  284.     HasAllMD5 = true;
  285.     HasAnyMD5 = false;
  286.   }
  287.   void trackMD5Usage(bool MD5Used) {
  288.     HasAllMD5 &= MD5Used;
  289.     HasAnyMD5 |= MD5Used;
  290.   }
  291.   bool isMD5UsageConsistent() const {
  292.     return MCDwarfFiles.empty() || (HasAllMD5 == HasAnyMD5);
  293.   }
  294.  
  295.   void setRootFile(StringRef Directory, StringRef FileName,
  296.                    std::optional<MD5::MD5Result> Checksum,
  297.                    std::optional<StringRef> Source) {
  298.     CompilationDir = std::string(Directory);
  299.     RootFile.Name = std::string(FileName);
  300.     RootFile.DirIndex = 0;
  301.     RootFile.Checksum = Checksum;
  302.     RootFile.Source = Source;
  303.     trackMD5Usage(Checksum.has_value());
  304.     HasSource = Source.has_value();
  305.   }
  306.  
  307.   void resetFileTable() {
  308.     MCDwarfDirs.clear();
  309.     MCDwarfFiles.clear();
  310.     RootFile.Name.clear();
  311.     resetMD5Usage();
  312.     HasSource = false;
  313.   }
  314.  
  315. private:
  316.   void emitV2FileDirTables(MCStreamer *MCOS) const;
  317.   void emitV5FileDirTables(MCStreamer *MCOS,
  318.                            std::optional<MCDwarfLineStr> &LineStr) const;
  319. };
  320.  
  321. class MCDwarfDwoLineTable {
  322.   MCDwarfLineTableHeader Header;
  323.   bool HasSplitLineTable = false;
  324.  
  325. public:
  326.   void maybeSetRootFile(StringRef Directory, StringRef FileName,
  327.                         std::optional<MD5::MD5Result> Checksum,
  328.                         std::optional<StringRef> Source) {
  329.     if (!Header.RootFile.Name.empty())
  330.       return;
  331.     Header.setRootFile(Directory, FileName, Checksum, Source);
  332.   }
  333.  
  334.   unsigned getFile(StringRef Directory, StringRef FileName,
  335.                    std::optional<MD5::MD5Result> Checksum,
  336.                    uint16_t DwarfVersion, std::optional<StringRef> Source) {
  337.     HasSplitLineTable = true;
  338.     return cantFail(Header.tryGetFile(Directory, FileName, Checksum, Source,
  339.                                       DwarfVersion));
  340.   }
  341.  
  342.   void Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params,
  343.             MCSection *Section) const;
  344. };
  345.  
  346. class MCDwarfLineTable {
  347.   MCDwarfLineTableHeader Header;
  348.   MCLineSection MCLineSections;
  349.  
  350. public:
  351.   // This emits the Dwarf file and the line tables for all Compile Units.
  352.   static void emit(MCStreamer *MCOS, MCDwarfLineTableParams Params);
  353.  
  354.   // This emits the Dwarf file and the line tables for a given Compile Unit.
  355.   void emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params,
  356.               std::optional<MCDwarfLineStr> &LineStr) const;
  357.  
  358.   // This emits a single line table associated with a given Section.
  359.   static void
  360.   emitOne(MCStreamer *MCOS, MCSection *Section,
  361.           const MCLineSection::MCDwarfLineEntryCollection &LineEntries);
  362.  
  363.   Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName,
  364.                                 std::optional<MD5::MD5Result> Checksum,
  365.                                 std::optional<StringRef> Source,
  366.                                 uint16_t DwarfVersion, unsigned FileNumber = 0);
  367.   unsigned getFile(StringRef &Directory, StringRef &FileName,
  368.                    std::optional<MD5::MD5Result> Checksum,
  369.                    std::optional<StringRef> Source, uint16_t DwarfVersion,
  370.                    unsigned FileNumber = 0) {
  371.     return cantFail(tryGetFile(Directory, FileName, Checksum, Source,
  372.                                DwarfVersion, FileNumber));
  373.   }
  374.  
  375.   void setRootFile(StringRef Directory, StringRef FileName,
  376.                    std::optional<MD5::MD5Result> Checksum,
  377.                    std::optional<StringRef> Source) {
  378.     Header.CompilationDir = std::string(Directory);
  379.     Header.RootFile.Name = std::string(FileName);
  380.     Header.RootFile.DirIndex = 0;
  381.     Header.RootFile.Checksum = Checksum;
  382.     Header.RootFile.Source = Source;
  383.     Header.trackMD5Usage(Checksum.has_value());
  384.     Header.HasSource = Source.has_value();
  385.   }
  386.  
  387.   void resetFileTable() { Header.resetFileTable(); }
  388.  
  389.   bool hasRootFile() const { return !Header.RootFile.Name.empty(); }
  390.  
  391.   MCDwarfFile &getRootFile() { return Header.RootFile; }
  392.   const MCDwarfFile &getRootFile() const { return Header.RootFile; }
  393.  
  394.   // Report whether MD5 usage has been consistent (all-or-none).
  395.   bool isMD5UsageConsistent() const { return Header.isMD5UsageConsistent(); }
  396.  
  397.   MCSymbol *getLabel() const {
  398.     return Header.Label;
  399.   }
  400.  
  401.   void setLabel(MCSymbol *Label) {
  402.     Header.Label = Label;
  403.   }
  404.  
  405.   const SmallVectorImpl<std::string> &getMCDwarfDirs() const {
  406.     return Header.MCDwarfDirs;
  407.   }
  408.  
  409.   SmallVectorImpl<std::string> &getMCDwarfDirs() {
  410.     return Header.MCDwarfDirs;
  411.   }
  412.  
  413.   const SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() const {
  414.     return Header.MCDwarfFiles;
  415.   }
  416.  
  417.   SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() {
  418.     return Header.MCDwarfFiles;
  419.   }
  420.  
  421.   const MCLineSection &getMCLineSections() const {
  422.     return MCLineSections;
  423.   }
  424.   MCLineSection &getMCLineSections() {
  425.     return MCLineSections;
  426.   }
  427. };
  428.  
  429. class MCDwarfLineAddr {
  430. public:
  431.   /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas.
  432.   static void Encode(MCContext &Context, MCDwarfLineTableParams Params,
  433.                      int64_t LineDelta, uint64_t AddrDelta, raw_ostream &OS);
  434.  
  435.   /// Utility function to emit the encoding to a streamer.
  436.   static void Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
  437.                    int64_t LineDelta, uint64_t AddrDelta);
  438. };
  439.  
  440. class MCGenDwarfInfo {
  441. public:
  442.   //
  443.   // When generating dwarf for assembly source files this emits the Dwarf
  444.   // sections.
  445.   //
  446.   static void Emit(MCStreamer *MCOS);
  447. };
  448.  
  449. // When generating dwarf for assembly source files this is the info that is
  450. // needed to be gathered for each symbol that will have a dwarf label.
  451. class MCGenDwarfLabelEntry {
  452. private:
  453.   // Name of the symbol without a leading underbar, if any.
  454.   StringRef Name;
  455.   // The dwarf file number this symbol is in.
  456.   unsigned FileNumber;
  457.   // The line number this symbol is at.
  458.   unsigned LineNumber;
  459.   // The low_pc for the dwarf label is taken from this symbol.
  460.   MCSymbol *Label;
  461.  
  462. public:
  463.   MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, unsigned lineNumber,
  464.                        MCSymbol *label)
  465.       : Name(name), FileNumber(fileNumber), LineNumber(lineNumber),
  466.         Label(label) {}
  467.  
  468.   StringRef getName() const { return Name; }
  469.   unsigned getFileNumber() const { return FileNumber; }
  470.   unsigned getLineNumber() const { return LineNumber; }
  471.   MCSymbol *getLabel() const { return Label; }
  472.  
  473.   // This is called when label is created when we are generating dwarf for
  474.   // assembly source files.
  475.   static void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr,
  476.                    SMLoc &Loc);
  477. };
  478.  
  479. class MCCFIInstruction {
  480. public:
  481.   enum OpType {
  482.     OpSameValue,
  483.     OpRememberState,
  484.     OpRestoreState,
  485.     OpOffset,
  486.     OpLLVMDefAspaceCfa,
  487.     OpDefCfaRegister,
  488.     OpDefCfaOffset,
  489.     OpDefCfa,
  490.     OpRelOffset,
  491.     OpAdjustCfaOffset,
  492.     OpEscape,
  493.     OpRestore,
  494.     OpUndefined,
  495.     OpRegister,
  496.     OpWindowSave,
  497.     OpNegateRAState,
  498.     OpGnuArgsSize
  499.   };
  500.  
  501. private:
  502.   OpType Operation;
  503.   MCSymbol *Label;
  504.   unsigned Register;
  505.   union {
  506.     int Offset;
  507.     unsigned Register2;
  508.   };
  509.   unsigned AddressSpace;
  510.   std::vector<char> Values;
  511.   std::string Comment;
  512.  
  513.   MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, StringRef V,
  514.                    StringRef Comment = "")
  515.       : Operation(Op), Label(L), Register(R), Offset(O),
  516.         Values(V.begin(), V.end()), Comment(Comment) {
  517.     assert(Op != OpRegister && Op != OpLLVMDefAspaceCfa);
  518.   }
  519.  
  520.   MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2)
  521.       : Operation(Op), Label(L), Register(R1), Register2(R2) {
  522.     assert(Op == OpRegister);
  523.   }
  524.  
  525.   MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, unsigned AS)
  526.       : Operation(Op), Label(L), Register(R), Offset(O), AddressSpace(AS) {
  527.     assert(Op == OpLLVMDefAspaceCfa);
  528.   }
  529.  
  530. public:
  531.   /// .cfi_def_cfa defines a rule for computing CFA as: take address from
  532.   /// Register and add Offset to it.
  533.   static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register,
  534.                                     int Offset) {
  535.     return MCCFIInstruction(OpDefCfa, L, Register, Offset, "");
  536.   }
  537.  
  538.   /// .cfi_def_cfa_register modifies a rule for computing CFA. From now
  539.   /// on Register will be used instead of the old one. Offset remains the same.
  540.   static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register) {
  541.     return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, "");
  542.   }
  543.  
  544.   /// .cfi_def_cfa_offset modifies a rule for computing CFA. Register
  545.   /// remains the same, but offset is new. Note that it is the absolute offset
  546.   /// that will be added to a defined register to the compute CFA address.
  547.   static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int Offset) {
  548.     return MCCFIInstruction(OpDefCfaOffset, L, 0, Offset, "");
  549.   }
  550.  
  551.   /// .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but
  552.   /// Offset is a relative value that is added/subtracted from the previous
  553.   /// offset.
  554.   static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int Adjustment) {
  555.     return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, "");
  556.   }
  557.  
  558.   // FIXME: Update the remaining docs to use the new proposal wording.
  559.   /// .cfi_llvm_def_aspace_cfa defines the rule for computing the CFA to
  560.   /// be the result of evaluating the DWARF operation expression
  561.   /// `DW_OP_constu AS; DW_OP_aspace_bregx R, B` as a location description.
  562.   static MCCFIInstruction createLLVMDefAspaceCfa(MCSymbol *L, unsigned Register,
  563.                                                  int Offset,
  564.                                                  unsigned AddressSpace) {
  565.     return MCCFIInstruction(OpLLVMDefAspaceCfa, L, Register, Offset,
  566.                             AddressSpace);
  567.   }
  568.  
  569.   /// .cfi_offset Previous value of Register is saved at offset Offset
  570.   /// from CFA.
  571.   static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register,
  572.                                        int Offset) {
  573.     return MCCFIInstruction(OpOffset, L, Register, Offset, "");
  574.   }
  575.  
  576.   /// .cfi_rel_offset Previous value of Register is saved at offset
  577.   /// Offset from the current CFA register. This is transformed to .cfi_offset
  578.   /// using the known displacement of the CFA register from the CFA.
  579.   static MCCFIInstruction createRelOffset(MCSymbol *L, unsigned Register,
  580.                                           int Offset) {
  581.     return MCCFIInstruction(OpRelOffset, L, Register, Offset, "");
  582.   }
  583.  
  584.   /// .cfi_register Previous value of Register1 is saved in
  585.   /// register Register2.
  586.   static MCCFIInstruction createRegister(MCSymbol *L, unsigned Register1,
  587.                                          unsigned Register2) {
  588.     return MCCFIInstruction(OpRegister, L, Register1, Register2);
  589.   }
  590.  
  591.   /// .cfi_window_save SPARC register window is saved.
  592.   static MCCFIInstruction createWindowSave(MCSymbol *L) {
  593.     return MCCFIInstruction(OpWindowSave, L, 0, 0, "");
  594.   }
  595.  
  596.   /// .cfi_negate_ra_state AArch64 negate RA state.
  597.   static MCCFIInstruction createNegateRAState(MCSymbol *L) {
  598.     return MCCFIInstruction(OpNegateRAState, L, 0, 0, "");
  599.   }
  600.  
  601.   /// .cfi_restore says that the rule for Register is now the same as it
  602.   /// was at the beginning of the function, after all initial instructions added
  603.   /// by .cfi_startproc were executed.
  604.   static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register) {
  605.     return MCCFIInstruction(OpRestore, L, Register, 0, "");
  606.   }
  607.  
  608.   /// .cfi_undefined From now on the previous value of Register can't be
  609.   /// restored anymore.
  610.   static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) {
  611.     return MCCFIInstruction(OpUndefined, L, Register, 0, "");
  612.   }
  613.  
  614.   /// .cfi_same_value Current value of Register is the same as in the
  615.   /// previous frame. I.e., no restoration is needed.
  616.   static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) {
  617.     return MCCFIInstruction(OpSameValue, L, Register, 0, "");
  618.   }
  619.  
  620.   /// .cfi_remember_state Save all current rules for all registers.
  621.   static MCCFIInstruction createRememberState(MCSymbol *L) {
  622.     return MCCFIInstruction(OpRememberState, L, 0, 0, "");
  623.   }
  624.  
  625.   /// .cfi_restore_state Restore the previously saved state.
  626.   static MCCFIInstruction createRestoreState(MCSymbol *L) {
  627.     return MCCFIInstruction(OpRestoreState, L, 0, 0, "");
  628.   }
  629.  
  630.   /// .cfi_escape Allows the user to add arbitrary bytes to the unwind
  631.   /// info.
  632.   static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals,
  633.                                        StringRef Comment = "") {
  634.     return MCCFIInstruction(OpEscape, L, 0, 0, Vals, Comment);
  635.   }
  636.  
  637.   /// A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE
  638.   static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int Size) {
  639.     return MCCFIInstruction(OpGnuArgsSize, L, 0, Size, "");
  640.   }
  641.  
  642.   OpType getOperation() const { return Operation; }
  643.   MCSymbol *getLabel() const { return Label; }
  644.  
  645.   unsigned getRegister() const {
  646.     assert(Operation == OpDefCfa || Operation == OpOffset ||
  647.            Operation == OpRestore || Operation == OpUndefined ||
  648.            Operation == OpSameValue || Operation == OpDefCfaRegister ||
  649.            Operation == OpRelOffset || Operation == OpRegister ||
  650.            Operation == OpLLVMDefAspaceCfa);
  651.     return Register;
  652.   }
  653.  
  654.   unsigned getRegister2() const {
  655.     assert(Operation == OpRegister);
  656.     return Register2;
  657.   }
  658.  
  659.   unsigned getAddressSpace() const {
  660.     assert(Operation == OpLLVMDefAspaceCfa);
  661.     return AddressSpace;
  662.   }
  663.  
  664.   int getOffset() const {
  665.     assert(Operation == OpDefCfa || Operation == OpOffset ||
  666.            Operation == OpRelOffset || Operation == OpDefCfaOffset ||
  667.            Operation == OpAdjustCfaOffset || Operation == OpGnuArgsSize ||
  668.            Operation == OpLLVMDefAspaceCfa);
  669.     return Offset;
  670.   }
  671.  
  672.   StringRef getValues() const {
  673.     assert(Operation == OpEscape);
  674.     return StringRef(&Values[0], Values.size());
  675.   }
  676.  
  677.   StringRef getComment() const {
  678.     return Comment;
  679.   }
  680. };
  681.  
  682. struct MCDwarfFrameInfo {
  683.   MCDwarfFrameInfo() = default;
  684.  
  685.   MCSymbol *Begin = nullptr;
  686.   MCSymbol *End = nullptr;
  687.   const MCSymbol *Personality = nullptr;
  688.   const MCSymbol *Lsda = nullptr;
  689.   std::vector<MCCFIInstruction> Instructions;
  690.   unsigned CurrentCfaRegister = 0;
  691.   unsigned PersonalityEncoding = 0;
  692.   unsigned LsdaEncoding = 0;
  693.   uint32_t CompactUnwindEncoding = 0;
  694.   bool IsSignalFrame = false;
  695.   bool IsSimple = false;
  696.   unsigned RAReg = static_cast<unsigned>(INT_MAX);
  697.   bool IsBKeyFrame = false;
  698.   bool IsMTETaggedFrame = false;
  699. };
  700.  
  701. class MCDwarfFrameEmitter {
  702. public:
  703.   //
  704.   // This emits the frame info section.
  705.   //
  706.   static void Emit(MCObjectStreamer &streamer, MCAsmBackend *MAB, bool isEH);
  707.   static void EmitAdvanceLoc(MCObjectStreamer &Streamer, uint64_t AddrDelta);
  708.   static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta,
  709.                                raw_ostream &OS);
  710. };
  711.  
  712. } // end namespace llvm
  713.  
  714. #endif // LLVM_MC_MCDWARF_H
  715.