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/StringTableBuilder.h" 23 #include "llvm/Support/Error.h" 24 #include "llvm/Support/MD5.h" 25 #include "llvm/Support/StringSaver.h" 26 #include <cassert> 27 #include <cstdint> 28 #include <string> 29 #include <utility> 30 #include <vector> 31 32 namespace llvm { 33 34 template <typename T> class ArrayRef; 35 class MCAsmBackend; 36 class MCContext; 37 class 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 Optional<MD5::MD5Result> Checksum; 93 94 /// The source code of the file. Non-owning reference to data allocated in 95 /// MCContext. 96 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 Optional<MD5::MD5Result> Checksum, 274 Optional<StringRef> Source, 275 uint16_t DwarfVersion, 276 unsigned FileNumber = 0); 277 std::pair<MCSymbol *, MCSymbol *> 278 Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, 279 Optional<MCDwarfLineStr> &LineStr) const; 280 std::pair<MCSymbol *, MCSymbol *> 281 Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, 282 ArrayRef<char> SpecialOpcodeLengths, 283 Optional<MCDwarfLineStr> &LineStr) const; 284 void resetMD5Usage() { 285 HasAllMD5 = true; 286 HasAnyMD5 = false; 287 } 288 void trackMD5Usage(bool MD5Used) { 289 HasAllMD5 &= MD5Used; 290 HasAnyMD5 |= MD5Used; 291 } 292 bool isMD5UsageConsistent() const { 293 return MCDwarfFiles.empty() || (HasAllMD5 == HasAnyMD5); 294 } 295 296 void setRootFile(StringRef Directory, StringRef FileName, 297 Optional<MD5::MD5Result> Checksum, 298 Optional<StringRef> Source) { 299 CompilationDir = std::string(Directory); 300 RootFile.Name = std::string(FileName); 301 RootFile.DirIndex = 0; 302 RootFile.Checksum = Checksum; 303 RootFile.Source = Source; 304 trackMD5Usage(Checksum.has_value()); 305 HasSource = Source.has_value(); 306 } 307 308 void resetFileTable() { 309 MCDwarfDirs.clear(); 310 MCDwarfFiles.clear(); 311 RootFile.Name.clear(); 312 resetMD5Usage(); 313 HasSource = false; 314 } 315 316 private: 317 void emitV2FileDirTables(MCStreamer *MCOS) const; 318 void emitV5FileDirTables(MCStreamer *MCOS, 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 Optional<MD5::MD5Result> Checksum, 328 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 Optional<MD5::MD5Result> Checksum, uint16_t DwarfVersion, 336 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 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 Optional<MD5::MD5Result> Checksum, 365 Optional<StringRef> Source, 366 uint16_t DwarfVersion, 367 unsigned FileNumber = 0); 368 unsigned getFile(StringRef &Directory, StringRef &FileName, 369 Optional<MD5::MD5Result> Checksum, Optional<StringRef> Source, 370 uint16_t DwarfVersion, unsigned FileNumber = 0) { 371 return cantFail(tryGetFile(Directory, FileName, Checksum, Source, 372 DwarfVersion, FileNumber)); 373 } 374 375 void setRootFile(StringRef Directory, StringRef FileName, 376 Optional<MD5::MD5Result> Checksum, Optional<StringRef> Source) { 377 Header.CompilationDir = std::string(Directory); 378 Header.RootFile.Name = std::string(FileName); 379 Header.RootFile.DirIndex = 0; 380 Header.RootFile.Checksum = Checksum; 381 Header.RootFile.Source = Source; 382 Header.trackMD5Usage(Checksum.has_value()); 383 Header.HasSource = Source.has_value(); 384 } 385 386 void resetFileTable() { Header.resetFileTable(); } 387 388 bool hasRootFile() const { return !Header.RootFile.Name.empty(); } 389 390 MCDwarfFile &getRootFile() { return Header.RootFile; } 391 const MCDwarfFile &getRootFile() const { return Header.RootFile; } 392 393 // Report whether MD5 usage has been consistent (all-or-none). 394 bool isMD5UsageConsistent() const { return Header.isMD5UsageConsistent(); } 395 396 MCSymbol *getLabel() const { 397 return Header.Label; 398 } 399 400 void setLabel(MCSymbol *Label) { 401 Header.Label = Label; 402 } 403 404 const SmallVectorImpl<std::string> &getMCDwarfDirs() const { 405 return Header.MCDwarfDirs; 406 } 407 408 SmallVectorImpl<std::string> &getMCDwarfDirs() { 409 return Header.MCDwarfDirs; 410 } 411 412 const SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() const { 413 return Header.MCDwarfFiles; 414 } 415 416 SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() { 417 return Header.MCDwarfFiles; 418 } 419 420 const MCLineSection &getMCLineSections() const { 421 return MCLineSections; 422 } 423 MCLineSection &getMCLineSections() { 424 return MCLineSections; 425 } 426 }; 427 428 class MCDwarfLineAddr { 429 public: 430 /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. 431 static void Encode(MCContext &Context, MCDwarfLineTableParams Params, 432 int64_t LineDelta, uint64_t AddrDelta, raw_ostream &OS); 433 434 /// Utility function to emit the encoding to a streamer. 435 static void Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, 436 int64_t LineDelta, uint64_t AddrDelta); 437 }; 438 439 class MCGenDwarfInfo { 440 public: 441 // 442 // When generating dwarf for assembly source files this emits the Dwarf 443 // sections. 444 // 445 static void Emit(MCStreamer *MCOS); 446 }; 447 448 // When generating dwarf for assembly source files this is the info that is 449 // needed to be gathered for each symbol that will have a dwarf label. 450 class MCGenDwarfLabelEntry { 451 private: 452 // Name of the symbol without a leading underbar, if any. 453 StringRef Name; 454 // The dwarf file number this symbol is in. 455 unsigned FileNumber; 456 // The line number this symbol is at. 457 unsigned LineNumber; 458 // The low_pc for the dwarf label is taken from this symbol. 459 MCSymbol *Label; 460 461 public: 462 MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, unsigned lineNumber, 463 MCSymbol *label) 464 : Name(name), FileNumber(fileNumber), LineNumber(lineNumber), 465 Label(label) {} 466 467 StringRef getName() const { return Name; } 468 unsigned getFileNumber() const { return FileNumber; } 469 unsigned getLineNumber() const { return LineNumber; } 470 MCSymbol *getLabel() const { return Label; } 471 472 // This is called when label is created when we are generating dwarf for 473 // assembly source files. 474 static void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr, 475 SMLoc &Loc); 476 }; 477 478 class MCCFIInstruction { 479 public: 480 enum OpType { 481 OpSameValue, 482 OpRememberState, 483 OpRestoreState, 484 OpOffset, 485 OpLLVMDefAspaceCfa, 486 OpDefCfaRegister, 487 OpDefCfaOffset, 488 OpDefCfa, 489 OpRelOffset, 490 OpAdjustCfaOffset, 491 OpEscape, 492 OpRestore, 493 OpUndefined, 494 OpRegister, 495 OpWindowSave, 496 OpNegateRAState, 497 OpGnuArgsSize 498 }; 499 500 private: 501 OpType Operation; 502 MCSymbol *Label; 503 unsigned Register; 504 union { 505 int Offset; 506 unsigned Register2; 507 }; 508 unsigned AddressSpace; 509 std::vector<char> Values; 510 std::string Comment; 511 512 MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, StringRef V, 513 StringRef Comment = "") 514 : Operation(Op), Label(L), Register(R), Offset(O), 515 Values(V.begin(), V.end()), Comment(Comment) { 516 assert(Op != OpRegister && Op != OpLLVMDefAspaceCfa); 517 } 518 519 MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2) 520 : Operation(Op), Label(L), Register(R1), Register2(R2) { 521 assert(Op == OpRegister); 522 } 523 524 MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, unsigned AS) 525 : Operation(Op), Label(L), Register(R), Offset(O), AddressSpace(AS) { 526 assert(Op == OpLLVMDefAspaceCfa); 527 } 528 529 public: 530 /// .cfi_def_cfa defines a rule for computing CFA as: take address from 531 /// Register and add Offset to it. 532 static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register, 533 int Offset) { 534 return MCCFIInstruction(OpDefCfa, L, Register, Offset, ""); 535 } 536 537 /// .cfi_def_cfa_register modifies a rule for computing CFA. From now 538 /// on Register will be used instead of the old one. Offset remains the same. 539 static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register) { 540 return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, ""); 541 } 542 543 /// .cfi_def_cfa_offset modifies a rule for computing CFA. Register 544 /// remains the same, but offset is new. Note that it is the absolute offset 545 /// that will be added to a defined register to the compute CFA address. 546 static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int Offset) { 547 return MCCFIInstruction(OpDefCfaOffset, L, 0, Offset, ""); 548 } 549 550 /// .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but 551 /// Offset is a relative value that is added/subtracted from the previous 552 /// offset. 553 static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int Adjustment) { 554 return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, ""); 555 } 556 557 // FIXME: Update the remaining docs to use the new proposal wording. 558 /// .cfi_llvm_def_aspace_cfa defines the rule for computing the CFA to 559 /// be the result of evaluating the DWARF operation expression 560 /// `DW_OP_constu AS; DW_OP_aspace_bregx R, B` as a location description. 561 static MCCFIInstruction createLLVMDefAspaceCfa(MCSymbol *L, unsigned Register, 562 int Offset, 563 unsigned AddressSpace) { 564 return MCCFIInstruction(OpLLVMDefAspaceCfa, L, Register, Offset, 565 AddressSpace); 566 } 567 568 /// .cfi_offset Previous value of Register is saved at offset Offset 569 /// from CFA. 570 static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, 571 int Offset) { 572 return MCCFIInstruction(OpOffset, L, Register, Offset, ""); 573 } 574 575 /// .cfi_rel_offset Previous value of Register is saved at offset 576 /// Offset from the current CFA register. This is transformed to .cfi_offset 577 /// using the known displacement of the CFA register from the CFA. 578 static MCCFIInstruction createRelOffset(MCSymbol *L, unsigned Register, 579 int Offset) { 580 return MCCFIInstruction(OpRelOffset, L, Register, Offset, ""); 581 } 582 583 /// .cfi_register Previous value of Register1 is saved in 584 /// register Register2. 585 static MCCFIInstruction createRegister(MCSymbol *L, unsigned Register1, 586 unsigned Register2) { 587 return MCCFIInstruction(OpRegister, L, Register1, Register2); 588 } 589 590 /// .cfi_window_save SPARC register window is saved. 591 static MCCFIInstruction createWindowSave(MCSymbol *L) { 592 return MCCFIInstruction(OpWindowSave, L, 0, 0, ""); 593 } 594 595 /// .cfi_negate_ra_state AArch64 negate RA state. 596 static MCCFIInstruction createNegateRAState(MCSymbol *L) { 597 return MCCFIInstruction(OpNegateRAState, L, 0, 0, ""); 598 } 599 600 /// .cfi_restore says that the rule for Register is now the same as it 601 /// was at the beginning of the function, after all initial instructions added 602 /// by .cfi_startproc were executed. 603 static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register) { 604 return MCCFIInstruction(OpRestore, L, Register, 0, ""); 605 } 606 607 /// .cfi_undefined From now on the previous value of Register can't be 608 /// restored anymore. 609 static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) { 610 return MCCFIInstruction(OpUndefined, L, Register, 0, ""); 611 } 612 613 /// .cfi_same_value Current value of Register is the same as in the 614 /// previous frame. I.e., no restoration is needed. 615 static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) { 616 return MCCFIInstruction(OpSameValue, L, Register, 0, ""); 617 } 618 619 /// .cfi_remember_state Save all current rules for all registers. 620 static MCCFIInstruction createRememberState(MCSymbol *L) { 621 return MCCFIInstruction(OpRememberState, L, 0, 0, ""); 622 } 623 624 /// .cfi_restore_state Restore the previously saved state. 625 static MCCFIInstruction createRestoreState(MCSymbol *L) { 626 return MCCFIInstruction(OpRestoreState, L, 0, 0, ""); 627 } 628 629 /// .cfi_escape Allows the user to add arbitrary bytes to the unwind 630 /// info. 631 static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals, 632 StringRef Comment = "") { 633 return MCCFIInstruction(OpEscape, L, 0, 0, Vals, Comment); 634 } 635 636 /// A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE 637 static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int Size) { 638 return MCCFIInstruction(OpGnuArgsSize, L, 0, Size, ""); 639 } 640 641 OpType getOperation() const { return Operation; } 642 MCSymbol *getLabel() const { return Label; } 643 644 unsigned getRegister() const { 645 assert(Operation == OpDefCfa || Operation == OpOffset || 646 Operation == OpRestore || Operation == OpUndefined || 647 Operation == OpSameValue || Operation == OpDefCfaRegister || 648 Operation == OpRelOffset || Operation == OpRegister || 649 Operation == OpLLVMDefAspaceCfa); 650 return Register; 651 } 652 653 unsigned getRegister2() const { 654 assert(Operation == OpRegister); 655 return Register2; 656 } 657 658 unsigned getAddressSpace() const { 659 assert(Operation == OpLLVMDefAspaceCfa); 660 return AddressSpace; 661 } 662 663 int getOffset() const { 664 assert(Operation == OpDefCfa || Operation == OpOffset || 665 Operation == OpRelOffset || Operation == OpDefCfaOffset || 666 Operation == OpAdjustCfaOffset || Operation == OpGnuArgsSize || 667 Operation == OpLLVMDefAspaceCfa); 668 return Offset; 669 } 670 671 StringRef getValues() const { 672 assert(Operation == OpEscape); 673 return StringRef(&Values[0], Values.size()); 674 } 675 676 StringRef getComment() const { 677 return Comment; 678 } 679 }; 680 681 struct MCDwarfFrameInfo { 682 MCDwarfFrameInfo() = default; 683 684 MCSymbol *Begin = nullptr; 685 MCSymbol *End = nullptr; 686 const MCSymbol *Personality = nullptr; 687 const MCSymbol *Lsda = nullptr; 688 std::vector<MCCFIInstruction> Instructions; 689 unsigned CurrentCfaRegister = 0; 690 unsigned PersonalityEncoding = 0; 691 unsigned LsdaEncoding = 0; 692 uint32_t CompactUnwindEncoding = 0; 693 bool IsSignalFrame = false; 694 bool IsSimple = false; 695 unsigned RAReg = static_cast<unsigned>(INT_MAX); 696 bool IsBKeyFrame = false; 697 bool IsMTETaggedFrame = false; 698 }; 699 700 class MCDwarfFrameEmitter { 701 public: 702 // 703 // This emits the frame info section. 704 // 705 static void Emit(MCObjectStreamer &streamer, MCAsmBackend *MAB, bool isEH); 706 static void EmitAdvanceLoc(MCObjectStreamer &Streamer, uint64_t AddrDelta); 707 static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta, 708 raw_ostream &OS); 709 }; 710 711 } // end namespace llvm 712 713 #endif // LLVM_MC_MCDWARF_H 714