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