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

source code of llvm/include/llvm/MC/MCDwarf.h