Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //===- MCDwarf.h - Machine Code Dwarf 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 // This file contains the declaration of the MCDwarfFile to support the dwarf
0010 // .file directive and the .loc directive.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_MC_MCDWARF_H
0015 #define LLVM_MC_MCDWARF_H
0016 
0017 #include "llvm/ADT/MapVector.h"
0018 #include "llvm/ADT/SmallVector.h"
0019 #include "llvm/ADT/StringMap.h"
0020 #include "llvm/ADT/StringRef.h"
0021 #include "llvm/MC/StringTableBuilder.h"
0022 #include "llvm/Support/Error.h"
0023 #include "llvm/Support/MD5.h"
0024 #include "llvm/Support/SMLoc.h"
0025 #include "llvm/Support/StringSaver.h"
0026 #include <cassert>
0027 #include <cstdint>
0028 #include <optional>
0029 #include <string>
0030 #include <utility>
0031 #include <vector>
0032 
0033 namespace llvm {
0034 
0035 template <typename T> class ArrayRef;
0036 class MCAsmBackend;
0037 class MCContext;
0038 class MCObjectStreamer;
0039 class MCSection;
0040 class MCStreamer;
0041 class MCSymbol;
0042 class raw_ostream;
0043 class SourceMgr;
0044 
0045 namespace mcdwarf {
0046 // Emit the common part of the DWARF 5 range/locations list tables header.
0047 MCSymbol *emitListsTableHeaderStart(MCStreamer &S);
0048 } // namespace mcdwarf
0049 
0050 /// Manage the .debug_line_str section contents, if we use it.
0051 class MCDwarfLineStr {
0052   BumpPtrAllocator Alloc;
0053   StringSaver Saver{Alloc};
0054   MCSymbol *LineStrLabel = nullptr;
0055   StringTableBuilder LineStrings{StringTableBuilder::DWARF};
0056   bool UseRelocs = false;
0057 
0058 public:
0059   /// Construct an instance that can emit .debug_line_str (for use in a normal
0060   /// v5 line table).
0061   explicit MCDwarfLineStr(MCContext &Ctx);
0062 
0063   StringSaver &getSaver() { return Saver; }
0064 
0065   /// Emit a reference to the string.
0066   void emitRef(MCStreamer *MCOS, StringRef Path);
0067 
0068   /// Emit the .debug_line_str section if appropriate.
0069   void emitSection(MCStreamer *MCOS);
0070 
0071   /// Returns finalized section.
0072   SmallString<0> getFinalizedData();
0073 
0074   /// Adds path \p Path to the line string. Returns offset in the
0075   /// .debug_line_str section.
0076   size_t addString(StringRef Path);
0077 };
0078 
0079 /// Instances of this class represent the name of the dwarf .file directive and
0080 /// its associated dwarf file number in the MC file. MCDwarfFile's are created
0081 /// and uniqued by the MCContext class. In Dwarf 4 file numbers start from 1;
0082 /// i.e. the entry with file number 1 is the first element in the vector of
0083 /// DwarfFiles and there is no MCDwarfFile with file number 0. In Dwarf 5 file
0084 /// numbers start from 0, with the MCDwarfFile with file number 0 being the
0085 /// primary source file, and file numbers correspond to their index in the
0086 /// vector.
0087 struct MCDwarfFile {
0088   // The base name of the file without its directory path.
0089   std::string Name;
0090 
0091   // The index into the list of directory names for this file name.
0092   unsigned DirIndex = 0;
0093 
0094   /// The MD5 checksum, if there is one. Non-owning pointer to data allocated
0095   /// in MCContext.
0096   std::optional<MD5::MD5Result> Checksum;
0097 
0098   /// The source code of the file. Non-owning reference to data allocated in
0099   /// MCContext.
0100   std::optional<StringRef> Source;
0101 };
0102 
0103 /// Instances of this class represent the information from a
0104 /// dwarf .loc directive.
0105 class MCDwarfLoc {
0106   uint32_t FileNum;
0107   uint32_t Line;
0108   uint16_t Column;
0109   // Flags (see #define's below)
0110   uint8_t Flags;
0111   uint8_t Isa;
0112   uint32_t Discriminator;
0113 
0114 // Flag that indicates the initial value of the is_stmt_start flag.
0115 #define DWARF2_LINE_DEFAULT_IS_STMT 1
0116 
0117 #define DWARF2_FLAG_IS_STMT (1 << 0)
0118 #define DWARF2_FLAG_BASIC_BLOCK (1 << 1)
0119 #define DWARF2_FLAG_PROLOGUE_END (1 << 2)
0120 #define DWARF2_FLAG_EPILOGUE_BEGIN (1 << 3)
0121 
0122 private: // MCContext manages these
0123   friend class MCContext;
0124   friend class MCDwarfLineEntry;
0125 
0126   MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags,
0127              unsigned isa, unsigned discriminator)
0128       : FileNum(fileNum), Line(line), Column(column), Flags(flags), Isa(isa),
0129         Discriminator(discriminator) {}
0130 
0131   // Allow the default copy constructor and assignment operator to be used
0132   // for an MCDwarfLoc object.
0133 
0134 public:
0135   /// Get the FileNum of this MCDwarfLoc.
0136   unsigned getFileNum() const { return FileNum; }
0137 
0138   /// Get the Line of this MCDwarfLoc.
0139   unsigned getLine() const { return Line; }
0140 
0141   /// Get the Column of this MCDwarfLoc.
0142   unsigned getColumn() const { return Column; }
0143 
0144   /// Get the Flags of this MCDwarfLoc.
0145   unsigned getFlags() const { return Flags; }
0146 
0147   /// Get the Isa of this MCDwarfLoc.
0148   unsigned getIsa() const { return Isa; }
0149 
0150   /// Get the Discriminator of this MCDwarfLoc.
0151   unsigned getDiscriminator() const { return Discriminator; }
0152 
0153   /// Set the FileNum of this MCDwarfLoc.
0154   void setFileNum(unsigned fileNum) { FileNum = fileNum; }
0155 
0156   /// Set the Line of this MCDwarfLoc.
0157   void setLine(unsigned line) { Line = line; }
0158 
0159   /// Set the Column of this MCDwarfLoc.
0160   void setColumn(unsigned column) {
0161     assert(column <= UINT16_MAX);
0162     Column = column;
0163   }
0164 
0165   /// Set the Flags of this MCDwarfLoc.
0166   void setFlags(unsigned flags) {
0167     assert(flags <= UINT8_MAX);
0168     Flags = flags;
0169   }
0170 
0171   /// Set the Isa of this MCDwarfLoc.
0172   void setIsa(unsigned isa) {
0173     assert(isa <= UINT8_MAX);
0174     Isa = isa;
0175   }
0176 
0177   /// Set the Discriminator of this MCDwarfLoc.
0178   void setDiscriminator(unsigned discriminator) {
0179     Discriminator = discriminator;
0180   }
0181 };
0182 
0183 /// Instances of this class represent the line information for
0184 /// the dwarf line table entries.  Which is created after a machine
0185 /// instruction is assembled and uses an address from a temporary label
0186 /// created at the current address in the current section and the info from
0187 /// the last .loc directive seen as stored in the context.
0188 class MCDwarfLineEntry : public MCDwarfLoc {
0189   MCSymbol *Label;
0190 
0191 private:
0192   // Allow the default copy constructor and assignment operator to be used
0193   // for an MCDwarfLineEntry object.
0194 
0195 public:
0196   // Constructor to create an MCDwarfLineEntry given a symbol and the dwarf loc.
0197   MCDwarfLineEntry(MCSymbol *label, const MCDwarfLoc loc,
0198                    MCSymbol *lineStreamLabel = nullptr,
0199                    SMLoc streamLabelDefLoc = {})
0200       : MCDwarfLoc(loc), Label(label), LineStreamLabel(lineStreamLabel),
0201         StreamLabelDefLoc(streamLabelDefLoc) {}
0202 
0203   MCSymbol *getLabel() const { return Label; }
0204 
0205   // This is the label that is to be emitted into the line stream. If this is
0206   // non-null and we need to emit a label, also make sure to restart the current
0207   // line sequence.
0208   MCSymbol *LineStreamLabel;
0209 
0210   // Location where LineStreamLabel was defined. If there is an error emitting
0211   // LineStreamLabel, we can use the SMLoc to report an error.
0212   SMLoc StreamLabelDefLoc;
0213 
0214   // This indicates the line entry is synthesized for an end entry.
0215   bool IsEndEntry = false;
0216 
0217   // Override the label with the given EndLabel.
0218   void setEndLabel(MCSymbol *EndLabel) {
0219     Label = EndLabel;
0220     IsEndEntry = true;
0221   }
0222 
0223   // This is called when an instruction is assembled into the specified
0224   // section and if there is information from the last .loc directive that
0225   // has yet to have a line entry made for it is made.
0226   static void make(MCStreamer *MCOS, MCSection *Section);
0227 };
0228 
0229 /// Instances of this class represent the line information for a compile
0230 /// unit where machine instructions have been assembled after seeing .loc
0231 /// directives.  This is the information used to build the dwarf line
0232 /// table for a section.
0233 class MCLineSection {
0234 public:
0235   // Add an entry to this MCLineSection's line entries.
0236   void addLineEntry(const MCDwarfLineEntry &LineEntry, MCSection *Sec) {
0237     MCLineDivisions[Sec].push_back(LineEntry);
0238   }
0239 
0240   // Add an end entry by cloning the last entry, if exists, for the section
0241   // the given EndLabel belongs to. The label is replaced by the given EndLabel.
0242   void addEndEntry(MCSymbol *EndLabel);
0243 
0244   using MCDwarfLineEntryCollection = std::vector<MCDwarfLineEntry>;
0245   using iterator = MCDwarfLineEntryCollection::iterator;
0246   using const_iterator = MCDwarfLineEntryCollection::const_iterator;
0247   using MCLineDivisionMap = MapVector<MCSection *, MCDwarfLineEntryCollection>;
0248 
0249 private:
0250   // A collection of MCDwarfLineEntry for each section.
0251   MCLineDivisionMap MCLineDivisions;
0252 
0253 public:
0254   // Returns the collection of MCDwarfLineEntry for a given Compile Unit ID.
0255   const MCLineDivisionMap &getMCLineEntries() const {
0256     return MCLineDivisions;
0257   }
0258 };
0259 
0260 struct MCDwarfLineTableParams {
0261   /// First special line opcode - leave room for the standard opcodes.
0262   /// Note: If you want to change this, you'll have to update the
0263   /// "StandardOpcodeLengths" table that is emitted in
0264   /// \c Emit().
0265   uint8_t DWARF2LineOpcodeBase = 13;
0266   /// Minimum line offset in a special line info. opcode.  The value
0267   /// -5 was chosen to give a reasonable range of values.
0268   int8_t DWARF2LineBase = -5;
0269   /// Range of line offsets in a special line info. opcode.
0270   uint8_t DWARF2LineRange = 14;
0271 };
0272 
0273 struct MCDwarfLineTableHeader {
0274   MCSymbol *Label = nullptr;
0275   SmallVector<std::string, 3> MCDwarfDirs;
0276   SmallVector<MCDwarfFile, 3> MCDwarfFiles;
0277   StringMap<unsigned> SourceIdMap;
0278   std::string CompilationDir;
0279   MCDwarfFile RootFile;
0280   bool HasAnySource = false;
0281 
0282 private:
0283   bool HasAllMD5 = true;
0284   bool HasAnyMD5 = false;
0285 
0286 public:
0287   MCDwarfLineTableHeader() = default;
0288 
0289   Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName,
0290                                 std::optional<MD5::MD5Result> Checksum,
0291                                 std::optional<StringRef> Source,
0292                                 uint16_t DwarfVersion, unsigned FileNumber = 0);
0293   std::pair<MCSymbol *, MCSymbol *>
0294   Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
0295        std::optional<MCDwarfLineStr> &LineStr) const;
0296   std::pair<MCSymbol *, MCSymbol *>
0297   Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
0298        ArrayRef<char> SpecialOpcodeLengths,
0299        std::optional<MCDwarfLineStr> &LineStr) const;
0300   void resetMD5Usage() {
0301     HasAllMD5 = true;
0302     HasAnyMD5 = false;
0303   }
0304   void trackMD5Usage(bool MD5Used) {
0305     HasAllMD5 &= MD5Used;
0306     HasAnyMD5 |= MD5Used;
0307   }
0308   bool isMD5UsageConsistent() const {
0309     return MCDwarfFiles.empty() || (HasAllMD5 == HasAnyMD5);
0310   }
0311 
0312   void setRootFile(StringRef Directory, StringRef FileName,
0313                    std::optional<MD5::MD5Result> Checksum,
0314                    std::optional<StringRef> Source) {
0315     CompilationDir = std::string(Directory);
0316     RootFile.Name = std::string(FileName);
0317     RootFile.DirIndex = 0;
0318     RootFile.Checksum = Checksum;
0319     RootFile.Source = Source;
0320     trackMD5Usage(Checksum.has_value());
0321     HasAnySource |= Source.has_value();
0322   }
0323 
0324   void resetFileTable() {
0325     MCDwarfDirs.clear();
0326     MCDwarfFiles.clear();
0327     RootFile.Name.clear();
0328     resetMD5Usage();
0329     HasAnySource = false;
0330   }
0331 
0332 private:
0333   void emitV2FileDirTables(MCStreamer *MCOS) const;
0334   void emitV5FileDirTables(MCStreamer *MCOS,
0335                            std::optional<MCDwarfLineStr> &LineStr) const;
0336 };
0337 
0338 class MCDwarfDwoLineTable {
0339   MCDwarfLineTableHeader Header;
0340   bool HasSplitLineTable = false;
0341 
0342 public:
0343   void maybeSetRootFile(StringRef Directory, StringRef FileName,
0344                         std::optional<MD5::MD5Result> Checksum,
0345                         std::optional<StringRef> Source) {
0346     if (!Header.RootFile.Name.empty())
0347       return;
0348     Header.setRootFile(Directory, FileName, Checksum, Source);
0349   }
0350 
0351   unsigned getFile(StringRef Directory, StringRef FileName,
0352                    std::optional<MD5::MD5Result> Checksum,
0353                    uint16_t DwarfVersion, std::optional<StringRef> Source) {
0354     HasSplitLineTable = true;
0355     return cantFail(Header.tryGetFile(Directory, FileName, Checksum, Source,
0356                                       DwarfVersion));
0357   }
0358 
0359   void Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params,
0360             MCSection *Section) const;
0361 };
0362 
0363 class MCDwarfLineTable {
0364   MCDwarfLineTableHeader Header;
0365   MCLineSection MCLineSections;
0366 
0367 public:
0368   // This emits the Dwarf file and the line tables for all Compile Units.
0369   static void emit(MCStreamer *MCOS, MCDwarfLineTableParams Params);
0370 
0371   // This emits the Dwarf file and the line tables for a given Compile Unit.
0372   void emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params,
0373               std::optional<MCDwarfLineStr> &LineStr) const;
0374 
0375   // This emits a single line table associated with a given Section.
0376   static void
0377   emitOne(MCStreamer *MCOS, MCSection *Section,
0378           const MCLineSection::MCDwarfLineEntryCollection &LineEntries);
0379 
0380   void endCurrentSeqAndEmitLineStreamLabel(MCStreamer *MCOS, SMLoc DefLoc,
0381                                            StringRef Name);
0382 
0383   Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName,
0384                                 std::optional<MD5::MD5Result> Checksum,
0385                                 std::optional<StringRef> Source,
0386                                 uint16_t DwarfVersion, unsigned FileNumber = 0);
0387   unsigned getFile(StringRef &Directory, StringRef &FileName,
0388                    std::optional<MD5::MD5Result> Checksum,
0389                    std::optional<StringRef> Source, uint16_t DwarfVersion,
0390                    unsigned FileNumber = 0) {
0391     return cantFail(tryGetFile(Directory, FileName, Checksum, Source,
0392                                DwarfVersion, FileNumber));
0393   }
0394 
0395   void setRootFile(StringRef Directory, StringRef FileName,
0396                    std::optional<MD5::MD5Result> Checksum,
0397                    std::optional<StringRef> Source) {
0398     Header.CompilationDir = std::string(Directory);
0399     Header.RootFile.Name = std::string(FileName);
0400     Header.RootFile.DirIndex = 0;
0401     Header.RootFile.Checksum = Checksum;
0402     Header.RootFile.Source = Source;
0403     Header.trackMD5Usage(Checksum.has_value());
0404     Header.HasAnySource |= Source.has_value();
0405   }
0406 
0407   void resetFileTable() { Header.resetFileTable(); }
0408 
0409   bool hasRootFile() const { return !Header.RootFile.Name.empty(); }
0410 
0411   MCDwarfFile &getRootFile() { return Header.RootFile; }
0412   const MCDwarfFile &getRootFile() const { return Header.RootFile; }
0413 
0414   // Report whether MD5 usage has been consistent (all-or-none).
0415   bool isMD5UsageConsistent() const { return Header.isMD5UsageConsistent(); }
0416 
0417   MCSymbol *getLabel() const {
0418     return Header.Label;
0419   }
0420 
0421   void setLabel(MCSymbol *Label) {
0422     Header.Label = Label;
0423   }
0424 
0425   const SmallVectorImpl<std::string> &getMCDwarfDirs() const {
0426     return Header.MCDwarfDirs;
0427   }
0428 
0429   SmallVectorImpl<std::string> &getMCDwarfDirs() {
0430     return Header.MCDwarfDirs;
0431   }
0432 
0433   const SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() const {
0434     return Header.MCDwarfFiles;
0435   }
0436 
0437   SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() {
0438     return Header.MCDwarfFiles;
0439   }
0440 
0441   const MCLineSection &getMCLineSections() const {
0442     return MCLineSections;
0443   }
0444   MCLineSection &getMCLineSections() {
0445     return MCLineSections;
0446   }
0447 };
0448 
0449 class MCDwarfLineAddr {
0450 public:
0451   /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas.
0452   static void encode(MCContext &Context, MCDwarfLineTableParams Params,
0453                      int64_t LineDelta, uint64_t AddrDelta, SmallVectorImpl<char> &OS);
0454 
0455   /// Utility function to emit the encoding to a streamer.
0456   static void Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
0457                    int64_t LineDelta, uint64_t AddrDelta);
0458 };
0459 
0460 class MCGenDwarfInfo {
0461 public:
0462   //
0463   // When generating dwarf for assembly source files this emits the Dwarf
0464   // sections.
0465   //
0466   static void Emit(MCStreamer *MCOS);
0467 };
0468 
0469 // When generating dwarf for assembly source files this is the info that is
0470 // needed to be gathered for each symbol that will have a dwarf label.
0471 class MCGenDwarfLabelEntry {
0472 private:
0473   // Name of the symbol without a leading underbar, if any.
0474   StringRef Name;
0475   // The dwarf file number this symbol is in.
0476   unsigned FileNumber;
0477   // The line number this symbol is at.
0478   unsigned LineNumber;
0479   // The low_pc for the dwarf label is taken from this symbol.
0480   MCSymbol *Label;
0481 
0482 public:
0483   MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, unsigned lineNumber,
0484                        MCSymbol *label)
0485       : Name(name), FileNumber(fileNumber), LineNumber(lineNumber),
0486         Label(label) {}
0487 
0488   StringRef getName() const { return Name; }
0489   unsigned getFileNumber() const { return FileNumber; }
0490   unsigned getLineNumber() const { return LineNumber; }
0491   MCSymbol *getLabel() const { return Label; }
0492 
0493   // This is called when label is created when we are generating dwarf for
0494   // assembly source files.
0495   static void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr,
0496                    SMLoc &Loc);
0497 };
0498 
0499 class MCCFIInstruction {
0500 public:
0501   enum OpType : uint8_t {
0502     OpSameValue,
0503     OpRememberState,
0504     OpRestoreState,
0505     OpOffset,
0506     OpLLVMDefAspaceCfa,
0507     OpDefCfaRegister,
0508     OpDefCfaOffset,
0509     OpDefCfa,
0510     OpRelOffset,
0511     OpAdjustCfaOffset,
0512     OpEscape,
0513     OpRestore,
0514     OpUndefined,
0515     OpRegister,
0516     OpWindowSave,
0517     OpNegateRAState,
0518     OpNegateRAStateWithPC,
0519     OpGnuArgsSize,
0520     OpLabel,
0521     OpValOffset,
0522   };
0523 
0524 private:
0525   MCSymbol *Label;
0526   union {
0527     struct {
0528       unsigned Register;
0529       int64_t Offset;
0530     } RI;
0531     struct {
0532       unsigned Register;
0533       int64_t Offset;
0534       unsigned AddressSpace;
0535     } RIA;
0536     struct {
0537       unsigned Register;
0538       unsigned Register2;
0539     } RR;
0540     MCSymbol *CfiLabel;
0541   } U;
0542   OpType Operation;
0543   SMLoc Loc;
0544   std::vector<char> Values;
0545   std::string Comment;
0546 
0547   MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int64_t O, SMLoc Loc,
0548                    StringRef V = "", StringRef Comment = "")
0549       : Label(L), Operation(Op), Loc(Loc), Values(V.begin(), V.end()),
0550         Comment(Comment) {
0551     assert(Op != OpRegister && Op != OpLLVMDefAspaceCfa);
0552     U.RI = {R, O};
0553   }
0554   MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2, SMLoc Loc)
0555       : Label(L), Operation(Op), Loc(Loc) {
0556     assert(Op == OpRegister);
0557     U.RR = {R1, R2};
0558   }
0559   MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int64_t O, unsigned AS,
0560                    SMLoc Loc)
0561       : Label(L), Operation(Op), Loc(Loc) {
0562     assert(Op == OpLLVMDefAspaceCfa);
0563     U.RIA = {R, O, AS};
0564   }
0565 
0566   MCCFIInstruction(OpType Op, MCSymbol *L, MCSymbol *CfiLabel, SMLoc Loc)
0567       : Label(L), Operation(Op), Loc(Loc) {
0568     assert(Op == OpLabel);
0569     U.CfiLabel = CfiLabel;
0570   }
0571 
0572 public:
0573   /// .cfi_def_cfa defines a rule for computing CFA as: take address from
0574   /// Register and add Offset to it.
0575   static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register,
0576                                     int64_t Offset, SMLoc Loc = {}) {
0577     return MCCFIInstruction(OpDefCfa, L, Register, Offset, Loc);
0578   }
0579 
0580   /// .cfi_def_cfa_register modifies a rule for computing CFA. From now
0581   /// on Register will be used instead of the old one. Offset remains the same.
0582   static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register,
0583                                                SMLoc Loc = {}) {
0584     return MCCFIInstruction(OpDefCfaRegister, L, Register, INT64_C(0), Loc);
0585   }
0586 
0587   /// .cfi_def_cfa_offset modifies a rule for computing CFA. Register
0588   /// remains the same, but offset is new. Note that it is the absolute offset
0589   /// that will be added to a defined register to the compute CFA address.
0590   static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int64_t Offset,
0591                                           SMLoc Loc = {}) {
0592     return MCCFIInstruction(OpDefCfaOffset, L, 0, Offset, Loc);
0593   }
0594 
0595   /// .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but
0596   /// Offset is a relative value that is added/subtracted from the previous
0597   /// offset.
0598   static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int64_t Adjustment,
0599                                                 SMLoc Loc = {}) {
0600     return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, Loc);
0601   }
0602 
0603   // FIXME: Update the remaining docs to use the new proposal wording.
0604   /// .cfi_llvm_def_aspace_cfa defines the rule for computing the CFA to
0605   /// be the result of evaluating the DWARF operation expression
0606   /// `DW_OP_constu AS; DW_OP_aspace_bregx R, B` as a location description.
0607   static MCCFIInstruction createLLVMDefAspaceCfa(MCSymbol *L, unsigned Register,
0608                                                  int64_t Offset,
0609                                                  unsigned AddressSpace,
0610                                                  SMLoc Loc) {
0611     return MCCFIInstruction(OpLLVMDefAspaceCfa, L, Register, Offset,
0612                             AddressSpace, Loc);
0613   }
0614 
0615   /// .cfi_offset Previous value of Register is saved at offset Offset
0616   /// from CFA.
0617   static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register,
0618                                        int64_t Offset, SMLoc Loc = {}) {
0619     return MCCFIInstruction(OpOffset, L, Register, Offset, Loc);
0620   }
0621 
0622   /// .cfi_rel_offset Previous value of Register is saved at offset
0623   /// Offset from the current CFA register. This is transformed to .cfi_offset
0624   /// using the known displacement of the CFA register from the CFA.
0625   static MCCFIInstruction createRelOffset(MCSymbol *L, unsigned Register,
0626                                           int64_t Offset, SMLoc Loc = {}) {
0627     return MCCFIInstruction(OpRelOffset, L, Register, Offset, Loc);
0628   }
0629 
0630   /// .cfi_register Previous value of Register1 is saved in
0631   /// register Register2.
0632   static MCCFIInstruction createRegister(MCSymbol *L, unsigned Register1,
0633                                          unsigned Register2, SMLoc Loc = {}) {
0634     return MCCFIInstruction(OpRegister, L, Register1, Register2, Loc);
0635   }
0636 
0637   /// .cfi_window_save SPARC register window is saved.
0638   static MCCFIInstruction createWindowSave(MCSymbol *L, SMLoc Loc = {}) {
0639     return MCCFIInstruction(OpWindowSave, L, 0, INT64_C(0), Loc);
0640   }
0641 
0642   /// .cfi_negate_ra_state AArch64 negate RA state.
0643   static MCCFIInstruction createNegateRAState(MCSymbol *L, SMLoc Loc = {}) {
0644     return MCCFIInstruction(OpNegateRAState, L, 0, INT64_C(0), Loc);
0645   }
0646 
0647   /// .cfi_negate_ra_state_with_pc AArch64 negate RA state with PC.
0648   static MCCFIInstruction createNegateRAStateWithPC(MCSymbol *L,
0649                                                     SMLoc Loc = {}) {
0650     return MCCFIInstruction(OpNegateRAStateWithPC, L, 0, INT64_C(0), Loc);
0651   }
0652 
0653   /// .cfi_restore says that the rule for Register is now the same as it
0654   /// was at the beginning of the function, after all initial instructions added
0655   /// by .cfi_startproc were executed.
0656   static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register,
0657                                         SMLoc Loc = {}) {
0658     return MCCFIInstruction(OpRestore, L, Register, INT64_C(0), Loc);
0659   }
0660 
0661   /// .cfi_undefined From now on the previous value of Register can't be
0662   /// restored anymore.
0663   static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register,
0664                                           SMLoc Loc = {}) {
0665     return MCCFIInstruction(OpUndefined, L, Register, INT64_C(0), Loc);
0666   }
0667 
0668   /// .cfi_same_value Current value of Register is the same as in the
0669   /// previous frame. I.e., no restoration is needed.
0670   static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register,
0671                                           SMLoc Loc = {}) {
0672     return MCCFIInstruction(OpSameValue, L, Register, INT64_C(0), Loc);
0673   }
0674 
0675   /// .cfi_remember_state Save all current rules for all registers.
0676   static MCCFIInstruction createRememberState(MCSymbol *L, SMLoc Loc = {}) {
0677     return MCCFIInstruction(OpRememberState, L, 0, INT64_C(0), Loc);
0678   }
0679 
0680   /// .cfi_restore_state Restore the previously saved state.
0681   static MCCFIInstruction createRestoreState(MCSymbol *L, SMLoc Loc = {}) {
0682     return MCCFIInstruction(OpRestoreState, L, 0, INT64_C(0), Loc);
0683   }
0684 
0685   /// .cfi_escape Allows the user to add arbitrary bytes to the unwind
0686   /// info.
0687   static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals,
0688                                        SMLoc Loc = {}, StringRef Comment = "") {
0689     return MCCFIInstruction(OpEscape, L, 0, 0, Loc, Vals, Comment);
0690   }
0691 
0692   /// A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE
0693   static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int64_t Size,
0694                                             SMLoc Loc = {}) {
0695     return MCCFIInstruction(OpGnuArgsSize, L, 0, Size, Loc);
0696   }
0697 
0698   static MCCFIInstruction createLabel(MCSymbol *L, MCSymbol *CfiLabel,
0699                                       SMLoc Loc) {
0700     return MCCFIInstruction(OpLabel, L, CfiLabel, Loc);
0701   }
0702 
0703   /// .cfi_val_offset Previous value of Register is offset Offset from the
0704   /// current CFA register.
0705   static MCCFIInstruction createValOffset(MCSymbol *L, unsigned Register,
0706                                           int64_t Offset, SMLoc Loc = {}) {
0707     return MCCFIInstruction(OpValOffset, L, Register, Offset, Loc);
0708   }
0709 
0710   OpType getOperation() const { return Operation; }
0711   MCSymbol *getLabel() const { return Label; }
0712 
0713   unsigned getRegister() const {
0714     if (Operation == OpRegister)
0715       return U.RR.Register;
0716     if (Operation == OpLLVMDefAspaceCfa)
0717       return U.RIA.Register;
0718     assert(Operation == OpDefCfa || Operation == OpOffset ||
0719            Operation == OpRestore || Operation == OpUndefined ||
0720            Operation == OpSameValue || Operation == OpDefCfaRegister ||
0721            Operation == OpRelOffset || Operation == OpValOffset);
0722     return U.RI.Register;
0723   }
0724 
0725   unsigned getRegister2() const {
0726     assert(Operation == OpRegister);
0727     return U.RR.Register2;
0728   }
0729 
0730   unsigned getAddressSpace() const {
0731     assert(Operation == OpLLVMDefAspaceCfa);
0732     return U.RIA.AddressSpace;
0733   }
0734 
0735   int64_t getOffset() const {
0736     if (Operation == OpLLVMDefAspaceCfa)
0737       return U.RIA.Offset;
0738     assert(Operation == OpDefCfa || Operation == OpOffset ||
0739            Operation == OpRelOffset || Operation == OpDefCfaOffset ||
0740            Operation == OpAdjustCfaOffset || Operation == OpGnuArgsSize ||
0741            Operation == OpValOffset);
0742     return U.RI.Offset;
0743   }
0744 
0745   MCSymbol *getCfiLabel() const {
0746     assert(Operation == OpLabel);
0747     return U.CfiLabel;
0748   }
0749 
0750   StringRef getValues() const {
0751     assert(Operation == OpEscape);
0752     return StringRef(&Values[0], Values.size());
0753   }
0754 
0755   StringRef getComment() const { return Comment; }
0756   SMLoc getLoc() const { return Loc; }
0757 };
0758 
0759 struct MCDwarfFrameInfo {
0760   MCDwarfFrameInfo() = default;
0761 
0762   MCSymbol *Begin = nullptr;
0763   MCSymbol *End = nullptr;
0764   const MCSymbol *Personality = nullptr;
0765   const MCSymbol *Lsda = nullptr;
0766   std::vector<MCCFIInstruction> Instructions;
0767   unsigned CurrentCfaRegister = 0;
0768   unsigned PersonalityEncoding = 0;
0769   unsigned LsdaEncoding = 0;
0770   uint64_t CompactUnwindEncoding = 0;
0771   bool IsSignalFrame = false;
0772   bool IsSimple = false;
0773   unsigned RAReg = static_cast<unsigned>(INT_MAX);
0774   bool IsBKeyFrame = false;
0775   bool IsMTETaggedFrame = false;
0776 };
0777 
0778 class MCDwarfFrameEmitter {
0779 public:
0780   //
0781   // This emits the frame info section.
0782   //
0783   static void Emit(MCObjectStreamer &streamer, MCAsmBackend *MAB, bool isEH);
0784   static void encodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta,
0785                                SmallVectorImpl<char> &OS);
0786 };
0787 
0788 } // end namespace llvm
0789 
0790 #endif // LLVM_MC_MCDWARF_H