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