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