Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

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