• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     OpGnuArgsSize
434   };
435 
436 private:
437   OpType Operation;
438   MCSymbol *Label;
439   unsigned Register;
440   union {
441     int Offset;
442     unsigned Register2;
443   };
444   std::vector<char> Values;
445 
MCCFIInstruction(OpType Op,MCSymbol * L,unsigned R,int O,StringRef V)446   MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, StringRef V)
447       : Operation(Op), Label(L), Register(R), Offset(O),
448         Values(V.begin(), V.end()) {
449     assert(Op != OpRegister);
450   }
451 
MCCFIInstruction(OpType Op,MCSymbol * L,unsigned R1,unsigned R2)452   MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2)
453       : Operation(Op), Label(L), Register(R1), Register2(R2) {
454     assert(Op == OpRegister);
455   }
456 
457 public:
458   /// .cfi_def_cfa defines a rule for computing CFA as: take address from
459   /// Register and add Offset to it.
createDefCfa(MCSymbol * L,unsigned Register,int Offset)460   static MCCFIInstruction createDefCfa(MCSymbol *L, unsigned Register,
461                                        int Offset) {
462     return MCCFIInstruction(OpDefCfa, L, Register, -Offset, "");
463   }
464 
465   /// .cfi_def_cfa_register modifies a rule for computing CFA. From now
466   /// on Register will be used instead of the old one. Offset remains the same.
createDefCfaRegister(MCSymbol * L,unsigned Register)467   static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register) {
468     return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, "");
469   }
470 
471   /// .cfi_def_cfa_offset modifies a rule for computing CFA. Register
472   /// remains the same, but offset is new. Note that it is the absolute offset
473   /// that will be added to a defined register to the compute CFA address.
createDefCfaOffset(MCSymbol * L,int Offset)474   static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset) {
475     return MCCFIInstruction(OpDefCfaOffset, L, 0, -Offset, "");
476   }
477 
478   /// .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but
479   /// Offset is a relative value that is added/subtracted from the previous
480   /// offset.
createAdjustCfaOffset(MCSymbol * L,int Adjustment)481   static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int Adjustment) {
482     return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, "");
483   }
484 
485   /// .cfi_offset Previous value of Register is saved at offset Offset
486   /// from CFA.
createOffset(MCSymbol * L,unsigned Register,int Offset)487   static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register,
488                                        int Offset) {
489     return MCCFIInstruction(OpOffset, L, Register, Offset, "");
490   }
491 
492   /// .cfi_rel_offset Previous value of Register is saved at offset
493   /// Offset from the current CFA register. This is transformed to .cfi_offset
494   /// using the known displacement of the CFA register from the CFA.
createRelOffset(MCSymbol * L,unsigned Register,int Offset)495   static MCCFIInstruction createRelOffset(MCSymbol *L, unsigned Register,
496                                           int Offset) {
497     return MCCFIInstruction(OpRelOffset, L, Register, Offset, "");
498   }
499 
500   /// .cfi_register Previous value of Register1 is saved in
501   /// register Register2.
createRegister(MCSymbol * L,unsigned Register1,unsigned Register2)502   static MCCFIInstruction createRegister(MCSymbol *L, unsigned Register1,
503                                          unsigned Register2) {
504     return MCCFIInstruction(OpRegister, L, Register1, Register2);
505   }
506 
507   /// .cfi_window_save SPARC register window is saved.
createWindowSave(MCSymbol * L)508   static MCCFIInstruction createWindowSave(MCSymbol *L) {
509     return MCCFIInstruction(OpWindowSave, L, 0, 0, "");
510   }
511 
512   /// .cfi_restore says that the rule for Register is now the same as it
513   /// was at the beginning of the function, after all initial instructions added
514   /// by .cfi_startproc were executed.
createRestore(MCSymbol * L,unsigned Register)515   static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register) {
516     return MCCFIInstruction(OpRestore, L, Register, 0, "");
517   }
518 
519   /// .cfi_undefined From now on the previous value of Register can't be
520   /// restored anymore.
createUndefined(MCSymbol * L,unsigned Register)521   static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) {
522     return MCCFIInstruction(OpUndefined, L, Register, 0, "");
523   }
524 
525   /// .cfi_same_value Current value of Register is the same as in the
526   /// previous frame. I.e., no restoration is needed.
createSameValue(MCSymbol * L,unsigned Register)527   static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) {
528     return MCCFIInstruction(OpSameValue, L, Register, 0, "");
529   }
530 
531   /// .cfi_remember_state Save all current rules for all registers.
createRememberState(MCSymbol * L)532   static MCCFIInstruction createRememberState(MCSymbol *L) {
533     return MCCFIInstruction(OpRememberState, L, 0, 0, "");
534   }
535 
536   /// .cfi_restore_state Restore the previously saved state.
createRestoreState(MCSymbol * L)537   static MCCFIInstruction createRestoreState(MCSymbol *L) {
538     return MCCFIInstruction(OpRestoreState, L, 0, 0, "");
539   }
540 
541   /// .cfi_escape Allows the user to add arbitrary bytes to the unwind
542   /// info.
createEscape(MCSymbol * L,StringRef Vals)543   static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals) {
544     return MCCFIInstruction(OpEscape, L, 0, 0, Vals);
545   }
546 
547   /// A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE
createGnuArgsSize(MCSymbol * L,int Size)548   static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int Size) {
549     return MCCFIInstruction(OpGnuArgsSize, L, 0, Size, "");
550   }
551 
getOperation()552   OpType getOperation() const { return Operation; }
getLabel()553   MCSymbol *getLabel() const { return Label; }
554 
getRegister()555   unsigned getRegister() const {
556     assert(Operation == OpDefCfa || Operation == OpOffset ||
557            Operation == OpRestore || Operation == OpUndefined ||
558            Operation == OpSameValue || Operation == OpDefCfaRegister ||
559            Operation == OpRelOffset || Operation == OpRegister);
560     return Register;
561   }
562 
getRegister2()563   unsigned getRegister2() const {
564     assert(Operation == OpRegister);
565     return Register2;
566   }
567 
getOffset()568   int getOffset() const {
569     assert(Operation == OpDefCfa || Operation == OpOffset ||
570            Operation == OpRelOffset || Operation == OpDefCfaOffset ||
571            Operation == OpAdjustCfaOffset || Operation == OpGnuArgsSize);
572     return Offset;
573   }
574 
getValues()575   StringRef getValues() const {
576     assert(Operation == OpEscape);
577     return StringRef(&Values[0], Values.size());
578   }
579 };
580 
581 struct MCDwarfFrameInfo {
582   MCDwarfFrameInfo() = default;
583 
584   MCSymbol *Begin = nullptr;
585   MCSymbol *End = nullptr;
586   const MCSymbol *Personality = nullptr;
587   const MCSymbol *Lsda = nullptr;
588   std::vector<MCCFIInstruction> Instructions;
589   unsigned CurrentCfaRegister = 0;
590   unsigned PersonalityEncoding = 0;
591   unsigned LsdaEncoding = 0;
592   uint32_t CompactUnwindEncoding = 0;
593   bool IsSignalFrame = false;
594   bool IsSimple = false;
595   unsigned RAReg = static_cast<unsigned>(INT_MAX);
596 };
597 
598 class MCDwarfFrameEmitter {
599 public:
600   //
601   // This emits the frame info section.
602   //
603   static void Emit(MCObjectStreamer &streamer, MCAsmBackend *MAB, bool isEH);
604   static void EmitAdvanceLoc(MCObjectStreamer &Streamer, uint64_t AddrDelta);
605   static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta,
606                                raw_ostream &OS);
607 };
608 
609 } // end namespace llvm
610 
611 #endif // LLVM_MC_MCDWARF_H
612