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/Optional.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/StringMap.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/MC/StringTableBuilder.h"
23 #include "llvm/Support/Error.h"
24 #include "llvm/Support/MD5.h"
25 #include "llvm/Support/StringSaver.h"
26 #include <cassert>
27 #include <cstdint>
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   Optional<MD5::MD5Result> Checksum;
93 
94   /// The source code of the file. Non-owning reference to data allocated in
95   /// MCContext.
96   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                                 Optional<MD5::MD5Result> Checksum,
274                                 Optional<StringRef> Source,
275                                 uint16_t DwarfVersion,
276                                 unsigned FileNumber = 0);
277   std::pair<MCSymbol *, MCSymbol *>
278   Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
279        Optional<MCDwarfLineStr> &LineStr) const;
280   std::pair<MCSymbol *, MCSymbol *>
281   Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
282        ArrayRef<char> SpecialOpcodeLengths,
283        Optional<MCDwarfLineStr> &LineStr) const;
284   void resetMD5Usage() {
285     HasAllMD5 = true;
286     HasAnyMD5 = false;
287   }
288   void trackMD5Usage(bool MD5Used) {
289     HasAllMD5 &= MD5Used;
290     HasAnyMD5 |= MD5Used;
291   }
292   bool isMD5UsageConsistent() const {
293     return MCDwarfFiles.empty() || (HasAllMD5 == HasAnyMD5);
294   }
295 
296   void setRootFile(StringRef Directory, StringRef FileName,
297                    Optional<MD5::MD5Result> Checksum,
298                    Optional<StringRef> Source) {
299     CompilationDir = std::string(Directory);
300     RootFile.Name = std::string(FileName);
301     RootFile.DirIndex = 0;
302     RootFile.Checksum = Checksum;
303     RootFile.Source = Source;
304     trackMD5Usage(Checksum.has_value());
305     HasSource = Source.has_value();
306   }
307 
308   void resetFileTable() {
309     MCDwarfDirs.clear();
310     MCDwarfFiles.clear();
311     RootFile.Name.clear();
312     resetMD5Usage();
313     HasSource = false;
314   }
315 
316 private:
317   void emitV2FileDirTables(MCStreamer *MCOS) const;
318   void emitV5FileDirTables(MCStreamer *MCOS, 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                         Optional<MD5::MD5Result> Checksum,
328                         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                    Optional<MD5::MD5Result> Checksum, uint16_t DwarfVersion,
336                    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               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                                 Optional<MD5::MD5Result> Checksum,
365                                 Optional<StringRef> Source,
366                                 uint16_t DwarfVersion,
367                                 unsigned FileNumber = 0);
368   unsigned getFile(StringRef &Directory, StringRef &FileName,
369                    Optional<MD5::MD5Result> Checksum, Optional<StringRef> Source,
370                    uint16_t DwarfVersion, unsigned FileNumber = 0) {
371     return cantFail(tryGetFile(Directory, FileName, Checksum, Source,
372                                DwarfVersion, FileNumber));
373   }
374 
375   void setRootFile(StringRef Directory, StringRef FileName,
376                    Optional<MD5::MD5Result> Checksum, Optional<StringRef> Source) {
377     Header.CompilationDir = std::string(Directory);
378     Header.RootFile.Name = std::string(FileName);
379     Header.RootFile.DirIndex = 0;
380     Header.RootFile.Checksum = Checksum;
381     Header.RootFile.Source = Source;
382     Header.trackMD5Usage(Checksum.has_value());
383     Header.HasSource = Source.has_value();
384   }
385 
386   void resetFileTable() { Header.resetFileTable(); }
387 
388   bool hasRootFile() const { return !Header.RootFile.Name.empty(); }
389 
390   MCDwarfFile &getRootFile() { return Header.RootFile; }
391   const MCDwarfFile &getRootFile() const { return Header.RootFile; }
392 
393   // Report whether MD5 usage has been consistent (all-or-none).
394   bool isMD5UsageConsistent() const { return Header.isMD5UsageConsistent(); }
395 
396   MCSymbol *getLabel() const {
397     return Header.Label;
398   }
399 
400   void setLabel(MCSymbol *Label) {
401     Header.Label = Label;
402   }
403 
404   const SmallVectorImpl<std::string> &getMCDwarfDirs() const {
405     return Header.MCDwarfDirs;
406   }
407 
408   SmallVectorImpl<std::string> &getMCDwarfDirs() {
409     return Header.MCDwarfDirs;
410   }
411 
412   const SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() const {
413     return Header.MCDwarfFiles;
414   }
415 
416   SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() {
417     return Header.MCDwarfFiles;
418   }
419 
420   const MCLineSection &getMCLineSections() const {
421     return MCLineSections;
422   }
423   MCLineSection &getMCLineSections() {
424     return MCLineSections;
425   }
426 };
427 
428 class MCDwarfLineAddr {
429 public:
430   /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas.
431   static void Encode(MCContext &Context, MCDwarfLineTableParams Params,
432                      int64_t LineDelta, uint64_t AddrDelta, raw_ostream &OS);
433 
434   /// Utility function to emit the encoding to a streamer.
435   static void Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
436                    int64_t LineDelta, uint64_t AddrDelta);
437 };
438 
439 class MCGenDwarfInfo {
440 public:
441   //
442   // When generating dwarf for assembly source files this emits the Dwarf
443   // sections.
444   //
445   static void Emit(MCStreamer *MCOS);
446 };
447 
448 // When generating dwarf for assembly source files this is the info that is
449 // needed to be gathered for each symbol that will have a dwarf label.
450 class MCGenDwarfLabelEntry {
451 private:
452   // Name of the symbol without a leading underbar, if any.
453   StringRef Name;
454   // The dwarf file number this symbol is in.
455   unsigned FileNumber;
456   // The line number this symbol is at.
457   unsigned LineNumber;
458   // The low_pc for the dwarf label is taken from this symbol.
459   MCSymbol *Label;
460 
461 public:
462   MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, unsigned lineNumber,
463                        MCSymbol *label)
464       : Name(name), FileNumber(fileNumber), LineNumber(lineNumber),
465         Label(label) {}
466 
467   StringRef getName() const { return Name; }
468   unsigned getFileNumber() const { return FileNumber; }
469   unsigned getLineNumber() const { return LineNumber; }
470   MCSymbol *getLabel() const { return Label; }
471 
472   // This is called when label is created when we are generating dwarf for
473   // assembly source files.
474   static void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr,
475                    SMLoc &Loc);
476 };
477 
478 class MCCFIInstruction {
479 public:
480   enum OpType {
481     OpSameValue,
482     OpRememberState,
483     OpRestoreState,
484     OpOffset,
485     OpLLVMDefAspaceCfa,
486     OpDefCfaRegister,
487     OpDefCfaOffset,
488     OpDefCfa,
489     OpRelOffset,
490     OpAdjustCfaOffset,
491     OpEscape,
492     OpRestore,
493     OpUndefined,
494     OpRegister,
495     OpWindowSave,
496     OpNegateRAState,
497     OpGnuArgsSize
498   };
499 
500 private:
501   OpType Operation;
502   MCSymbol *Label;
503   unsigned Register;
504   union {
505     int Offset;
506     unsigned Register2;
507   };
508   unsigned AddressSpace;
509   std::vector<char> Values;
510   std::string Comment;
511 
512   MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, StringRef V,
513                    StringRef Comment = "")
514       : Operation(Op), Label(L), Register(R), Offset(O),
515         Values(V.begin(), V.end()), Comment(Comment) {
516     assert(Op != OpRegister && Op != OpLLVMDefAspaceCfa);
517   }
518 
519   MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2)
520       : Operation(Op), Label(L), Register(R1), Register2(R2) {
521     assert(Op == OpRegister);
522   }
523 
524   MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, unsigned AS)
525       : Operation(Op), Label(L), Register(R), Offset(O), AddressSpace(AS) {
526     assert(Op == OpLLVMDefAspaceCfa);
527   }
528 
529 public:
530   /// .cfi_def_cfa defines a rule for computing CFA as: take address from
531   /// Register and add Offset to it.
532   static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register,
533                                     int Offset) {
534     return MCCFIInstruction(OpDefCfa, L, Register, Offset, "");
535   }
536 
537   /// .cfi_def_cfa_register modifies a rule for computing CFA. From now
538   /// on Register will be used instead of the old one. Offset remains the same.
539   static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register) {
540     return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, "");
541   }
542 
543   /// .cfi_def_cfa_offset modifies a rule for computing CFA. Register
544   /// remains the same, but offset is new. Note that it is the absolute offset
545   /// that will be added to a defined register to the compute CFA address.
546   static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int Offset) {
547     return MCCFIInstruction(OpDefCfaOffset, L, 0, Offset, "");
548   }
549 
550   /// .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but
551   /// Offset is a relative value that is added/subtracted from the previous
552   /// offset.
553   static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int Adjustment) {
554     return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, "");
555   }
556 
557   // FIXME: Update the remaining docs to use the new proposal wording.
558   /// .cfi_llvm_def_aspace_cfa defines the rule for computing the CFA to
559   /// be the result of evaluating the DWARF operation expression
560   /// `DW_OP_constu AS; DW_OP_aspace_bregx R, B` as a location description.
561   static MCCFIInstruction createLLVMDefAspaceCfa(MCSymbol *L, unsigned Register,
562                                                  int Offset,
563                                                  unsigned AddressSpace) {
564     return MCCFIInstruction(OpLLVMDefAspaceCfa, L, Register, Offset,
565                             AddressSpace);
566   }
567 
568   /// .cfi_offset Previous value of Register is saved at offset Offset
569   /// from CFA.
570   static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register,
571                                        int Offset) {
572     return MCCFIInstruction(OpOffset, L, Register, Offset, "");
573   }
574 
575   /// .cfi_rel_offset Previous value of Register is saved at offset
576   /// Offset from the current CFA register. This is transformed to .cfi_offset
577   /// using the known displacement of the CFA register from the CFA.
578   static MCCFIInstruction createRelOffset(MCSymbol *L, unsigned Register,
579                                           int Offset) {
580     return MCCFIInstruction(OpRelOffset, L, Register, Offset, "");
581   }
582 
583   /// .cfi_register Previous value of Register1 is saved in
584   /// register Register2.
585   static MCCFIInstruction createRegister(MCSymbol *L, unsigned Register1,
586                                          unsigned Register2) {
587     return MCCFIInstruction(OpRegister, L, Register1, Register2);
588   }
589 
590   /// .cfi_window_save SPARC register window is saved.
591   static MCCFIInstruction createWindowSave(MCSymbol *L) {
592     return MCCFIInstruction(OpWindowSave, L, 0, 0, "");
593   }
594 
595   /// .cfi_negate_ra_state AArch64 negate RA state.
596   static MCCFIInstruction createNegateRAState(MCSymbol *L) {
597     return MCCFIInstruction(OpNegateRAState, L, 0, 0, "");
598   }
599 
600   /// .cfi_restore says that the rule for Register is now the same as it
601   /// was at the beginning of the function, after all initial instructions added
602   /// by .cfi_startproc were executed.
603   static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register) {
604     return MCCFIInstruction(OpRestore, L, Register, 0, "");
605   }
606 
607   /// .cfi_undefined From now on the previous value of Register can't be
608   /// restored anymore.
609   static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) {
610     return MCCFIInstruction(OpUndefined, L, Register, 0, "");
611   }
612 
613   /// .cfi_same_value Current value of Register is the same as in the
614   /// previous frame. I.e., no restoration is needed.
615   static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) {
616     return MCCFIInstruction(OpSameValue, L, Register, 0, "");
617   }
618 
619   /// .cfi_remember_state Save all current rules for all registers.
620   static MCCFIInstruction createRememberState(MCSymbol *L) {
621     return MCCFIInstruction(OpRememberState, L, 0, 0, "");
622   }
623 
624   /// .cfi_restore_state Restore the previously saved state.
625   static MCCFIInstruction createRestoreState(MCSymbol *L) {
626     return MCCFIInstruction(OpRestoreState, L, 0, 0, "");
627   }
628 
629   /// .cfi_escape Allows the user to add arbitrary bytes to the unwind
630   /// info.
631   static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals,
632                                        StringRef Comment = "") {
633     return MCCFIInstruction(OpEscape, L, 0, 0, Vals, Comment);
634   }
635 
636   /// A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE
637   static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int Size) {
638     return MCCFIInstruction(OpGnuArgsSize, L, 0, Size, "");
639   }
640 
641   OpType getOperation() const { return Operation; }
642   MCSymbol *getLabel() const { return Label; }
643 
644   unsigned getRegister() const {
645     assert(Operation == OpDefCfa || Operation == OpOffset ||
646            Operation == OpRestore || Operation == OpUndefined ||
647            Operation == OpSameValue || Operation == OpDefCfaRegister ||
648            Operation == OpRelOffset || Operation == OpRegister ||
649            Operation == OpLLVMDefAspaceCfa);
650     return Register;
651   }
652 
653   unsigned getRegister2() const {
654     assert(Operation == OpRegister);
655     return Register2;
656   }
657 
658   unsigned getAddressSpace() const {
659     assert(Operation == OpLLVMDefAspaceCfa);
660     return AddressSpace;
661   }
662 
663   int getOffset() const {
664     assert(Operation == OpDefCfa || Operation == OpOffset ||
665            Operation == OpRelOffset || Operation == OpDefCfaOffset ||
666            Operation == OpAdjustCfaOffset || Operation == OpGnuArgsSize ||
667            Operation == OpLLVMDefAspaceCfa);
668     return Offset;
669   }
670 
671   StringRef getValues() const {
672     assert(Operation == OpEscape);
673     return StringRef(&Values[0], Values.size());
674   }
675 
676   StringRef getComment() const {
677     return Comment;
678   }
679 };
680 
681 struct MCDwarfFrameInfo {
682   MCDwarfFrameInfo() = default;
683 
684   MCSymbol *Begin = nullptr;
685   MCSymbol *End = nullptr;
686   const MCSymbol *Personality = nullptr;
687   const MCSymbol *Lsda = nullptr;
688   std::vector<MCCFIInstruction> Instructions;
689   unsigned CurrentCfaRegister = 0;
690   unsigned PersonalityEncoding = 0;
691   unsigned LsdaEncoding = 0;
692   uint32_t CompactUnwindEncoding = 0;
693   bool IsSignalFrame = false;
694   bool IsSimple = false;
695   unsigned RAReg = static_cast<unsigned>(INT_MAX);
696   bool IsBKeyFrame = false;
697   bool IsMTETaggedFrame = false;
698 };
699 
700 class MCDwarfFrameEmitter {
701 public:
702   //
703   // This emits the frame info section.
704   //
705   static void Emit(MCObjectStreamer &streamer, MCAsmBackend *MAB, bool isEH);
706   static void EmitAdvanceLoc(MCObjectStreamer &Streamer, uint64_t AddrDelta);
707   static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta,
708                                raw_ostream &OS);
709 };
710 
711 } // end namespace llvm
712 
713 #endif // LLVM_MC_MCDWARF_H
714