]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/MC/MCDwarf.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / MC / MCDwarf.h
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
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.
99   unsigned getFileNum() const { return FileNum; }
100
101   /// Get the Line of this MCDwarfLoc.
102   unsigned getLine() const { return Line; }
103
104   /// Get the Column of this MCDwarfLoc.
105   unsigned getColumn() const { return Column; }
106
107   /// Get the Flags of this MCDwarfLoc.
108   unsigned getFlags() const { return Flags; }
109
110   /// Get the Isa of this MCDwarfLoc.
111   unsigned getIsa() const { return Isa; }
112
113   /// Get the Discriminator of this MCDwarfLoc.
114   unsigned getDiscriminator() const { return Discriminator; }
115
116   /// Set the FileNum of this MCDwarfLoc.
117   void setFileNum(unsigned fileNum) { FileNum = fileNum; }
118
119   /// Set the Line of this MCDwarfLoc.
120   void setLine(unsigned line) { Line = line; }
121
122   /// Set the Column of this MCDwarfLoc.
123   void setColumn(unsigned column) {
124     assert(column <= UINT16_MAX);
125     Column = column;
126   }
127
128   /// Set the Flags of this MCDwarfLoc.
129   void setFlags(unsigned flags) {
130     assert(flags <= UINT8_MAX);
131     Flags = flags;
132   }
133
134   /// Set the Isa of this MCDwarfLoc.
135   void setIsa(unsigned isa) {
136     assert(isa <= UINT8_MAX);
137     Isa = isa;
138   }
139
140   /// Set the Discriminator of this MCDwarfLoc.
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.
160   MCDwarfLineEntry(MCSymbol *label, const MCDwarfLoc loc)
161       : MCDwarfLoc(loc), Label(label) {}
162
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.
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.
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;
237   void resetMD5Usage() {
238     HasAllMD5 = true;
239     HasAnyMD5 = false;
240   }
241   void trackMD5Usage(bool MD5Used) {
242     HasAllMD5 &= MD5Used;
243     HasAnyMD5 |= MD5Used;
244   }
245   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:
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
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
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
315   void resetRootFile() {
316     assert(Header.MCDwarfFiles.empty());
317     Header.RootFile.Name.clear();
318     Header.resetMD5Usage();
319     Header.HasSource = false;
320   }
321
322   bool hasRootFile() const { return !Header.RootFile.Name.empty(); }
323
324   // Report whether MD5 usage has been consistent (all-or-none).
325   bool isMD5UsageConsistent() const { return Header.isMD5UsageConsistent(); }
326
327   MCSymbol *getLabel() const {
328     return Header.Label;
329   }
330
331   void setLabel(MCSymbol *Label) {
332     Header.Label = Label;
333   }
334
335   const SmallVectorImpl<std::string> &getMCDwarfDirs() const {
336     return Header.MCDwarfDirs;
337   }
338
339   SmallVectorImpl<std::string> &getMCDwarfDirs() {
340     return Header.MCDwarfDirs;
341   }
342
343   const SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() const {
344     return Header.MCDwarfFiles;
345   }
346
347   SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() {
348     return Header.MCDwarfFiles;
349   }
350
351   const MCLineSection &getMCLineSections() const {
352     return MCLineSections;
353   }
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:
400   MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, unsigned lineNumber,
401                        MCSymbol *label)
402       : Name(name), FileNumber(fileNumber), LineNumber(lineNumber),
403         Label(label) {}
404
405   StringRef getName() const { return Name; }
406   unsigned getFileNumber() const { return FileNumber; }
407   unsigned getLineNumber() const { return LineNumber; }
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
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
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.
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.
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.
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.
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.
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.
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.
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.
509   static MCCFIInstruction createWindowSave(MCSymbol *L) {
510     return MCCFIInstruction(OpWindowSave, L, 0, 0, "");
511   }
512
513   /// .cfi_negate_ra_state AArch64 negate RA state.
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.
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.
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.
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.
538   static MCCFIInstruction createRememberState(MCSymbol *L) {
539     return MCCFIInstruction(OpRememberState, L, 0, 0, "");
540   }
541
542   /// .cfi_restore_state Restore the previously saved state.
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.
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
554   static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int Size) {
555     return MCCFIInstruction(OpGnuArgsSize, L, 0, Size, "");
556   }
557
558   OpType getOperation() const { return Operation; }
559   MCSymbol *getLabel() const { return Label; }
560
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
569   unsigned getRegister2() const {
570     assert(Operation == OpRegister);
571     return Register2;
572   }
573
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
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