]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/MC/MCDwarf.h
Merge clang 7.0.1 and several follow-up changes
[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     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
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
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
532   static MCCFIInstruction createRememberState(MCSymbol *L) {
533     return MCCFIInstruction(OpRememberState, L, 0, 0, "");
534   }
535
536   /// .cfi_restore_state Restore the previously saved state.
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.
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
548   static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int Size) {
549     return MCCFIInstruction(OpGnuArgsSize, L, 0, Size, "");
550   }
551
552   OpType getOperation() const { return Operation; }
553   MCSymbol *getLabel() const { return Label; }
554
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
563   unsigned getRegister2() const {
564     assert(Operation == OpRegister);
565     return Register2;
566   }
567
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
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