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