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