]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/MC/MCDwarf.h
Merge lld trunk r338150, and resolve conflicts.
[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 emit the encoding to a streamer.
366   static void Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
367                    int64_t LineDelta, uint64_t AddrDelta);
368 };
369
370 class MCGenDwarfInfo {
371 public:
372   //
373   // When generating dwarf for assembly source files this emits the Dwarf
374   // sections.
375   //
376   static void Emit(MCStreamer *MCOS);
377 };
378
379 // When generating dwarf for assembly source files this is the info that is
380 // needed to be gathered for each symbol that will have a dwarf label.
381 class MCGenDwarfLabelEntry {
382 private:
383   // Name of the symbol without a leading underbar, if any.
384   StringRef Name;
385   // The dwarf file number this symbol is in.
386   unsigned FileNumber;
387   // The line number this symbol is at.
388   unsigned LineNumber;
389   // The low_pc for the dwarf label is taken from this symbol.
390   MCSymbol *Label;
391
392 public:
393   MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, unsigned lineNumber,
394                        MCSymbol *label)
395       : Name(name), FileNumber(fileNumber), LineNumber(lineNumber),
396         Label(label) {}
397
398   StringRef getName() const { return Name; }
399   unsigned getFileNumber() const { return FileNumber; }
400   unsigned getLineNumber() const { return LineNumber; }
401   MCSymbol *getLabel() const { return Label; }
402
403   // This is called when label is created when we are generating dwarf for
404   // assembly source files.
405   static void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr,
406                    SMLoc &Loc);
407 };
408
409 class MCCFIInstruction {
410 public:
411   enum OpType {
412     OpSameValue,
413     OpRememberState,
414     OpRestoreState,
415     OpOffset,
416     OpDefCfaRegister,
417     OpDefCfaOffset,
418     OpDefCfa,
419     OpRelOffset,
420     OpAdjustCfaOffset,
421     OpEscape,
422     OpRestore,
423     OpUndefined,
424     OpRegister,
425     OpWindowSave,
426     OpGnuArgsSize
427   };
428
429 private:
430   OpType Operation;
431   MCSymbol *Label;
432   unsigned Register;
433   union {
434     int Offset;
435     unsigned Register2;
436   };
437   std::vector<char> Values;
438
439   MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, StringRef V)
440       : Operation(Op), Label(L), Register(R), Offset(O),
441         Values(V.begin(), V.end()) {
442     assert(Op != OpRegister);
443   }
444
445   MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2)
446       : Operation(Op), Label(L), Register(R1), Register2(R2) {
447     assert(Op == OpRegister);
448   }
449
450 public:
451   /// .cfi_def_cfa defines a rule for computing CFA as: take address from
452   /// Register and add Offset to it.
453   static MCCFIInstruction createDefCfa(MCSymbol *L, unsigned Register,
454                                        int Offset) {
455     return MCCFIInstruction(OpDefCfa, L, Register, -Offset, "");
456   }
457
458   /// .cfi_def_cfa_register modifies a rule for computing CFA. From now
459   /// on Register will be used instead of the old one. Offset remains the same.
460   static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register) {
461     return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, "");
462   }
463
464   /// .cfi_def_cfa_offset modifies a rule for computing CFA. Register
465   /// remains the same, but offset is new. Note that it is the absolute offset
466   /// that will be added to a defined register to the compute CFA address.
467   static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset) {
468     return MCCFIInstruction(OpDefCfaOffset, L, 0, -Offset, "");
469   }
470
471   /// .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but
472   /// Offset is a relative value that is added/subtracted from the previous
473   /// offset.
474   static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int Adjustment) {
475     return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, "");
476   }
477
478   /// .cfi_offset Previous value of Register is saved at offset Offset
479   /// from CFA.
480   static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register,
481                                        int Offset) {
482     return MCCFIInstruction(OpOffset, L, Register, Offset, "");
483   }
484
485   /// .cfi_rel_offset Previous value of Register is saved at offset
486   /// Offset from the current CFA register. This is transformed to .cfi_offset
487   /// using the known displacement of the CFA register from the CFA.
488   static MCCFIInstruction createRelOffset(MCSymbol *L, unsigned Register,
489                                           int Offset) {
490     return MCCFIInstruction(OpRelOffset, L, Register, Offset, "");
491   }
492
493   /// .cfi_register Previous value of Register1 is saved in
494   /// register Register2.
495   static MCCFIInstruction createRegister(MCSymbol *L, unsigned Register1,
496                                          unsigned Register2) {
497     return MCCFIInstruction(OpRegister, L, Register1, Register2);
498   }
499
500   /// .cfi_window_save SPARC register window is saved.
501   static MCCFIInstruction createWindowSave(MCSymbol *L) {
502     return MCCFIInstruction(OpWindowSave, L, 0, 0, "");
503   }
504
505   /// .cfi_restore says that the rule for Register is now the same as it
506   /// was at the beginning of the function, after all initial instructions added
507   /// by .cfi_startproc were executed.
508   static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register) {
509     return MCCFIInstruction(OpRestore, L, Register, 0, "");
510   }
511
512   /// .cfi_undefined From now on the previous value of Register can't be
513   /// restored anymore.
514   static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) {
515     return MCCFIInstruction(OpUndefined, L, Register, 0, "");
516   }
517
518   /// .cfi_same_value Current value of Register is the same as in the
519   /// previous frame. I.e., no restoration is needed.
520   static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) {
521     return MCCFIInstruction(OpSameValue, L, Register, 0, "");
522   }
523
524   /// .cfi_remember_state Save all current rules for all registers.
525   static MCCFIInstruction createRememberState(MCSymbol *L) {
526     return MCCFIInstruction(OpRememberState, L, 0, 0, "");
527   }
528
529   /// .cfi_restore_state Restore the previously saved state.
530   static MCCFIInstruction createRestoreState(MCSymbol *L) {
531     return MCCFIInstruction(OpRestoreState, L, 0, 0, "");
532   }
533
534   /// .cfi_escape Allows the user to add arbitrary bytes to the unwind
535   /// info.
536   static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals) {
537     return MCCFIInstruction(OpEscape, L, 0, 0, Vals);
538   }
539
540   /// A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE
541   static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int Size) {
542     return MCCFIInstruction(OpGnuArgsSize, L, 0, Size, "");
543   }
544
545   OpType getOperation() const { return Operation; }
546   MCSymbol *getLabel() const { return Label; }
547
548   unsigned getRegister() const {
549     assert(Operation == OpDefCfa || Operation == OpOffset ||
550            Operation == OpRestore || Operation == OpUndefined ||
551            Operation == OpSameValue || Operation == OpDefCfaRegister ||
552            Operation == OpRelOffset || Operation == OpRegister);
553     return Register;
554   }
555
556   unsigned getRegister2() const {
557     assert(Operation == OpRegister);
558     return Register2;
559   }
560
561   int getOffset() const {
562     assert(Operation == OpDefCfa || Operation == OpOffset ||
563            Operation == OpRelOffset || Operation == OpDefCfaOffset ||
564            Operation == OpAdjustCfaOffset || Operation == OpGnuArgsSize);
565     return Offset;
566   }
567
568   StringRef getValues() const {
569     assert(Operation == OpEscape);
570     return StringRef(&Values[0], Values.size());
571   }
572 };
573
574 struct MCDwarfFrameInfo {
575   MCDwarfFrameInfo() = default;
576
577   MCSymbol *Begin = nullptr;
578   MCSymbol *End = nullptr;
579   const MCSymbol *Personality = nullptr;
580   const MCSymbol *Lsda = nullptr;
581   std::vector<MCCFIInstruction> Instructions;
582   unsigned CurrentCfaRegister = 0;
583   unsigned PersonalityEncoding = 0;
584   unsigned LsdaEncoding = 0;
585   uint32_t CompactUnwindEncoding = 0;
586   bool IsSignalFrame = false;
587   bool IsSimple = false;
588   unsigned RAReg = static_cast<unsigned>(INT_MAX);
589 };
590
591 class MCDwarfFrameEmitter {
592 public:
593   //
594   // This emits the frame info section.
595   //
596   static void Emit(MCObjectStreamer &streamer, MCAsmBackend *MAB, bool isEH);
597   static void EmitAdvanceLoc(MCObjectStreamer &Streamer, uint64_t AddrDelta);
598   static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta,
599                                raw_ostream &OS);
600 };
601
602 } // end namespace llvm
603
604 #endif // LLVM_MC_MCDWARF_H